@botconnector/bccli 0.4.0-beta.27 → 0.4.0-beta.29
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/dist/{chunk-CJEIJ5VW.js → chunk-DJR4EAVL.js} +1 -1
- package/dist/{chunk-IXAVAK7R.js → chunk-WWQVALA5.js} +1 -0
- package/dist/{chunk-HP3J6JEY.js → chunk-YPD4D6E3.js} +27 -0
- package/dist/cli.js +29 -14
- package/dist/{login-MOXJVDKB.js → login-HUPT4247.js} +1 -1
- package/dist/{providerCli-G5OGC2UN.js → providerCli-II7TQDYQ.js} +1 -1
- package/dist/{ui-SRXPL7KU.js → ui-H3IDVNE7.js} +18 -7
- package/package.json +4 -2
|
@@ -35,7 +35,7 @@ function readSecret(prompt) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
async function runLogin(providerId, cwd) {
|
|
38
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
38
|
+
const { runProviderCommand } = await import("./providerCli-II7TQDYQ.js");
|
|
39
39
|
const { parseCliArgs } = await import("./args-XQYEBOKB.js");
|
|
40
40
|
return runProviderCommand(parseCliArgs(["provider", "add", providerId]), {
|
|
41
41
|
env: process.env,
|
|
@@ -285,6 +285,7 @@ function lunaToolPlan(tools, enableProgrammaticToolCalling = false, programmatic
|
|
|
285
285
|
name: tool.function.name,
|
|
286
286
|
description: tool.function.description,
|
|
287
287
|
parameters: tool.function.parameters,
|
|
288
|
+
...tool.function.output_schema ? { output_schema: tool.function.output_schema } : {},
|
|
288
289
|
strict: false
|
|
289
290
|
}));
|
|
290
291
|
const mcpIndexes = native.map((tool, index) => String(tool.name).startsWith("mcp__") ? index : -1).filter((index) => index >= 0);
|
|
@@ -247,10 +247,37 @@ function ignorePatterns(root) {
|
|
|
247
247
|
return patterns;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
// src/tools/globSafety.ts
|
|
251
|
+
var MAX_GLOB_LENGTH = 4096;
|
|
252
|
+
var MAX_BRACE_DEPTH = 16;
|
|
253
|
+
function validateGlobPattern(pattern) {
|
|
254
|
+
if (pattern.length > MAX_GLOB_LENGTH) return `Glob pattern is too long (max ${MAX_GLOB_LENGTH} characters).`;
|
|
255
|
+
let depth = 0;
|
|
256
|
+
let escaped = false;
|
|
257
|
+
for (const char of pattern) {
|
|
258
|
+
if (escaped) {
|
|
259
|
+
escaped = false;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (char === "\\") {
|
|
263
|
+
escaped = true;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (char === "{") {
|
|
267
|
+
depth++;
|
|
268
|
+
if (depth > MAX_BRACE_DEPTH) return `Glob brace nesting is too deep (max ${MAX_BRACE_DEPTH}).`;
|
|
269
|
+
} else if (char === "}" && depth > 0) {
|
|
270
|
+
depth--;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return void 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
250
276
|
export {
|
|
251
277
|
toolLabel,
|
|
252
278
|
runPrint,
|
|
253
279
|
ignorePatterns,
|
|
280
|
+
validateGlobPattern,
|
|
254
281
|
BUILTIN_AGENTS,
|
|
255
282
|
instructionPaths,
|
|
256
283
|
buildSystemPrompt,
|
package/dist/cli.js
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
loadCommands,
|
|
8
8
|
loadSkills,
|
|
9
9
|
parseFrontmatter,
|
|
10
|
-
runPrint
|
|
11
|
-
|
|
10
|
+
runPrint,
|
|
11
|
+
validateGlobPattern
|
|
12
|
+
} from "./chunk-YPD4D6E3.js";
|
|
12
13
|
import {
|
|
13
14
|
helpText,
|
|
14
15
|
parseCliArgs
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
createProvider,
|
|
23
24
|
hasPendingProgrammaticReplay,
|
|
24
25
|
listAllModels
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-WWQVALA5.js";
|
|
26
27
|
import {
|
|
27
28
|
providerName,
|
|
28
29
|
readGlobalConfigFile
|
|
@@ -30,7 +31,7 @@ import {
|
|
|
30
31
|
import "./chunk-SN3ODJZN.js";
|
|
31
32
|
import {
|
|
32
33
|
runLogin
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-DJR4EAVL.js";
|
|
34
35
|
import {
|
|
35
36
|
Session,
|
|
36
37
|
pruneSessions
|
|
@@ -570,7 +571,7 @@ async function loadPage(inputUrl, signal) {
|
|
|
570
571
|
var fetchTool = createFetchTool();
|
|
571
572
|
|
|
572
573
|
// src/tools/glob.ts
|
|
573
|
-
import
|
|
574
|
+
import { glob as nativeGlob } from "fs/promises";
|
|
574
575
|
import { z as z4 } from "zod";
|
|
575
576
|
var MAX_OUTPUT_CHARS = 24e3;
|
|
576
577
|
var globTool = defineTool({
|
|
@@ -583,8 +584,14 @@ var globTool = defineTool({
|
|
|
583
584
|
kind: "read",
|
|
584
585
|
target: (input) => input.pattern,
|
|
585
586
|
async run(input, ctx) {
|
|
587
|
+
const invalid = validateGlobPattern(input.pattern);
|
|
588
|
+
if (invalid) return { output: invalid, isError: true };
|
|
586
589
|
const root = resolvePath(ctx.cwd, input.path ?? ".");
|
|
587
|
-
const files =
|
|
590
|
+
const files = [];
|
|
591
|
+
for await (const file of nativeGlob(input.pattern, { cwd: root, exclude: ignorePatterns(root) })) {
|
|
592
|
+
files.push(file);
|
|
593
|
+
}
|
|
594
|
+
files.sort();
|
|
588
595
|
if (!files.length) return { output: "No matching files." };
|
|
589
596
|
const first = files.slice(0, 500);
|
|
590
597
|
const shown = [];
|
|
@@ -606,13 +613,16 @@ var globTool = defineTool({
|
|
|
606
613
|
// src/tools/grep.ts
|
|
607
614
|
import { execFile } from "child_process";
|
|
608
615
|
import { readFile as readFile2 } from "fs/promises";
|
|
609
|
-
import
|
|
616
|
+
import { glob as nativeGlob2 } from "fs/promises";
|
|
610
617
|
import { z as z5 } from "zod";
|
|
611
618
|
var MAX_MATCHES = 200;
|
|
612
619
|
var MAX_OUTPUT_CHARS2 = 24e3;
|
|
613
620
|
async function grepJs(pattern, opts) {
|
|
614
621
|
const regex = new RegExp(pattern, opts.ignoreCase ? "i" : "");
|
|
615
|
-
const files =
|
|
622
|
+
const files = [];
|
|
623
|
+
for await (const file of nativeGlob2(opts.glob ?? "**/*", { cwd: opts.root, exclude: ignorePatterns(opts.root) })) {
|
|
624
|
+
files.push(file);
|
|
625
|
+
}
|
|
616
626
|
const out = [];
|
|
617
627
|
for (const file of files.sort()) {
|
|
618
628
|
let text;
|
|
@@ -657,6 +667,10 @@ var grepTool = defineTool({
|
|
|
657
667
|
kind: "read",
|
|
658
668
|
target: (input) => input.pattern,
|
|
659
669
|
async run(input, ctx) {
|
|
670
|
+
if (input.glob) {
|
|
671
|
+
const invalid = validateGlobPattern(input.glob);
|
|
672
|
+
if (invalid) return { output: invalid, isError: true };
|
|
673
|
+
}
|
|
660
674
|
const opts = { root: resolvePath(ctx.cwd, input.path ?? "."), glob: input.glob, ignoreCase: input.ignore_case };
|
|
661
675
|
try {
|
|
662
676
|
new RegExp(input.pattern);
|
|
@@ -783,7 +797,7 @@ var ALL_TOOLS = [readTool, writeTool, editTool, bashTool, grepTool, globTool, fe
|
|
|
783
797
|
function toolDefinitions(tools) {
|
|
784
798
|
return tools.map((tool) => {
|
|
785
799
|
const { $schema: _ignored, ...parameters } = tool.jsonSchema ?? z8.toJSONSchema(tool.schema);
|
|
786
|
-
return { type: "function", function: { name: tool.name, description: tool.description, parameters } };
|
|
800
|
+
return { type: "function", function: { name: tool.name, description: tool.description, parameters, ...tool.outputJsonSchema ? { output_schema: tool.outputJsonSchema } : {} } };
|
|
787
801
|
});
|
|
788
802
|
}
|
|
789
803
|
|
|
@@ -1247,6 +1261,7 @@ var McpManager = class {
|
|
|
1247
1261
|
description: `[MCP ${server}] ${tool.description ?? tool.name}`.slice(0, 1024),
|
|
1248
1262
|
schema: z9.record(z9.string(), z9.unknown()),
|
|
1249
1263
|
jsonSchema: tool.inputSchema,
|
|
1264
|
+
...tool.outputSchema ? { outputJsonSchema: tool.outputSchema } : {},
|
|
1250
1265
|
kind: "mcp",
|
|
1251
1266
|
programmaticSafe: tool.annotations?.readOnlyHint === true,
|
|
1252
1267
|
target: (input) => {
|
|
@@ -1661,7 +1676,7 @@ function createRuntime(opts) {
|
|
|
1661
1676
|
}
|
|
1662
1677
|
|
|
1663
1678
|
// src/version.ts
|
|
1664
|
-
var VERSION = true ? "0.4.0-beta.
|
|
1679
|
+
var VERSION = true ? "0.4.0-beta.29" : "0.0.0-dev";
|
|
1665
1680
|
|
|
1666
1681
|
// src/cli.ts
|
|
1667
1682
|
function chooseLanguage(argv) {
|
|
@@ -1687,12 +1702,12 @@ async function main() {
|
|
|
1687
1702
|
if (args.command === "login") return runLogin(args.loginProvider ?? "bc-cloud", cwd);
|
|
1688
1703
|
if (args.command === "mcp") {
|
|
1689
1704
|
const { runMcpCommand } = await import("./mcpCli-J43FHF2H.js");
|
|
1690
|
-
const { readSecret } = await import("./login-
|
|
1705
|
+
const { readSecret } = await import("./login-HUPT4247.js");
|
|
1691
1706
|
return runMcpCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
1692
1707
|
}
|
|
1693
1708
|
if (args.command === "provider") {
|
|
1694
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
1695
|
-
const { readSecret } = await import("./login-
|
|
1709
|
+
const { runProviderCommand } = await import("./providerCli-II7TQDYQ.js");
|
|
1710
|
+
const { readSecret } = await import("./login-HUPT4247.js");
|
|
1696
1711
|
return runProviderCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
1697
1712
|
}
|
|
1698
1713
|
if (args.command === "connect" || args.command === "disconnect" || args.command === "integrations") {
|
|
@@ -1732,7 +1747,7 @@ async function main() {
|
|
|
1732
1747
|
}
|
|
1733
1748
|
}
|
|
1734
1749
|
if (!process.stdin.isTTY) throw new ConfigError(t('Interactive mode needs a terminal. For scripts/CI use: bccli -p "task"'));
|
|
1735
|
-
const { startInteractive } = await import("./ui-
|
|
1750
|
+
const { startInteractive } = await import("./ui-H3IDVNE7.js");
|
|
1736
1751
|
return startInteractive(rt, { initialPrompt: args.prompt, resume: args.resume, version: VERSION });
|
|
1737
1752
|
}
|
|
1738
1753
|
main().then(
|
|
@@ -4,8 +4,9 @@ import {
|
|
|
4
4
|
ignorePatterns,
|
|
5
5
|
instructionPaths,
|
|
6
6
|
parseFrontmatter,
|
|
7
|
-
toolLabel
|
|
8
|
-
|
|
7
|
+
toolLabel,
|
|
8
|
+
validateGlobPattern
|
|
9
|
+
} from "./chunk-YPD4D6E3.js";
|
|
9
10
|
import {
|
|
10
11
|
nextMode
|
|
11
12
|
} from "./chunk-ELML4KVQ.js";
|
|
@@ -50,7 +51,7 @@ import { render } from "ink";
|
|
|
50
51
|
import { execFile as execFile2 } from "child_process";
|
|
51
52
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
52
53
|
import { homedir } from "os";
|
|
53
|
-
import { dirname, join, relative, resolve } from "path";
|
|
54
|
+
import { dirname, join as join2, relative, resolve } from "path";
|
|
54
55
|
import { Box as Box13, Static, Text as Text15, useApp, useInput as useInput9 } from "ink";
|
|
55
56
|
import { useCallback, useEffect as useEffect2, useRef, useState as useState8 } from "react";
|
|
56
57
|
|
|
@@ -801,13 +802,23 @@ import { Box as Box8, Text as Text8, useInput as useInput6 } from "ink";
|
|
|
801
802
|
import { useState as useState5 } from "react";
|
|
802
803
|
|
|
803
804
|
// src/ui/complete.ts
|
|
804
|
-
import
|
|
805
|
+
import { globSync } from "fs";
|
|
806
|
+
import { statSync } from "fs";
|
|
807
|
+
import { join } from "path";
|
|
805
808
|
function completeFile(value, cwd) {
|
|
806
809
|
const match = /(^|\s)@([^\s]*)$/.exec(value);
|
|
807
810
|
if (!match) return value;
|
|
808
811
|
const prefix = match[2];
|
|
809
812
|
const escaped = prefix.replace(/([*?[\]{}()!])/g, "\\$1");
|
|
810
|
-
const
|
|
813
|
+
const pattern = `${escaped}*`;
|
|
814
|
+
if (validateGlobPattern(pattern)) return value;
|
|
815
|
+
const found = globSync(pattern, { cwd, exclude: ignorePatterns(cwd) }).map((entry2) => {
|
|
816
|
+
try {
|
|
817
|
+
return statSync(join(cwd, entry2)).isDirectory() ? `${entry2}/` : entry2;
|
|
818
|
+
} catch {
|
|
819
|
+
return entry2;
|
|
820
|
+
}
|
|
821
|
+
}).sort();
|
|
811
822
|
if (!found.length) return value;
|
|
812
823
|
const pick = found[0];
|
|
813
824
|
return `${value.slice(0, value.length - prefix.length)}${pick}${pick.endsWith("/") ? "" : " "}`;
|
|
@@ -1403,7 +1414,7 @@ function App({ runtime, initialPrompt, version }) {
|
|
|
1403
1414
|
notice(t("Write the text: /memory global <text>."), "warn");
|
|
1404
1415
|
return;
|
|
1405
1416
|
}
|
|
1406
|
-
const file = global ?
|
|
1417
|
+
const file = global ? join2(runtime.home, "BCCLI.md") : join2(runtime.cwd, "AGENTS.md");
|
|
1407
1418
|
try {
|
|
1408
1419
|
mkdirSync(dirname(file), { recursive: true });
|
|
1409
1420
|
appendMemory(file, text);
|
|
@@ -1509,7 +1520,7 @@ function App({ runtime, initialPrompt, version }) {
|
|
|
1509
1520
|
return;
|
|
1510
1521
|
}
|
|
1511
1522
|
process.stdout.write(osc52(last.content, !!process.env.TMUX));
|
|
1512
|
-
const file =
|
|
1523
|
+
const file = join2(runtime.home, "last-answer.md");
|
|
1513
1524
|
mkdirSync(runtime.home, { recursive: true });
|
|
1514
1525
|
writeFileSync(file, last.content);
|
|
1515
1526
|
notice(t("Copied to the clipboard (if the terminal supports OSC 52) and saved to {file}.", { file }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botconnector/bccli",
|
|
3
|
-
"version": "0.4.0-beta.
|
|
3
|
+
"version": "0.4.0-beta.29",
|
|
4
4
|
"description": "BCCLI — BotConnector AI coding agent for the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@modelcontextprotocol/sdk": "^1.30.1",
|
|
28
28
|
"diff": "^9.0.0",
|
|
29
|
-
"fast-glob": "^3.3.3",
|
|
30
29
|
"ink": "^7.1.1",
|
|
31
30
|
"openai": "^7.27.0",
|
|
32
31
|
"react": "^19.3.0",
|
|
@@ -43,5 +42,8 @@
|
|
|
43
42
|
"tsup": "^8.5.1",
|
|
44
43
|
"typescript": "^7.0.2",
|
|
45
44
|
"vitest": "^5.0.2"
|
|
45
|
+
},
|
|
46
|
+
"overrides": {
|
|
47
|
+
"esbuild": "0.28.2"
|
|
46
48
|
}
|
|
47
49
|
}
|