@bike4mind/cli 0.18.3 → 0.18.4

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.
@@ -476,6 +476,25 @@ z.enum({
476
476
  ...SpeechToTextModels,
477
477
  ...VideoModels
478
478
  });
479
+ /**
480
+ * Integer credits charged per $1 of provider cost. Derived once with rounding
481
+ * because the raw division carries float noise (0.0006 is inexact in binary):
482
+ * naive ceil((usd * 3) / 0.0006) charges a phantom credit on exact multiples.
483
+ */
484
+ const CREDITS_PER_USD_COST = Math.round(3 / 6e-4);
485
+ /**
486
+ * Converts a USD cost to credits, including markup
487
+ * @param usd - The raw provider cost in USD to convert
488
+ * @returns The number of credits with markup, rounded up to the nearest whole number (minimum 1)
489
+ *
490
+ * Examples:
491
+ * $1 USD = 5000 credits (3× markup at $0.0006/credit)
492
+ * $0.001 USD = 5 credits
493
+ * $0.0001 USD = 1 credit (minimum)
494
+ */
495
+ const usdToCredits = (usd) => {
496
+ return Math.max(1, Math.ceil(usd * CREDITS_PER_USD_COST));
497
+ };
479
498
  z$1.enum([
480
499
  "openai",
481
500
  "test",
@@ -3574,14 +3593,27 @@ z$1.object({
3574
3593
  prefix: z$1.string().optional()
3575
3594
  });
3576
3595
  /**
3577
- * Constants for BFL safety tolerance settings
3596
+ * Constants for BFL safety tolerance settings.
3597
+ *
3598
+ * BFL scale: 0 = strictest filtering, 6 = effectively unfiltered. MAX is a
3599
+ * hard cap (#9776, 18 U.S.C. §2258A exposure) — enforced in the zod schemas
3600
+ * here AND clamped last-mile in BFLImageService, so no caller can raise it.
3601
+ * BFL itself caps its editing endpoints at 2.
3578
3602
  */
3579
3603
  const BFL_SAFETY_TOLERANCE = {
3580
3604
  MIN: 0,
3581
- MAX: 6,
3582
- DEFAULT: 4
3605
+ MAX: 2,
3606
+ DEFAULT: 2,
3607
+ /** Pre-cap sessions may have stored up to 6 — accepted as input, clamped to MAX on parse. */
3608
+ LEGACY_INPUT_MAX: 6
3583
3609
  };
3584
3610
  /**
3611
+ * Shared safety_tolerance schema: accepts the legacy 0-6 stored range but
3612
+ * clamps the parsed output to the hard cap (coerce, not reject — rejecting
3613
+ * would break image generation for sessions saved before the cap existed).
3614
+ */
3615
+ const BFLSafetyToleranceSchema = z.number().min(BFL_SAFETY_TOLERANCE.MIN).max(BFL_SAFETY_TOLERANCE.LEGACY_INPUT_MAX).optional().prefault(BFL_SAFETY_TOLERANCE.DEFAULT).transform((value) => Math.min(value, BFL_SAFETY_TOLERANCE.MAX));
3616
+ /**
3585
3617
  * List of image models supported by BlackForest Labs
3586
3618
  */
3587
3619
  const BFL_IMAGE_MODELS = [
@@ -3594,7 +3626,7 @@ const BFL_IMAGE_MODELS = [
3594
3626
  ];
3595
3627
  const CommonBFLParams = z.object({
3596
3628
  prompt: z.string().nullable().optional(),
3597
- safety_tolerance: z.number().min(BFL_SAFETY_TOLERANCE.MIN).max(BFL_SAFETY_TOLERANCE.MAX).optional().prefault(BFL_SAFETY_TOLERANCE.DEFAULT),
3629
+ safety_tolerance: BFLSafetyToleranceSchema,
3598
3630
  output_format: z.enum(["jpeg", "png"]).nullable().optional().prefault("jpeg"),
3599
3631
  image_prompt: z.string().nullable().optional(),
3600
3632
  webhook_url: z.string().min(1).max(2083).nullable().optional(),
@@ -3966,6 +3998,7 @@ z.enum([
3966
3998
  "EnableInertArtifactRender",
3967
3999
  "pricePerCredit",
3968
4000
  "ModerationEnabled",
4001
+ "ImageModerationEnabled",
3969
4002
  "tagLineMain",
3970
4003
  "tagLineSub",
3971
4004
  "defaultTags",
@@ -4025,6 +4058,7 @@ z.enum([
4025
4058
  "enforceCredits",
4026
4059
  "enableTeamPlan",
4027
4060
  "allowOpenRegistration",
4061
+ "blockDisposableEmails",
4028
4062
  "defaultFreeCredits",
4029
4063
  "enableGoogleCalendar",
4030
4064
  "googleCalendarServiceAccountEmail",
@@ -4081,6 +4115,9 @@ z.enum([
4081
4115
  "contextTelemetryAlerts",
4082
4116
  "sreAgentConfig",
4083
4117
  "secopsTriageConfig",
4118
+ "apiRateLimitFreePerMin",
4119
+ "apiRateLimitBasicPerMin",
4120
+ "apiRateLimitProPerMin",
4084
4121
  "overwatchRollupSync",
4085
4122
  "orchestrationDefaults"
4086
4123
  ]);
@@ -5413,13 +5450,33 @@ const API_SERVICE_GROUPS = {
5413
5450
  order: 3
5414
5451
  }
5415
5452
  ]
5453
+ },
5454
+ RATE_LIMITING: {
5455
+ id: "rateLimitingService",
5456
+ name: "API Rate Limiting",
5457
+ description: "Per-user request rate limits on /chat and /opti, tunable per subscription tier (#9780)",
5458
+ icon: "Speed",
5459
+ settings: [
5460
+ {
5461
+ key: "apiRateLimitFreePerMin",
5462
+ order: 1
5463
+ },
5464
+ {
5465
+ key: "apiRateLimitBasicPerMin",
5466
+ order: 2
5467
+ },
5468
+ {
5469
+ key: "apiRateLimitProPerMin",
5470
+ order: 3
5471
+ }
5472
+ ]
5416
5473
  }
5417
5474
  };
5418
5475
  const settingsMap = {
5419
5476
  DefaultAPIModel: makeStringSetting({
5420
5477
  key: "DefaultAPIModel",
5421
5478
  name: "Default API Model",
5422
- defaultValue: "claude-sonnet-5",
5479
+ defaultValue: "global.anthropic.claude-sonnet-5",
5423
5480
  description: "The default AI model to use for API requests when no model is specified.",
5424
5481
  options: CHAT_MODELS,
5425
5482
  category: "AI",
@@ -5699,6 +5756,13 @@ const settingsMap = {
5699
5756
  description: "Whether to enable moderation for LLM prompts.",
5700
5757
  category: "AI Moderation"
5701
5758
  }),
5759
+ ImageModerationEnabled: makeBooleanSetting({
5760
+ key: "ImageModerationEnabled",
5761
+ name: "Image Moderation Enabled",
5762
+ defaultValue: true,
5763
+ description: "Whether to run generated images through content moderation (Rekognition) and block explicit content. Legal-safety control (#9776) — default ON.",
5764
+ category: "AI Moderation"
5765
+ }),
5702
5766
  FormatPromptTemplate: makeStringSetting({
5703
5767
  key: "FormatPromptTemplate",
5704
5768
  name: "Format Prompt Template",
@@ -5748,6 +5812,39 @@ const settingsMap = {
5748
5812
  group: API_SERVICE_GROUPS.CREDITS.id,
5749
5813
  order: 1
5750
5814
  }),
5815
+ apiRateLimitFreePerMin: makeNumberSetting({
5816
+ key: "apiRateLimitFreePerMin",
5817
+ name: "API Rate Limit — Free (requests/min)",
5818
+ defaultValue: 10,
5819
+ min: 1,
5820
+ max: 1e5,
5821
+ description: "Max /chat and /opti requests per minute for users with no active paid subscription.",
5822
+ category: "SecOps",
5823
+ group: API_SERVICE_GROUPS.RATE_LIMITING.id,
5824
+ order: 1
5825
+ }),
5826
+ apiRateLimitBasicPerMin: makeNumberSetting({
5827
+ key: "apiRateLimitBasicPerMin",
5828
+ name: "API Rate Limit — Basic (requests/min)",
5829
+ defaultValue: 30,
5830
+ min: 1,
5831
+ max: 1e5,
5832
+ description: "Max /chat and /opti requests per minute for Basic-tier subscribers (e.g. Professional plan).",
5833
+ category: "SecOps",
5834
+ group: API_SERVICE_GROUPS.RATE_LIMITING.id,
5835
+ order: 2
5836
+ }),
5837
+ apiRateLimitProPerMin: makeNumberSetting({
5838
+ key: "apiRateLimitProPerMin",
5839
+ name: "API Rate Limit — Pro (requests/min)",
5840
+ defaultValue: 60,
5841
+ min: 1,
5842
+ max: 1e5,
5843
+ description: "Max /chat and /opti requests per minute for Pro-tier subscribers.",
5844
+ category: "SecOps",
5845
+ group: API_SERVICE_GROUPS.RATE_LIMITING.id,
5846
+ order: 3
5847
+ }),
5751
5848
  tagLineMain: makeStringSetting({
5752
5849
  key: "tagLineMain",
5753
5850
  name: "Tag Line Main",
@@ -6075,6 +6172,14 @@ const settingsMap = {
6075
6172
  group: API_SERVICE_GROUPS.CREDITS.id,
6076
6173
  category: "Users"
6077
6174
  }),
6175
+ blockDisposableEmails: makeBooleanSetting({
6176
+ key: "blockDisposableEmails",
6177
+ name: "Block Disposable Emails",
6178
+ defaultValue: true,
6179
+ description: "Rejects new registrations whose email domain (or any parent domain) is a known disposable/burner provider — free credits cannot be farmed with throwaway inboxes (#9779). Applies at registration only; existing accounts on such domains can still sign in. Turn OFF only to work around a false positive.",
6180
+ group: API_SERVICE_GROUPS.CREDITS.id,
6181
+ category: "Users"
6182
+ }),
6078
6183
  defaultFreeCredits: makeNumberSetting({
6079
6184
  key: "defaultFreeCredits",
6080
6185
  name: "Default Free Credits",
@@ -8314,7 +8419,8 @@ z$1.object({
8314
8419
  description: z$1.string().max(2e3).optional(),
8315
8420
  fileTagPrefix: z$1.string().min(2).max(30).refine((s) => s.endsWith(":"), "Tag prefix must end with \":\" (e.g. \"acme:\")"),
8316
8421
  requiredUserTag: z$1.string().min(1).max(100).optional(),
8317
- requiredEntitlement: z$1.string().min(3).max(100).refine((s) => s.includes(":") && s.split(":").every((part) => part.length > 0), "Entitlement key must be namespaced with non-empty parts (e.g. \"product:pro\")").optional()
8422
+ requiredEntitlement: z$1.string().min(3).max(100).refine((s) => s.includes(":") && s.split(":").every((part) => part.length > 0), "Entitlement key must be namespaced with non-empty parts (e.g. \"product:pro\")").optional(),
8423
+ organizationId: z$1.string().optional()
8318
8424
  });
8319
8425
  z$1.object({
8320
8426
  name: z$1.string().min(1).max(200).optional(),
@@ -8516,7 +8622,8 @@ function toDataLakeConfig(dl) {
8516
8622
  requiredEntitlement: dl.requiredEntitlement,
8517
8623
  fileTagPrefix: dl.fileTagPrefix,
8518
8624
  datalakeTag: dl.datalakeTag,
8519
- organizationId: dl.organizationId
8625
+ organizationId: dl.organizationId,
8626
+ description: dl.description
8520
8627
  };
8521
8628
  }
8522
8629
  /**
@@ -8773,7 +8880,8 @@ z.object({
8773
8880
  "classifier",
8774
8881
  "mention",
8775
8882
  "user-default",
8776
- "agent_literal"
8883
+ "agent_literal",
8884
+ "complexity"
8777
8885
  ])
8778
8886
  }).optional()
8779
8887
  }).extend({
@@ -9425,6 +9533,26 @@ z.object({
9425
9533
  /** Custom notebook name (optional, defaults to curated-notebook-{sessionId}) */
9426
9534
  customNotebookName: z.string().optional()
9427
9535
  });
9536
+ /**
9537
+ * ImageModerationIncident — audit record for a generated image blocked by
9538
+ * auto-moderation (#9776 Q2a). Metadata-only (no image bytes); byte
9539
+ * preservation for §2258A retention is a later quest.
9540
+ */
9541
+ const ModerationLabelHitSchema = z.object({
9542
+ name: z.string(),
9543
+ parentName: z.string(),
9544
+ confidence: z.number()
9545
+ });
9546
+ z.object({
9547
+ userId: z.string(),
9548
+ sessionId: z.string().optional(),
9549
+ questId: z.string().optional(),
9550
+ provider: z.string(),
9551
+ model: z.string(),
9552
+ labels: z.array(ModerationLabelHitSchema),
9553
+ createdAt: z.union([z.string(), z.date()]).optional(),
9554
+ updatedAt: z.union([z.string(), z.date()]).optional()
9555
+ });
9428
9556
  function isGPTImageModel(model) {
9429
9557
  if (!model) return false;
9430
9558
  return OPENAI_IMAGE_MODELS.includes(model) || model.startsWith("gpt-image-");
@@ -9597,7 +9725,7 @@ z.array(triggerWordSchema).max(20, "Up to 20 trigger words allowed.").transform(
9597
9725
  * - `$1`, `$2`, ... — individual positional args
9598
9726
  *
9599
9727
  * Why a shared helper: the CLI already implemented this in
9600
- * `apps/cli/src/utils/argumentSubstitution.ts`. Centralizing here avoids a
9728
+ * `packages/cli/src/utils/argumentSubstitution.ts`. Centralizing here avoids a
9601
9729
  * second drift surface — a skill body authored on the web and run in the CLI
9602
9730
  * (or vice versa) must expand identically.
9603
9731
  */
@@ -10693,7 +10821,7 @@ QWORK_PROVIDERS.filter((p) => QWORK_PROVIDER_CAPABILITIES[p].enabled);
10693
10821
  //#region src/utils/apiUrl.ts
10694
10822
  /**
10695
10823
  * Default service endpoint, baked in at build time via tsdown's `env` option
10696
- * (see `apps/cli/tsdown.config.ts`). The hosted publisher builds with its own
10824
+ * (see `packages/cli/tsdown.config.ts`). The hosted publisher builds with its own
10697
10825
  * service as the default; a fork sets `B4M_DEFAULT_API_URL` to publish under a
10698
10826
  * different brand, so a fork's bundle never embeds the upstream brand literal.
10699
10827
  * Empty when unset — the user then supplies an endpoint via `/set-api` or the
@@ -11130,7 +11258,7 @@ const CliConfigSchema = z.object({
11130
11258
  enableCoordinatorMode: z.boolean().optional().prefault(false),
11131
11259
  /**
11132
11260
  * System-prompt variant. 'current' uses the elaborate behavioral-scaffolding
11133
- * prompt; 'minimal' uses a pi-style short prompt. See apps/cli/src/core/prompts.ts.
11261
+ * prompt; 'minimal' uses a pi-style short prompt. See packages/cli/src/core/prompts.ts.
11134
11262
  * Defaults to 'current' for backward compatibility; switch via /config or by
11135
11263
  * editing the config file directly.
11136
11264
  */
@@ -11884,4 +12012,4 @@ var ConfigStore = class {
11884
12012
  }
11885
12013
  };
11886
12014
  //#endregion
11887
- export { PermissionDeniedError as $, wrapUntrustedSkillBody as $t, FriendshipEvents as A, XAI_IMAGE_MODELS as At, InboxEvents as B, isSupportedEmbeddingModel as Bt, CorruptedFileError as C, TransferCreditTransaction as Ct, FeedbackEvents as D, VIDEO_SIZE_CONSTRAINTS as Dt, FavoriteDocumentType as E, UnprocessableEntityError as Et, HTTPError as F, getViewById as Ft, LLMEvents as G, resolveNavigationIntents as Gt, InviteEvents as H, mapMimeTypeToArtifactType as Ht, HttpStatus as I, intersectAllowedTools as It, ModelBackend as J, settingsMap as Jt, MiscEvents as K, sanitizeTelemetryError as Kt, ImageEditUsageTransaction as L, isGPTImage2Model as Lt, GenerateImageToolCallSchema as M, dayjsConfig_default as Mt, GenericCreditAddTransaction as N, getAccessibleDataLakes as Nt, FileEvents as O, VideoGenerationUsageTransaction as Ot, GenericCreditDeductTransaction as P, getMcpProviderMetadata as Pt, Permission as Q, validateNotebookPath as Qt, ImageGenerationUsageTransaction as R, isGPTImageModel as Rt, CompletionApiUsageTransaction as S, ToolUsageTransaction as St, ElabsEvents as T, UnauthorizedError as Tt, InviteType as U, obfuscateApiKey as Ut, InternalServerError as V, isZodError as Vt, KnowledgeType as W, parseSkillArguments as Wt, OpenAIEmbeddingModel as X, toDataLakeConfig as Xt, NotFoundError as Y, substituteArguments as Yt, OpenAIImageGenerationInput as Z, validateJupyterKernelName as Zt, BadRequestError as _, SupportedFabFileMimeTypes as _t, getDefaultApiUrl as a, QuestMasterParamsSchema as at, ChatModels as b, TextGenerationUsageTransaction as bt, AiEvents as c, RechartsChartTypeList as ct, ApiKeyType as d, ResearchTaskExecutionType as dt, buildRateLimitLogEntry as en, ProfileEvents as et, AppFileEvents as f, ResearchTaskPeriodicFrequencyType as ft, BFL_SAFETY_TOLERANCE as g, SubscriptionCreditTransaction as gt, BFL_IMAGE_MODELS as h, SpeechToTextUsageTransaction as ht, getCreditsUrl as i, CollectionType as in, PurchaseTransaction as it, GEMINI_IMAGE_MODELS as j, b4mLLMTools as jt, ForbiddenError as k, VideoModels as kt, ApiKeyEvents as l, RegInviteEvents as lt, AuthEvents as m, SessionEvents as mt, logger as n, isNearLimit as nn, PromptIntentSchema as nt, getEnvironmentName as o, RealtimeVoiceUsageTransaction as ot, ArtifactTypeSchema as p, ResearchTaskType as pt, ModalEvents as q, secureParameters as qt, getApiUrl as r, parseRateLimitHeaders as rn, PromptMetaZodSchema as rt, ALERT_THRESHOLDS as s, ReceivedCreditTransaction as st, ConfigStore as t, extractSnippetMeta as tn, ProjectEvents as tt, ApiKeyScope as u, ResearchModeParamsSchema as ut, CREDIT_DEDUCT_TRANSACTION_TYPES as v, TagType as vt, DashboardParamsSchema as w, UiNavigationEvents as wt, ClaudeArtifactMimeTypes as x, TooManyRequestsError as xt, ChatCompletionCreateInputSchema as y, TaskScheduleHandler as yt, ImageModels as z, isModelAccessible as zt };
12015
+ export { Permission as $, validateJupyterKernelName as $t, ForbiddenError as A, VideoModels as At, ImageModels as B, isModelAccessible as Bt, CompletionApiUsageTransaction as C, ToolUsageTransaction as Ct, FavoriteDocumentType as D, UnprocessableEntityError as Dt, ElabsEvents as E, UnauthorizedError as Et, GenericCreditDeductTransaction as F, getMcpProviderMetadata as Ft, KnowledgeType as G, parseSkillArguments as Gt, InternalServerError as H, isZodError as Ht, HTTPError as I, getViewById as It, ModalEvents as J, secureParameters as Jt, LLMEvents as K, resolveNavigationIntents as Kt, HttpStatus as L, intersectAllowedTools as Lt, GEMINI_IMAGE_MODELS as M, b4mLLMTools as Mt, GenerateImageToolCallSchema as N, dayjsConfig_default as Nt, FeedbackEvents as O, VIDEO_SIZE_CONSTRAINTS as Ot, GenericCreditAddTransaction as P, getAccessibleDataLakes as Pt, OpenAIImageGenerationInput as Q, usdToCredits as Qt, ImageEditUsageTransaction as R, isGPTImage2Model as Rt, ClaudeArtifactMimeTypes as S, TooManyRequestsError as St, DashboardParamsSchema as T, UiNavigationEvents as Tt, InviteEvents as U, mapMimeTypeToArtifactType as Ut, InboxEvents as V, isSupportedEmbeddingModel as Vt, InviteType as W, obfuscateApiKey as Wt, NotFoundError as X, substituteArguments as Xt, ModelBackend as Y, settingsMap as Yt, OpenAIEmbeddingModel as Z, toDataLakeConfig as Zt, BFL_SAFETY_TOLERANCE as _, SubscriptionCreditTransaction as _t, getDefaultApiUrl as a, parseRateLimitHeaders as an, PurchaseTransaction as at, ChatCompletionCreateInputSchema as b, TaskScheduleHandler as bt, AiEvents as c, ReceivedCreditTransaction as ct, ApiKeyType as d, ResearchModeParamsSchema as dt, validateNotebookPath as en, PermissionDeniedError as et, AppFileEvents as f, ResearchTaskExecutionType as ft, BFL_IMAGE_MODELS as g, SpeechToTextUsageTransaction as gt, BFLSafetyToleranceSchema as h, SessionEvents as ht, getCreditsUrl as i, isNearLimit as in, PromptMetaZodSchema as it, FriendshipEvents as j, XAI_IMAGE_MODELS as jt, FileEvents as k, VideoGenerationUsageTransaction as kt, ApiKeyEvents as l, RechartsChartTypeList as lt, AuthEvents as m, ResearchTaskType as mt, logger as n, buildRateLimitLogEntry as nn, ProjectEvents as nt, getEnvironmentName as o, CollectionType as on, QuestMasterParamsSchema as ot, ArtifactTypeSchema as p, ResearchTaskPeriodicFrequencyType as pt, MiscEvents as q, sanitizeTelemetryError as qt, getApiUrl as r, extractSnippetMeta as rn, PromptIntentSchema as rt, ALERT_THRESHOLDS as s, RealtimeVoiceUsageTransaction as st, ConfigStore as t, wrapUntrustedSkillBody as tn, ProfileEvents as tt, ApiKeyScope as u, RegInviteEvents as ut, BadRequestError as v, SupportedFabFileMimeTypes as vt, CorruptedFileError as w, TransferCreditTransaction as wt, ChatModels as x, TextGenerationUsageTransaction as xt, CREDIT_DEDUCT_TRANSACTION_TYPES as y, TagType as yt, ImageGenerationUsageTransaction as z, isGPTImageModel as zt };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as getDefaultApiUrl, t as ConfigStore } from "../ConfigStore-DL7p3ZiY.mjs";
2
+ import { a as getDefaultApiUrl, t as ConfigStore } from "../ConfigStore-Cq20962p.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-B-ONmxJ7.mjs";
2
+ import { t as version } from "../package-CBaK53NX.mjs";
3
3
  import { a as fetchLatestVersion, c as isNpmPrefixWritable, i as compareSemver } from "../updateChecker-C8xsNY2L.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-DL7p3ZiY.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-Cq20962p.mjs";
3
3
  //#region src/commands/envCommand.ts
4
4
  /**
5
5
  * Environment switching for the `--dev` / `--prod` launch flags.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { C as createCoordinateTaskTool, D as FallbackLlmBackend, E as ApiClient, F as generateCliTools, G as ReActAgent, N as loadContextFiles, O as ServerLlmBackend, P as PermissionManager, Q as CheckpointStore, T as createAgentDelegateTool, W as setWebSocketToolExecutor, X as RemoteSkillSource, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createGetFileStructureTool, a as WebSocketToolExecutor, b as createWriteTodosTool, et as SessionStore, i as McpManager, n as SubagentOrchestrator, o as WebSocketConnectionManager, q as buildSystemPrompt, r as AgentStore, s as WebSocketLlmBackend, t as BackgroundAgentManager, v as createFindDefinitionTool, w as createBackgroundAgentTools, x as createSkillTool, y as createTodoStore } from "../BackgroundAgentManager-H_MnlEXz.mjs";
3
- import { n as logger, r as getApiUrl, t as ConfigStore } from "../ConfigStore-DL7p3ZiY.mjs";
2
+ import { C as createCoordinateTaskTool, D as FallbackLlmBackend, E as ApiClient, F as generateCliTools, G as ReActAgent, N as loadContextFiles, O as ServerLlmBackend, P as PermissionManager, Q as CheckpointStore, T as createAgentDelegateTool, W as setWebSocketToolExecutor, X as RemoteSkillSource, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createGetFileStructureTool, a as WebSocketToolExecutor, b as createWriteTodosTool, et as SessionStore, i as McpManager, n as SubagentOrchestrator, o as WebSocketConnectionManager, q as buildSystemPrompt, r as AgentStore, s as WebSocketLlmBackend, t as BackgroundAgentManager, v as createFindDefinitionTool, w as createBackgroundAgentTools, x as createSkillTool, y as createTodoStore } from "../BackgroundAgentManager-DOesheMD.mjs";
3
+ import { n as logger, r as getApiUrl, t as ConfigStore } from "../ConfigStore-Cq20962p.mjs";
4
4
  import { t as DEFAULT_SANDBOX_CONFIG } from "../types-LyRNHOiS.mjs";
5
5
  import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-ChGlxSGQ.mjs";
6
6
  import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BoINxbX4.mjs";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-DL7p3ZiY.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-Cq20962p.mjs";
3
3
  //#region src/commands/mcpCommand.ts
4
4
  /**
5
5
  * External MCP commands (b4m mcp list, b4m mcp add, etc.)
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "../package-B-ONmxJ7.mjs";
2
+ import { t as version } from "../package-CBaK53NX.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-C8xsNY2L.mjs";
4
4
  import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
5
5
  import { execSync, spawnSync } from "child_process";
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { $ as CommandHistoryStore, A as substituteArguments, B as DEFAULT_RETRY_CONFIG, C as createCoordinateTaskTool, D as FallbackLlmBackend, E as ApiClient, F as generateCliTools, G as ReActAgent, H as clearFeatureModuleTools, I as getProcessHooks, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as extractCompactInstructions, N as loadContextFiles, O as ServerLlmBackend, P as PermissionManager, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as parseAgentConfig, T as createAgentDelegateTool, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as RemoteSkillSource, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createGetFileStructureTool, a as WebSocketToolExecutor, at as mergeCommands, b as createWriteTodosTool, c as createReviewGateStore, ct as warmFileCache, d as createBlockerStore, et as SessionStore, f as createBlockerTools, g as formatDecisionsOutput, h as createDecisionStore, i as McpManager, it as searchCommands, j as formatStep, k as isTransientNetworkError, l as createReviewGateTool, m as createDecisionLogTool, n as SubagentOrchestrator, nt as hasFileReferences, o as WebSocketConnectionManager, ot as formatFileSize, p as formatBlockersOutput, q as buildSystemPrompt, r as AgentStore, rt as processFileReferences, s as WebSocketLlmBackend, st as searchFiles, t as BackgroundAgentManager, tt as OAuthClient, u as formatReviewGatesOutput, v as createFindDefinitionTool, w as createBackgroundAgentTools, x as createSkillTool, y as createTodoStore, z as DEFAULT_MAX_ITERATIONS } from "./BackgroundAgentManager-H_MnlEXz.mjs";
2
+ import { $ as CommandHistoryStore, A as substituteArguments, B as DEFAULT_RETRY_CONFIG, C as createCoordinateTaskTool, D as FallbackLlmBackend, E as ApiClient, F as generateCliTools, G as ReActAgent, H as clearFeatureModuleTools, I as getProcessHooks, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as extractCompactInstructions, N as loadContextFiles, O as ServerLlmBackend, P as PermissionManager, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as parseAgentConfig, T as createAgentDelegateTool, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as RemoteSkillSource, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createGetFileStructureTool, a as WebSocketToolExecutor, at as mergeCommands, b as createWriteTodosTool, c as createReviewGateStore, ct as warmFileCache, d as createBlockerStore, et as SessionStore, f as createBlockerTools, g as formatDecisionsOutput, h as createDecisionStore, i as McpManager, it as searchCommands, j as formatStep, k as isTransientNetworkError, l as createReviewGateTool, m as createDecisionLogTool, n as SubagentOrchestrator, nt as hasFileReferences, o as WebSocketConnectionManager, ot as formatFileSize, p as formatBlockersOutput, q as buildSystemPrompt, r as AgentStore, rt as processFileReferences, s as WebSocketLlmBackend, st as searchFiles, t as BackgroundAgentManager, tt as OAuthClient, u as formatReviewGatesOutput, v as createFindDefinitionTool, w as createBackgroundAgentTools, x as createSkillTool, y as createTodoStore, z as DEFAULT_MAX_ITERATIONS } from "./BackgroundAgentManager-DOesheMD.mjs";
3
3
  import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-DV5s-qni.mjs";
4
- import { Qt as validateNotebookPath$1, Zt as validateJupyterKernelName, b as ChatModels, i as getCreditsUrl, n as logger, o as getEnvironmentName, r as getApiUrl, t as ConfigStore, v as CREDIT_DEDUCT_TRANSACTION_TYPES } from "./ConfigStore-DL7p3ZiY.mjs";
5
- import { t as version } from "./package-B-ONmxJ7.mjs";
4
+ import { $t as validateJupyterKernelName, en as validateNotebookPath$1, i as getCreditsUrl, n as logger, o as getEnvironmentName, r as getApiUrl, t as ConfigStore, x as ChatModels, y as CREDIT_DEDUCT_TRANSACTION_TYPES } from "./ConfigStore-Cq20962p.mjs";
5
+ import { t as version } from "./package-CBaK53NX.mjs";
6
6
  import { r as checkForUpdate } from "./updateChecker-C8xsNY2L.mjs";
7
7
  import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
8
8
  import { Box, Static, Text, render, useApp, useInput, usePaste, useStdout } from "ink";
@@ -3005,7 +3005,7 @@ async function writeLocalHandoffFile(session, options = {}) {
3005
3005
  * and falling back would mask a real bug.
3006
3006
  *
3007
3007
  * Keep the substring matches below in sync with the error strings thrown by
3008
- * `apps/cli/src/llm/ServerLlmBackend.ts` (see its catch block around the
3008
+ * `packages/cli/src/llm/ServerLlmBackend.ts` (see its catch block around the
3009
3009
  * `Request failed with status` / `Authentication ...` / `Cannot connect ...`
3010
3010
  * / `Failed to complete LLM request` throws). Renames there will silently
3011
3011
  * break the auto-fallback — a typed error hierarchy would be a more robust
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  //#region package.json
3
- var version = "0.18.3";
3
+ var version = "0.18.4";
4
4
  //#endregion
5
5
  export { version as t };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { timingSafeEqual } from "crypto";
2
+ import { createHash, timingSafeEqual } from "crypto";
3
3
  import speakeasy from "speakeasy";
4
4
  import QRCode from "qrcode";
5
5
  //#region ../../b4m-core/auth/dist/mfaService/utils.mjs
@@ -35,8 +35,18 @@ function verifyTOTPToken(secret, token, window = 1) {
35
35
  });
36
36
  }
37
37
  /**
38
- * Generate cryptographically secure backup codes for MFA
39
- * Using speakeasy's secure random generation to be consistent with TOTP secrets
38
+ * Hash a backup code for at-rest storage.
39
+ * Codes are high-entropy random strings (speakeasy base32, ~50 bits), so a
40
+ * fast SHA-256 is appropriate — no dictionary attack risk, and the migration
41
+ * backfill over thousands of users stays instantaneous.
42
+ */
43
+ function hashBackupCode(code) {
44
+ return createHash("sha256").update(code.trim().toUpperCase()).digest("hex");
45
+ }
46
+ /**
47
+ * Generate cryptographically secure backup codes for MFA.
48
+ * Returns plaintext codes for display to the user; callers are responsible for
49
+ * hashing them (via hashBackupCode) before storing in the database.
40
50
  */
41
51
  function generateBackupCodes(count = 10) {
42
52
  return Array.from({ length: count }, () => {
@@ -44,15 +54,17 @@ function generateBackupCodes(count = 10) {
44
54
  });
45
55
  }
46
56
  /**
47
- * Verify a backup code against the user's backup codes
57
+ * Verify a backup code against stored hashes.
58
+ * Hashes the provided code and compares against stored SHA-256 hashes using
59
+ * constant-time comparison to prevent timing attacks.
48
60
  */
49
61
  function verifyBackupCode(userBackupCodes, providedCode) {
50
62
  if (!userBackupCodes || !providedCode) return { isValid: false };
51
- const cleanProvidedCode = providedCode.trim().toUpperCase();
52
- const providedBuf = Buffer.from(cleanProvidedCode, "utf8");
63
+ const providedHash = hashBackupCode(providedCode);
64
+ const providedBuf = Buffer.from(providedHash, "utf8");
53
65
  let matchIdx = -1;
54
66
  for (let i = 0; i < userBackupCodes.length; i++) {
55
- const storedBuf = Buffer.from(userBackupCodes[i].trim().toUpperCase(), "utf8");
67
+ const storedBuf = Buffer.from(userBackupCodes[i], "utf8");
56
68
  if (storedBuf.length === providedBuf.length && timingSafeEqual(storedBuf, providedBuf)) {
57
69
  matchIdx = i;
58
70
  break;
@@ -75,7 +87,7 @@ function userRequiresMFA(user, enforceMFASetting) {
75
87
  * Check if a user has MFA configured
76
88
  */
77
89
  function userHasMFAConfigured(user) {
78
- return !!(user.mfa && user.mfa.totpEnabled && user.mfa.totpSecret);
90
+ return !!(user.mfa && user.mfa.totpEnabled);
79
91
  }
80
92
  /**
81
93
  * Server-side attempt tracking to prevent bypass via refresh/cancel
@@ -143,4 +155,4 @@ function userCanDisableMFA(user, enforceMFASetting) {
143
155
  return !enforceMFASetting;
144
156
  }
145
157
  //#endregion
146
- export { isUserLockedOut as a, userCanDisableMFA as c, userRequiresMFA as d, verifyBackupCode as f, getLockoutTimeRemaining as i, userEligibleForMFA as l, generateBackupCodes as n, recordFailedAttempt as o, verifyTOTPToken as p, generateTOTPSetup as r, shouldResetFailedAttempts as s, clearFailedAttempts as t, userHasMFAConfigured as u };
158
+ export { hashBackupCode as a, shouldResetFailedAttempts as c, userHasMFAConfigured as d, userRequiresMFA as f, getLockoutTimeRemaining as i, userCanDisableMFA as l, verifyTOTPToken as m, generateBackupCodes as n, isUserLockedOut as o, verifyBackupCode as p, generateTOTPSetup as r, recordFailedAttempt as s, clearFailedAttempts as t, userEligibleForMFA as u };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { m as verifyTOTPToken } from "./utils-Cdktpk_k.mjs";
3
+ export { verifyTOTPToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.18.3",
3
+ "version": "0.18.4",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -96,7 +96,7 @@
96
96
  "tree-sitter-wasms": "^0.1.13",
97
97
  "turndown": "^7.2.4",
98
98
  "undici": "^7.28.0",
99
- "unpdf": "^0.10.0",
99
+ "unpdf": "^1.6.2",
100
100
  "uuid": "^13.0.2",
101
101
  "voyageai": "^0.4.0",
102
102
  "web-tree-sitter": "0.25.10",
@@ -107,8 +107,8 @@
107
107
  "zod": "^4.4.3",
108
108
  "zod-validation-error": "^5.0.0",
109
109
  "zustand": "^5.0.13",
110
- "@bike4mind/fab-pipeline": "0.4.7",
111
- "@bike4mind/llm-adapters": "0.8.0",
110
+ "@bike4mind/fab-pipeline": "0.4.8",
111
+ "@bike4mind/llm-adapters": "0.9.0",
112
112
  "@bike4mind/observability": "0.2.0"
113
113
  },
114
114
  "devDependencies": {
@@ -124,11 +124,11 @@
124
124
  "tsx": "^4.22.3",
125
125
  "typescript": "^5.9.3",
126
126
  "vitest": "^4.1.9",
127
- "@bike4mind/agents": "0.18.1",
128
- "@bike4mind/common": "2.118.1",
129
- "@bike4mind/mcp": "1.40.1",
130
- "@bike4mind/services": "2.102.0",
131
- "@bike4mind/utils": "2.26.1"
127
+ "@bike4mind/agents": "0.18.2",
128
+ "@bike4mind/common": "2.119.0",
129
+ "@bike4mind/mcp": "1.40.2",
130
+ "@bike4mind/services": "2.103.0",
131
+ "@bike4mind/utils": "2.27.0"
132
132
  },
133
133
  "optionalDependencies": {
134
134
  "@vscode/ripgrep": "^1.18.0"
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- import { p as verifyTOTPToken } from "./utils-fqhJmuB8.mjs";
3
- export { verifyTOTPToken };