@bike4mind/cli 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +69 -67
  2. package/dist/index.js +101 -141
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -34,20 +34,6 @@ From the project root:
34
34
  pnpm install
35
35
  ```
36
36
 
37
- ## Development
38
-
39
- ```bash
40
- # Run in development mode
41
- cd apps/cli
42
- pnpm dev
43
-
44
- # Build for production
45
- pnpm build
46
-
47
- # Type check
48
- pnpm typecheck
49
- ```
50
-
51
37
  ## Usage
52
38
 
53
39
  ### Start Interactive Session
@@ -56,79 +42,84 @@ pnpm typecheck
56
42
  b4m
57
43
  ```
58
44
 
59
- ### Quick Query
60
-
61
- ```bash
62
- b4m "What's the weather in San Francisco?"
63
- ```
45
+ The CLI will prompt you to authenticate with your Bike4Mind account on first run.
64
46
 
65
- ### With Options
47
+ ## Commands
66
48
 
67
- ```bash
68
- # Use specific model
69
- b4m --model claude-3-5-haiku-20241022
49
+ While in interactive mode:
70
50
 
71
- # Load saved session
72
- b4m --session my-project
51
+ **Authentication:**
52
+ - `/login` - Authenticate with your B4M account
53
+ - `/logout` - Clear authentication and sign out
54
+ - `/whoami` - Show current authenticated user
73
55
 
74
- # Debug mode
75
- b4m --debug
76
- ```
56
+ **Session Management:**
57
+ - `/save <name>` - Save current session
58
+ - `/sessions` - List saved sessions
77
59
 
78
- ## Commands
60
+ **API Configuration:**
61
+ - `/set-api <url>` - Connect to self-hosted Bike4Mind instance
62
+ - `/reset-api` - Reset to Bike4Mind main service
63
+ - `/api-info` - Show current API configuration
79
64
 
