@bike4mind/cli 0.2.7-feat-cli-tool-lambda-v2.17129 → 0.2.7-feat-organization-overview-enhancements.17130

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 (2) hide show
  1. package/dist/index.js +295 -355
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -8763,338 +8763,6 @@ Last modified: ${stats.mtime.toLocaleString()}`;
8763
8763
  }
8764
8764
  }
8765
8765
 
8766
- // src/utils/Logger.ts
8767
- import fs10 from "fs/promises";
8768
- import path11 from "path";
8769
- import os from "os";
8770
- var Logger2 = class _Logger {
8771
- constructor() {
8772
- this.logFilePath = null;
8773
- this.sessionId = null;
8774
- this.fileLoggingEnabled = true;
8775
- this.consoleVerbose = false;
8776
- }
8777
- static {
8778
- this.instance = null;
8779
- }
8780
- static getInstance() {
8781
- if (!_Logger.instance) {
8782
- _Logger.instance = new _Logger();
8783
- }
8784
- return _Logger.instance;
8785
- }
8786
- /**
8787
- * Initialize the logger with a session ID
8788
- */
8789
- async initialize(sessionId) {
8790
- this.sessionId = sessionId;
8791
- const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
8792
- await fs10.mkdir(debugDir, { recursive: true });
8793
- this.logFilePath = path11.join(debugDir, `${sessionId}.txt`);
8794
- await this.writeToFile("INFO", "=== CLI SESSION START ===");
8795
- }
8796
- /**
8797
- * Set whether verbose console logging is enabled
8798
- */
8799
- setVerbose(enabled) {
8800
- this.consoleVerbose = enabled;
8801
- }
8802
- /**
8803
- * Set whether file logging is enabled
8804
- */
8805
- setFileLoggingEnabled(enabled) {
8806
- this.fileLoggingEnabled = enabled;
8807
- }
8808
- /**
8809
- * DEBUG level - verbose-only console, always file
8810
- */
8811
- debug(message) {
8812
- this.writeToFile("DEBUG", message).catch(() => {
8813
- });
8814
- if (this.consoleVerbose) {
8815
- console.log(message);
8816
- }
8817
- }
8818
- /**
8819
- * INFO level - always shown to user
8820
- */
8821
- info(message) {
8822
- this.writeToFile("INFO", message).catch(() => {
8823
- });
8824
- console.log(message);
8825
- }
8826
- /**
8827
- * WARN level - always shown to user
8828
- */
8829
- warn(message) {
8830
- this.writeToFile("WARN", message).catch(() => {
8831
- });
8832
- console.warn(message);
8833
- }
8834
- /**
8835
- * ERROR level - always shown to user
8836
- */
8837
- error(message, err) {
8838
- this.writeToFile("ERROR", message).catch(() => {
8839
- });
8840
- if (err) {
8841
- this.logErrorDetailsToFile(err).catch(() => {
8842
- });
8843
- }
8844
- console.error(message);
8845
- }
8846
- /**
8847
- * Write log entry to file
8848
- */
8849
- async writeToFile(level, message) {
8850
- if (!this.fileLoggingEnabled || !this.logFilePath) {
8851
- return;
8852
- }
8853
- try {
8854
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
8855
- const logEntry = `[${timestamp}] [${level}] ${message}
8856
- `;
8857
- await fs10.appendFile(this.logFilePath, logEntry, "utf-8");
8858
- } catch (error) {
8859
- console.error("File logging failed:", error);
8860
- }
8861
- }
8862
- /**
8863
- * Log error details to file
8864
- */
8865
- async logErrorDetailsToFile(err) {
8866
- if (!this.fileLoggingEnabled || !this.logFilePath) {
8867
- return;
8868
- }
8869
- try {
8870
- if (err && typeof err === "object" && "response" in err && err.response) {
8871
- const response = err.response;
8872
- const config = err && typeof err === "object" && "config" in err ? err.config : void 0;
8873
- await this.writeToFile("ERROR", ` Status: ${response.status} ${response.statusText || ""}`);
8874
- await this.writeToFile("ERROR", ` URL: ${config?.url || "unknown"}`);
8875
- await this.writeToFile("ERROR", ` Headers: ${this.safeStringify(response.headers)}`);
8876
- if (response.data) {
8877
- const errorText = this.extractErrorMessage(response.data);
8878
- if (errorText.trim().startsWith("<!DOCTYPE") || errorText.trim().startsWith("<html")) {
8879
- await this.writeToFile("ERROR", ` Response Type: HTML Error Page`);
8880
- const parsedError = this.parseHtmlError(errorText);
8881
- if (parsedError) {
8882
- await this.writeToFile("ERROR", ` Error Message: ${parsedError}`);
8883
- }
8884
- await this.writeToFile("ERROR", ` Raw HTML: ${this.truncate(errorText, 1e3)}`);
8885
- } else {
8886
- const preview = this.truncate(errorText, 500);
8887
- await this.writeToFile("ERROR", ` Response: ${preview}`);
8888
- }
8889
- } else {
8890
- await this.writeToFile("ERROR", ` Response: (no data)`);
8891
- }
8892
- }
8893
- if (err && typeof err === "object" && "stack" in err && typeof err.stack === "string") {
8894
- const stackLines = err.stack.split("\n").slice(0, 5).join("\n ");
8895
- await this.writeToFile("ERROR", ` Stack: ${stackLines}`);
8896
- } else if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
8897
- await this.writeToFile("ERROR", ` Message: ${err.message}`);
8898
- }
8899
- } catch (error) {
8900
- }
8901
- }
8902
- /**
8903
- * Safely stringify object, handling circular references
8904
- */
8905
- safeStringify(obj) {
8906
- try {
8907
- return JSON.stringify(obj);
8908
- } catch (error) {
8909
- if (error instanceof Error && error.message.includes("circular")) {
8910
- try {
8911
- const seen = /* @__PURE__ */ new WeakSet();
8912
- return JSON.stringify(obj, (key, value) => {
8913
- if (typeof value === "object" && value !== null) {
8914
- if (seen.has(value)) {
8915
- return "[Circular]";
8916
- }
8917
- seen.add(value);
8918
- }
8919
- return value;
8920
- });
8921
- } catch {
8922
- return "[Unable to stringify]";
8923
- }
8924
- }
8925
- return "[Stringify error]";
8926
- }
8927
- }
8928
- /**
8929
- * Extract readable text from error response data
8930
- */
8931
- extractErrorMessage(data) {
8932
- if (Buffer.isBuffer(data)) {
8933
- return data.toString("utf-8");
8934
- }
8935
- if (typeof data === "string") {
8936
- return data;
8937
- }
8938
- if (data && typeof data === "object" && "_readableState" in data && data._readableState && typeof data._readableState === "object" && "buffer" in data._readableState && Array.isArray(data._readableState.buffer) && data._readableState.buffer.length > 0) {
8939
- const chunks = [];
8940
- for (const chunk of data._readableState.buffer) {
8941
- if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "Buffer" && "data" in chunk && Array.isArray(chunk.data)) {
8942
- chunks.push(Buffer.from(chunk.data));
8943
- } else if (Buffer.isBuffer(chunk)) {
8944
- chunks.push(chunk);
8945
- } else if (chunk && typeof chunk === "object" && "data" in chunk) {
8946
- if (Buffer.isBuffer(chunk.data)) {
8947
- chunks.push(chunk.data);
8948
- } else if (Array.isArray(chunk.data)) {
8949
- chunks.push(Buffer.from(chunk.data));
8950
- }
8951
- }
8952
- }
8953
- if (chunks.length > 0) {
8954
- return Buffer.concat(chunks).toString("utf-8");
8955
- }
8956
- }
8957
- return this.safeStringify(data);
8958
- }
8959
- /**
8960
- * Parse HTML error page to extract error message
8961
- */
8962
- parseHtmlError(html) {
8963
- const titleMatch = html.match(/<title>(.*?)<\/title>/i);
8964
- const h1Match = html.match(/<h1>(.*?)<\/h1>/i);
8965
- const bodyMatch = html.match(/<body[^>]*>(.*?)<\/body>/is);
8966
- if (titleMatch && titleMatch[1] !== "Error") {
8967
- return titleMatch[1].trim();
8968
- }
8969
- if (h1Match) {
8970
- return h1Match[1].trim();
8971
- }
8972
- if (bodyMatch) {
8973
- const text = bodyMatch[1].replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
8974
- return text.substring(0, 200);
8975
- }
8976
- return null;
8977
- }
8978
- /**
8979
- * Truncate string to max length with ellipsis
8980
- */
8981
- truncate(str, maxLength) {
8982
- if (str.length <= maxLength) {
8983
- return str;
8984
- }
8985
- return str.substring(0, maxLength) + "... [truncated]";
8986
- }
8987
- /**
8988
- * Format bytes to human-readable size
8989
- */
8990
- formatBytes(bytes) {
8991
- if (bytes === 0) return "0 B";
8992
- const k = 1024;
8993
- const sizes = ["B", "KB", "MB", "GB"];
8994
- const i = Math.floor(Math.log(bytes) / Math.log(k));
8995
- return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
8996
- }
8997
- /**
8998
- * Clean up old debug logs (older than 30 days)
8999
- */
9000
- async cleanupOldLogs() {
9001
- if (!this.fileLoggingEnabled) return;
9002
- try {
9003
- const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
9004
- const files = await fs10.readdir(debugDir);
9005
- const now = Date.now();
9006
- const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
9007
- for (const file of files) {
9008
- const filePath = path11.join(debugDir, file);
9009
- const stats = await fs10.stat(filePath);
9010
- if (stats.mtime.getTime() < thirtyDaysAgo) {
9011
- await fs10.unlink(filePath);
9012
- }
9013
- }
9014
- } catch (error) {
9015
- console.error("Failed to cleanup old logs:", error);
9016
- }
9017
- }
9018
- };
9019
- var logger = Logger2.getInstance();
9020
-
9021
- // src/llm/ServerToolExecutor.ts
9022
- var ServerToolExecutor = class {
9023
- constructor(apiClient) {
9024
- this.toolsEndpoint = "/api/ai/v1/tools";
9025
- this.apiClient = apiClient;
9026
- }
9027
- /**
9028
- * Execute a tool server-side
9029
- *
9030
- * @param toolName - Name of the tool to execute (e.g., 'weather_info', 'web_search')
9031
- * @param input - Tool input parameters
9032
- * @returns Tool execution result (content or error)
9033
- */
9034
- async executeTool(toolName, input) {
9035
- logger.debug(`[ServerToolExecutor] Executing tool: ${toolName}`);
9036
- logger.debug(`[ServerToolExecutor] Endpoint: ${this.toolsEndpoint}`);
9037
- logger.debug(`[ServerToolExecutor] Input: ${JSON.stringify(input)}`);
9038
- try {
9039
- const result = await this.apiClient.post(this.toolsEndpoint, {
9040
- toolName,
9041
- input
9042
- });
9043
- logger.debug(`[ServerToolExecutor] Response: ${JSON.stringify(result)}`);
9044
- if (!result.success) {
9045
- const errorMessage = result.error || "Tool execution failed";
9046
- logger.error(`[ServerToolExecutor] Tool ${toolName} failed: ${errorMessage}`);
9047
- return `Error executing ${toolName}: ${errorMessage}`;
9048
- }
9049
- logger.debug(`[ServerToolExecutor] Tool ${toolName} succeeded in ${result.executionTimeMs}ms`);
9050
- return result.content || "";
9051
- } catch (error) {
9052
- const err = error;
9053
- const errorMessage = err?.response?.data?.error || err?.message || "Unknown error";
9054
- const status = err?.response?.status || "unknown";
9055
- logger.error(`[ServerToolExecutor] Request failed for ${toolName}: ${errorMessage} (status: ${status})`);
9056
- logger.error(`[ServerToolExecutor] Full error: ${JSON.stringify(err, null, 2)}`);
9057
- return `Error executing ${toolName}: ${errorMessage}`;
9058
- }
9059
- }
9060
- };
9061
-
9062
- // src/llm/ToolRouter.ts
9063
- var SERVER_TOOLS = ["weather_info", "web_search"];
9064
- var LOCAL_TOOLS = [
9065
- "file_read",
9066
- "create_file",
9067
- "glob_files",
9068
- "grep_search",
9069
- "delete_file",
9070
- "edit_file",
9071
- "dice_roll",
9072
- "math_evaluate",
9073
- "current_datetime"
9074
- ];
9075
- function isServerTool(toolName) {
9076
- return SERVER_TOOLS.includes(toolName);
9077
- }
9078
- function isLocalTool(toolName) {
9079
- return LOCAL_TOOLS.includes(toolName);
9080
- }
9081
- async function executeTool(toolName, input, apiClient, localToolFn) {
9082
- if (isServerTool(toolName)) {
9083
- logger.debug(`[ToolRouter] Routing ${toolName} to server`);
9084
- const executor = new ServerToolExecutor(apiClient);
9085
- return await executor.executeTool(toolName, input);
9086
- } else if (isLocalTool(toolName)) {
9087
- logger.debug(`[ToolRouter] Executing ${toolName} locally`);
9088
- if (!localToolFn) {
9089
- throw new Error(`Local tool ${toolName} has no implementation`);
9090
- }
9091
- const result = await localToolFn(input);
9092
- return typeof result === "string" ? result : JSON.stringify(result);
9093
- } else {
9094
- throw new Error(`Unknown tool: ${toolName}`);
9095
- }
9096
- }
9097
-
9098
8766
  // src/utils/toolsAdapter.ts
9099
8767
  var NoOpStorage = class extends BaseStorage {
9100
8768
  async upload(input, destination, options) {
@@ -9134,14 +8802,14 @@ var CliLogger = class extends Logger {
9134
8802
  log(...args) {
9135
8803
  }
9136
8804
  };
9137
- function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient) {
8805
+ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore) {
9138
8806
  const originalFn = tool.toolFn;
9139
8807
  const toolName = tool.toolSchema.name;
9140
8808
  return {
9141
8809
  ...tool,
9142
8810
  toolFn: async (args) => {
9143
8811
  if (!permissionManager.needsPermission(toolName)) {
9144
- const result2 = await executeTool(toolName, args, apiClient, originalFn);
8812
+ const result2 = await originalFn(args);
9145
8813
  agentContext.observationQueue.push({ toolName, result: result2 });
9146
8814
  return result2;
9147
8815
  }
@@ -9198,13 +8866,13 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
9198
8866
  }
9199
8867
  }
9200
8868
  }
9201
- const result = await executeTool(toolName, args, apiClient, originalFn);
8869
+ const result = await originalFn(args);
9202
8870
  agentContext.observationQueue.push({ toolName, result });
9203
8871
  return result;
9204
8872
  }
9205
8873
  };
9206
8874
  }
9207
- function generateCliTools(userId, llm, model, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient) {
8875
+ function generateCliTools(userId, llm, model, permissionManager, showPermissionPrompt, agentContext, configStore, toolApiKeys) {
9208
8876
  const logger2 = new CliLogger();
9209
8877
  const storage = new NoOpStorage();
9210
8878
  const user = {
@@ -9221,6 +8889,18 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9221
8889
  };
9222
8890
  const mockAdminSettings = {
9223
8891
  findBySettingName: async (settingName) => {
8892
+ if (settingName === "OpenWeatherKey") {
8893
+ const key = toolApiKeys?.openweather || process.env.OPENWEATHER_API_KEY;
8894
+ if (key) {
8895
+ return { settingValue: key };
8896
+ }
8897
+ }
8898
+ if (settingName === "SerperKey") {
8899
+ const key = toolApiKeys?.serper || process.env.SERPER_API_KEY;
8900
+ if (key) {
8901
+ return { settingValue: key };
8902
+ }
8903
+ }
9224
8904
  return null;
9225
8905
  }
9226
8906
  };
@@ -9230,22 +8910,27 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9230
8910
  adminSettings: mockAdminSettings
9231
8911
  }
9232
8912
  };
8913
+ const hasSerperKey = !!(toolApiKeys?.serper || process.env.SERPER_API_KEY);
8914
+ const hasOpenWeatherKey = !!(toolApiKeys?.openweather || process.env.OPENWEATHER_API_KEY);
9233
8915
  const toolConfig = {
9234
- // Local-only tools (no external API keys needed)
8916
+ // Enable these tools for CLI (no external API keys needed)
9235
8917
  dice_roll: {},
9236
8918
  math_evaluate: {},
9237
8919
  current_datetime: {},
9238
8920
  prompt_enhancement: {},
9239
- // File operation tools (CLI-specific, local execution)
8921
+ // File operation tools (CLI-specific)
9240
8922
  file_read: {},
9241
8923
  create_file: {},
9242
8924
  glob_files: {},
9243
8925
  grep_search: {},
9244
8926
  delete_file: {},
9245
- // Server-side tools (executed via /api/ai/v1/tools Lambda)
9246
- // Routed by ToolRouter to use B4M company API keys
9247
- weather_info: {},
9248
- web_search: {}
8927
+ // Tools requiring API keys (only include if API key is available)
8928
+ ...hasSerperKey && { web_search: {} },
8929
+ // Requires SERPER_API_KEY
8930
+ ...hasOpenWeatherKey && { weather_info: {} },
8931
+ // Requires OPENWEATHER_API_KEY
8932
+ ...hasSerperKey && { deep_research: {} }
8933
+ // Requires SERPER_API_KEY
9249
8934
  // Disable web-only tools
9250
8935
  // blog_publish: undefined,
9251
8936
  // blog_edit: undefined,
@@ -9255,7 +8940,6 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9255
8940
  // mermaid_chart: undefined,
9256
8941
  // recharts: undefined,
9257
8942
  // edit_file: undefined,
9258
- // deep_research: undefined,
9259
8943
  };
9260
8944
  const toolsMap = generateTools(
9261
8945
  userId,
@@ -9273,7 +8957,7 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9273
8957
  model
9274
8958
  );
9275
8959
  const tools2 = Object.entries(toolsMap).filter(([key]) => toolConfig[key] !== void 0).map(
9276
- ([_, tool]) => wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient)
8960
+ ([_, tool]) => wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore)
9277
8961
  );
9278
8962
  return { tools: tools2, agentContext };
9279
8963
  }
@@ -9468,6 +9152,261 @@ function getEnvironmentName(configApiConfig) {
9468
9152
  return "Bike4Mind";
9469
9153
  }
9470
9154
 
9155
+ // src/utils/Logger.ts
9156
+ import fs10 from "fs/promises";
9157
+ import path11 from "path";
9158
+ import os from "os";
9159
+ var Logger2 = class _Logger {
9160
+ constructor() {
9161
+ this.logFilePath = null;
9162
+ this.sessionId = null;
9163
+ this.fileLoggingEnabled = true;
9164
+ this.consoleVerbose = false;
9165
+ }
9166
+ static {
9167
+ this.instance = null;
9168
+ }
9169
+ static getInstance() {
9170
+ if (!_Logger.instance) {
9171
+ _Logger.instance = new _Logger();
9172
+ }
9173
+ return _Logger.instance;
9174
+ }
9175
+ /**
9176
+ * Initialize the logger with a session ID
9177
+ */
9178
+ async initialize(sessionId) {
9179
+ this.sessionId = sessionId;
9180
+ const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
9181
+ await fs10.mkdir(debugDir, { recursive: true });
9182
+ this.logFilePath = path11.join(debugDir, `${sessionId}.txt`);
9183
+ await this.writeToFile("INFO", "=== CLI SESSION START ===");
9184
+ }
9185
+ /**
9186
+ * Set whether verbose console logging is enabled
9187
+ */
9188
+ setVerbose(enabled) {
9189
+ this.consoleVerbose = enabled;
9190
+ }
9191
+ /**
9192
+ * Set whether file logging is enabled
9193
+ */
9194
+ setFileLoggingEnabled(enabled) {
9195
+ this.fileLoggingEnabled = enabled;
9196
+ }
9197
+ /**
9198
+ * DEBUG level - verbose-only console, always file
9199
+ */
9200
+ debug(message) {
9201
+ this.writeToFile("DEBUG", message).catch(() => {
9202
+ });
9203
+ if (this.consoleVerbose) {
9204
+ console.log(message);
9205
+ }
9206
+ }
9207
+ /**
9208
+ * INFO level - always shown to user
9209
+ */
9210
+ info(message) {
9211
+ this.writeToFile("INFO", message).catch(() => {
9212
+ });
9213
+ console.log(message);
9214
+ }
9215
+ /**
9216
+ * WARN level - always shown to user
9217
+ */
9218
+ warn(message) {
9219
+ this.writeToFile("WARN", message).catch(() => {
9220
+ });
9221
+ console.warn(message);
9222
+ }
9223
+ /**
9224
+ * ERROR level - always shown to user
9225
+ */
9226
+ error(message, err) {
9227
+ this.writeToFile("ERROR", message).catch(() => {
9228
+ });
9229
+ if (err) {
9230
+ this.logErrorDetailsToFile(err).catch(() => {
9231
+ });
9232
+ }
9233
+ console.error(message);
9234
+ }
9235
+ /**
9236
+ * Write log entry to file
9237
+ */
9238
+ async writeToFile(level, message) {
9239
+ if (!this.fileLoggingEnabled || !this.logFilePath) {
9240
+ return;
9241
+ }
9242
+ try {
9243
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
9244
+ const logEntry = `[${timestamp}] [${level}] ${message}
9245
+ `;
9246
+ await fs10.appendFile(this.logFilePath, logEntry, "utf-8");
9247
+ } catch (error) {
9248
+ console.error("File logging failed:", error);
9249
+ }
9250
+ }
9251
+ /**
9252
+ * Log error details to file
9253
+ */
9254
+ async logErrorDetailsToFile(err) {
9255
+ if (!this.fileLoggingEnabled || !this.logFilePath) {
9256
+ return;
9257
+ }
9258
+ try {
9259
+ if (err && typeof err === "object" && "response" in err && err.response) {
9260
+ const response = err.response;
9261
+ const config = err && typeof err === "object" && "config" in err ? err.config : void 0;
9262
+ await this.writeToFile("ERROR", ` Status: ${response.status} ${response.statusText || ""}`);
9263
+ await this.writeToFile("ERROR", ` URL: ${config?.url || "unknown"}`);
9264
+ await this.writeToFile("ERROR", ` Headers: ${this.safeStringify(response.headers)}`);
9265
+ if (response.data) {
9266
+ const errorText = this.extractErrorMessage(response.data);
9267
+ if (errorText.trim().startsWith("<!DOCTYPE") || errorText.trim().startsWith("<html")) {
9268
+ await this.writeToFile("ERROR", ` Response Type: HTML Error Page`);
9269
+ const parsedError = this.parseHtmlError(errorText);
9270
+ if (parsedError) {
9271
+ await this.writeToFile("ERROR", ` Error Message: ${parsedError}`);
9272
+ }
9273
+ await this.writeToFile("ERROR", ` Raw HTML: ${this.truncate(errorText, 1e3)}`);
9274
+ } else {
9275
+ const preview = this.truncate(errorText, 500);
9276
+ await this.writeToFile("ERROR", ` Response: ${preview}`);
9277
+ }
9278
+ } else {
9279
+ await this.writeToFile("ERROR", ` Response: (no data)`);
9280
+ }
9281
+ }
9282
+ if (err && typeof err === "object" && "stack" in err && typeof err.stack === "string") {
9283
+ const stackLines = err.stack.split("\n").slice(0, 5).join("\n ");
9284
+ await this.writeToFile("ERROR", ` Stack: ${stackLines}`);
9285
+ } else if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
9286
+ await this.writeToFile("ERROR", ` Message: ${err.message}`);
9287
+ }
9288
+ } catch (error) {
9289
+ }
9290
+ }
9291
+ /**
9292
+ * Safely stringify object, handling circular references
9293
+ */
9294
+ safeStringify(obj) {
9295
+ try {
9296
+ return JSON.stringify(obj);
9297
+ } catch (error) {
9298
+ if (error instanceof Error && error.message.includes("circular")) {
9299
+ try {
9300
+ const seen = /* @__PURE__ */ new WeakSet();
9301
+ return JSON.stringify(obj, (key, value) => {
9302
+ if (typeof value === "object" && value !== null) {
9303
+ if (seen.has(value)) {
9304
+ return "[Circular]";
9305
+ }
9306
+ seen.add(value);
9307
+ }
9308
+ return value;
9309
+ });
9310
+ } catch {
9311
+ return "[Unable to stringify]";
9312
+ }
9313
+ }
9314
+ return "[Stringify error]";
9315
+ }
9316
+ }
9317
+ /**
9318
+ * Extract readable text from error response data
9319
+ */
9320
+ extractErrorMessage(data) {
9321
+ if (Buffer.isBuffer(data)) {
9322
+ return data.toString("utf-8");
9323
+ }
9324
+ if (typeof data === "string") {
9325
+ return data;
9326
+ }
9327
+ if (data && typeof data === "object" && "_readableState" in data && data._readableState && typeof data._readableState === "object" && "buffer" in data._readableState && Array.isArray(data._readableState.buffer) && data._readableState.buffer.length > 0) {
9328
+ const chunks = [];
9329
+ for (const chunk of data._readableState.buffer) {
9330
+ if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "Buffer" && "data" in chunk && Array.isArray(chunk.data)) {
9331
+ chunks.push(Buffer.from(chunk.data));
9332
+ } else if (Buffer.isBuffer(chunk)) {
9333
+ chunks.push(chunk);
9334
+ } else if (chunk && typeof chunk === "object" && "data" in chunk) {
9335
+ if (Buffer.isBuffer(chunk.data)) {
9336
+ chunks.push(chunk.data);
9337
+ } else if (Array.isArray(chunk.data)) {
9338
+ chunks.push(Buffer.from(chunk.data));
9339
+ }
9340
+ }
9341
+ }
9342
+ if (chunks.length > 0) {
9343
+ return Buffer.concat(chunks).toString("utf-8");
9344
+ }
9345
+ }
9346
+ return this.safeStringify(data);
9347
+ }
9348
+ /**
9349
+ * Parse HTML error page to extract error message
9350
+ */
9351
+ parseHtmlError(html) {
9352
+ const titleMatch = html.match(/<title>(.*?)<\/title>/i);
9353
+ const h1Match = html.match(/<h1>(.*?)<\/h1>/i);
9354
+ const bodyMatch = html.match(/<body[^>]*>(.*?)<\/body>/is);
9355
+ if (titleMatch && titleMatch[1] !== "Error") {
9356
+ return titleMatch[1].trim();
9357
+ }
9358
+ if (h1Match) {
9359
+ return h1Match[1].trim();
9360
+ }
9361
+ if (bodyMatch) {
9362
+ const text = bodyMatch[1].replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
9363
+ return text.substring(0, 200);
9364
+ }
9365
+ return null;
9366
+ }
9367
+ /**
9368
+ * Truncate string to max length with ellipsis
9369
+ */
9370
+ truncate(str, maxLength) {
9371
+ if (str.length <= maxLength) {
9372
+ return str;
9373
+ }
9374
+ return str.substring(0, maxLength) + "... [truncated]";
9375
+ }
9376
+ /**
9377
+ * Format bytes to human-readable size
9378
+ */
9379
+ formatBytes(bytes) {
9380
+ if (bytes === 0) return "0 B";
9381
+ const k = 1024;
9382
+ const sizes = ["B", "KB", "MB", "GB"];
9383
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
9384
+ return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
9385
+ }
9386
+ /**
9387
+ * Clean up old debug logs (older than 30 days)
9388
+ */
9389
+ async cleanupOldLogs() {
9390
+ if (!this.fileLoggingEnabled) return;
9391
+ try {
9392
+ const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
9393
+ const files = await fs10.readdir(debugDir);
9394
+ const now = Date.now();
9395
+ const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
9396
+ for (const file of files) {
9397
+ const filePath = path11.join(debugDir, file);
9398
+ const stats = await fs10.stat(filePath);
9399
+ if (stats.mtime.getTime() < thirtyDaysAgo) {
9400
+ await fs10.unlink(filePath);
9401
+ }
9402
+ }
9403
+ } catch (error) {
9404
+ console.error("Failed to cleanup old logs:", error);
9405
+ }
9406
+ }
9407
+ };
9408
+ var logger = Logger2.getInstance();
9409
+
9471
9410
  // ../../b4m-core/packages/mcp/dist/src/client.js
9472
9411
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
9473
9412
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
@@ -10271,10 +10210,7 @@ var ApiClient = class {
10271
10210
  * Make a POST request
10272
10211
  */
10273
10212
  async post(url, data, config) {
10274
- logger.debug(`[ApiClient] POST ${this.client.defaults.baseURL}${url}`);
10275
- logger.debug(`[ApiClient] Request body: ${JSON.stringify(data)}`);
10276
10213
  const response = await this.client.post(url, data, config);
10277
- logger.debug(`[ApiClient] Response status: ${response.status}`);
10278
10214
  return response.data;
10279
10215
  }
10280
10216
  /**
@@ -10325,7 +10261,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
10325
10261
  // package.json
10326
10262
  var package_default = {
10327
10263
  name: "@bike4mind/cli",
10328
- version: "0.2.7-feat-cli-tool-lambda-v2.17129+8e46f37a5",
10264
+ version: "0.2.7-feat-organization-overview-enhancements.17130+2e676f9be",
10329
10265
  type: "module",
10330
10266
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
10331
10267
  license: "UNLICENSED",
@@ -10428,11 +10364,11 @@ var package_default = {
10428
10364
  },
10429
10365
  devDependencies: {
10430
10366
  "@bike4mind/agents": "0.1.0",
10431
- "@bike4mind/common": "2.38.1-feat-cli-tool-lambda-v2.17129+8e46f37a5",
10432
- "@bike4mind/mcp": "1.20.1-feat-cli-tool-lambda-v2.17129+8e46f37a5",
10433
- "@bike4mind/services": "2.33.1-feat-cli-tool-lambda-v2.17129+8e46f37a5",
10434
- "@bike4mind/utils": "2.1.2-feat-cli-tool-lambda-v2.17129+8e46f37a5",
10435
- "@types/better-sqlite3": "^7.6.12",
10367
+ "@bike4mind/common": "2.38.1-feat-organization-overview-enhancements.17130+2e676f9be",
10368
+ "@bike4mind/mcp": "1.20.1-feat-organization-overview-enhancements.17130+2e676f9be",
10369
+ "@bike4mind/services": "2.33.1-feat-organization-overview-enhancements.17130+2e676f9be",
10370
+ "@bike4mind/utils": "2.1.2-feat-organization-overview-enhancements.17130+2e676f9be",
10371
+ "@types/better-sqlite3": "^7.6.13",
10436
10372
  "@types/diff": "^5.0.9",
10437
10373
  "@types/jsonwebtoken": "^9.0.4",
10438
10374
  "@types/node": "^22.9.0",
@@ -10444,7 +10380,7 @@ var package_default = {
10444
10380
  typescript: "^5.9.3",
10445
10381
  vitest: "^3.2.4"
10446
10382
  },
10447
- gitHead: "8e46f37a5b295f66cc4da97b2134509dc23cd237"
10383
+ gitHead: "2e676f9bedcd3876486314a5bcade6acc1491e3f"
10448
10384
  };
10449
10385
 
10450
10386
  // src/config/constants.ts
@@ -10668,6 +10604,10 @@ function CliApp() {
10668
10604
  setPermissionPrompt(prompt);
10669
10605
  });
10670
10606
  };
10607
+ console.log("\u{1F511} Tool API Keys:", {
10608
+ openweather: config.toolApiKeys?.openweather ? "\u2713 configured" : "\u2717 missing",
10609
+ serper: config.toolApiKeys?.serper ? "\u2713 configured" : "\u2717 missing"
10610
+ });
10671
10611
  const agentContext = {
10672
10612
  currentAgent: null,
10673
10613
  observationQueue: []
@@ -10680,7 +10620,7 @@ function CliApp() {
10680
10620
  promptFn,
10681
10621
  agentContext,
10682
10622
  state.configStore,
10683
- apiClient
10623
+ config.toolApiKeys
10684
10624
  );
10685
10625
  console.log(`\u{1F6E0}\uFE0F Loaded ${b4mTools.length} B4M tool(s)`);
10686
10626
  const mcpManager = new McpManager(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.7-feat-cli-tool-lambda-v2.17129+8e46f37a5",
3
+ "version": "0.2.7-feat-organization-overview-enhancements.17130+2e676f9be",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -103,11 +103,11 @@
103
103
  },
104
104
  "devDependencies": {
105
105
  "@bike4mind/agents": "0.1.0",
106
- "@bike4mind/common": "2.38.1-feat-cli-tool-lambda-v2.17129+8e46f37a5",
107
- "@bike4mind/mcp": "1.20.1-feat-cli-tool-lambda-v2.17129+8e46f37a5",
108
- "@bike4mind/services": "2.33.1-feat-cli-tool-lambda-v2.17129+8e46f37a5",
109
- "@bike4mind/utils": "2.1.2-feat-cli-tool-lambda-v2.17129+8e46f37a5",
110
- "@types/better-sqlite3": "^7.6.12",
106
+ "@bike4mind/common": "2.38.1-feat-organization-overview-enhancements.17130+2e676f9be",
107
+ "@bike4mind/mcp": "1.20.1-feat-organization-overview-enhancements.17130+2e676f9be",
108
+ "@bike4mind/services": "2.33.1-feat-organization-overview-enhancements.17130+2e676f9be",
109
+ "@bike4mind/utils": "2.1.2-feat-organization-overview-enhancements.17130+2e676f9be",
110
+ "@types/better-sqlite3": "^7.6.13",
111
111
  "@types/diff": "^5.0.9",
112
112
  "@types/jsonwebtoken": "^9.0.4",
113
113
  "@types/node": "^22.9.0",
@@ -119,5 +119,5 @@
119
119
  "typescript": "^5.9.3",
120
120
  "vitest": "^3.2.4"
121
121
  },
122
- "gitHead": "8e46f37a5b295f66cc4da97b2134509dc23cd237"
122
+ "gitHead": "2e676f9bedcd3876486314a5bcade6acc1491e3f"
123
123
  }