@bike4mind/cli 0.1.2 → 0.1.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.
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getEffectiveApiKey,
5
5
  getOpenWeatherKey,
6
6
  getSerperKey
7
- } from "./chunk-XANFVWI6.js";
8
- import "./chunk-TPSQ5MIR.js";
9
- import "./chunk-KZGZGNHL.js";
7
+ } from "./chunk-43ZKBRTE.js";
8
+ import "./chunk-FNZZAMET.js";
9
+ import "./chunk-ZT7Z4QVD.js";
10
10
  import {
11
11
  BFLImageService,
12
12
  BaseStorage,
@@ -15,7 +15,7 @@ import {
15
15
  OpenAIBackend,
16
16
  OpenAIImageService,
17
17
  XAIImageService
18
- } from "./chunk-B3YFSFVU.js";
18
+ } from "./chunk-EVPT4ARN.js";
19
19
  import {
20
20
  Logger
21
21
  } from "./chunk-CC67R4RB.js";
@@ -72,7 +72,7 @@ import {
72
72
  XAI_IMAGE_MODELS,
73
73
  b4mLLMTools,
74
74
  getMcpProviderMetadata
75
- } from "./chunk-MKO2KCCS.js";
75
+ } from "./chunk-VVV7WLJ6.js";
76
76
  import {
77
77
  __require
78
78
  } from "./chunk-PDX44BCA.js";
@@ -151,6 +151,19 @@ var COMMANDS = [
151
151
  name: "config",
152
152
  description: "Show configuration"
153
153
  },
154
+ {
155
+ name: "set-api",
156
+ description: "Connect to self-hosted Bike4Mind instance",
157
+ args: "<url>"
158
+ },
159
+ {
160
+ name: "reset-api",
161
+ description: "Reset to Bike4Mind main service"
162
+ },
163
+ {
164
+ name: "api-info",
165
+ description: "Show current API configuration"
166
+ },
154
167
  {
155
168
  name: "trust",
156
169
  description: "Trust a tool (won't ask permission again)",
@@ -194,6 +207,7 @@ function InputPrompt({ onSubmit, disabled = false, history = [] }) {
194
207
  const [selectedIndex, setSelectedIndex] = useState(0);
195
208
  const [historyIndex, setHistoryIndex] = useState(-1);
196
209
  const [tempInput, setTempInput] = useState("");
210
+ const [inputKey, setInputKey] = useState(0);
197
211
  const shouldShowAutocomplete = value.startsWith("/") && !disabled;
198
212
  const query = shouldShowAutocomplete ? value.slice(1) : "";
199
213
  const filteredCommands = useMemo(() => {
@@ -240,6 +254,12 @@ function InputPrompt({ onSubmit, disabled = false, history = [] }) {
240
254
  if (shouldShowAutocomplete && filteredCommands.length > 0) {
241
255
  const selectedCommand = filteredCommands[selectedIndex];
242
256
  const commandText = `/${selectedCommand.name}`;
257
+ if (selectedCommand.args) {
258
+ setValue(commandText + " ");
259
+ setHistoryIndex(-1);
260
+ setInputKey((prev) => prev + 1);
261
+ return;
262
+ }
243
263
  setValue("");
244
264
  setHistoryIndex(-1);
245
265
  onSubmit(commandText);
@@ -259,6 +279,7 @@ function InputPrompt({ onSubmit, disabled = false, history = [] }) {
259
279
  return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React3.createElement(
260
280
  TextInput,
261
281
  {
282
+ key: inputKey,
262
283
  value,
263
284
  onChange: handleChange,
264
285
  onSubmit: handleSubmit,
@@ -450,6 +471,7 @@ import React9, { useState as useState2, useEffect as useEffect2 } from "react";
450
471
  import { Box as Box9, Text as Text8 } from "ink";
451
472
  import Spinner2 from "ink-spinner";
452
473
  import jwt from "jsonwebtoken";
474
+ import open from "open";
453
475
 
454
476
  // src/auth/OAuthClient.ts
455
477
  import axios from "axios";
@@ -601,6 +623,13 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
601
623
  };
602
624
  runLoginFlow();
603
625
  }, [apiUrl, configStore, onSuccess, onError]);
626
+ useEffect2(() => {
627
+ if (deviceFlow && status === "waiting") {
628
+ open(deviceFlow.verification_uri_complete).catch((err) => {
629
+ console.error("Failed to auto-open browser:", err);
630
+ });
631
+ }
632
+ }, [deviceFlow, status]);
604
633
  if (status === "initiating") {
605
634
  return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text8, { color: "cyan" }, /* @__PURE__ */ React9.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
606
635
  }
@@ -610,7 +639,7 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
610
639
  if (status === "success") {
611
640
  return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "You can now use B4M CLI with your account.")));
612
641
  }
613
- return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, null, "Please visit the following URL to authorize this device:")), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, null, "Enter this code when prompted:")), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "cyan" }, /* @__PURE__ */ React9.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
642
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, null, "And enter this code when prompted:")), /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "cyan" }, /* @__PURE__ */ React9.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
614
643
  }