80
- While in interactive mode:
65
+ **Tool Permissions:**
66
+ - `/trust <tool-name>` - Trust a tool (won't ask permission again)
67
+ - `/untrust <tool-name>` - Remove tool from trusted list
68
+ - `/trusted` - List all trusted tools
81
69
 
70
+ **General:**
82
71
  - `/help` - Show help
83
72
  - `/exit` - Exit CLI
84
- - `/save <name>` - Save current session
85
- - `/sessions` - List saved sessions
86
73
  - `/config` - Show configuration
87
- - `/models` - List available models
88
- - `/tools` - List available tools
89
74
 
90
75
  ## Configuration
91
76
 
92
77
  Configuration is stored in `~/.bike4mind/config.json`
93
78
 
94
- ### Required: LLM API Keys
79
+ ### Authentication
95
80
 
96
- Set at least one LLM API key in `~/.bike4mind/config.json`:
81
+ The CLI uses OAuth to authenticate with your Bike4Mind account. On first run, you'll be prompted to log in through the device authorization flow:
97
82
 
98
- ```json
99
- {
100
- "apiKeys": {
101
- "anthropic": "sk-ant-...",
102
- "openai": "sk-..."
103
- },
104
- "defaultModel": "claude-3-5-sonnet-20241022",
105
- "preferences": {
106
- "maxTokens": 4096,
107
- "temperature": 0.7,
108
- "autoSave": true
109
- },
110
- "mcpServers": []
111
- }
83
+ 1. Run `b4m` or use the `/login` command
84
+ 2. Visit the verification URL shown in the terminal
85
+ 3. Enter the user code to authorize the CLI
86
+ 4. The CLI will automatically receive access tokens
87
+
88
+ Authentication tokens are securely stored in your config file with restricted permissions (0600).
89
+
90
+ ### API Configuration
91
+
92
+ By default, the CLI connects to the main Bike4Mind service at `https://app.bike4mind.com`.
93
+
94
+ **For Self-Hosted Instances:**
95
+
96
+ If your organization runs a self-hosted Bike4Mind instance, connect to it using:
97
+
98
+ ```bash
99
+ /set-api https://your-company.bike4mind.com
100
+ ```
101
+
102
+ To return to the main Bike4Mind service:
103
+
104
+ ```bash
105
+ /reset-api
106
+ ```
107
+
108
+ Check your current API configuration:
109
+
110
+ ```bash
111
+ /api-info
112
112
  ```
113
113
 
114
- ### Optional: Tool API Keys
114
+ ### Tool API Keys
115
115
 
116
- Some tools require additional API keys. Add them to your config file:
116
+ Some built-in tools require API keys to function. Add them to `~/.bike4mind/config.json`:
117
117
 
118
118
  ```json
119
119
  {
120
- "apiKeys": {
121
- "anthropic": "sk-ant-..."
122
- },
123
120
  "toolApiKeys": {
124
121
  "openweather": "your-openweather-key",
125
122
  "serper": "your-serper-key"
126
- },
127
- "defaultModel": "claude-3-5-sonnet-20241022",
128
- "preferences": {
129
- "maxTokens": 4096,
130
- "temperature": 0.7,
131
- "autoSave": true
132
123
  }
133
124
  }
134
125
  ```
@@ -140,7 +131,7 @@ export OPENWEATHER_API_KEY="your-key-here"
140
131
  export SERPER_API_KEY="your-key-here"
141
132
  ```
142
133
 
143
- **Available tools**:
134
+ **Available Tools:**
144
135
  - ✅ `dice_roll` - No API key needed
145
136
  - ✅ `math_evaluate` - No API key needed
146
137
  - ✅ `current_datetime` - No API key needed
@@ -149,19 +140,16 @@ export SERPER_API_KEY="your-key-here"
149
140
  - 🔑 `web_search` - Requires `toolApiKeys.serper`
150
141
  - 🔑 `deep_research` - Requires `toolApiKeys.serper`
151
142
 
152
- **Get API keys**:
143
+ **Get API Keys:**
153
144
  - OpenWeather API: https://openweathermap.org/api
154
145
  - Serper API: https://serper.dev/
155
146
 
156
147
  ### Optional: MCP Servers
157
148
 
158
- MCP (Model Context Protocol) servers provide additional tools and capabilities. Configure them in your config file:
149
+ MCP (Model Context Protocol) servers provide additional tools and capabilities. Configure them in `~/.bike4mind/config.json`:
159
150
 
160
151
  ```json
161
152
  {
162
- "apiKeys": {
163
- "anthropic": "sk-ant-..."
164
- },
165
153
  "mcpServers": [
166
154
  {
167
155
  "name": "github",
@@ -193,6 +181,20 @@ Each session includes:
193
181
  - Agent reasoning steps
194
182
  - Metadata
195
183
 
184
+ ## Development
185
+
186
+ ```bash
187
+ # Run in development mode
188
+ cd apps/cli
189
+ pnpm dev
190
+
191
+ # Build for production
192
+ pnpm build
193
+
194
+ # Type check
195
+ pnpm typecheck
196
+ ```
197
+
196
198
  ## Architecture
197
199
 
198
200
  ```
package/dist/index.js CHANGED
@@ -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)",
@@ -744,8 +757,6 @@ var AuthTokensSchema = z.object({
744
757
  userId: z.string()
745
758
  });
746
759
  var ApiConfigSchema = z.object({
747
- environment: z.enum(["production", "staging", "preview", "local", "custom"]),
748
- previewStage: z.string().optional(),
749
760
  customUrl: z.string().url().optional()
750
761
  });
751
762
  var CliConfigSchema = z.object({
@@ -842,6 +853,15 @@ var ConfigStore = class {
842
853
  }
843
854
  const data = await fs2.readFile(this.configPath, "utf-8");
844
855
  const rawConfig = JSON.parse(data);
856
+ if (rawConfig.apiConfig && "environment" in rawConfig.apiConfig) {
857
+ const oldApiConfig = rawConfig.apiConfig;
858
+ if (oldApiConfig.environment === "custom" && oldApiConfig.customUrl) {
859
+ rawConfig.apiConfig = { customUrl: oldApiConfig.customUrl };
860
+ } else {
861
+ rawConfig.apiConfig = {};
862
+ }
863
+ console.log("[ConfigStore] Auto-migrated API config from old environment format");
864
+ }
845
865
  const validated = CliConfigSchema.parse(rawConfig);
846
866
  this.config = {
847
867
  ...DEFAULT_CONFIG,
@@ -1047,23 +1067,16 @@ var ConfigStore = class {
1047
1067
  return config.apiConfig;
1048
1068
  }
1049
1069
  /**
1050
- * Set API environment
1051
- */
1052
- async setApiEnvironment(environment, options) {
1053
- 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)
1070
+ * Set custom API URL for self-hosted Bike4Mind instance
1071
+ * Pass null to reset to Bike4Mind main service
1063
1072
  */
1064
- async clearApiConfig() {
1073
+ async setCustomApiUrl(url) {
1065
1074
  const config = await this.load();
1066
- config.apiConfig = void 0;
1075
+ if (url === null) {
1076
+ config.apiConfig = void 0;
1077
+ } else {
1078
+ config.apiConfig = { customUrl: url };
1079
+ }
1067
1080
  await this.save(config);
1068
1081
  }
1069
1082
  };
@@ -6424,60 +6437,18 @@ var PermissionManager = class {
6424
6437
  };
6425
6438
 
6426
6439
  // src/utils/apiUrl.ts
6427
- function getApiUrl(configApiConfig, envVarUrl, cliFlagUrl) {
6428
- if (cliFlagUrl) {
6429
- return cliFlagUrl;
6430
- }
6431
- if (envVarUrl) {
6432
- return envVarUrl;
6433
- }
6434
- if (configApiConfig) {
6435
- return resolveEnvironmentUrl(configApiConfig);
6436
- }
6437
- return "https://app.bike4mind.com";
6438
- }
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";
6440
+ var BIKE4MIND_URL = "https://app.bike4mind.com";
6441
+ function getApiUrl(configApiConfig) {
6442
+ if (configApiConfig?.customUrl) {
6443
+ return configApiConfig.customUrl;
6455
6444
  }
6445
+ return BIKE4MIND_URL;
6456
6446
  }
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";
6447
+ function getEnvironmentName(configApiConfig) {
6448
+ if (configApiConfig?.customUrl) {
6449
+ return "Self-Hosted";
6480
6450
  }
6451
+ return "Bike4Mind";
6481
6452
  }
6482
6453
 
6483
6454
  // ../../b4m-core/packages/mcp/dist/src/client.js
@@ -7133,10 +7104,10 @@ function CliApp() {
7133
7104
  setIsInitialized(true);
7134
7105
  return;
7135
7106
  }
7136
- const apiBaseURL = getApiUrl(config.apiConfig, process.env.B4M_API_URL);
7137
- const envName = getEnvironmentName(config.apiConfig, process.env.B4M_API_URL);
7107
+ const apiBaseURL = getApiUrl(config.apiConfig);
7108
+ const envName = getEnvironmentName(config.apiConfig);
7138
7109
  const isDevMode2 = import.meta.url.includes("/src/") || process.env.NODE_ENV === "development";
7139
- if (isDevMode2 || envName !== "production") {
7110
+ if (isDevMode2 || envName !== "Bike4Mind") {
7140
7111
  console.log(`\u{1F30D} API Environment: ${envName} (${apiBaseURL})`);
7141
7112
  }
7142
7113
  const apiClient = new ApiClient(apiBaseURL, state.configStore);
@@ -7372,8 +7343,13 @@ Available commands:
7372
7343
  /save <name> - Save current session
7373
7344
  /sessions - List saved sessions
7374
7345
  /config - Show configuration
7375
- /config show-env - Show current API environment
7376
- /config set-env <env> - Set API environment (production|staging|preview|local|custom)
7346
+
7347
+ API Configuration:
7348
+ /set-api <url> - Connect to self-hosted Bike4Mind instance
7349
+ /reset-api - Reset to Bike4Mind main service
7350
+ /api-info - Show current API configuration
7351
+
7352
+ Tool Permissions:
7377
7353
  /trust <tool-name> - Trust a tool (won't ask permission again)
7378
7354
  /untrust <tool-name> - Remove tool from trusted list
7379
7355
  /trusted - List all trusted tools
@@ -7405,77 +7381,61 @@ Available commands:
7405
7381
  console.log("");
7406
7382
  break;
7407
7383
  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
- }
7384
+ const config = await state.configStore.get();
7385
+ console.log("\n\u2699\uFE0F Configuration:\n");
7386
+ console.log(`Default Model: ${config.defaultModel}`);
7387
+ console.log(`Max Tokens: ${config.preferences.maxTokens}`);
7388
+ console.log(`Temperature: ${config.preferences.temperature}`);
7389
+ const apiUrl = getApiUrl(config.apiConfig);
7390
+ const apiType = getEnvironmentName(config.apiConfig);
7391
+ console.log(`API: ${apiType} (${apiUrl})`);
7392
+ console.log("");
7393
+ console.log("Related commands:");
7394
+ console.log(" /api-info - Show detailed API configuration");
7395
+ console.log(" /set-api - Connect to self-hosted instance");
7396
+ console.log(" /reset-api - Reset to Bike4Mind main service");
7397
+ console.log("");
7398
+ break;
7399
+ }
7400
+ case "set-api": {
7401
+ const url = args[0];
7402
+ if (!url) {
7403
+ console.log("Usage: /set-api <url>");
7462
7404
  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})`);
7405
+ console.log("Connect to a self-hosted Bike4Mind instance.");
7473
7406
  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");
7407
+ console.log("Example:");
7408
+ console.log(" /set-api https://bike4mind.mycompany.com");
7477
7409
  console.log("");
7410
+ return;
7411
+ }
7412
+ try {
7413
+ new URL(url);
7414
+ } catch {
7415
+ console.log(`
7416
+ \u274C Invalid URL: ${url}`);
7417
+ console.log("Please provide a valid HTTPS URL (e.g., https://bike4mind.mycompany.com)\n");
7418
+ return;
7478
7419
  }
7420
+ await state.configStore.setCustomApiUrl(url);
7421
+ console.log(`
7422
+ \u2705 Connected to self-hosted instance: ${url}`);
7423
+ console.log("Please restart the CLI for changes to take effect.\n");
7424
+ break;
7425
+ }
7426
+ case "reset-api":
7427
+ await state.configStore.setCustomApiUrl(null);
7428
+ console.log("\n\u2705 Reset to Bike4Mind main service");
7429
+ console.log("Please restart the CLI for changes to take effect.\n");
7430
+ break;
7431
+ case "api-info": {
7432
+ const config = await state.configStore.get();
7433
+ const apiUrl = getApiUrl(config.apiConfig);
7434
+ const apiType = getEnvironmentName(config.apiConfig);
7435
+ console.log("\n\u{1F30D} API Configuration:\n");
7436
+ console.log(`Type: ${apiType}`);
7437
+ console.log(`URL: ${apiUrl}`);
7438
+ console.log("");
7479
7439
  break;
7480
7440
  }
7481
7441
  case "trust":
@@ -7553,7 +7513,7 @@ Available commands:
7553
7513
  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
7514
  }
7555
7515
  if (state.showLoginFlow) {
7556
- const loginApiUrl = getApiUrl(state.config?.apiConfig, process.env.B4M_API_URL);
7516
+ const loginApiUrl = getApiUrl(state.config?.apiConfig);
7557
7517
  return /* @__PURE__ */ React10.createElement(
7558
7518
  LoginFlow,
7559
7519
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",