@bike4mind/cli 1.0.0 → 1.2.0

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 (36) hide show
  1. package/README.md +1 -0
  2. package/bin/bike4mind-cli.mjs +0 -5
  3. package/dist/AgentHistoryStore-B2NEOvSW.mjs +18014 -0
  4. package/dist/{ApiClient-EUTyn5yu.mjs → ApiClient-D0fQ2FT6.mjs} +2 -2
  5. package/dist/{BubblewrapRuntime-CkL9-gnG.mjs → BubblewrapRuntime-5bLPTwEC.mjs} +2 -2
  6. package/dist/{ConfigStore-DHNgFdOu.mjs → ConfigStore-qV7NrCgZ.mjs} +2259 -1283
  7. package/dist/{ProxyManager-C1-lgzEU.mjs → ProxyManager-B0-RuR2w.mjs} +21 -4
  8. package/dist/{SandboxOrchestrator-C8uleDn2.mjs → SandboxOrchestrator-BcUv9fQ3.mjs} +47 -13
  9. package/dist/{SandboxRuntimeAdapter-ChGlxSGQ.mjs → SandboxRuntimeAdapter-BgLUVTJL.mjs} +2 -2
  10. package/dist/{SandboxRuntimeAdapter-CKelGICD.mjs → SandboxRuntimeAdapter-BmHELLuM.mjs} +1 -1
  11. package/dist/{SeatbeltRuntime-Qqt19cAN.mjs → SeatbeltRuntime-C_Y8q8Mr.mjs} +9 -1
  12. package/dist/buildAgent-C-C-VGff.mjs +2001 -0
  13. package/dist/commands/acpCommand.mjs +36 -13
  14. package/dist/commands/apiCommand.mjs +1 -1
  15. package/dist/commands/doctorCommand.mjs +1 -1
  16. package/dist/commands/envCommand.mjs +1 -1
  17. package/dist/commands/headlessCommand.mjs +92 -42
  18. package/dist/commands/mcpCommand.mjs +8 -13
  19. package/dist/commands/pluginCommand.mjs +9 -15
  20. package/dist/commands/updateCommand.mjs +1 -1
  21. package/dist/{createFile-DPv180yF-BnWFIxey.mjs → createFile-B8bur5Rb-CVzCarEA.mjs} +2 -2
  22. package/dist/{deleteFile-BdjUwUQF-B3XOJmg3.mjs → deleteFile-9B3gW_Nb-DG2sovIl.mjs} +2 -2
  23. package/dist/{globFiles-DjfDGaUK-CNR8pMRC.mjs → globFiles-CwJ8qmYo-BR5b2KvO.mjs} +3 -2
  24. package/dist/{grepSearch-BaYUfIYs-n0XKoGnL.mjs → grepSearch-BgoOOwGe-DtlV8Gn-.mjs} +3 -3
  25. package/dist/index.mjs +638 -129
  26. package/dist/{package-7a45-Svr.mjs → package-CGZIoxcs.mjs} +1 -1
  27. package/dist/{pathValidation-D8tjkQXE-1HwvsuYT.mjs → pathValidation-BRqf4HFX-CHwtwp3O.mjs} +7 -3
  28. package/dist/{serve-CavAHPdQ.mjs → serve-CPXqcEZr.mjs} +2 -2
  29. package/dist/types-CdIKgWWe.mjs +3 -0
  30. package/dist/{types-LyRNHOiS.mjs → types-F61_hxmG.mjs} +2 -0
  31. package/package.json +28 -29
  32. package/dist/AgentHistoryStore-CrRb8cMt.mjs +0 -38586
  33. package/dist/ProxyManager-B1jFWL7b.mjs +0 -3
  34. package/dist/SandboxOrchestrator-BFPVpmB5.mjs +0 -3
  35. package/dist/buildAgent-CJrkEG0M.mjs +0 -824
  36. package/dist/types-CqscS34o.mjs +0 -3
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { $ as RemoteSkillSource, A as FallbackLlmBackend, C as createWriteTodosTool, D as createResumeAgentTool, E as createCoordinateTaskTool, I as PermissionManager, J as setWebSocketToolExecutor, O as createBackgroundAgentTools, Q as isReadOnlyTool, S as createTodoStore, et as CustomCommandStore, k as createAgentDelegateTool, nt as SessionStore, tt as CheckpointStore, w as createSkillTool, x as createFindDefinitionTool, y as createGetFileStructureTool } from "../AgentHistoryStore-CrRb8cMt.mjs";
3
- import { c as requireApiUrl, n as logger, t as ConfigStore } from "../ConfigStore-DHNgFdOu.mjs";
4
- import { t as ApiClient } from "../ApiClient-EUTyn5yu.mjs";
5
- import { a as createToolSearchTool, i as buildLlmBackend, n as buildSupportingStores, o as deferredToolRegistry, r as buildSandbox, s as NotifyingLlmBackend, t as buildAgent } from "../buildAgent-CJrkEG0M.mjs";
2
+ import { $ as CustomCommandStore, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, J as setWebSocketToolExecutor, L as wrapTools, O as createResumeAgentTool, Q as RemoteSkillSource, S as createFindDefinitionTool, T as createSkillTool, b as createGetFileStructureTool, et as CheckpointStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, s as buildSandbox, tt as SessionStore, w as createWriteTodosTool } from "../AgentHistoryStore-B2NEOvSW.mjs";
3
+ import { h as requireApiUrl, n as logger, s as isReadOnlyTool, t as ConfigStore } from "../ConfigStore-qV7NrCgZ.mjs";
4
+ import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "../buildAgent-C-C-VGff.mjs";
5
+ import { t as ApiClient } from "../ApiClient-D0fQ2FT6.mjs";
6
6
  import { randomUUID } from "crypto";
