@bike4mind/cli 0.17.1 → 0.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,116 @@
1
+ Business Source License 1.1
2
+
3
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
4
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
5
+
6
+ -----------------------------------------------------------------------------
7
+
8
+ Parameters
9
+
10
+ Licensor: Bike4Mind, Inc.
11
+
12
+ Licensed Work: Bike4Mind (the lumina5 repository and the components
13
+ distributed under this License).
14
+ The Licensed Work is (c) 2026 Bike4Mind, Inc.
15
+
16
+ Additional Use Grant: You may make production use of the Licensed Work,
17
+ including building, distributing, and commercializing
18
+ your own products that incorporate or are built on the
19
+ Licensed Work, provided that you may not provide to
20
+ third parties a Bike4Mind Service. A "Bike4Mind Service"
21
+ is a commercial offering (including a managed, hosted,
22
+ or software-as-a-service offering) that allows third
23
+ parties — other than your own employees and individual
24
+ contractors — to access a substantial portion of the
25
+ functionality of the Licensed Work in a manner that
26
+ competes with a commercial offering of Bike4Mind, Inc.
27
+ For the avoidance of doubt, you may self-host and operate
28
+ the Licensed Work on your own hardware or infrastructure
29
+ for your own internal purposes (including use by your
30
+ organization's employees and individual contractors).
31
+ Such internal use — including running it for your own
32
+ sovereignty, independent of any hyperscaler or model
33
+ provider — is expressly permitted and is not a Bike4Mind
34
+ Service.
35
+
36
+ Change Date: Four years from the date a given version of the Licensed
37
+ Work is first made publicly available. Each version
38
+ carries its own Change Date (see Terms). Bike4Mind, Inc.
39
+ may, at its discretion, designate an earlier Change Date
40
+ for any version.
41
+
42
+ Change License: Apache License, Version 2.0
43
+
44
+ For information about alternative licensing arrangements for the Licensed Work,
45
+ please contact licensing@bike4mind.com.
46
+
47
+ -----------------------------------------------------------------------------
48
+
49
+ Notice
50
+
51
+ Business Source License 1.1
52
+
53
+ Terms
54
+
55
+ The Licensor hereby grants you the right to copy, modify, create derivative
56
+ works, redistribute, and make non-production use of the Licensed Work. The
57
+ Licensor may make an Additional Use Grant, above, permitting limited production
58
+ use.
59
+
60
+ Effective on the Change Date, or the fourth anniversary of the first publicly
61
+ available distribution of a specific version of the Licensed Work under this
62
+ License, whichever comes first, the Licensor hereby grants you rights under
63
+ the terms of the Change License, and the rights granted in the paragraph
64
+ above terminate.
65
+
66
+ If your use of the Licensed Work does not comply with the requirements
67
+ currently in effect as described in this License, you must purchase a
68
+ commercial license from the Licensor, its affiliated entities, or authorized
69
+ resellers, or you must refrain from using the Licensed Work.
70
+
71
+ All copies of the original and modified Licensed Work, and derivative works of
72
+ the Licensed Work, are subject to this License. This License applies separately
73
+ for each version of the Licensed Work and the Change Date may vary for each
74
+ version of the Licensed Work released by Licensor.
75
+
76
+ You must conspicuously display this License on each original or modified copy of
77
+ the Licensed Work. If you receive the Licensed Work in original or modified form
78
+ from a third party, the terms and conditions set forth in this License apply to
79
+ your use of that work.
80
+
81
+ Any use of the Licensed Work in violation of this License will automatically
82
+ terminate your rights under this License for the current and all other versions
83
+ of the Licensed Work.
84
+
85
+ This License does not grant you any right in any trademark or logo of Licensor
86
+ or its affiliates (provided that you may use a trademark or logo of Licensor as
87
+ expressly required by this License).
88
+
89
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN
90
+ "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS
91
+ OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY,
92
+ FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
93
+
94
+ MariaDB hereby grants you permission to use this License's text to license your
95
+ works, and to refer to it using the trademark "Business Source License", as long
96
+ as you comply with the Covenants of Licensor below.
97
+
98
+ Covenants of Licensor
99
+
100
+ In consideration of the right to use this License's text and the "Business Source
101
+ License" name and trademark, Licensor covenants to MariaDB, and to all other
102
+ recipients of the licensed work to be provided by Licensor:
103
+
104
+ 1. To specify as the Change License the GPL Version 2.0 or any later version, or
105
+ a license that is compatible with GPL Version 2.0 or a later version, where
106
+ "compatible" means that software provided under the Change License can be
107
+ included in a program with software provided under GPL Version 2.0 or a later
108
+ version. Licensor may specify additional Change Licenses without limitation.
109
+
110
+ 2. To either: (a) specify an additional grant of rights to use that does not
111
+ impose any additional restriction on the right granted in this License, as the
112
+ Additional Use Grant; or (b) insert the text "None".
113
+
114
+ 3. To specify a Change Date.
115
+
116
+ 4. Not to modify this License in any other way.
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { $ as ProjectEvents, $t as parseRateLimitHeaders, A as GenerateImageToolCallSchema, At as dayjsConfig_default, B as InviteEvents, Bt as obfuscateApiKey, C as ElabsEvents, Ct as UnauthorizedError, D as ForbiddenError, Dt as VideoModels, E as FileEvents, Et as VideoGenerationUsageTransaction, F as ImageEditUsageTransaction, Ft as isGPTImageModel, G as ModalEvents, Gt as settingsMap, H as KnowledgeType, Ht as resolveNavigationIntents, I as ImageGenerationUsageTransaction, It as isModelAccessible, J as OpenAIEmbeddingModel, K as ModelBackend, Kt as substituteArguments$1, L as ImageModels, Lt as isSupportedEmbeddingModel, M as GenericCreditDeductTransaction, Mt as getMcpProviderMetadata, N as HTTPError, Nt as getViewById, O as FriendshipEvents, Ot as XAI_IMAGE_MODELS, P as HttpStatus, Pt as isGPTImage2Model, Q as ProfileEvents, Qt as isNearLimit, R as InboxEvents, Rt as isZodError, S as DashboardParamsSchema, St as UiNavigationEvents, T as FeedbackEvents, Tt as VIDEO_SIZE_CONSTRAINTS, U as LLMEvents, Ut as sanitizeTelemetryError, V as InviteType, Vt as parseSkillArguments, W as MiscEvents, Wt as secureParameters, X as Permission, Xt as buildRateLimitLogEntry, Y as OpenAIImageGenerationInput, Z as PermissionDeniedError, Zt as extractSnippetMeta, _ as ChatCompletionCreateInputSchema, _t as TaskScheduleHandler, a as ALERT_THRESHOLDS, at as ReceivedCreditTransaction, b as CompletionApiUsageTransaction, bt as ToolUsageTransaction, c as ApiKeyScope, ct as ResearchModeParamsSchema, d as ArtifactTypeSchema, dt as ResearchTaskType, en as CollectionType, et as PromptIntentSchema, f as AuthEvents, ft as SessionEvents, gt as TagType, h as BadRequestError, ht as SupportedFabFileMimeTypes, it as RealtimeVoiceUsageTransaction, j as GenericCreditAddTransaction, jt as getAccessibleDataLakes, k as GEMINI_IMAGE_MODELS, kt as b4mLLMTools, l as ApiKeyType, lt as ResearchTaskExecutionType, m as BFL_SAFETY_TOLERANCE, mt as SubscriptionCreditTransaction, n as logger, nt as PurchaseTransaction, o as AiEvents, ot as RechartsChartTypeList, p as BFL_IMAGE_MODELS, pt as SpeechToTextUsageTransaction, q as NotFoundError, qt as toDataLakeConfig, rt as QuestMasterParamsSchema, s as ApiKeyEvents, st as RegInviteEvents, t as ConfigStore, tt as PromptMetaZodSchema, u as AppFileEvents, ut as ResearchTaskPeriodicFrequencyType, v as ChatModels, vt as TextGenerationUsageTransaction, w as FavoriteDocumentType, wt as UnprocessableEntityError, x as CorruptedFileError, xt as TransferCreditTransaction, y as ClaudeArtifactMimeTypes, yt as TooManyRequestsError, z as InternalServerError, zt as mapMimeTypeToArtifactType } from "./ConfigStore-gV8aHo9b.mjs";
3
- import { a as isUserLockedOut, c as userCanDisableMFA, d as userRequiresMFA, f as verifyBackupCode, i as getLockoutTimeRemaining, l as userEligibleForMFA, n as generateBackupCodes, o as recordFailedAttempt, p as verifyTOTPToken, r as generateTOTPSetup, s as shouldResetFailedAttempts, t as clearFailedAttempts, u as userHasMFAConfigured } from "./utils-PpNti-tY.mjs";
2
+ import { $ as ProjectEvents, $t as parseRateLimitHeaders, A as GenerateImageToolCallSchema, At as dayjsConfig_default, B as InviteEvents, Bt as obfuscateApiKey, C as ElabsEvents, Ct as UnauthorizedError, D as ForbiddenError, Dt as VideoModels, E as FileEvents, Et as VideoGenerationUsageTransaction, F as ImageEditUsageTransaction, Ft as isGPTImageModel, G as ModalEvents, Gt as settingsMap, H as KnowledgeType, Ht as resolveNavigationIntents, I as ImageGenerationUsageTransaction, It as isModelAccessible, J as OpenAIEmbeddingModel, K as ModelBackend, Kt as substituteArguments$1, L as ImageModels, Lt as isSupportedEmbeddingModel, M as GenericCreditDeductTransaction, Mt as getMcpProviderMetadata, N as HTTPError, Nt as getViewById, O as FriendshipEvents, Ot as XAI_IMAGE_MODELS, P as HttpStatus, Pt as isGPTImage2Model, Q as ProfileEvents, Qt as isNearLimit, R as InboxEvents, Rt as isZodError, S as DashboardParamsSchema, St as UiNavigationEvents, T as FeedbackEvents, Tt as VIDEO_SIZE_CONSTRAINTS, U as LLMEvents, Ut as sanitizeTelemetryError, V as InviteType, Vt as parseSkillArguments, W as MiscEvents, Wt as secureParameters, X as Permission, Xt as buildRateLimitLogEntry, Y as OpenAIImageGenerationInput, Z as PermissionDeniedError, Zt as extractSnippetMeta, _ as ChatCompletionCreateInputSchema, _t as TaskScheduleHandler, a as ALERT_THRESHOLDS, at as ReceivedCreditTransaction, b as CompletionApiUsageTransaction, bt as ToolUsageTransaction, c as ApiKeyScope, ct as ResearchModeParamsSchema, d as ArtifactTypeSchema, dt as ResearchTaskType, en as CollectionType, et as PromptIntentSchema, f as AuthEvents, ft as SessionEvents, gt as TagType, h as BadRequestError, ht as SupportedFabFileMimeTypes, it as RealtimeVoiceUsageTransaction, j as GenericCreditAddTransaction, jt as getAccessibleDataLakes, k as GEMINI_IMAGE_MODELS, kt as b4mLLMTools, l as ApiKeyType, lt as ResearchTaskExecutionType, m as BFL_SAFETY_TOLERANCE, mt as SubscriptionCreditTransaction, n as logger, nt as PurchaseTransaction, o as AiEvents, ot as RechartsChartTypeList, p as BFL_IMAGE_MODELS, pt as SpeechToTextUsageTransaction, q as NotFoundError, qt as toDataLakeConfig, rt as QuestMasterParamsSchema, s as ApiKeyEvents, st as RegInviteEvents, t as ConfigStore, tt as PromptMetaZodSchema, u as AppFileEvents, ut as ResearchTaskPeriodicFrequencyType, v as ChatModels, vt as TextGenerationUsageTransaction, w as FavoriteDocumentType, wt as UnprocessableEntityError, x as CorruptedFileError, xt as TransferCreditTransaction, y as ClaudeArtifactMimeTypes, yt as TooManyRequestsError, z as InternalServerError, zt as mapMimeTypeToArtifactType } from "./ConfigStore-7kcIJ-ux.mjs";
3
+ import { a as isUserLockedOut, c as userCanDisableMFA, d as userRequiresMFA, f as verifyBackupCode, i as getLockoutTimeRemaining, l as userEligibleForMFA, n as generateBackupCodes, o as recordFailedAttempt, p as verifyTOTPToken, r as generateTOTPSetup, s as shouldResetFailedAttempts, t as clearFailedAttempts, u as userHasMFAConfigured } from "./utils-fqhJmuB8.mjs";
4
4
  import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
5
- import { t as version } from "./package-Dzetdo6D.mjs";
5
+ import { t as version } from "./package-DLM23Ze7.mjs";
6
6
  import { execFile, execFileSync, spawn } from "child_process";
7
7
  import crypto, { createHash, randomBytes, randomUUID } from "crypto";
8
8
  import { existsSync, promises, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from "fs";
@@ -3300,6 +3300,12 @@ const MIME_TO_EXT = {
3300
3300
  };
3301
3301
  const INFINITE_VALUE = 14;
3302
3302
  const MAX_FILE_SIZE$2 = 6e3;
3303
+ /** Cap on generated images surfaced to the model for editing (keeps the context note small). */
3304
+ const MAX_RECENT_GENERATED_IMAGES = 6;
3305
+ /** Chars of the originating prompt kept per generated image, for context without bloat. */
3306
+ const RECENT_IMAGE_PROMPT_PREVIEW_CHARS = 120;
3307
+ /** quest.images also holds non-image generated artifacts (e.g. .xlsx); only these extensions are editable. */
3308
+ const EDITABLE_IMAGE_KEY_RE = /\.(jpe?g|png|webp|gif)$/i;
3303
3309
  const PREVIEW_CHUNK = 700;
3304
3310
  const CHARS_PER_TOKEN = 3.5;
3305
3311
  const MAX_IMAGE_DIMENSION_PX = 2e3;
@@ -3407,70 +3413,85 @@ async function fetchAndProcessPreviousMessages(session, historyCount = null, { d
3407
3413
  chatHistoryItems.splice(0, chatHistoryItems.length, ...filtered);
3408
3414
  }
3409
3415
  const oldestIncludedQuestId = chatHistoryItems[0]?.id ?? null;
3410
- return [
3411
- chatHistoryItems.reduce((acc, cur) => {
3412
- if (cur.prompt) acc.push({
3416
+ const convertedMessages = chatHistoryItems.reduce((acc, cur) => {
3417
+ if (cur.prompt) acc.push({
3418
+ role: "user",
3419
+ content: cur.prompt
3420
+ });
3421
+ if (cur.structuredReplies && cur.structuredReplies.length > 0) {
3422
+ for (const structuredReply of cur.structuredReplies) acc.push({
3423
+ role: "assistant",
3424
+ content: structuredReply.content
3425
+ });
3426
+ if (cur.toolResults && cur.toolResults.length > 0) acc.push({
3413
3427
  role: "user",
3414
- content: cur.prompt
3428
+ content: cur.toolResults.map((tr) => ({
3429
+ type: "tool_result",
3430
+ tool_use_id: tr.tool_use_id,
3431
+ content: tr.content,
3432
+ is_error: tr.is_error
3433
+ }))
3415
3434
  });
3416
- if (cur.structuredReplies && cur.structuredReplies.length > 0) {
3417
- for (const structuredReply of cur.structuredReplies) acc.push({
3435
+ } else if (cur.promptMeta?.functionCalls && cur.promptMeta.functionCalls.length > 0 && cur.promptMeta.functionCalls.some((fc) => fc.id)) {
3436
+ const textReply = cur.replies?.find((reply) => !reply.trim().startsWith("<think>")) || "";
3437
+ const assistantContent = [];
3438
+ if (textReply) assistantContent.push({
3439
+ type: "text",
3440
+ text: textReply
3441
+ });
3442
+ for (const fc of cur.promptMeta.functionCalls) if (fc.id && fc.name) assistantContent.push({
3443
+ type: "tool_use",
3444
+ id: fc.id,
3445
+ name: fc.name,
3446
+ input: fc.parameters || {}
3447
+ });
3448
+ if (assistantContent.length > 0) {
3449
+ acc.push({
3418
3450
  role: "assistant",
3419
- content: structuredReply.content
3451
+ content: assistantContent
3420
3452
  });
3421
- if (cur.toolResults && cur.toolResults.length > 0) acc.push({
3453
+ const toolResults = cur.promptMeta.functionCalls.filter((fc) => fc.id && fc.name).map((fc) => ({
3454
+ type: "tool_result",
3455
+ tool_use_id: fc.id,
3456
+ content: fc.returnValue ?? (fc.success === false ? "Tool execution failed" : ""),
3457
+ is_error: fc.success === false
3458
+ }));
3459
+ if (toolResults.length > 0) acc.push({
3422
3460
  role: "user",
3423
- content: cur.toolResults.map((tr) => ({
3424
- type: "tool_result",
3425
- tool_use_id: tr.tool_use_id,
3426
- content: tr.content,
3427
- is_error: tr.is_error
3428
- }))
3429
- });
3430
- } else if (cur.promptMeta?.functionCalls && cur.promptMeta.functionCalls.length > 0 && cur.promptMeta.functionCalls.some((fc) => fc.id)) {
3431
- const textReply = cur.replies?.find((reply) => !reply.trim().startsWith("<think>")) || "";
3432
- const assistantContent = [];
3433
- if (textReply) assistantContent.push({
3434
- type: "text",
3435
- text: textReply
3436
- });
3437
- for (const fc of cur.promptMeta.functionCalls) if (fc.id && fc.name) assistantContent.push({
3438
- type: "tool_use",
3439
- id: fc.id,
3440
- name: fc.name,
3441
- input: fc.parameters || {}
3442
- });
3443
- if (assistantContent.length > 0) {
3444
- acc.push({
3445
- role: "assistant",
3446
- content: assistantContent
3447
- });
3448
- const toolResults = cur.promptMeta.functionCalls.filter((fc) => fc.id && fc.name).map((fc) => ({
3449
- type: "tool_result",
3450
- tool_use_id: fc.id,
3451
- content: fc.returnValue ?? (fc.success === false ? "Tool execution failed" : ""),
3452
- is_error: fc.success === false
3453
- }));
3454
- if (toolResults.length > 0) acc.push({
3455
- role: "user",
3456
- content: toolResults
3457
- });
3458
- }
3459
- } else if (cur.replies && Array.isArray(cur.replies)) {
3460
- const validReply = cur.replies.find((reply) => !reply.trim().startsWith("<think>"));
3461
- if (validReply) acc.push({
3462
- role: "assistant",
3463
- content: validReply
3461
+ content: toolResults
3464
3462
  });
3465
3463
  }
3466
- return acc;
3467
- }, new Array()),
3464
+ } else if (cur.replies && Array.isArray(cur.replies)) {
3465
+ const validReply = cur.replies.find((reply) => !reply.trim().startsWith("<think>"));
3466
+ if (validReply) acc.push({
3467
+ role: "assistant",
3468
+ content: validReply
3469
+ });
3470
+ }
3471
+ return acc;
3472
+ }, new Array());
3473
+ const recentGeneratedImages = [];
3474
+ for (let i = chatHistoryItems.length - 1; i >= 0 && recentGeneratedImages.length < MAX_RECENT_GENERATED_IMAGES; i--) {
3475
+ const item = chatHistoryItems[i];
3476
+ if (!Array.isArray(item.images) || item.images.length === 0) continue;
3477
+ const prompt = (item.prompt ?? "").slice(0, RECENT_IMAGE_PROMPT_PREVIEW_CHARS);
3478
+ for (const key of item.images) {
3479
+ if (recentGeneratedImages.length >= MAX_RECENT_GENERATED_IMAGES) break;
3480
+ if (typeof key === "string" && EDITABLE_IMAGE_KEY_RE.test(key)) recentGeneratedImages.push({
3481
+ key,
3482
+ prompt
3483
+ });
3484
+ }
3485
+ }
3486
+ return [
3487
+ convertedMessages,
3468
3488
  chatHistoryItems.length,
3469
3489
  {
3470
3490
  cacheHit: fetchTime < 50,
3471
3491
  fetchTime,
3472
3492
  itemCount: chatHistoryItems.length,
3473
- oldestIncludedQuestId
3493
+ oldestIncludedQuestId,
3494
+ recentGeneratedImages
3474
3495
  }
3475
3496
  ];
3476
3497
  }
@@ -11228,7 +11249,7 @@ function continuousToy() {
11228
11249
  }
11229
11250
  schedulingToy(), routingToy(), packingToy(), assignmentToy(), networkToy(), partitioningToy(), selectionToy(), economicToy(), continuousToy();
11230
11251
  //#endregion
11231
- //#region ../../b4m-core/services/dist/tools-Dzibx4fx.mjs
11252
+ //#region ../../b4m-core/services/dist/tools-FLVnTwId.mjs
11232
11253
  async function performDeepResearch(context, params, config = {}) {
11233
11254
  const maxDepth = config.maxDepth || 7;
11234
11255
  const duration = config.duration || 4.5;
@@ -12966,6 +12987,39 @@ async function getImageFromFileId(fileId, context) {
12966
12987
  if (fabFile.fileUrl) return fabFile.fileUrl;
12967
12988
  throw new Error(`File ${fileId} has no accessible URL`);
12968
12989
  }
12990
+ /**
12991
+ * Resolve a generated-image storage key (the bare key persisted in
12992
+ * `quest.images`, e.g. "86cdc650-….jpg") to a downloadable URL.
12993
+ *
12994
+ * image_generation / edit_image upload their output to `imageGenerateStorage`
12995
+ * and persist only the bare key — no fabFile record is created — so a generated
12996
+ * image is NOT addressable as a fabFile ObjectId. Resolving it against the image
12997
+ * bucket is what lets a follow-up edit ("make it cartoonish") target a
12998
+ * previously generated image. The model learns these keys from the "Recently
12999
+ * generated images" system note assembled in ChatCompletionProcess.
13000
+ */
13001
+ async function getGeneratedImageUrl(storageKey, context) {
13002
+ try {
13003
+ return await context.imageGenerateStorage.getSignedUrl(storageKey);
13004
+ } catch (error) {
13005
+ const detail = error instanceof Error ? error.message : String(error);
13006
+ throw new Error(`Could not resolve generated image "${storageKey}". Use the exact id from the "Recently generated images" system note, a fabFile ID from "Available Files", or a full URL. (${detail})`);
13007
+ }
13008
+ }
13009
+ /**
13010
+ * Resolve an image input (source or mask) to a downloadable URL. Accepts, in
13011
+ * priority order:
13012
+ * • an http(s)/data URL — passed straight through
13013
+ * • a fabFile ObjectId (24-char hex) — an uploaded image from "Available Files"
13014
+ * • otherwise a generated-image storage key (the bare key in quest.images,
13015
+ * e.g. "86cdc650-….jpg") — resolved against the image bucket
13016
+ * Source and mask share this so a generated-image key works for either.
13017
+ */
13018
+ async function resolveImageInputUrl(input, context) {
13019
+ if (input.startsWith("http://") || input.startsWith("https://") || input.startsWith("data:")) return input;
13020
+ if (/^[0-9a-fA-F]{24}$/.test(input)) return getImageFromFileId(input, context);
13021
+ return getGeneratedImageUrl(input, context);
13022
+ }
12969
13023
  async function processAndStoreImage(imageUrl, context) {
12970
13024
  const buffer = await downloadImage(imageUrl);
12971
13025
  const fileType = await fileTypeFromBuffer(buffer);
@@ -13039,17 +13093,9 @@ Please select a supported edit model in your image settings modal.`;
13039
13093
  quality: imageConfig?.quality,
13040
13094
  prompt
13041
13095
  });
13042
- let sourceImageUrl;
13043
- if (toolImage.startsWith("http://") || toolImage.startsWith("https://") || toolImage.startsWith("data:")) sourceImageUrl = toolImage;
13044
- else sourceImageUrl = await getImageFromFileId(toolImage, context);
13045
- const sourceBase64Image = await imageUrlToBase64(sourceImageUrl);
13096
+ const sourceBase64Image = await imageUrlToBase64(await resolveImageInputUrl(toolImage, context));
13046
13097
  let maskBase64Image = null;
13047
- if (toolMask) {
13048
- let maskImageUrl;
13049
- if (toolMask.startsWith("http://") || toolMask.startsWith("https://") || toolMask.startsWith("data:")) maskImageUrl = toolMask;
13050
- else maskImageUrl = await getImageFromFileId(toolMask, context);
13051
- maskBase64Image = await imageUrlToBase64(maskImageUrl);
13052
- }
13098
+ if (toolMask) maskBase64Image = await imageUrlToBase64(await resolveImageInputUrl(toolMask, context));
13053
13099
  if (isBFLModel) {
13054
13100
  const service = new BFLImageService(await (0, apiKeyService_exports.getEffectiveApiKey)(context.userId, { type: ApiKeyType.bfl }, { db: context.db }), context.logger, context.imageProcessorLambdaName);
13055
13101
  let bflModel = editModel;
@@ -13143,13 +13189,13 @@ Please check your BFL API key in settings and ensure it is configured correctly.
13143
13189
  },
13144
13190
  toolSchema: {
13145
13191
  name: "edit_image",
13146
- description: "Edit an existing image based on a text prompt. Use this when the user wants to modify, change, edit, or transform an image they have uploaded or attached to the conversation. Supports removing backgrounds, changing colors, adding/removing objects, and other visual modifications.",
13192
+ description: "Edit an existing image based on a text prompt. Use this when the user wants to modify, change, edit, or transform an image — whether they uploaded/attached it OR it was generated earlier in this conversation (e.g. \"make the previous image more cartoonish\", \"adjust the angle\"). Supports removing backgrounds, changing colors, adding/removing objects, and other visual modifications.",
13147
13193
  parameters: {
13148
13194
  type: "object",
13149
13195
  properties: {
13150
13196
  image: {
13151
13197
  type: "string",
13152
- description: "The file ID of the image to edit (e.g., \"67abc123def456\"). Look for image file IDs in the \"Available Files\" system message. You can also use an S3 URL or data URL if provided by the user."
13198
+ description: "The image to edit. Provide one of: the exact id of a previously generated image from the \"Recently generated images\" system note (e.g. \"86cdc650-43d2-416e-aca6-23ff4fe23081.jpg\"); a fabFile ID of an uploaded image from the \"Available Files\" system message (e.g. \"67abc123def456\"); or a full http(s)/data URL."
13153
13199
  },
13154
13200
  prompt: {
13155
13201
  type: "string",
@@ -13613,9 +13659,12 @@ const getWikipediaOnThisDay = async (parameters = {}) => {
13613
13659
  try {
13614
13660
  const { month, day } = parseMonthDay(date);
13615
13661
  const url = `https://en.wikipedia.org/api/rest_v1/feed/onthisday/${type}/${month}/${day}`;
13662
+ const brand = process.env.APP_NAME || "";
13663
+ const websiteUrl = process.env.WEBSITE_URL || "";
13664
+ const userAgent = brand ? `${brand}/1.0${websiteUrl ? ` (${websiteUrl})` : ""}` : "App/1.0";
13616
13665
  const response = await fetch(url, { headers: {
13617
13666
  Accept: "application/json",
13618
- "User-Agent": "Bike4Mind/1.0 (https://bike4mind.com; contact@bike4mind.com)"
13667
+ "User-Agent": userAgent
13619
13668
  } });
13620
13669
  if (!response.ok) {
13621
13670
  if (response.status === 404) throw new Error(`No data available for ${month}-${day}. The date may be invalid.`);
@@ -16053,7 +16102,8 @@ function applyCellStyle(cell, style) {
16053
16102
  */
16054
16103
  async function generateExcel(params) {
16055
16104
  const workbook = new ExcelJS.Workbook();
16056
- workbook.creator = "Bike4Mind AI";
16105
+ const brand = process.env.APP_NAME || "";
16106
+ workbook.creator = brand ? `${brand} AI` : "AI";
16057
16107
  workbook.created = /* @__PURE__ */ new Date();
16058
16108
  for (const sheetData of params.sheets) {
16059
16109
  const worksheet = workbook.addWorksheet(sheetData.name.slice(0, LIMITS.MAX_SHEET_NAME_LENGTH));
@@ -16118,7 +16168,18 @@ const excelGenerationTool = {
16118
16168
  },
16119
16169
  toolSchema: {
16120
16170
  name: "excel_generation",
16121
- description: `Generate Excel (.xlsx) files with formatting. Supports: multiple sheets, formulas (SUM, AVERAGE, IF, etc.), styling (bold, colors, borders), number formats, merged cells, frozen panes. Limits: max ${LIMITS.MAX_SHEETS} sheets, ${LIMITS.MAX_CELLS_PER_SHEET} cells/sheet, rows 1-${LIMITS.MAX_ROW}, cols 1-${LIMITS.MAX_COL}.`,
16171
+ description: `Generate a well-formed Excel (.xlsx) workbook. Supports: multiple sheets, formulas (SUM, AVERAGE, IF, VLOOKUP, etc.; only a safe whitelisted subset), styling (bold, colors, borders), number formats, merged cells, frozen panes.
16172
+
16173
+ HARD LIMITS (the request is REJECTED if any are exceeded, not truncated, so data is never silently dropped):
16174
+ - At most ${LIMITS.MAX_SHEETS} sheets per workbook.
16175
+ - At most ${LIMITS.MAX_CELLS_PER_SHEET} populated cells per sheet (count the cell objects you pass in "data", not the grid area).
16176
+ - Row numbers 1-${LIMITS.MAX_ROW} and column numbers 1-${LIMITS.MAX_COL} only.
16177
+ - Sheet names: 1-${LIMITS.MAX_SHEET_NAME_LENGTH} characters.
16178
+ - Formulas may only use whitelisted functions; volatile/external ones (HYPERLINK, WEBSERVICE, CMD, etc.) are blocked.
16179
+
16180
+ Addressing is 1-indexed numeric row/col (row 1, col 1 = cell A1); do NOT pass A1-style strings. Provide only the cells you want populated; empty cells need no entry.
16181
+
16182
+ Before calling: if the user's request would exceed any limit (e.g. a dataset larger than ${LIMITS.MAX_CELLS_PER_SHEET} cells or more than ${LIMITS.MAX_SHEETS} sheets), do not promise the full result; tell the user what you can deliver within these limits and either split the data across sheets/files or summarize. Only commit to what this tool can actually produce.`,
16122
16183
  parameters: {
16123
16184
  type: "object",
16124
16185
  properties: {
@@ -17695,7 +17756,7 @@ var mfaService_exports$1 = /* @__PURE__ */ __exportAll$3({
17695
17756
  * This generates the secret and backup codes but doesn't enable MFA yet
17696
17757
  * The user must verify the setup before MFA is enabled
17697
17758
  */
17698
- async function setupMFA({ user, appName = "Bike4Mind" }, userRepository) {
17759
+ async function setupMFA({ user, appName = process.env.APP_NAME || "" }, userRepository) {
17699
17760
  if (!userEligibleForMFA(user)) throw new Error("User is not eligible for MFA setup.");
17700
17761
  if (user.mfa && user.mfa.totpEnabled) throw new Error("MFA is already enabled for this user.");
17701
17762
  if (user.mfa && user.mfa.totpEnabled === false) user.mfa = null;
@@ -17725,7 +17786,7 @@ async function setupMFA({ user, appName = "Bike4Mind" }, userRepository) {
17725
17786
  async function verifyMFASetup(user, token, userRepository) {
17726
17787
  if (!user.mfa || !user.mfa.totpSecret) throw new Error("No MFA setup in progress for this user.");
17727
17788
  if (user.mfa.totpEnabled) throw new Error("MFA is already enabled for this user.");
17728
- const { verifyTOTPToken } = await import("./utils-BGtSXfce.mjs");
17789
+ const { verifyTOTPToken } = await import("./utils-CLjLKvqQ.mjs");
17729
17790
  if (!verifyTOTPToken(user.mfa.totpSecret, token)) throw new Error("Invalid TOTP code.");
17730
17791
  const updatedMFA = { ...user.mfa };
17731
17792
  updatedMFA.totpEnabled = true;
@@ -20146,6 +20207,7 @@ z.object({
20146
20207
  surface: z.string().optional(),
20147
20208
  enabledTools: z.array(z.string()).optional(),
20148
20209
  disabledTools: z.array(z.string()).optional(),
20210
+ disableUserIntegrations: z.boolean().optional(),
20149
20211
  forceKnowledgeRetrieval: z.boolean().optional(),
20150
20212
  retrievalTags: z.array(z.string()).optional(),
20151
20213
  citationStyle: z.enum(["named", "indexed"]).optional(),
@@ -20160,8 +20222,7 @@ z.object({
20160
20222
  clonedSourceId: z.string().optional().nullable(),
20161
20223
  forkedSourceId: z.string().optional().nullable(),
20162
20224
  projectId: z.string().optional(),
20163
- lastUsedModel: z.string().optional().nullable(),
20164
- optiHashi: z.boolean().optional()
20225
+ lastUsedModel: z.string().optional().nullable()
20165
20226
  });
20166
20227
  z.object({ id: z.string() });
20167
20228
  z.object({ id: z.string() });
@@ -21,8 +21,8 @@ let CollectionType = /* @__PURE__ */ function(CollectionType) {
21
21
  CollectionType["AI_IMAGE"] = "ai_image";
22
22
  return CollectionType;
23
23
  }({});
24
- //#endregion
25
- //#region ../../b4m-core/common/dist/api--fTBBxKG.mjs
24
+ process.env.APP_NAME;
25
+ process.env.WEBSITE_URL;
26
26
  const extractSnippetMeta = (content) => {
27
27
  const snippetRegex = /<!--snippet-meta\s*(\{[\s\S]*?\})\s*-->[\n\s]*([\s\S]*?)(?=<!--snippet-meta|$)/g;
28
28
  const sections = [];
@@ -3817,6 +3817,8 @@ z.enum([
3817
3817
  "EnableArtifactsDefault",
3818
3818
  "EnableAgents",
3819
3819
  "EnableAgentsDefault",
3820
+ "EnableAgentMode",
3821
+ "EnableAgentModeDefault",
3820
3822
  "EnableRapidReply",
3821
3823
  "EnableRapidReplyDefault",
3822
3824
  "EnableLattice",
@@ -3978,7 +3980,10 @@ const OrchestrationDefaultsSchema = z.object({
3978
3980
  "sunrise_sunset",
3979
3981
  "planet_visibility",
3980
3982
  "code_execute",
3981
- "coordinate_task"
3983
+ "coordinate_task",
3984
+ "image_generation",
3985
+ "edit_image",
3986
+ "excel_generation"
3982
3987
  ]),
3983
3988
  /**
3984
3989
  * Tool names explicitly forbidden. Enforced as a final subtraction in
@@ -4005,10 +4010,7 @@ const OrchestrationDefaultsSchema = z.object({
4005
4010
  "lattice_create_model",
4006
4011
  "lattice_add_entity",
4007
4012
  "lattice_set_value",
4008
- "lattice_create_rule",
4009
- "image_generation",
4010
- "edit_image",
4011
- "excel_generation"
4013
+ "lattice_create_rule"
4012
4014
  ]),
4013
4015
  /** Per-thoroughness iteration ceiling. Matches `IAgent.maxIterations`. */
4014
4016
  maxIterations: z.object({
@@ -4884,6 +4886,14 @@ const API_SERVICE_GROUPS = {
4884
4886
  key: "enableAgentProactiveMessages",
4885
4887
  order: 12
4886
4888
  },
4889
+ {
4890
+ key: "EnableAgentMode",
4891
+ order: 15
4892
+ },
4893
+ {
4894
+ key: "EnableAgentModeDefault",
4895
+ order: 16
4896
+ },
4887
4897
  {
4888
4898
  key: "EnableArtifacts",
4889
4899
  order: 20
@@ -5446,6 +5456,25 @@ const settingsMap = {
5446
5456
  order: 11,
5447
5457
  dependsOn: "EnableAgents"
5448
5458
  }),
5459
+ EnableAgentMode: makeBooleanSetting({
5460
+ key: "EnableAgentMode",
5461
+ name: "Enable Agent Mode (Smart Routing)",
5462
+ defaultValue: true,
5463
+ description: "Whether the Agent Mode / Smart Routing feature is available to users. When enabled, users can opt in via the Beta Features tab to have complex prompts automatically routed to multi-step agents. Set to off to hide the feature org-wide.",
5464
+ category: "Experimental",
5465
+ group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
5466
+ order: 15
5467
+ }),
5468
+ EnableAgentModeDefault: makeBooleanSetting({
5469
+ key: "EnableAgentModeDefault",
5470
+ name: "Agent Mode: On by default for users",
5471
+ defaultValue: false,
5472
+ description: "When enabled, Agent Mode / Smart Routing is active for users who have never explicitly toggled it. Leave off for an opt-in rollout.",
5473
+ category: "Experimental",
5474
+ group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
5475
+ order: 16,
5476
+ dependsOn: "EnableAgentMode"
5477
+ }),
5449
5478
  EnableRapidReply: makeBooleanSetting({
5450
5479
  key: "EnableRapidReply",
5451
5480
  name: "Enable Rapid Reply",
@@ -5544,7 +5573,7 @@ const settingsMap = {
5544
5573
  tagLineMain: makeStringSetting({
5545
5574
  key: "tagLineMain",
5546
5575
  name: "Tag Line Main",
5547
- defaultValue: "Bike4Mind",
5576
+ defaultValue: process.env.NEXT_PUBLIC_APP_NAME || process.env.APP_NAME || "",
5548
5577
  description: "The main tag line to display on the app.",
5549
5578
  category: "Branding",
5550
5579
  group: API_SERVICE_GROUPS.BRANDING.id,
@@ -6190,7 +6219,7 @@ const settingsMap = {
6190
6219
  key: "qWorkUrl",
6191
6220
  name: "Q/Work URL",
6192
6221
  defaultValue: "",
6193
- description: "The base URL for the Q/Work API (for example: https://q.bike4mind.com).",
6222
+ description: "The base URL for the Q/Work API (for example: https://q.your-deployment.example.com).",
6194
6223
  category: "Tools",
6195
6224
  group: API_SERVICE_GROUPS.Q_WORK.id,
6196
6225
  order: 1
@@ -9318,7 +9347,7 @@ z.array(triggerWordSchema).max(20, "Up to 20 trigger words allowed.").transform(
9318
9347
  const key = word.toLowerCase();
9319
9348
  if (seen.has(key)) continue;
9320
9349
  seen.add(key);
9321
- out.push(word);
9350
+ out.push(key);
9322
9351
  }
9323
9352
  return out;
9324
9353
  });
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-gV8aHo9b.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-7kcIJ-ux.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-Dzetdo6D.mjs";
2
+ import { t as version } from "../package-DLM23Ze7.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-gV8aHo9b.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-7kcIJ-ux.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-C5HEirFN.mjs";
3
- import { n as logger, r as getApiUrl, t as ConfigStore } from "../ConfigStore-gV8aHo9b.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-DQjlUwRw.mjs";
3
+ import { n as logger, r as getApiUrl, t as ConfigStore } from "../ConfigStore-7kcIJ-ux.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-gV8aHo9b.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-7kcIJ-ux.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-Dzetdo6D.mjs";
2
+ import { t as version } from "../package-DLM23Ze7.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-C5HEirFN.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-DQjlUwRw.mjs";
3
3
  import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-DV5s-qni.mjs";
4
- import { Jt as validateJupyterKernelName, Yt as validateNotebookPath$1, g as CREDIT_DEDUCT_TRANSACTION_TYPES, i as getEnvironmentName, n as logger, r as getApiUrl, t as ConfigStore, v as ChatModels } from "./ConfigStore-gV8aHo9b.mjs";
5
- import { t as version } from "./package-Dzetdo6D.mjs";
4
+ import { Jt as validateJupyterKernelName, Yt as validateNotebookPath$1, g as CREDIT_DEDUCT_TRANSACTION_TYPES, i as getEnvironmentName, n as logger, r as getApiUrl, t as ConfigStore, v as ChatModels } from "./ConfigStore-7kcIJ-ux.mjs";
5
+ import { t as version } from "./package-DLM23Ze7.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";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  //#region package.json
3
- var version = "0.17.1";
3
+ var version = "0.17.2";
4
4
  //#endregion
5
5
  export { version as t };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { p as verifyTOTPToken } from "./utils-fqhJmuB8.mjs";
3
+ export { verifyTOTPToken };
@@ -13,8 +13,8 @@ process.emitWarning = originalEmitWarning;
13
13
  * Generate TOTP setup data including secret and QR code
14
14
  * Using the same implementation as polaris
15
15
  */
16
- async function generateTOTPSetup(userEmail, appName = "Bike4Mind") {
17
- const secret = speakeasy.generateSecret({ name: `${appName} (${userEmail})` });
16
+ async function generateTOTPSetup(userEmail, appName = process.env.APP_NAME || "") {
17
+ const secret = speakeasy.generateSecret({ name: appName ? `${appName} (${userEmail})` : userEmail });
18
18
  const qrCodeUrl = await QRCode.toDataURL(secret.otpauth_url);
19
19
  return {
20
20
  secret: secret.base32,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.17.1",
3
+ "version": "0.17.2",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -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.1",
111
- "@bike4mind/llm-adapters": "0.5.1",
110
+ "@bike4mind/fab-pipeline": "0.4.2",
111
+ "@bike4mind/llm-adapters": "0.6.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.16.1",
128
- "@bike4mind/common": "2.113.0",
129
- "@bike4mind/mcp": "1.39.1",
130
- "@bike4mind/services": "2.97.1",
131
- "@bike4mind/utils": "2.25.1"
127
+ "@bike4mind/agents": "0.16.2",
128
+ "@bike4mind/common": "2.114.0",
129
+ "@bike4mind/mcp": "1.39.2",
130
+ "@bike4mind/services": "2.98.0",
131
+ "@bike4mind/utils": "2.25.2"
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-PpNti-tY.mjs";
3
- export { verifyTOTPToken };