fast-cxt-mcp 1.1.2 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-cxt-mcp",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "AI-driven semantic code search MCP server (Node.js)",
5
5
  "type": "module",
6
6
  "main": "src/server.mjs",
package/src/core.mjs CHANGED
@@ -1014,8 +1014,9 @@ export async function search({
1014
1014
 
1015
1015
  // Total API calls = maxTurns + 1 (last round for answer)
1016
1016
  const totalApiCalls = maxTurns + 1;
1017
+ let compensatedTurns = 0;
1017
1018
 
1018
- for (let turn = 0; turn < totalApiCalls; turn++) {
1019
+ for (let turn = 0; turn < totalApiCalls + compensatedTurns; turn++) {
1019
1020
  log(`Turn ${turn + 1}/${totalApiCalls}`);
1020
1021
 
1021
1022
  const proto = _buildRequest(apiKey, jwt, messages, toolDefs);
@@ -1077,6 +1078,16 @@ export async function search({
1077
1078
  const cmds = Object.keys(toolArgs).filter((k) => k.startsWith("command"));
1078
1079
  log(`Executing ${cmds.length} local commands`);
1079
1080
 
1081
+ // Check for valid commands (those with a type field)
1082
+ const validCommands = cmds.filter((k) => {
1083
+ const cmd = toolArgs[k];
1084
+ return cmd && typeof cmd === "object" && cmd.type;
1085
+ });
1086
+ if (validCommands.length === 0) {
1087
+ compensatedTurns++;
1088
+ log("Turn compensation: no valid commands, extending search by 1 turn");
1089
+ }
1090
+
1080
1091
  const results = await executor.execToolCallAsync(toolArgs);
1081
1092
 
1082
1093
  messages.push({
package/src/executor.mjs CHANGED
@@ -409,6 +409,9 @@ export class ToolExecutor {
409
409
  * @returns {Promise<string>}
410
410
  */
411
411
  async execCommandAsync(cmd) {
412
+ if (!cmd || typeof cmd !== "object") {
413
+ return "Error: missing or invalid command";
414
+ }
412
415
  const t = cmd.type || "";
413
416
  switch (t) {
414
417
  case "rg":
@@ -432,6 +435,9 @@ export class ToolExecutor {
432
435
  * @returns {string}
433
436
  */
434
437
  execCommand(cmd) {
438
+ if (!cmd || typeof cmd !== "object") {
439
+ return "Error: missing or invalid command";
440
+ }
435
441
  const t = cmd.type || "";
436
442
  switch (t) {
437
443
  case "rg":
@@ -455,13 +461,14 @@ export class ToolExecutor {
455
461
  * @returns {Promise<string>}
456
462
  */
457
463
  async execToolCallAsync(args) {
464
+ if (!args || typeof args !== "object") {
465
+ return "Error: missing or invalid tool args";
466
+ }
458
467
  const keys = Object.keys(args).filter((k) => k.startsWith("command")).sort();
459
- const tasks = keys
460
- .filter((key) => typeof args[key] === "object")
461
- .map(async (key) => {
462
- const output = await this.execCommandAsync(args[key]);
463
- return `<${key}_result>\n${output}\n</${key}_result>`;
464
- });
468
+ const tasks = keys.map(async (key) => {
469
+ const output = await this.execCommandAsync(args[key]);
470
+ return `<${key}_result>\n${output}\n</${key}_result>`;
471
+ });
465
472
  const results = await Promise.all(tasks);
466
473
  return results.join("");
467
474
  }
@@ -473,12 +480,13 @@ export class ToolExecutor {
473
480
  */
474
481
  execToolCall(args) {
475
482
  const parts = [];
483
+ if (!args || typeof args !== "object") {
484
+ return "Error: missing or invalid tool args";
485
+ }
476
486
  const keys = Object.keys(args).filter((k) => k.startsWith("command")).sort();
477
487
  for (const key of keys) {
478
- if (typeof args[key] === "object") {
479
- const output = this.execCommand(args[key]);
480
- parts.push(`<${key}_result>\n${output}\n</${key}_result>`);
481
- }
488
+ const output = this.execCommand(args[key]);
489
+ parts.push(`<${key}_result>\n${output}\n</${key}_result>`);
482
490
  }
483
491
  return parts.join("");
484
492
  }