7
7
  import { existsSync, realpathSync, statSync } from "fs";
8
8
  import { isAbsolute } from "path";
@@ -634,7 +634,12 @@ var AcpServer = class {
634
634
  agentStore,
635
635
  backgroundManager,
636
636
  historyStore,
637
- sessionId: stackSessionId
637
+ sessionId: stackSessionId,
638
+ permissionManager,
639
+ agentContext,
640
+ apiClient,
641
+ sandboxOrchestrator: sandboxOrchestrator ?? void 0,
642
+ allowedDirectories: additionalDirectories
638
643
  });
639
644
  const agentToolsRef = { current: null };
640
645
  const toolSearchTool = deferredToolRegistry.size() > 0 ? createToolSearchTool(() => {
@@ -678,24 +683,42 @@ var AcpServer = class {
678
683
  };
679
684
  }
680
685
  buildCliTools(input) {
681
- const { config, orchestrator, agentStore, backgroundManager, historyStore, sessionId } = input;
686
+ const { config, orchestrator, agentStore, backgroundManager, historyStore, sessionId, permissionManager, agentContext, apiClient, sandboxOrchestrator, allowedDirectories } = input;
687
+ const cliWrapDeps = {
688
+ permissionManager,
689
+ showPermissionPrompt: this.promptFn,
690
+ agentContext,
691
+ configStore: this.configStore,
692
+ apiClient,
693
+ sandboxOrchestrator,
694
+ allowedDirectories
695
+ };
696
+ const wrappedSecurityTools = wrapTools([
697
+ createFindDefinitionTool(allowedDirectories),
698
+ createGetFileStructureTool(allowedDirectories),
699
+ ...config.preferences.enableSkillTool !== false ? [createSkillTool({
700
+ customCommandStore: this.customCommandStore,
701
+ subagentOrchestrator: orchestrator,
702
+ sessionId,
703
+ permission: {
704
+ permissionManager,
705
+ promptFn: this.promptFn
706
+ },
707
+ allowedDirectories
708
+ })] : []
709
+ ], cliWrapDeps);
682
710
  const tools = [
683
711
  createAgentDelegateTool(orchestrator, agentStore, sessionId, backgroundManager),
684
712
  ...createBackgroundAgentTools(backgroundManager),
685
713
  createResumeAgentTool(orchestrator, historyStore, backgroundManager),
686
714
  createWriteTodosTool(createTodoStore()),
687
- createFindDefinitionTool(),
688
- createGetFileStructureTool()
715
+ ...wrappedSecurityTools
689
716
  ];
690
- if (config.preferences.enableSkillTool !== false) tools.push(createSkillTool({
691
- customCommandStore: this.customCommandStore,
692
- subagentOrchestrator: orchestrator,
693
- sessionId
694
- }));
695
717
  if (config.preferences.enableCoordinatorMode === true) tools.push(createCoordinateTaskTool(orchestrator, agentStore, sessionId));
696
718
  return tools;
697
719
  }
698
720
  async loadCustomCommands() {
721
+ this.customCommandStore.setProjectTrusted(this.configStore.isProjectTrusted());
699
722
  try {
700
723
  await this.customCommandStore.loadCommands();
701
724
  } catch {}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { l as resolveApiEndpoint, s as parseApiUrl, t as ConfigStore } from "../ConfigStore-DHNgFdOu.mjs";
2
+ import { g as resolveApiEndpoint, m as parseApiUrl, t as ConfigStore } from "../ConfigStore-qV7NrCgZ.mjs";
3
3
  //#region src/commands/apiCommand.ts
4
4
  /**
5
5
  * External API config command (--api-url / --reset-api)
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "../package-7a45-Svr.mjs";
2
+ import { t as version } from "../package-CGZIoxcs.mjs";
3
3
  import { a as fetchLatestVersion, c as isNpmPrefixWritable, i as compareSemver } from "../updateChecker-CQW8bxo6.mjs";
4
4
  import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
5
5
  import { execSync } from "child_process";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-DHNgFdOu.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-qV7NrCgZ.mjs";
3
3
  //#region src/commands/envCommand.ts
4
4
  /**
5
5
  * Environment switching for the `--dev` / `--prod` launch flags.
@@ -1,12 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { $ as RemoteSkillSource, A as FallbackLlmBackend, B as classifyCommandRisk, C as createWriteTodosTool, D as createResumeAgentTool, E as createCoordinateTaskTool, F as loadContextFiles, I as PermissionManager, J as setWebSocketToolExecutor, L as generateCliTools, M as ReActAgent, O as createBackgroundAgentTools, Q as isReadOnlyTool, S as createTodoStore, X as buildSystemPrompt, a as McpManager, b as createWorkItemTools, et as CustomCommandStore, i as AgentStore, k as createAgentDelegateTool, n as BackgroundAgentManager, nt as SessionStore, o as createSseBackend, r as SubagentOrchestrator, t as AgentHistoryStore, tt as CheckpointStore, w as createSkillTool, x as createFindDefinitionTool, y as createGetFileStructureTool, z as SHELL_LIKE_TOOL_COMMAND_FIELDS } from "../AgentHistoryStore-CrRb8cMt.mjs";
3
- import { c as requireApiUrl, n as logger, t as ConfigStore } from "../ConfigStore-DHNgFdOu.mjs";
4
- import { t as ApiClient } from "../ApiClient-EUTyn5yu.mjs";
5
- import { t as DEFAULT_SANDBOX_CONFIG } from "../types-LyRNHOiS.mjs";
2
+ import { $ as CustomCommandStore, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, G as classifyCommandRisk, I as generateCliTools, J as setWebSocketToolExecutor, L as wrapTools, N as ReActAgent, O as createResumeAgentTool, Q as RemoteSkillSource, S as createFindDefinitionTool, T as createSkillTool, X as buildSystemPrompt, a as loadProjectContext, b as createGetFileStructureTool, c as createSseBackend, et as CheckpointStore, i as buildProjectAgentStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, n as BackgroundAgentManager, o as McpManager, r as SubagentOrchestrator, s as buildSandbox, t as AgentHistoryStore, tt as SessionStore, w as createWriteTodosTool, x as createWorkItemTools, z as SHELL_LIKE_TOOL_COMMAND_FIELDS } from "../AgentHistoryStore-B2NEOvSW.mjs";
3
+ import { h as requireApiUrl, n as logger, s as isReadOnlyTool, t as ConfigStore } from "../ConfigStore-qV7NrCgZ.mjs";
4
+ import { t as ApiClient } from "../ApiClient-D0fQ2FT6.mjs";
6
5
  import { r as reconstructTurnBlocks, t as WorkItemsClient } from "../WorkItemsClient-Cow6nXx7.mjs";
7
- import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-ChGlxSGQ.mjs";
8
- import { t as SandboxOrchestrator } from "../SandboxOrchestrator-C8uleDn2.mjs";
9
- import { t as ProxyManager } from "../ProxyManager-C1-lgzEU.mjs";
10
6
  import { randomBytes } from "crypto";
11
7
  import { v4 } from "uuid";
12
8
  import { readFile } from "fs/promises";
@@ -120,8 +116,9 @@ const HEADLESS_PERMISSION_POLICY_KEYS = [
120
116
  ];
121
117
  const RISK_RANK = {
122
118
  low: 0,
123
- medium: 1,
124
- high: 2
119
+ unclassified: 1,
120
+ medium: 2,
121
+ high: 3
125
122
  };
126
123
  function readOptionalStringArray(value, label) {
127
124
  if (value === void 0) return [];
@@ -174,6 +171,39 @@ function evaluatePermissionPolicy(policy, toolName, riskLevel) {
174
171
  reason: `policy default (${policy.defaultAction})`
175
172
  };
176
173
  }
174
+ /**
175
+ * Resolve a headless permission decision from the fixed precedence ladder:
176
+ * --dangerously-skip-permissions -> allow-once (explicit blanket override)
177
+ * a directory-grant request -> deny (widening the filesystem allow-list is
178
+ * its own decision; headless has no human to
179
+ * grant it, so fail closed - never inherit the
180
+ * originating tool's policy verdict)
181
+ * a --permission-policy -> its per-tool/per-risk verdict
182
+ * otherwise -> deny (safe default, no silent auto-approve)
183
+ * Extracted from the headless prompt closure so the ladder is unit-testable.
184
+ */
185
+ function resolveHeadlessPermissionDecision(params) {
186
+ const { dangerouslySkipPermissions, isDirectoryGrant, toolName, riskLevel, permissionPolicy } = params;
187
+ if (dangerouslySkipPermissions) return {
188
+ action: "allow-once",
189
+ reason: "dangerously-skip-permissions"
190
+ };
191
+ if (isDirectoryGrant) return {
192
+ action: "deny",
193
+ reason: "directory access not granted in headless mode"
194
+ };
195
+ if (permissionPolicy) {
196
+ const verdict = evaluatePermissionPolicy(permissionPolicy, toolName, riskLevel);
197
+ return {
198
+ action: verdict.action === "allow" ? "allow-once" : "deny",
199
+ reason: verdict.reason
200
+ };
201
+ }
202
+ return {
203
+ action: "deny",
204
+ reason: "no permission policy; default deny"
205
+ };
206
+ }
177
207
  //#endregion
178
208
  //#region src/commands/headlessCommand.ts
179
209
  /**
@@ -182,6 +212,16 @@ function evaluatePermissionPolicy(policy, toolName, riskLevel) {
182
212
  * Enables non-interactive execution for CI/CD pipelines, scripting, and automation.
183
213
  * Runs the agent once with the given prompt and exits with an appropriate exit code.
184
214
  */
215
+ /**
216
+ * Sandbox status/warning sink for headless mode. Headless emits its NDJSON protocol
217
+ * on stdout, so BOTH info and warn must go to stderr - routing either to stdout would
218
+ * corrupt the protocol stream. Exported so this invariant is unit-tested (see
219
+ * headlessSandboxLog.test.ts) rather than left as an inline lambda nothing pins.
220
+ */
221
+ const headlessSandboxLog = {
222
+ info: (line) => void process.stderr.write(`${line}\n`),
223
+ warn: (line) => void process.stderr.write(`${line}\n`)
224
+ };
185
225
  /** Read all data from stdin if it's being piped (non-TTY). Returns empty string if no piped data. */
186
226
  async function readStdin() {
187
227
  if (process.stdin.isTTY) return "";
@@ -227,6 +267,7 @@ async function handleHeadlessCommand(options) {
227
267
  }
228
268
  permissionPolicy = parsePermissionPolicy(policyRaw);
229
269
  }
270
+ customCommandStore.setProjectTrusted(configStore.isProjectTrusted());
230
271
  try {
231
272
  await customCommandStore.loadCommands();
232
273
  } catch {}
@@ -280,28 +321,20 @@ async function handleHeadlessCommand(options) {
280
321
  const permissionManager = new PermissionManager(config.trustedTools ?? [], void 0, config.tools.disabled);
281
322
  const emit = createHeadlessEmitter(runId, (line) => process.stdout.write(line));
282
323
  const streaming = outputFormat === "stream-json";
283
- const promptFn = (toolName, args, _preview) => {
324
+ const promptFn = (toolName, args, _preview, kind) => {
284
325
  const risk = classifyToolRisk(toolName, args, permissionManager.getCategory(toolName));
285
326
  if (streaming) emit({
286
327
  type: "permission_request",
287
328
  toolName,
288
329
  risk
289
330
  });
290
- let decision;
291
- if (dangerouslySkipPermissions) decision = {
292
- action: "allow-once",
293
- reason: "dangerously-skip-permissions"
294
- };
295
- else if (permissionPolicy) {
296
- const verdict = evaluatePermissionPolicy(permissionPolicy, toolName, risk.level);
297
- decision = {
298
- action: verdict.action === "allow" ? "allow-once" : "deny",
299
- reason: verdict.reason
300
- };
301
- } else decision = {
302
- action: "deny",
303
- reason: "no permission policy; default deny"
304
- };
331
+ const decision = resolveHeadlessPermissionDecision({
332
+ dangerouslySkipPermissions,
333
+ isDirectoryGrant: kind === "directory-grant",
334
+ toolName,
335
+ riskLevel: risk.level,
336
+ permissionPolicy
337
+ });
305
338
  if (streaming) emit({
306
339
  type: "permission_decision",
307
340
  toolName,
@@ -317,28 +350,38 @@ async function handleHeadlessCommand(options) {
317
350
  process.stderr.write("Warning: Agent requested user input; headless mode cannot respond interactively. Answering with empty response.\n");
318
351
  return Promise.resolve({ answers: [] });
319
352
  };
320
- const sandboxConfig = config.sandbox ?? DEFAULT_SANDBOX_CONFIG;
321
353
  const checkpointProjectDir = configStore.getProjectConfigDir() ?? process.cwd();
322
354
  const checkpointStore = new CheckpointStore(checkpointProjectDir);
323
- const [sandboxRuntime] = await Promise.all([createSandboxRuntime(), checkpointStore.init(session.id).catch(() => {})]);
324
- const proxyManager = new ProxyManager(sandboxConfig.network);
325
- const sandboxOrchestrator = new SandboxOrchestrator(sandboxConfig, sandboxRuntime, proxyManager);
326
- permissionManager.setSandboxState(sandboxConfig.mode, sandboxOrchestrator.isActive());
355
+ const { sandboxOrchestrator } = await buildSandbox({
356
+ config,
357
+ sessionId: session.id,
358
+ permissionManager,
359
+ checkpointStore,
360
+ log: headlessSandboxLog
361
+ });
327
362
  const agentContext = {
328
363
  currentAgent: null,
329
364
  observationQueue: []
330
365
  };
331
366
  const { tools: b4mTools } = await generateCliTools(config.userId, llm, modelInfo.id, permissionManager, promptFn, agentContext, configStore, apiClient, void 0, userQuestionFn, checkpointStore, sandboxOrchestrator, additionalDirectories);
332
367
  const mcpManager = new McpManager(config);
333
- const projectConfigDir = configStore.getProjectConfigDir();
334
368
  const builtinAgentsDir = new URL("../agents/defaults/", import.meta.url).pathname;
335
- const agentStore = new AgentStore(builtinAgentsDir, projectConfigDir ?? process.cwd());
369
+ const agentStore = buildProjectAgentStore(builtinAgentsDir, configStore);
336
370
  const [, , contextResult] = await Promise.all([
337
371
  mcpManager.initialize(),
338
372
  agentStore.loadAgents(),
339
- loadContextFiles(projectConfigDir)
373
+ loadProjectContext(configStore)
340
374
  ]);
341
- const mcpTools = mcpManager.getTools();
375
+ const cliWrapDeps = {
376
+ permissionManager,
377
+ showPermissionPrompt: promptFn,
378
+ agentContext,
379
+ configStore,
380
+ apiClient,
381
+ sandboxOrchestrator,
382
+ allowedDirectories: additionalDirectories
383
+ };
384
+ const mcpTools = wrapTools(mcpManager.getTools(), cliWrapDeps);
342
385
  const historyStore = new AgentHistoryStore(config.preferences.subagentHistoryTtlMs ?? 36e5);
343
386
  const orchestrator = new SubagentOrchestrator({
344
387
  userId: config.userId,
@@ -353,7 +396,9 @@ async function handleHeadlessCommand(options) {
353
396
  enableParallelToolExecution: config.preferences.enableParallelToolExecution === true,
354
397
  showUserQuestion: userQuestionFn,
355
398
  checkpointStore,
356
- historyStore
399
+ historyStore,
400
+ sandboxOrchestrator,
401
+ additionalDirectories
357
402
  });
358
403
  const backgroundManager = new BackgroundAgentManager(orchestrator);
359
404
  const agentDelegateTool = createAgentDelegateTool(orchestrator, agentStore, session.id, backgroundManager);
@@ -361,15 +406,20 @@ async function handleHeadlessCommand(options) {
361
406
  const resumeAgentTool = createResumeAgentTool(orchestrator, historyStore, backgroundManager);
362
407
  const todoStore = createTodoStore();
363
408
  const writeTodosTool = createWriteTodosTool(todoStore);
364
- const findDefinitionTool = createFindDefinitionTool();
365
- const getFileStructureTool = createGetFileStructureTool();
409
+ const findDefinitionTool = wrapTools([createFindDefinitionTool(additionalDirectories)], cliWrapDeps)[0];
410
+ const getFileStructureTool = wrapTools([createGetFileStructureTool(additionalDirectories)], cliWrapDeps)[0];
366
411
  const workItemTools = config.preferences.enableWorkItemTools ? createWorkItemTools(new WorkItemsClient(apiClient)) : [];
367
412
  const enableSkillTool = config.preferences.enableSkillTool !== false;
368
- const skillTool = enableSkillTool ? createSkillTool({
413
+ const skillTool = enableSkillTool ? wrapTools([createSkillTool({
369
414
  customCommandStore,
370
415
  subagentOrchestrator: orchestrator,
371
- sessionId: session.id
372
- }) : null;
416
+ sessionId: session.id,
417
+ permission: {
418
+ permissionManager,
419
+ promptFn
420
+ },
421
+ allowedDirectories: additionalDirectories
422
+ })], cliWrapDeps)[0] : null;
373
423
  const cliTools = [
374
424
  agentDelegateTool,
375
425
  ...backgroundTools,
@@ -392,7 +442,7 @@ async function handleHeadlessCommand(options) {
392
442
  const systemPrompt = buildSystemPrompt(config.preferences.promptVariant ?? "current", {
393
443
  contextContent: contextResult.mergedContent,
394
444
  agentStore,
395
- customCommands: customCommandStore.getAllCommands(),
445
+ customCommands: customCommandStore.getModelReachableCommands(),
396
446
  enableSkillTool,
397
447
  enableDynamicAgentCreation: false,
398
448
  additionalDirectories
@@ -527,4 +577,4 @@ async function handleHeadlessCommand(options) {
527
577
  }
528
578
  }
529
579
  //#endregion
530
- export { handleHeadlessCommand };
580
+ export { handleHeadlessCommand, headlessSandboxLog };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-DHNgFdOu.mjs";
3
- import { t as version } from "../package-7a45-Svr.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-qV7NrCgZ.mjs";
3
+ import { t as version } from "../package-CGZIoxcs.mjs";
4
4
  //#region src/commands/mcpCommand.ts
5
5
  /**
6
6
  * External MCP commands (b4m mcp list, b4m mcp add, etc.)
@@ -70,7 +70,7 @@ async function handleMcpCommand(subcommand, argv) {
70
70
  await handleDisable(config, argv.name, configStore);
71
71
  break;
72
72
  case "serve": {
73
- const { handleMcpServeCommand } = await import("../serve-CavAHPdQ.mjs");
73
+ const { handleMcpServeCommand } = await import("../serve-CPXqcEZr.mjs");
74
74
  await handleMcpServeCommand({
75
75
  http: Boolean(argv.http),
76
76
  port: typeof argv.port === "number" ? argv.port : void 0,
@@ -146,9 +146,8 @@ async function handleAdd(config, name, command, args, configStore) {
146
146
  env: {},
147
147
  enabled: true
148
148
  };
149
- config.mcpServers.push(newServer);
150
149
  try {
151
- await configStore.save(config);
150
+ await configStore.addMcpServer(newServer);
152
151
  console.log(`✅ Added MCP server "${name}"`);
153
152
  console.log("");
154
153
  console.log("Configuration saved to: ~/.bike4mind/config.json");
@@ -163,14 +162,12 @@ async function handleAdd(config, name, command, args, configStore) {
163
162
  * Remove an MCP server
164
163
  */
165
164
  async function handleRemove(config, name, configStore) {
166
- const index = config.mcpServers.findIndex((s) => s.name === name);
167
- if (index === -1) {
165
+ if (config.mcpServers.findIndex((s) => s.name === name) === -1) {
168
166
  console.error(`❌ MCP server "${name}" not found.`);
169
167
  process.exit(1);
170
168
  }
171
- config.mcpServers.splice(index, 1);
172
169
  try {
173
- await configStore.save(config);
170
+ await configStore.removeMcpServer(name);
174
171
  console.log(`✅ Removed MCP server "${name}"`);
175
172
  console.log("");
176
173
  console.log("Configuration saved to: ~/.bike4mind/config.json");
@@ -192,9 +189,8 @@ async function handleEnable(config, name, configStore) {
192
189
  console.log(`ℹ️ MCP server "${name}" is already enabled.`);
193
190
  return;
194
191
  }
195
- server.enabled = true;
196
192
  try {
197
- await configStore.save(config);
193
+ await configStore.toggleMcpServer(name, true);
198
194
  console.log(`✅ Enabled MCP server "${name}"`);
199
195
  console.log("");
200
196
  console.log("The server will connect next time you start the CLI.");
@@ -216,9 +212,8 @@ async function handleDisable(config, name, configStore) {
216
212
  console.log(`ℹ️ MCP server "${name}" is already disabled.`);
217
213
  return;
218
214
  }
219
- server.enabled = false;
220
215
  try {
221
- await configStore.save(config);
216
+ await configStore.toggleMcpServer(name, false);
222
217
  console.log(`✅ Disabled MCP server "${name}"`);
223
218
  console.log("");
224
219
  console.log("The server will not connect next time you start the CLI.");
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as getDefaultPluginsDir, r as isFeatureEnabled, t as PluginStore } from "../PluginStore-DwvOJ-G3.mjs";
3
- import { t as ConfigStore } from "../ConfigStore-DHNgFdOu.mjs";
3
+ import { t as ConfigStore } from "../ConfigStore-qV7NrCgZ.mjs";
4
4
  import { execFileSync } from "child_process";
5
5
  import { promises } from "fs";
6
6
  import path from "path";
@@ -152,13 +152,10 @@ async function handleAdd(spec, pluginsDir, configStore) {
152
152
  continue;
153
153
  }
154
154
  const config = await configStore.load();
155
- await configStore.save({
156
- ...config,
157
- features: {
158
- ...config.features,
159
- [descriptor.configKey]: true
160
- }
161
- });
155
+ await configStore.save({ features: {
156
+ ...config.features,
157
+ [descriptor.configKey]: true
158
+ } });
162
159
  console.log(`✅ Installed ${descriptor.name}@${descriptor.version} (plugin key: ${descriptor.configKey})`);
163
160
  console.log(`Enabled feature "${descriptor.configKey}". It will load next time you start b4m.`);
164
161
  }
@@ -186,13 +183,10 @@ async function handleRemove(name, pluginsDir, configStore) {
186
183
  ], pluginsDir, "remove", plugin.name);
187
184
  if (plugin.valid) {
188
185
  const config = await configStore.load();
189
- await configStore.save({
190
- ...config,
191
- features: {
192
- ...config.features,
193
- [plugin.configKey]: false
194
- }
195
- });
186
+ await configStore.save({ features: {
187
+ ...config.features,
188
+ [plugin.configKey]: false
189
+ } });
196
190
  }
197
191
  console.log(`✅ Removed plugin ${plugin.name}${plugin.valid ? ` and disabled "${plugin.configKey}"` : ""}.`);
198
192
  }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "../package-7a45-Svr.mjs";
2
+ import { t as version } from "../package-CGZIoxcs.mjs";
3
3
  import { c as isNpmPrefixWritable, l as setAutoUpdatePreference, n as REEXEC_GUARD_ENV, o as forceCheckForUpdate, r as checkForUpdate, s as getAutoUpdatePreference, t as INSTALL_CMD, u as shouldAttemptAutoUpdate } from "../updateChecker-CQW8bxo6.mjs";
4
4
  import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
5
5
  import { execSync, spawnSync } from "child_process";
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { t as assertPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
2
+ import { t as assertPathAllowed } from "./pathValidation-BRqf4HFX-CHwtwp3O.mjs";
3
3
  import { existsSync, promises } from "fs";
4
4
  import path from "path";
5
- //#region ../../b4m-core/services/dist/createFile-DPv180yF.mjs
5
+ //#region ../../b4m-core/services/dist/createFile-B8bur5Rb.mjs
6
6
  async function createFile(params, allowedDirectories) {
7
7
  const { path: filePath, content, createDirectories = true } = params;
8
8
  const resolvedPath = assertPathAllowed(filePath, allowedDirectories, "create");
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { t as assertPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
2
+ import { t as assertPathAllowed } from "./pathValidation-BRqf4HFX-CHwtwp3O.mjs";
3
3
  import { existsSync, promises, statSync } from "fs";
4
4
  import path from "path";
5
- //#region ../../b4m-core/services/dist/deleteFile-BdjUwUQF.mjs
5
+ //#region ../../b4m-core/services/dist/deleteFile-9B3gW_Nb.mjs
6
6
  async function deleteFile(params, allowedDirectories) {
7
7
  const { path: filePath, recursive = false } = params;
8
8
  const resolvedPath = assertPathAllowed(filePath, allowedDirectories, "delete");
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { n as isPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
2
+ import { n as isPathAllowed } from "./pathValidation-BRqf4HFX-CHwtwp3O.mjs";
3
3
  import path from "path";
4
4
  import { stat } from "fs/promises";
5
5
  import { glob } from "glob";
6
- //#region ../../b4m-core/services/dist/globFiles-DjfDGaUK.mjs
6
+ //#region ../../b4m-core/services/dist/globFiles-CwJ8qmYo.mjs
7
7
  const DEFAULT_IGNORE_PATTERNS = [
8
8
  "**/node_modules/**",
9
9
  "**/.git/**",
@@ -24,6 +24,7 @@ async function findFiles(params, allowedDirectories) {
24
24
  const dirsMsg = allowedDirectories && allowedDirectories.length > 0 ? `Allowed directories: ${[baseCwd, ...allowedDirectories].join(", ")}` : `Working directory: ${baseCwd}`;
25
25
  throw new Error(`Access denied: Cannot search outside allowed directories. ${dirsMsg}`);
26
26
  }
27
+ if (path.isAbsolute(pattern) || pattern.split("/").includes("..")) throw new Error("Access denied: Cannot search outside allowed directories. The pattern must be relative to the search directory.");
27
28
  const matches = await glob(pattern, {
28
29
  cwd: targetDir,
29
30
  dot: false,
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { n as isPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
2
+ import { n as isPathAllowed } from "./pathValidation-BRqf4HFX-CHwtwp3O.mjs";
3
3
  import { execFile } from "child_process";
4
4
  import { existsSync } from "fs";
5
5
  import path from "path";
6
6
  import { promisify } from "util";
7
7
  import { stat } from "fs/promises";
8
- //#region ../../b4m-core/services/dist/grepSearch-BaYUfIYs.mjs
8
+ //#region ../../b4m-core/services/dist/grepSearch-BgoOOwGe.mjs
9
9
  const execFileAsync = promisify(execFile);
10
10
  /** Cached ripgrep binary path after first resolution */
11
11
  let cachedRgPath = null;
@@ -64,7 +64,7 @@ async function searchFiles(params, allowedDirectories) {
64
64
  if (globs.length > 0) globs.forEach((glob) => {
65
65
  rgArgs.push("--glob", glob);
66
66
  });
67
- rgArgs.push(pattern, targetDir);
67
+ rgArgs.push("--", pattern, targetDir);
68
68
  let stdout;
69
69
  try {
70
70
  stdout = (await execFileAsync(rgPath, rgArgs, { maxBuffer: 52428800 })).stdout;