@botconnector/bccli 0.4.0-beta.21 → 0.4.0-beta.22

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.
@@ -222,14 +222,36 @@ function responseInputFromMessages(messages) {
222
222
  }
223
223
  return input;
224
224
  }
225
- function responseTools(tools) {
226
- return (tools ?? []).map((tool) => ({
225
+ var LUNA_TOOL_SEARCH_MIN_MCP_TOOLS = 20;
226
+ var LUNA_TOOL_SEARCH_MIN_MCP_SCHEMA_CHARS = 32e3;
227
+ function lunaToolPlan(tools) {
228
+ const native = (tools ?? []).map((tool) => ({
227
229
  type: "function",
228
230
  name: tool.function.name,
229
231
  description: tool.function.description,
230
232
  parameters: tool.function.parameters,
231
233
  strict: false
232
234
  }));
235
+ const mcpIndexes = native.map((tool, index) => String(tool.name).startsWith("mcp__") ? index : -1).filter((index) => index >= 0);
236
+ const deferredSchemaChars = mcpIndexes.reduce((sum, index) => sum + JSON.stringify(native[index]).length, 0);
237
+ const useToolSearch = mcpIndexes.length >= LUNA_TOOL_SEARCH_MIN_MCP_TOOLS || deferredSchemaChars >= LUNA_TOOL_SEARCH_MIN_MCP_SCHEMA_CHARS;
238
+ if (!useToolSearch) {
239
+ return { tools: native, useToolSearch: false, deferredToolCount: 0, deferredSchemaChars };
240
+ }
241
+ for (const index of mcpIndexes) native[index] = { ...native[index], defer_loading: true };
242
+ native.push({
243
+ type: "tool_search",
244
+ execution: "server"
245
+ });
246
+ return {
247
+ tools: native,
248
+ useToolSearch: true,
249
+ deferredToolCount: mcpIndexes.length,
250
+ deferredSchemaChars
251
+ };
252
+ }
253
+ function responseTools(tools) {
254
+ return lunaToolPlan(tools).tools;
233
255
  }
234
256
  function responseReasoning(level) {
235
257
  if (level === "auto") return {};
@@ -35,7 +35,7 @@ function readSecret(prompt) {
35
35
  });
36
36
  }
37
37
  async function runLogin(providerId, cwd) {
38
- const { runProviderCommand } = await import("./providerCli-6FXMBKQL.js");
38
+ const { runProviderCommand } = await import("./providerCli-FLYQK6DX.js");
39
39
  const { parseCliArgs } = await import("./args-XQYEBOKB.js");
40
40
  return runProviderCommand(parseCliArgs(["provider", "add", providerId]), {
41
41
  env: process.env,
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  addProviderKey,
21
21
  createProvider,
22
22
  listAllModels
23
- } from "./chunk-34STZH4U.js";
23
+ } from "./chunk-JM75AWC3.js";
24
24
  import {
25
25
  providerName,
26
26
  readGlobalConfigFile
@@ -28,7 +28,7 @@ import {
28
28
  import "./chunk-SN3ODJZN.js";
29
29
  import {
30
30
  runLogin
31
- } from "./chunk-VNIUYPVN.js";
31
+ } from "./chunk-OQG5NP6C.js";
32
32
  import {
33
33
  Session,
34
34
  pruneSessions
@@ -570,6 +570,7 @@ var fetchTool = createFetchTool();
570
570
  // src/tools/glob.ts
571
571
  import fg from "fast-glob";
572
572
  import { z as z4 } from "zod";
573
+ var MAX_OUTPUT_CHARS = 24e3;
573
574
  var globTool = defineTool({
574
575
  name: "glob",
575
576
  description: 'Find files by glob pattern, e.g. "src/**/*.ts". Respects .gitignore. Max 500 results.',
@@ -583,9 +584,19 @@ var globTool = defineTool({
583
584
  const root = resolvePath(ctx.cwd, input.path ?? ".");
584
585
  const files = (await fg(input.pattern, { cwd: root, ignore: ignorePatterns(root), onlyFiles: true, dot: true })).sort();
585
586
  if (!files.length) return { output: "No matching files." };
586
- const shown = files.slice(0, 500);
587
- const more = files.length > shown.length ? `
588
- \u2026 ${files.length - shown.length} more files` : "";
587
+ const first = files.slice(0, 500);
588
+ const shown = [];
589
+ let size = 0;
590
+ for (const file of first) {
591
+ const extra = file.length + (shown.length ? 1 : 0);
592
+ if (shown.length && size + extra > MAX_OUTPUT_CHARS) break;
593
+ shown.push(file);
594
+ size += extra;
595
+ if (size >= MAX_OUTPUT_CHARS) break;
596
+ }
597
+ const omitted = files.length - shown.length;
598
+ const more = omitted > 0 ? `
599
+ \u2026 ${omitted} more files omitted (narrow pattern/path)` : "";
589
600
  return { output: shown.join("\n") + more, display: `${files.length} file` };
590
601
  }
591
602
  });
@@ -596,6 +607,7 @@ import { readFile as readFile2 } from "fs/promises";
596
607
  import fg2 from "fast-glob";
597
608
  import { z as z5 } from "zod";
598
609
  var MAX_MATCHES = 200;
610
+ var MAX_OUTPUT_CHARS2 = 24e3;
599
611
  async function grepJs(pattern, opts) {
600
612
  const regex = new RegExp(pattern, opts.ignoreCase ? "i" : "");
601
613
  const files = await fg2(opts.glob ?? "**/*", { cwd: opts.root, ignore: ignorePatterns(opts.root), onlyFiles: true, dot: true });
@@ -651,7 +663,19 @@ var grepTool = defineTool({
651
663
  }
652
664
  const matches = await grepRg(input.pattern, opts) ?? await grepJs(input.pattern, opts);
653
665
  if (!matches.length) return { output: "No matches." };
654
- return { output: matches.join("\n"), display: t("{n} results", { n: matches.length }) };
666
+ const shown = [];
667
+ let size = 0;
668
+ for (const match of matches) {
669
+ const extra = match.length + (shown.length ? 1 : 0);
670
+ if (shown.length && size + extra > MAX_OUTPUT_CHARS2) break;
671
+ shown.push(match);
672
+ size += extra;
673
+ if (size >= MAX_OUTPUT_CHARS2) break;
674
+ }
675
+ const omitted = matches.length - shown.length;
676
+ const suffix = omitted > 0 ? `
677
+ \u2026 ${omitted} more matches omitted (narrow pattern/path/glob)` : "";
678
+ return { output: shown.join("\n") + suffix, display: t("{n} results", { n: matches.length }) };
655
679
  }
656
680
  });
657
681
 
@@ -659,6 +683,7 @@ var grepTool = defineTool({
659
683
  import { readFile as readFile3 } from "fs/promises";
660
684
  import { z as z6 } from "zod";
661
685
  var MAX_LINE = 2e3;
686
+ var MAX_OUTPUT_CHARS3 = 4e4;
662
687
  var readTool = defineTool({
663
688
  name: "read",
664
689
  description: "Read a text file. Returns numbered lines (default first 2000). Use offset/limit for large files. Always read a file before editing it.",
@@ -683,17 +708,29 @@ var readTool = defineTool({
683
708
  const lines = buffer.toString("utf8").split(/\r?\n/);
684
709
  const start = (input.offset ?? 1) - 1;
685
710
  const limit = input.limit ?? 2e3;
686
- const slice = lines.slice(start, start + limit);
687
- const body = slice.map((line, i) => {
711
+ const requested = lines.slice(start, start + limit);
712
+ const shown = [];
713
+ let size = 0;
714
+ for (let i = 0; i < requested.length; i++) {
715
+ const line = requested[i];
688
716
  const text = line.length > MAX_LINE ? `${line.slice(0, MAX_LINE)}\u2026 [line truncated]` : line;
689
- return `${String(start + i + 1).padStart(6)} ${text}`;
690
- }).join("\n");
691
- const remaining = lines.length - start - slice.length;
717
+ const rendered = `${String(start + i + 1).padStart(6)} ${text}`;
718
+ const extra = rendered.length + (shown.length ? 1 : 0);
719
+ if (shown.length && size + extra > MAX_OUTPUT_CHARS3) break;
720
+ shown.push(rendered);
721
+ size += extra;
722
+ if (size >= MAX_OUTPUT_CHARS3) break;
723
+ }
724
+ const body = shown.join("\n");
725
+ const remaining = lines.length - start - shown.length;
726
+ const tokenBudgetHit = shown.length < requested.length;
727
+ const nextOffset = start + shown.length + 1;
692
728
  ctx.readFiles.add(abs);
693
729
  return {
694
- output: remaining > 0 ? `${body}
730
+ output: remaining > 0 ? tokenBudgetHit ? `${body}
731
+ \u2026 ${remaining} more lines (token budget reached; continue with offset=${nextOffset})` : `${body}
695
732
  \u2026 ${remaining} more lines (use offset)` : body,
696
- display: t("{n} lines", { n: slice.length })
733
+ display: t("{n} lines", { n: shown.length })
697
734
  };
698
735
  }
699
736
  });
@@ -1140,6 +1177,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
1140
1177
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1141
1178
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
1142
1179
  import { z as z9 } from "zod";
1180
+ var MCP_OUTPUT_MAX_CHARS = 32e3;
1143
1181
  function mcpToolName(server, tool, taken) {
1144
1182
  const clean2 = (s) => s.replace(/[^A-Za-z0-9_-]+/g, "_");
1145
1183
  const base = `mcp__${clean2(server)}__${clean2(tool)}`.slice(0, 64);
@@ -1213,8 +1251,11 @@ var McpManager = class {
1213
1251
  try {
1214
1252
  const result = await client.callTool({ name: tool.name, arguments: input }, void 0, { signal: ctx.signal });
1215
1253
  const output = (result.content ?? []).map((c) => c.type === "text" ? c.text ?? "" : `[${c.type}]`).join("\n") || "(empty)";
1216
- return { output: output.length > 5e4 ? `${output.slice(0, 5e4)}
1217
- \u2026 [truncated]` : output, isError: !!result.isError };
1254
+ return {
1255
+ output: output.length > MCP_OUTPUT_MAX_CHARS ? `${output.slice(0, MCP_OUTPUT_MAX_CHARS)}
1256
+ \u2026 [truncated at ${MCP_OUTPUT_MAX_CHARS} characters; narrow the MCP request if possible]` : output,
1257
+ isError: !!result.isError
1258
+ };
1218
1259
  } catch (error) {
1219
1260
  return { output: `Server MCP ${server} error: ${error.message}`, isError: true };
1220
1261
  }
@@ -1604,7 +1645,7 @@ function createRuntime(opts) {
1604
1645
  }
1605
1646
 
1606
1647
  // src/version.ts
1607
- var VERSION = true ? "0.4.0-beta.21" : "0.0.0-dev";
1648
+ var VERSION = true ? "0.4.0-beta.22" : "0.0.0-dev";
1608
1649
 
1609
1650
  // src/cli.ts
1610
1651
  function chooseLanguage(argv) {
@@ -1630,12 +1671,12 @@ async function main() {
1630
1671
  if (args.command === "login") return runLogin(args.loginProvider ?? "bc-cloud", cwd);
1631
1672
  if (args.command === "mcp") {
1632
1673
  const { runMcpCommand } = await import("./mcpCli-J43FHF2H.js");
1633
- const { readSecret } = await import("./login-TG5LQP3I.js");
1674
+ const { readSecret } = await import("./login-5AQCNXSR.js");
1634
1675
  return runMcpCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
1635
1676
  }
1636
1677
  if (args.command === "provider") {
1637
- const { runProviderCommand } = await import("./providerCli-6FXMBKQL.js");
1638
- const { readSecret } = await import("./login-TG5LQP3I.js");
1678
+ const { runProviderCommand } = await import("./providerCli-FLYQK6DX.js");
1679
+ const { readSecret } = await import("./login-5AQCNXSR.js");
1639
1680
  return runProviderCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
1640
1681
  }
1641
1682
  if (args.command === "connect" || args.command === "disconnect" || args.command === "integrations") {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  readSecret,
4
4
  runLogin
5
- } from "./chunk-VNIUYPVN.js";
5
+ } from "./chunk-OQG5NP6C.js";
6
6
  export {
7
7
  readSecret,
8
8
  runLogin
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  addProviderKey,
4
4
  runProviderCommand
5
- } from "./chunk-34STZH4U.js";
5
+ } from "./chunk-JM75AWC3.js";
6
6
  import "./chunk-K5JNR3HL.js";
7
7
  import "./chunk-SN3ODJZN.js";
8
8
  import "./chunk-EO7IVVX4.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botconnector/bccli",
3
- "version": "0.4.0-beta.21",
3
+ "version": "0.4.0-beta.22",
4
4
  "description": "BCCLI — BotConnector AI coding agent for the terminal",
5
5
  "type": "module",
6
6
  "bin": {