@bike4mind/cli 0.2.72-feat-tavern-leveling-system.22139 → 0.2.72-feat-parallel-tool-execution.22214

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.
@@ -67,7 +67,7 @@ let ImageModels = /* @__PURE__ */ function(ImageModels) {
67
67
  ImageModels["FLUX_DEV"] = "flux-dev";
68
68
  ImageModels["FLUX_KONTEXT_PRO"] = "flux-kontext-pro";
69
69
  ImageModels["FLUX_KONTEXT_MAX"] = "flux-kontext-max";
70
- ImageModels["GROK_2_IMAGE"] = "grok-2-image-1212";
70
+ ImageModels["GROK_2_IMAGE"] = "grok-2-image";
71
71
  ImageModels["GEMINI_2_5_FLASH_IMAGE"] = "gemini-2.5-flash-image";
72
72
  ImageModels["GEMINI_3_PRO_IMAGE_PREVIEW"] = "gemini-3-pro-image-preview";
73
73
  return ImageModels;
@@ -1005,6 +1005,7 @@ const SecopsTriageConfigSchema = z.object({
1005
1005
  high: "P1"
1006
1006
  }),
1007
1007
  maxIssuesPerScan: z.number().min(1).max(100).default(20),
1008
+ slackWorkspaceId: z.string().optional(),
1008
1009
  slackChannelId: z.string().optional(),
1009
1010
  dryRun: z.boolean().default(false)
1010
1011
  });
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as version, n as fetchLatestVersion, r as forceCheckForUpdate } from "../updateChecker-CuZI7FU7.mjs";
2
+ import { i as version, n as fetchLatestVersion, r as forceCheckForUpdate } from "../updateChecker-C30s9nuB.mjs";
3
3
  import { execSync } from "child_process";
4
4
  import { constants, existsSync, promises } from "fs";
5
5
  import { homedir } from "os";
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { B as CustomCommandStore, C as getApiUrl, E as generateCliTools, I as buildCoreSystemPrompt, P as setWebSocketToolExecutor, R as isReadOnlyTool, S as loadContextFiles, T as PermissionManager, U as SessionStore, V as CheckpointStore, _ as ServerLlmBackend, a as createBackgroundAgentTools, c as AgentStore, f as ApiClient, g as WebSocketLlmBackend, h as FallbackLlmBackend, i as createWriteTodosTool, l as SubagentOrchestrator, m as WebSocketConnectionManager, n as createFindDefinitionTool, o as BackgroundAgentManager, p as WebSocketToolExecutor, r as createTodoStore, s as createAgentDelegateTool, t as createGetFileStructureTool, u as createSkillTool, v as McpManager, z as ReActAgent } from "../tools-DFy4F6t7.mjs";
3
- import { n as logger, t as ConfigStore } from "../ConfigStore-BPX3nHEn.mjs";
2
+ import { B as CustomCommandStore, C as getApiUrl, E as generateCliTools, I as buildCoreSystemPrompt, P as setWebSocketToolExecutor, R as isReadOnlyTool, S as loadContextFiles, T as PermissionManager, U as SessionStore, V as CheckpointStore, _ as ServerLlmBackend, a as createBackgroundAgentTools, c as AgentStore, f as ApiClient, g as WebSocketLlmBackend, h as FallbackLlmBackend, i as createWriteTodosTool, l as SubagentOrchestrator, m as WebSocketConnectionManager, n as createFindDefinitionTool, o as BackgroundAgentManager, p as WebSocketToolExecutor, r as createTodoStore, s as createAgentDelegateTool, t as createGetFileStructureTool, u as createSkillTool, v as McpManager, z as ReActAgent } from "../tools-7hRqnVPL.mjs";
3
+ import { n as logger, t as ConfigStore } from "../ConfigStore-Chtdkz1u.mjs";
4
4
  import { t as DEFAULT_SANDBOX_CONFIG } from "../types-DBEjF9YS.mjs";
5
5
  import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-C1B4t20N.mjs";
6
6
  import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BEW3rqYi.mjs";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as ConfigStore } from "../ConfigStore-BPX3nHEn.mjs";