615
644
 
616
645
  // src/storage/SessionStore.ts
@@ -744,8 +773,6 @@ var AuthTokensSchema = z.object({
744
773
  userId: z.string()
745
774
  });
746
775
  var ApiConfigSchema = z.object({
747
- environment: z.enum(["production", "staging", "preview", "local", "custom"]),
748
- previewStage: z.string().optional(),
749
776
  customUrl: z.string().url().optional()
750
777
  });
751
778
  var CliConfigSchema = z.object({
@@ -842,6 +869,14 @@ var ConfigStore = class {
842
869
  }
843
870
  const data = await fs2.readFile(this.configPath, "utf-8");
844
871
  const rawConfig = JSON.parse(data);
872
+ if (rawConfig.apiConfig && "environment" in rawConfig.apiConfig) {
873
+ const oldApiConfig = rawConfig.apiConfig;
874
+ if (oldApiConfig.environment === "custom" && oldApiConfig.customUrl) {
875
+ rawConfig.apiConfig = { customUrl: oldApiConfig.customUrl };
876
+ } else {
877
+ rawConfig.apiConfig = {};
878
+ }
879
+ }
845
880
  const validated = CliConfigSchema.parse(rawConfig);
846
881
  this.config = {
847
882
  ...DEFAULT_CONFIG,
@@ -862,10 +897,6 @@ var ConfigStore = class {
862
897
  },
863
898
  trustedTools: validated.trustedTools || []
864
899
  };
865
- console.log("[ConfigStore] Loaded config with auth:", !!this.config.auth);
866
- if (this.config.auth) {
867
- console.log("[ConfigStore] Auth userId:", this.config.auth.userId);
868
- }
869
900
  return this.config;
870
901
  } catch (error) {
871
902
  if (error.code === "ENOENT") {
@@ -909,13 +940,8 @@ var ConfigStore = class {
909
940
  throw new Error("No configuration to save");
910
941
  }
911
942
  try {
912
- console.log("[ConfigStore] Saving config with auth:", !!this.config.auth);
913
- if (this.config.auth) {
914
- console.log("[ConfigStore] Auth userId:", this.config.auth.userId);
915
- }
916
943
  await fs2.writeFile(this.configPath, JSON.stringify(this.config, null, 2), "utf-8");
917
944
  await fs2.chmod(this.configPath, 384);
918
- console.log("[ConfigStore] Config saved to:", this.configPath);
919
945
  } catch (error) {
920
946
  console.error("Failed to save config:", error);
921
947
  throw error;
@@ -1047,23 +1073,16 @@ var ConfigStore = class {
1047
1073
  return config.apiConfig;
1048
1074
  }
1049
1075
  /**
1050
- * Set API environment
1076
+ * Set custom API URL for self-hosted Bike4Mind instance
1077
+ * Pass null to reset to Bike4Mind main service
1051
1078
  */
1052
- async setApiEnvironment(environment, options) {
1079
+ async setCustomApiUrl(url) {
1053
1080
  const config = await this.load();
1054
- config.apiConfig = {
1055
- environment,
1056
- previewStage: options?.previewStage,
1057
- customUrl: options?.customUrl
1058
- };
1059
- await this.save(config);
1060
- }
1061
- /**
1062
- * Clear API configuration (revert to default production)
1063
- */
1064
- async clearApiConfig() {
1065
- const config = await this.load();
1066
- config.apiConfig = void 0;
1081
+ if (url === null) {
1082
+ config.apiConfig = void 0;
1083
+ } else {
1084
+ config.apiConfig = { customUrl: url };
1085
+ }
1067
1086
  await this.save(config);
1068
1087
  }
1069
1088
  };
@@ -6424,60 +6443,18 @@ var PermissionManager = class {
6424
6443
  };
6425
6444
 
6426
6445
  // src/utils/apiUrl.ts
6427
- function getApiUrl(configApiConfig, envVarUrl, cliFlagUrl) {
6428
- if (cliFlagUrl) {
6429
- return cliFlagUrl;
6446
+ var BIKE4MIND_URL = "https://app.bike4mind.com";
6447
+ function getApiUrl(configApiConfig) {
6448
+ if (configApiConfig?.customUrl) {
6449
+ return configApiConfig.customUrl;
6430
6450
  }
6431
- if (envVarUrl) {
6432
- return envVarUrl;
6433
- }
6434
- if (configApiConfig) {
6435
- return resolveEnvironmentUrl(configApiConfig);
6436
- }
6437
- return "https://app.bike4mind.com";
6451
+ return BIKE4MIND_URL;
6438
6452
  }
6439
- function resolveEnvironmentUrl(apiConfig) {
6440
- switch (apiConfig.environment) {
6441
- case "production":
6442
- return "https://app.bike4mind.com";
6443
- case "staging":
6444
- return "https://app.staging.bike4mind.com";
6445
- case "preview": {
6446
- const stage = apiConfig.previewStage || "dev";
6447
- return `https://app.${stage}.preview.bike4mind.com`;
6448
- }
6449
- case "local":
6450
- return "http://localhost:3000";
6451
- case "custom":
6452
- return apiConfig.customUrl || "http://localhost:3000";
6453
- default:
6454
- return "https://app.bike4mind.com";
6455
- }
6456
- }
6457
- function getEnvironmentName(configApiConfig, envVarUrl, cliFlagUrl) {
6458
- if (cliFlagUrl) {
6459
- return `custom (${cliFlagUrl})`;
6460
- }
6461
- if (envVarUrl) {
6462
- return `env var (${envVarUrl})`;
6463
- }
6464
- if (!configApiConfig) {
6465
- return "production";
6466
- }
6467
- switch (configApiConfig.environment) {
6468
- case "production":
6469
- return "production";
6470
- case "staging":
6471
- return "staging";
6472
- case "preview":
6473
- return `preview (${configApiConfig.previewStage || "dev"})`;
6474
- case "local":
6475
- return "local";
6476
- case "custom":
6477
- return `custom (${configApiConfig.customUrl || "localhost:3000"})`;
6478
- default:
6479
- return "production";
6453
+ function getEnvironmentName(configApiConfig) {
6454
+ if (configApiConfig?.customUrl) {
6455
+ return "Self-Hosted";
6480
6456
  }
6457
+ return "Bike4Mind";
6481
6458
  }
6482
6459
 
6483
6460
  // ../../b4m-core/packages/mcp/dist/src/client.js
@@ -6723,7 +6700,7 @@ function stripThinkingBlocks(text) {
6723
6700
  }
6724
6701
  var ServerLlmBackend = class {
6725
6702
  constructor(options) {
6726
- this.completionsEndpoint = "/api/cli/completions";
6703
+ this.completionsEndpoint = "/api/ai/v1/completions";
6727
6704
  this.apiClient = options.apiClient;
6728
6705
  this.currentModel = options.model;
6729
6706
  }
@@ -6830,8 +6807,8 @@ var ServerLlmBackend = class {
6830
6807
  });
6831
6808
  } catch (error) {
6832
6809
  if (error instanceof Error) {
6833
- if (error.message.includes("Authentication expired")) {
6834
- reject(new Error("Authentication expired. Please run `b4m login` again."));
6810
+ if (error.message.includes("Authentication expired") || error.message.includes("Authentication failed")) {
6811
+ reject(error);
6835
6812
  } else if (error.message.includes("ECONNREFUSED")) {
6836
6813
  reject(new Error("Cannot connect to Bike4Mind server. Please check your internet connection."));
6837
6814
  } else if (error.message.includes("Rate limit exceeded")) {
@@ -6933,7 +6910,6 @@ var ApiClient = class {
6933
6910
  if (!tokens) {
6934
6911
  throw new Error("Not authenticated");
6935
6912
  }
6936
- console.log("\u{1F504} Access token expired, refreshing...");
6937
6913
  const newTokens = await this.oauthClient.refreshToken(tokens.refreshToken);
6938
6914
  const expiresAt = new Date(Date.now() + newTokens.expires_in * 1e3).toISOString();
6939
6915
  await this.configStore.setAuthTokens({
@@ -6943,7 +6919,6 @@ var ApiClient = class {
6943
6919
  userId: tokens.userId
6944
6920
  // Preserve userId
6945
6921
  });
6946
- console.log("\u2705 Token refreshed successfully");
6947
6922
  originalRequest.headers.Authorization = `Bearer ${newTokens.access_token}`;
6948
6923
  return this.client(originalRequest);
6949
6924
  } catch (refreshError) {
@@ -6956,6 +6931,10 @@ var ApiClient = class {
6956
6931
  throw new Error("Authentication expired. Please run `b4m login` again.");
6957
6932
  }
6958
6933
  }
6934
+ if (error.response?.status === 401 && originalRequest._retry) {
6935
+ await this.configStore.clearAuthTokens();
6936
+ throw new Error("Authentication failed. Please run /login to authenticate.");
6937
+ }
6959
6938
  return Promise.reject(error);
6960
6939
  }
6961
6940
  );
@@ -7133,10 +7112,10 @@ function CliApp() {
7133
7112
  setIsInitialized(true);
7134
7113
  return;
7135
7114
  }
7136
- const apiBaseURL = getApiUrl(config.apiConfig, process.env.B4M_API_URL);
7137
- const envName = getEnvironmentName(config.apiConfig, process.env.B4M_API_URL);
7115
+ const apiBaseURL = getApiUrl(config.apiConfig);
7116
+ const envName = getEnvironmentName(config.apiConfig);
7138
7117
  const isDevMode2 = import.meta.url.includes("/src/") || process.env.NODE_ENV === "development";
7139
- if (isDevMode2 || envName !== "production") {
7118
+ if (isDevMode2 || envName !== "Bike4Mind") {
7140
7119
  console.log(`\u{1F30D} API Environment: ${envName} (${apiBaseURL})`);
7141
7120
  }
7142
7121
  const apiClient = new ApiClient(apiBaseURL, state.configStore);
@@ -7356,6 +7335,13 @@ Remember: Use context from previous messages to understand follow-up questions.`
7356
7335
  setStoreSession(updatedSession);
7357
7336
  await state.sessionStore.save(updatedSession);
7358
7337
  } catch (error) {
7338
+ if (error instanceof Error) {
7339
+ if (error.message.includes("Authentication failed") || error.message.includes("Authentication expired")) {
7340
+ console.log("\n\u274C Authentication failed");
7341
+ console.log("\u{1F4A1} Run /login to authenticate with your API environment.\n");
7342
+ return;
7343
+ }
7344
+ }
7359
7345
  console.error("Error processing message:", error);
7360
7346
  }
7361
7347
  };
@@ -7372,8 +7358,13 @@ Available commands:
7372
7358
  /save <name> - Save current session
7373
7359
  /sessions - List saved sessions
7374
7360
  /config - Show configuration
7375
- /config show-env - Show current API environment
7376
- /config set-env <env> - Set API environment (production|staging|preview|local|custom)
7361
+
7362
+ API Configuration:
7363
+ /set-api <url> - Connect to self-hosted Bike4Mind instance
7364
+ /reset-api - Reset to Bike4Mind main service
7365
+ /api-info - Show current API configuration
7366
+
7367
+ Tool Permissions:
7377
7368
  /trust <tool-name> - Trust a tool (won't ask permission again)
7378
7369
  /untrust <tool-name> - Remove tool from trusted list
7379
7370
  /trusted - List all trusted tools
@@ -7405,77 +7396,67 @@ Available commands:
7405
7396
  console.log("");
7406
7397
  break;
7407
7398
  case "config": {
7408
- const subcommand = args[0];
7409
- if (subcommand === "set-env") {
7410
- const environment = args[1];
7411
- if (!environment) {
7412
- console.log("Usage: /config set-env <production|staging|preview|local|custom> [options]");
7413
- console.log(" /config set-env production");
7414
- console.log(" /config set-env staging");
7415
- console.log(" /config set-env preview --stage my-feature");
7416
- console.log(" /config set-env local");
7417
- console.log(" /config set-env custom --url https://custom.api.com");
7418
- return;
7419
- }
7420
- const validEnvironments = ["production", "staging", "preview", "local", "custom"];
7421
- if (!validEnvironments.includes(environment)) {
7422
- console.log(`Invalid environment: ${environment}`);
7423
- console.log("Valid environments: production, staging, preview, local, custom");
7424
- return;
7425
- }
7426
- const stageIndex = args.indexOf("--stage");
7427
- const urlIndex = args.indexOf("--url");
7428
- const previewStage = stageIndex !== -1 ? args[stageIndex + 1] : void 0;
7429
- const customUrl = urlIndex !== -1 ? args[urlIndex + 1] : void 0;
7430
- if (environment === "preview" && !previewStage) {
7431
- console.log("Preview environment requires --stage option");
7432
- console.log("Usage: /config set-env preview --stage my-feature");
7433
- return;
7434
- }
7435
- if (environment === "custom" && !customUrl) {
7436
- console.log("Custom environment requires --url option");
7437
- console.log("Usage: /config set-env custom --url https://custom.api.com");
7438
- return;
7439
- }
7440
- await state.configStore.setApiEnvironment(environment, {
7441
- previewStage,
7442
- customUrl
7443
- });
7444
- console.log(`
7445
- \u2705 API environment set to: ${environment}`);
7446
- if (previewStage) console.log(` Stage: ${previewStage}`);
7447
- if (customUrl) console.log(` URL: ${customUrl}`);
7448
- console.log("");
7449
- } else if (subcommand === "show-env") {
7450
- const config = await state.configStore.get();
7451
- const envVarUrl = process.env.B4M_API_URL;
7452
- const apiUrl = getApiUrl(config.apiConfig, envVarUrl);
7453
- const envName = getEnvironmentName(config.apiConfig, envVarUrl);
7454
- console.log("\n\u{1F30D} API Environment:\n");
7455
- console.log(`Environment: ${envName}`);
7456
- console.log(`URL: ${apiUrl}`);
7457
- if (envVarUrl) {
7458
- console.log(`
7459
- \u26A0\uFE0F B4M_API_URL environment variable is set: ${envVarUrl}`);
7460
- console.log(" This will override the config file setting.");
7461
- }
7399
+ const config = await state.configStore.get();
7400
+ console.log("\n\u2699\uFE0F Configuration:\n");
7401
+ console.log(`Default Model: ${config.defaultModel}`);
7402
+ console.log(`Max Tokens: ${config.preferences.maxTokens}`);
7403
+ console.log(`Temperature: ${config.preferences.temperature}`);
7404
+ const apiUrl = getApiUrl(config.apiConfig);
7405
+ const apiType = getEnvironmentName(config.apiConfig);
7406
+ console.log(`API: ${apiType} (${apiUrl})`);
7407
+ console.log("");
7408
+ console.log("Related commands:");
7409
+ console.log(" /api-info - Show detailed API configuration");
7410
+ console.log(" /set-api - Connect to self-hosted instance");
7411
+ console.log(" /reset-api - Reset to Bike4Mind main service");
7412
+ console.log("");
7413
+ break;
7414
+ }
7415
+ case "set-api": {
7416
+ const url = args[0];
7417
+ if (!url) {
7418
+ console.log("Usage: /set-api <url>");
7462
7419
  console.log("");
7463
- } else {
7464
- const config = await state.configStore.get();
7465
- console.log("\n\u2699\uFE0F Configuration:\n");
7466
- console.log(`Default Model: ${config.defaultModel}`);
7467
- console.log(`Max Tokens: ${config.preferences.maxTokens}`);
7468
- console.log(`Temperature: ${config.preferences.temperature}`);
7469
- const envVarUrl = process.env.B4M_API_URL;
7470
- const apiUrl = getApiUrl(config.apiConfig, envVarUrl);
7471
- const envName = getEnvironmentName(config.apiConfig, envVarUrl);
7472
- console.log(`API Environment: ${envName} (${apiUrl})`);
7420
+ console.log("Connect to a self-hosted Bike4Mind instance.");
7473
7421
  console.log("");
7474
- console.log("Subcommands:");
7475
- console.log(" /config show-env - Show current API environment");
7476
- console.log(" /config set-env <env> - Set API environment");
7422
+ console.log("Example:");
7423
+ console.log(" /set-api https://bike4mind.mycompany.com");
7477
7424
  console.log("");
7425
+ return;
7426
+ }
7427
+ try {
7428
+ new URL(url);
7429
+ } catch {
7430
+ console.log(`
7431
+ \u274C Invalid URL: ${url}`);
7432
+ console.log("Please provide a valid HTTPS URL (e.g., https://bike4mind.mycompany.com)\n");
7433
+ return;
7478
7434
  }
7435
+ await state.configStore.setCustomApiUrl(url);
7436
+ await state.configStore.clearAuthTokens();
7437
+ console.log(`
7438
+ \u2705 API URL updated: ${url}`);
7439
+ console.log("\u{1F513} Authentication cleared");
7440
+ console.log(`\u{1F4A1} Run /login to authenticate with ${url}`);
7441
+ console.log("Please restart the CLI for changes to take effect.\n");
7442
+ break;
7443
+ }
7444
+ case "reset-api":
7445
+ await state.configStore.setCustomApiUrl(null);
7446
+ await state.configStore.clearAuthTokens();
7447
+ console.log("\n\u2705 API URL reset to Bike4Mind main service");
7448
+ console.log("\u{1F513} Authentication cleared");
7449
+ console.log("\u{1F4A1} Run /login to authenticate");
7450
+ console.log("Please restart the CLI for changes to take effect.\n");
7451
+ break;
7452
+ case "api-info": {
7453
+ const config = await state.configStore.get();
7454
+ const apiUrl = getApiUrl(config.apiConfig);
7455
+ const apiType = getEnvironmentName(config.apiConfig);
7456
+ console.log("\n\u{1F30D} API Configuration:\n");
7457
+ console.log(`Type: ${apiType}`);
7458
+ console.log(`URL: ${apiUrl}`);
7459
+ console.log("");
7479
7460
  break;
7480
7461
  }
7481
7462
  case "trust":
@@ -7553,7 +7534,7 @@ Available commands:
7553
7534
  return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React10.createElement(Text9, null, initError), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
7554
7535
  }
7555
7536
  if (state.showLoginFlow) {
7556
- const loginApiUrl = getApiUrl(state.config?.apiConfig, process.env.B4M_API_URL);
7537
+ const loginApiUrl = getApiUrl(state.config?.apiConfig);
7557
7538
  return /* @__PURE__ */ React10.createElement(
7558
7539
  LoginFlow,
7559
7540
  {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-MKO2KCCS.js";
4
+ } from "./chunk-VVV7WLJ6.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/llmMarkdownGenerator.js
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-MKO2KCCS.js";
4
+ } from "./chunk-VVV7WLJ6.js";
5
5
  import "./chunk-PDX44BCA.js";
6
6
 
7
7
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/markdownGenerator.js
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-XANFVWI6.js";
6
- import "./chunk-B3YFSFVU.js";
5
+ } from "./chunk-43ZKBRTE.js";
6
+ import "./chunk-EVPT4ARN.js";
7
7
  import "./chunk-CC67R4RB.js";
8
- import "./chunk-MKO2KCCS.js";
8
+ import "./chunk-VVV7WLJ6.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  findMostSimilarMemento,
@@ -291,7 +291,7 @@ import {
291
291
  validateQuestMasterArtifactV2,
292
292
  validateReactArtifactV2,
293
293
  validateSvgArtifactV2
294
- } from "./chunk-MKO2KCCS.js";
294
+ } from "./chunk-VVV7WLJ6.js";
295
295
  import "./chunk-PDX44BCA.js";
296
296
  export {
297
297
  ALL_IMAGE_MODELS,
@@ -117,7 +117,7 @@ import {
117
117
  validateMermaidSyntax,
118
118
  warmUpSettingsCache,
119
119
  withRetry
120
- } from "./chunk-B3YFSFVU.js";
120
+ } from "./chunk-EVPT4ARN.js";
121
121
  import {
122
122
  Logger,
123
123
  NotificationDeduplicator,
@@ -126,7 +126,7 @@ import {
126
126
  postLowCreditsNotificationToSlack,
127
127
  postMessageToSlack
128
128
  } from "./chunk-CC67R4RB.js";
129
- import "./chunk-MKO2KCCS.js";
129
+ import "./chunk-VVV7WLJ6.js";
130
130
  import "./chunk-PDX44BCA.js";
131
131
  export {
132
132
  AWSBackend,
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-TPSQ5MIR.js";
6
- import "./chunk-B3YFSFVU.js";
5
+ } from "./chunk-FNZZAMET.js";
6
+ import "./chunk-EVPT4ARN.js";
7
7
  import "./chunk-CC67R4RB.js";
8
- import "./chunk-MKO2KCCS.js";
8
+ import "./chunk-VVV7WLJ6.js";
9
9
  import "./chunk-PDX44BCA.js";
10
10
  export {
11
11
  SubtractCreditsSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -76,6 +76,7 @@
76
76
  "mime-types": "^2.1.35",
77
77
  "mongoose": "^8.8.3",
78
78
  "ollama": "^0.5.12",
79
+ "open": "^11.0.0",
79
80
  "openai": "^5.12.2",
80
81
  "p-limit": "^6.2.0",
81
82
  "qrcode": "^1.5.4",