2
+ import { t as ConfigStore } from "../ConfigStore-Chtdkz1u.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 { i as version, r as forceCheckForUpdate } from "../updateChecker-CuZI7FU7.mjs";
2
+ import { i as version, r as forceCheckForUpdate } from "../updateChecker-C30s9nuB.mjs";
3
3
  import { execSync } from "child_process";
4
4
  //#region src/commands/updateCommand.ts
5
5
  /**
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-Dw1nZX2Y.mjs";
3
- import { A as DEFAULT_RETRY_CONFIG, B as CustomCommandStore, C as getApiUrl, D as ALWAYS_DENIED_FOR_AGENTS, E as generateCliTools, F as OllamaBackend, G as hasFileReferences, H as CommandHistoryStore, I as buildCoreSystemPrompt, J as mergeCommands, K as processFileReferences, L as buildSkillsPromptSection, M as clearFeatureModuleTools, N as registerFeatureModuleTools, O as DEFAULT_AGENT_MODEL, P as setWebSocketToolExecutor, R as isReadOnlyTool, S as loadContextFiles, T as PermissionManager, U as SessionStore, V as CheckpointStore, W as OAuthClient, X as searchFiles, Y as formatFileSize, Z as warmFileCache, _ as ServerLlmBackend, a as createBackgroundAgentTools, b as formatStep, c as AgentStore, d as parseAgentConfig, f as ApiClient, g as WebSocketLlmBackend, h as FallbackLlmBackend, i as createWriteTodosTool, j as DEFAULT_THOROUGHNESS, k as DEFAULT_MAX_ITERATIONS, l as SubagentOrchestrator, m as WebSocketConnectionManager, n as createFindDefinitionTool, o as BackgroundAgentManager, p as WebSocketToolExecutor, q as searchCommands, r as createTodoStore, s as createAgentDelegateTool, t as createGetFileStructureTool, u as createSkillTool, v as McpManager, w as getEnvironmentName, x as extractCompactInstructions, y as substituteArguments, z as ReActAgent } from "./tools-DFy4F6t7.mjs";
4
- import { Dt as validateNotebookPath$1, Et as validateJupyterKernelName, g as ChatModels, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-BPX3nHEn.mjs";
5
- import { i as version, t as checkForUpdate } from "./updateChecker-CuZI7FU7.mjs";
3
+ import { A as DEFAULT_RETRY_CONFIG, B as CustomCommandStore, C as getApiUrl, D as ALWAYS_DENIED_FOR_AGENTS, E as generateCliTools, F as OllamaBackend, G as hasFileReferences, H as CommandHistoryStore, I as buildCoreSystemPrompt, J as mergeCommands, K as processFileReferences, L as buildSkillsPromptSection, M as clearFeatureModuleTools, N as registerFeatureModuleTools, O as DEFAULT_AGENT_MODEL, P as setWebSocketToolExecutor, R as isReadOnlyTool, S as loadContextFiles, T as PermissionManager, U as SessionStore, V as CheckpointStore, W as OAuthClient, X as searchFiles, Y as formatFileSize, Z as warmFileCache, _ as ServerLlmBackend, a as createBackgroundAgentTools, b as formatStep, c as AgentStore, d as parseAgentConfig, f as ApiClient, g as WebSocketLlmBackend, h as FallbackLlmBackend, i as createWriteTodosTool, j as DEFAULT_THOROUGHNESS, k as DEFAULT_MAX_ITERATIONS, l as SubagentOrchestrator, m as WebSocketConnectionManager, n as createFindDefinitionTool, o as BackgroundAgentManager, p as WebSocketToolExecutor, q as searchCommands, r as createTodoStore, s as createAgentDelegateTool, t as createGetFileStructureTool, u as createSkillTool, v as McpManager, w as getEnvironmentName, x as extractCompactInstructions, y as substituteArguments, z as ReActAgent } from "./tools-7hRqnVPL.mjs";
4
+ import { Dt as validateNotebookPath$1, Et as validateJupyterKernelName, g as ChatModels, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-Chtdkz1u.mjs";
5
+ import { i as version, t as checkForUpdate } from "./updateChecker-C30s9nuB.mjs";
6
6
  import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
7
7
  import { Box, Static, Text, render, useApp, useInput } from "ink";
8
8
  import { execSync } from "child_process";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as RegInviteEvents, A as ImageGenerationUsageTransaction, B as OpenAIEmbeddingModel, C as FileEvents, Ct as isGPTImageModel, D as GenericCreditAddTransaction, E as GenerateImageToolCallSchema, F as KnowledgeType, G as ProjectEvents, H as Permission, I as LLMEvents, J as QuestMasterParamsSchema, K as PromptMetaZodSchema, L as MiscEvents, M as InboxEvents, N as InviteEvents, O as GenericCreditDeductTransaction, Ot as CollectionType, P as InviteType, Q as RechartsChartTypeList, R as ModalEvents, S as FeedbackEvents, St as getViewById, T as GEMINI_IMAGE_MODELS, Tt as sanitizeTelemetryError, U as PermissionDeniedError, V as OpenAIImageGenerationInput, W as ProfileEvents, X as RealtimeVoiceUsageTransaction, Y as REASONING_SUPPORTED_MODELS, Z as ReceivedCreditTransaction, _ as CompletionApiUsageTransaction, _t as VoyageAIEmbeddingModel, a as ApiKeyEvents, at as SpeechToTextModels, b as FIXED_TEMPERATURE_MODELS, bt as getDataLakeTags, c as AppFileEvents, ct as TagType, d as BFL_IMAGE_MODELS, dt as ToolUsageTransaction, et as ResearchModeParamsSchema, f as BFL_SAFETY_TOLERANCE, ft as TransferCreditTransaction, g as ChatModels, gt as VideoModels, h as ChatCompletionCreateInputSchema, ht as VideoGenerationUsageTransaction, i as AiEvents, it as SessionEvents, j as ImageModels, k as ImageEditUsageTransaction, l as ArtifactTypeSchema, lt as TaskScheduleHandler, mt as VIDEO_SIZE_CONSTRAINTS, n as logger, nt as ResearchTaskPeriodicFrequencyType, o as ApiKeyScope, ot as SubscriptionCreditTransaction, p as BedrockEmbeddingModel, pt as UiNavigationEvents, q as PurchaseTransaction, r as ALERT_THRESHOLDS, rt as ResearchTaskType, s as ApiKeyType, st as SupportedFabFileMimeTypes, t as ConfigStore, tt as ResearchTaskExecutionType, u as AuthEvents, ut as TextGenerationUsageTransaction, v as DashboardParamsSchema, vt as XAI_IMAGE_MODELS, w as FriendshipEvents, wt as resolveNavigationIntents, x as FavoriteDocumentType, xt as getMcpProviderMetadata, y as ElabsEvents, yt as b4mLLMTools, z as ModelBackend } from "./ConfigStore-BPX3nHEn.mjs";
2
+ import { $ as RegInviteEvents, A as ImageGenerationUsageTransaction, B as OpenAIEmbeddingModel, C as FileEvents, Ct as isGPTImageModel, D as GenericCreditAddTransaction, E as GenerateImageToolCallSchema, F as KnowledgeType, G as ProjectEvents, H as Permission, I as LLMEvents, J as QuestMasterParamsSchema, K as PromptMetaZodSchema, L as MiscEvents, M as InboxEvents, N as InviteEvents, O as GenericCreditDeductTransaction, Ot as CollectionType, P as InviteType, Q as RechartsChartTypeList, R as ModalEvents, S as FeedbackEvents, St as getViewById, T as GEMINI_IMAGE_MODELS, Tt as sanitizeTelemetryError, U as PermissionDeniedError, V as OpenAIImageGenerationInput, W as ProfileEvents, X as RealtimeVoiceUsageTransaction, Y as REASONING_SUPPORTED_MODELS, Z as ReceivedCreditTransaction, _ as CompletionApiUsageTransaction, _t as VoyageAIEmbeddingModel, a as ApiKeyEvents, at as SpeechToTextModels, b as FIXED_TEMPERATURE_MODELS, bt as getDataLakeTags, c as AppFileEvents, ct as TagType, d as BFL_IMAGE_MODELS, dt as ToolUsageTransaction, et as ResearchModeParamsSchema, f as BFL_SAFETY_TOLERANCE, ft as TransferCreditTransaction, g as ChatModels, gt as VideoModels, h as ChatCompletionCreateInputSchema, ht as VideoGenerationUsageTransaction, i as AiEvents, it as SessionEvents, j as ImageModels, k as ImageEditUsageTransaction, l as ArtifactTypeSchema, lt as TaskScheduleHandler, mt as VIDEO_SIZE_CONSTRAINTS, n as logger, nt as ResearchTaskPeriodicFrequencyType, o as ApiKeyScope, ot as SubscriptionCreditTransaction, p as BedrockEmbeddingModel, pt as UiNavigationEvents, q as PurchaseTransaction, r as ALERT_THRESHOLDS, rt as ResearchTaskType, s as ApiKeyType, st as SupportedFabFileMimeTypes, t as ConfigStore, tt as ResearchTaskExecutionType, u as AuthEvents, ut as TextGenerationUsageTransaction, v as DashboardParamsSchema, vt as XAI_IMAGE_MODELS, w as FriendshipEvents, wt as resolveNavigationIntents, x as FavoriteDocumentType, xt as getMcpProviderMetadata, y as ElabsEvents, yt as b4mLLMTools, z as ModelBackend } from "./ConfigStore-Chtdkz1u.mjs";
3
3
  import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-CIytuhr3-Dt5dntLx.mjs";
4
4
  import { execFile, execFileSync, spawn } from "child_process";
5
5
  import { createHash, randomBytes } from "crypto";
@@ -4359,69 +4359,129 @@ var OpenAIBackend = class {
4359
4359
  id: toolCall.id
4360
4360
  });
4361
4361
  }
4362
- if (options.executeTools !== false) for (const toolCall of c.message.tool_calls) {
4363
- if (toolCall.type !== "function") continue;
4364
- const toolFn = options.tools?.find((tool) => tool.toolSchema.name === toolCall.function.name)?.toolFn;
4365
- if (toolFn && toolCall.function.arguments) {
4366
- this.logger.debug("Using tool:", toolCall.function.name);
4367
- this.logger.debug("Tool arguments:", toolCall.function.arguments);
4362
+ if (options.executeTools !== false) {
4363
+ const resolvedTools = [];
4364
+ for (const toolCall of c.message.tool_calls) {
4365
+ if (toolCall.type !== "function" || !toolCall.function.arguments) continue;
4366
+ const toolDef = options.tools?.find((t) => t.toolSchema.name === toolCall.function.name);
4367
+ const toolFn = toolDef?.toolFn;
4368
+ if (!toolFn) continue;
4368
4369
  try {
4369
- const result = await toolFn(JSON.parse(toolCall.function.arguments));
4370
- this.logger.debug(`[Tool Result] Tool executed for ${toolCall.function.name}:`, result.toString().substring(0, 200) + "...");
4371
- let artifactWasStreamed = false;
4372
- await handleToolResultStreaming(toolCall.function.name, result, async (results) => {
4373
- artifactWasStreamed = true;
4374
- await callback(results, {
4375
- inputTokens: 0,
4376
- outputTokens: 0,
4377
- toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0
4378
- });
4379
- });
4380
- const resultStr = result.toString();
4381
- const sanitizedResult = artifactWasStreamed ? resultStr.replace(/<artifact(?:\s[^>]*)?>[\s\S]*?<\/artifact>/gi, "[Artifact rendered and delivered to user]") : resultStr;
4382
- this.pushToolMessages(messages, {
4370
+ const parsedParams = JSON.parse(toolCall.function.arguments);
4371
+ resolvedTools.push({
4383
4372
  id: toolCall.id,
4384
4373
  name: toolCall.function.name,
4385
- parameters: toolCall.function.arguments
4386
- }, sanitizedResult);
4387
- const isMcpTool = options.tools?.find((t) => t.toolSchema.name === toolCall.function.name)?._isMcpTool;
4388
- let recursiveBuffer = "";
4389
- let recursiveMeta = {
4390
- inputTokens: 0,
4391
- outputTokens: 0
4374
+ parameters: toolCall.function.arguments,
4375
+ parsedParams,
4376
+ toolFn,
4377
+ isMcpTool: toolDef?._isMcpTool ?? false
4378
+ });
4379
+ } catch {
4380
+ console.error(`JSON parse error for ${toolCall.function.name} arguments`);
4381
+ }
4382
+ }
4383
+ const parallelEnabled = options.parallelToolExecution !== false;
4384
+ let outcomes;
4385
+ if (parallelEnabled && resolvedTools.length > 1) {
4386
+ this.logger.debug("[Tool Execution] Executing tools in parallel (OpenAI non-streaming)", { toolNames: resolvedTools.map((t) => t.name) });
4387
+ outcomes = (await Promise.allSettled(resolvedTools.map(async ({ id, name, parameters, parsedParams, toolFn, isMcpTool }) => {
4388
+ this.logger.debug("Using tool (parallel):", name);
4389
+ return {
4390
+ ok: true,
4391
+ id,
4392
+ name,
4393
+ parameters,
4394
+ isMcpTool,
4395
+ result: await toolFn(parsedParams)
4392
4396
  };
4393
- const recursiveCallback = artifactWasStreamed ? async (results, meta) => {
4394
- for (const r of results) if (r != null) recursiveBuffer += r;
4395
- if (meta.inputTokens || meta.outputTokens) recursiveMeta = { ...meta };
4396
- } : callback;
4397
- if (isMcpTool) await this.complete(model, messages, {
4398
- ...options,
4399
- _internal: {
4400
- ...options._internal,
4401
- toolCallCount: toolCallCount + 1
4402
- }
4403
- }, recursiveCallback, toolsUsed);
4404
- else await this.complete(model, messages, {
4405
- ...options,
4406
- tools: void 0,
4407
- _internal: {
4408
- ...options._internal,
4409
- toolCallCount: toolCallCount + 1
4410
- }
4411
- }, recursiveCallback, toolsUsed);
4412
- if (artifactWasStreamed && recursiveBuffer) {
4413
- const cleaned = recursiveBuffer.replace(/<artifact(?:\s[^>]*)?>[\s\S]*?<\/artifact>/gi, "").trim();
4414
- if (cleaned) await callback([cleaned], recursiveMeta);
4397
+ }))).map((s, i) => s.status === "fulfilled" ? s.value : {
4398
+ ok: false,
4399
+ id: resolvedTools[i].id,
4400
+ name: resolvedTools[i].name,
4401
+ parameters: resolvedTools[i].parameters,
4402
+ error: s.reason
4403
+ });
4404
+ } else {
4405
+ outcomes = [];
4406
+ for (const { id, name, parameters, parsedParams, toolFn, isMcpTool } of resolvedTools) {
4407
+ this.logger.debug("Using tool:", name);
4408
+ this.logger.debug("Tool arguments:", parameters);
4409
+ try {
4410
+ const result = await toolFn(parsedParams);
4411
+ outcomes.push({
4412
+ ok: true,
4413
+ id,
4414
+ name,
4415
+ parameters,
4416
+ isMcpTool,
4417
+ result
4418
+ });
4419
+ } catch (error) {
4420
+ if (error instanceof PermissionDeniedError) throw error;
4421
+ console.error(`Error processing ${name} tool:`, error);
4422
+ outcomes.push({
4423
+ ok: false,
4424
+ id,
4425
+ name,
4426
+ parameters,
4427
+ error
4428
+ });
4415
4429
  }
4416
- return;
4417
- } catch (error) {
4418
- if (error instanceof PermissionDeniedError) throw error;
4419
- console.error(`Error processing ${toolCall.function.name} tool:`, error);
4420
- streamedText[c.index] = `Error processing ${toolCall.function.name} tool: ${error instanceof Error ? error.message : "Unknown error"}`;
4421
4430
  }
4422
4431
  }
4423
- }
4424
- else {
4432
+ let anyArtifactWasStreamed = false;
4433
+ const anyMcpTool = resolvedTools.some((t) => t.isMcpTool);
4434
+ for (const outcome of outcomes) {
4435
+ if (!outcome.ok) {
4436
+ if (outcome.error instanceof PermissionDeniedError) throw outcome.error;
4437
+ streamedText[c.index] = `Error processing ${outcome.name} tool: ${outcome.error instanceof Error ? outcome.error.message : "Unknown error"}`;
4438
+ this.pushToolMessages(messages, {
4439
+ id: outcome.id,
4440
+ name: outcome.name,
4441
+ parameters: outcome.parameters
4442
+ }, `Error processing ${outcome.name} tool: ${outcome.error instanceof Error ? outcome.error.message : "Unknown error"}`);
4443
+ continue;
4444
+ }
4445
+ const resultStr = outcome.result.toString();
4446
+ this.logger.debug(`[Tool Result] Tool executed for ${outcome.name}:`, resultStr.substring(0, 200) + "...");
4447
+ await handleToolResultStreaming(outcome.name, outcome.result, async (results) => {
4448
+ anyArtifactWasStreamed = true;
4449
+ await callback(results, {
4450
+ inputTokens: 0,
4451
+ outputTokens: 0,
4452
+ toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0
4453
+ });
4454
+ });
4455
+ const sanitizedResult = anyArtifactWasStreamed ? resultStr.replace(/<artifact(?:\s[^>]*)?>[\s\S]*?<\/artifact>/gi, "[Artifact rendered and delivered to user]") : resultStr;
4456
+ this.pushToolMessages(messages, {
4457
+ id: outcome.id,
4458
+ name: outcome.name,
4459
+ parameters: outcome.parameters
4460
+ }, sanitizedResult);
4461
+ }
4462
+ let recursiveBuffer = "";
4463
+ let recursiveMeta = {
4464
+ inputTokens: 0,
4465
+ outputTokens: 0
4466
+ };
4467
+ const recursiveCallback = anyArtifactWasStreamed ? async (results, meta) => {
4468
+ for (const r of results) if (r != null) recursiveBuffer += r;
4469
+ if (meta.inputTokens || meta.outputTokens) recursiveMeta = { ...meta };
4470
+ } : callback;
4471
+ await this.complete(model, messages, {
4472
+ ...options,
4473
+ tools: anyMcpTool ? options.tools : void 0,
4474
+ _internal: {
4475
+ ...options._internal,
4476
+ toolCallCount: toolCallCount + 1
4477
+ }
4478
+ }, recursiveCallback, toolsUsed);
4479
+ if (anyArtifactWasStreamed && recursiveBuffer) {
4480
+ const cleaned = recursiveBuffer.replace(/<artifact(?:\s[^>]*)?>[\s\S]*?<\/artifact>/gi, "").trim();
4481
+ if (cleaned) await callback([cleaned], recursiveMeta);
4482
+ }
4483
+ return;
4484
+ } else {
4425
4485
  this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback`);
4426
4486
  await callback([null], {
4427
4487
  inputTokens: response.usage?.prompt_tokens || 0,
@@ -4514,42 +4574,109 @@ var OpenAIBackend = class {
4514
4574
  id: tool.id
4515
4575
  });
4516
4576
  if (options.executeTools !== false) {
4517
- let anyArtifactWasStreamed = false;
4518
- for await (const tool of func) {
4577
+ const resolvedTools = [];
4578
+ for (const tool of func) {
4519
4579
  const { id, name } = tool;
4580
+ if (!id || !name) continue;
4520
4581
  const parameters = tool.parameters || "{}";
4521
- const toolFn = options.tools?.find((tool) => tool.toolSchema.name === name)?.toolFn;
4522
- if (id && name && toolFn) try {
4523
- this.logger.debug("Using tool:", name);
4524
- this.logger.debug("Tool arguments:", parameters);
4525
- const result = await toolFn(JSON.parse(parameters));
4526
- this.logger.debug(`[Tool Result] Tool executed for ${name}:`, result.toString().substring(0, 200) + "...");
4527
- await handleToolResultStreaming(name, result, async (results) => {
4528
- anyArtifactWasStreamed = true;
4529
- await callback(results, {
4530
- inputTokens,
4531
- outputTokens,
4532
- toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0,
4533
- cacheStats
4534
- });
4535
- });
4536
- const resultStr = result.toString();
4537
- const sanitizedResult = anyArtifactWasStreamed ? resultStr.replace(/<artifact(?:\s[^>]*)?>[\s\S]*?<\/artifact>/gi, "[Artifact rendered and delivered to user]") : resultStr;
4538
- this.pushToolMessages(messages, {
4582
+ const toolFn = options.tools?.find((t) => t.toolSchema.name === name)?.toolFn;
4583
+ if (!toolFn) continue;
4584
+ try {
4585
+ const parsedParams = JSON.parse(parameters);
4586
+ resolvedTools.push({
4539
4587
  id,
4540
4588
  name,
4541
- parameters
4542
- }, sanitizedResult);
4543
- } catch (error) {
4544
- if (error instanceof PermissionDeniedError) throw error;
4545
- this.logger.updateMetadata({
4546
- tool: name,
4589
+ parameters,
4590
+ parsedParams,
4591
+ toolFn
4592
+ });
4593
+ } catch {
4594
+ this.logger.warn("JSON parse error for tool parameters (skipping):", {
4595
+ name,
4547
4596
  parameters
4548
4597
  });
4549
- if (error instanceof SyntaxError && /JSON/.test(error.message)) this.logger.warn("JSON parse error processing tool parameters:", error);
4550
- else this.logger.error("Error processing tool:", error);
4598
+ }
4599
+ }
4600
+ const parallelEnabled = options.parallelToolExecution !== false;
4601
+ let outcomes;
4602
+ if (parallelEnabled && resolvedTools.length > 1) {
4603
+ this.logger.debug("[Tool Execution] Executing tools in parallel (OpenAI streaming)", { toolNames: resolvedTools.map((t) => t.name) });
4604
+ outcomes = (await Promise.allSettled(resolvedTools.map(async ({ id, name, parameters, parsedParams, toolFn }) => {
4605
+ this.logger.debug("Using tool (parallel):", name);
4606
+ return {
4607
+ ok: true,
4608
+ id,
4609
+ name,
4610
+ parameters,
4611
+ result: await toolFn(parsedParams)
4612
+ };
4613
+ }))).map((s, i) => s.status === "fulfilled" ? s.value : {
4614
+ ok: false,
4615
+ id: resolvedTools[i].id,
4616
+ name: resolvedTools[i].name,
4617
+ parameters: resolvedTools[i].parameters,
4618
+ error: s.reason
4619
+ });
4620
+ } else {
4621
+ outcomes = [];
4622
+ for (const { id, name, parameters, parsedParams, toolFn } of resolvedTools) {
4623
+ this.logger.debug("Using tool:", name);
4624
+ this.logger.debug("Tool arguments:", parameters);
4625
+ try {
4626
+ const result = await toolFn(parsedParams);
4627
+ outcomes.push({
4628
+ ok: true,
4629
+ id,
4630
+ name,
4631
+ parameters,
4632
+ result
4633
+ });
4634
+ } catch (error) {
4635
+ if (error instanceof PermissionDeniedError) throw error;
4636
+ this.logger.updateMetadata({
4637
+ tool: name,
4638
+ parameters
4639
+ });
4640
+ if (error instanceof SyntaxError && /JSON/.test(error.message)) this.logger.warn("JSON parse error processing tool parameters:", error);
4641
+ else this.logger.error("Error processing tool:", error);
4642
+ outcomes.push({
4643
+ ok: false,
4644
+ id,
4645
+ name,
4646
+ parameters,
4647
+ error
4648
+ });
4649
+ }
4650
+ }
4651
+ }
4652
+ let anyArtifactWasStreamed = false;
4653
+ for (const outcome of outcomes) {
4654
+ if (!outcome.ok) {
4655
+ if (outcome.error instanceof PermissionDeniedError) throw outcome.error;
4656
+ this.pushToolMessages(messages, {
4657
+ id: outcome.id,
4658
+ name: outcome.name,
4659
+ parameters: outcome.parameters
4660
+ }, `Error processing ${outcome.name} tool: ${outcome.error instanceof Error ? outcome.error.message : "Unknown error"}`);
4551
4661
  continue;
4552
4662
  }
4663
+ const resultStr = outcome.result.toString();
4664
+ this.logger.debug(`[Tool Result] Tool executed for ${outcome.name}:`, resultStr.substring(0, 200) + "...");
4665
+ await handleToolResultStreaming(outcome.name, outcome.result, async (results) => {
4666
+ anyArtifactWasStreamed = true;
4667
+ await callback(results, {
4668
+ inputTokens,
4669
+ outputTokens,
4670
+ toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0,
4671
+ cacheStats
4672
+ });
4673
+ });
4674
+ const sanitizedResult = anyArtifactWasStreamed ? resultStr.replace(/<artifact(?:\s[^>]*)?>[\s\S]*?<\/artifact>/gi, "[Artifact rendered and delivered to user]") : resultStr;
4675
+ this.pushToolMessages(messages, {
4676
+ id: outcome.id,
4677
+ name: outcome.name,
4678
+ parameters: outcome.parameters
4679
+ }, sanitizedResult);
4553
4680
  }
4554
4681
  if (anyArtifactWasStreamed) {
4555
4682
  let recursiveBuffer = "";
@@ -5604,7 +5731,7 @@ var XAIImageService = class extends AIImageService {
5604
5731
  } catch (error) {
5605
5732
  Logger.error("XAI image generation failed:", error);
5606
5733
  if (error instanceof Error) {
5607
- if (error.message.includes("model") && !error.message.includes("unavailable")) throw new Error(`XAI image generation failed: Invalid model. Only 'grok-2-image' is supported for image generation. Original error: ${error.message}`);
5734
+ if (error.message.includes("model") && !error.message.includes("unavailable")) throw new Error(`XAI image generation failed: Invalid model. Only '${ImageModels.GROK_2_IMAGE}' is supported for image generation. Original error: ${error.message}`);
5608
5735
  if (error.message.includes("unauthorized") || error.message.includes("api_key")) throw new Error(`XAI image generation failed: Invalid API key or unauthorized access. Please check your XAI API key. Original error: ${error.message}`);
5609
5736
  if (error.message.includes("rate_limit")) throw new Error(`XAI image generation failed: Rate limit exceeded. Please try again later. Original error: ${error.message}`);
5610
5737
  throw new Error(`XAI image generation failed: ${error.message}`);
@@ -4,7 +4,7 @@ import { homedir } from "os";
4
4
  import path from "path";
5
5
  import axios from "axios";
6
6
  //#region package.json
7
- var version = "0.2.72-feat-tavern-leveling-system.22139+d90502009";
7
+ var version = "0.2.72-feat-parallel-tool-execution.22214+9b9abcac1";
8
8
  //#endregion
9
9
  //#region src/utils/updateChecker.ts
10
10
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.72-feat-tavern-leveling-system.22139+d90502009",
3
+ "version": "0.2.72-feat-parallel-tool-execution.22214+9b9abcac1",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -115,11 +115,11 @@
115
115
  "zustand": "^4.5.4"
116
116
  },
117
117
  "devDependencies": {
118
- "@bike4mind/agents": "0.4.9-feat-tavern-leveling-system.22139+d90502009",
119
- "@bike4mind/common": "2.79.1-feat-tavern-leveling-system.22139+d90502009",
120
- "@bike4mind/mcp": "1.33.28-feat-tavern-leveling-system.22139+d90502009",
121
- "@bike4mind/services": "2.72.1-feat-tavern-leveling-system.22139+d90502009",
122
- "@bike4mind/utils": "2.16.10-feat-tavern-leveling-system.22139+d90502009",
118
+ "@bike4mind/agents": "0.4.9-feat-parallel-tool-execution.22214+9b9abcac1",
119
+ "@bike4mind/common": "2.79.1-feat-parallel-tool-execution.22214+9b9abcac1",
120
+ "@bike4mind/mcp": "1.33.28-feat-parallel-tool-execution.22214+9b9abcac1",
121
+ "@bike4mind/services": "2.72.1-feat-parallel-tool-execution.22214+9b9abcac1",
122
+ "@bike4mind/utils": "2.16.10-feat-parallel-tool-execution.22214+9b9abcac1",
123
123
  "@types/better-sqlite3": "^7.6.13",
124
124
  "@types/jsonwebtoken": "^9.0.4",
125
125
  "@types/node": "^22.9.0",
@@ -136,5 +136,5 @@
136
136
  "optionalDependencies": {
137
137
  "@vscode/ripgrep": "^1.17.1"
138
138
  },
139
- "gitHead": "d90502009e692b1c633a7b4a35cc38c960cb8474"
139
+ "gitHead": "9b9abcac12778fe16b153237d469214f2ca5d399"
140
140
  }