@botconnector/bccli 0.4.0-beta.40 → 0.4.0-beta.41
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/{acp-5A7EXLCG.js → acp-SZWZ5EE4.js} +1 -1
- package/dist/{chunk-RV74TCEP.js → chunk-BUHWQU3V.js} +1 -1
- package/dist/{chunk-ZMU7MXCH.js → chunk-DBHDZ5EP.js} +65 -16
- package/dist/{chunk-PDVS4UWM.js → chunk-EQQTTE2K.js} +1 -1
- package/dist/{chunk-WH7XLDGZ.js → chunk-M4IYXI3V.js} +1 -1
- package/dist/cli.js +9 -9
- package/dist/sdk.js +81 -32
- package/dist/{serve-JNQUP7CZ.js → serve-KQ35P4W3.js} +3 -3
- package/dist/{setup-I7UY7X7C.js → setup-45WQXUBK.js} +2 -2
- package/dist/{ui-GVIMUZNS.js → ui-S4QFJJIB.js} +2 -2
- package/dist/{update-SZUG3YSB.js → update-VBDEHHMR.js} +1 -1
- package/package.json +1 -1
|
@@ -98,7 +98,7 @@ function runtimeAgent(cwd) {
|
|
|
98
98
|
return {
|
|
99
99
|
async run(text, onChunk, signal) {
|
|
100
100
|
const { parseCliArgs } = await import("./args-4SMOHFN5.js");
|
|
101
|
-
const { createRuntime } = await import("./setup-
|
|
101
|
+
const { createRuntime } = await import("./setup-45WQXUBK.js");
|
|
102
102
|
const rt = createRuntime({ cwd, args: { ...parseCliArgs([]), allowAll: true } });
|
|
103
103
|
rt.agent.onEvent = (event) => {
|
|
104
104
|
if (event.type === "text") onChunk(event.delta);
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/tools/bash.ts
|
|
10
10
|
import { spawn } from "child_process";
|
|
11
|
+
import { existsSync as existsSync2 } from "fs";
|
|
11
12
|
import { z } from "zod";
|
|
12
13
|
|
|
13
14
|
// src/tools/sandbox.ts
|
|
@@ -57,6 +58,40 @@ function sandboxArgv(command, opts) {
|
|
|
57
58
|
return void 0;
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
// src/tools/shell.ts
|
|
62
|
+
import { existsSync } from "fs";
|
|
63
|
+
import { win32 } from "path";
|
|
64
|
+
var PS_PRELUDE = "[Console]::OutputEncoding=[Text.Encoding]::UTF8; $OutputEncoding=[Text.Encoding]::UTF8; ";
|
|
65
|
+
var PS_EPILOGUE = "\nif ($LASTEXITCODE -ne $null) { exit $LASTEXITCODE } elseif (-not $?) { exit 1 }";
|
|
66
|
+
function gitBashCandidates(env) {
|
|
67
|
+
const roots = [env.ProgramW6432, env.ProgramFiles, env["ProgramFiles(x86)"], env.LOCALAPPDATA && win32.join(env.LOCALAPPDATA, "Programs")];
|
|
68
|
+
const fromRoots = roots.filter((root) => !!root).map((root) => win32.join(root, "Git", "bin", "bash.exe"));
|
|
69
|
+
const fromPath = (env.PATH ?? env.Path ?? "").split(";").filter(Boolean).map((dir) => win32.join(dir, "..", "bin", "bash.exe"));
|
|
70
|
+
return [...fromRoots, ...fromPath];
|
|
71
|
+
}
|
|
72
|
+
function resolveShell(deps) {
|
|
73
|
+
if (deps.platform !== "win32") return void 0;
|
|
74
|
+
const bash = gitBashCandidates(deps.env).find((candidate) => deps.exists(candidate));
|
|
75
|
+
if (bash) return { name: "bash", file: bash, args: (command) => ["-c", command] };
|
|
76
|
+
return {
|
|
77
|
+
name: "powershell",
|
|
78
|
+
file: "powershell.exe",
|
|
79
|
+
args: (command) => [
|
|
80
|
+
"-NoProfile",
|
|
81
|
+
"-NonInteractive",
|
|
82
|
+
"-ExecutionPolicy",
|
|
83
|
+
"Bypass",
|
|
84
|
+
"-EncodedCommand",
|
|
85
|
+
Buffer.from(PS_PRELUDE + command + PS_EPILOGUE, "utf16le").toString("base64")
|
|
86
|
+
]
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
var cachedDefault = null;
|
|
90
|
+
function defaultShell() {
|
|
91
|
+
if (cachedDefault === null) cachedDefault = resolveShell({ platform: process.platform, env: process.env, exists: existsSync });
|
|
92
|
+
return cachedDefault;
|
|
93
|
+
}
|
|
94
|
+
|
|
60
95
|
// src/tools/bash.ts
|
|
61
96
|
var HALF = 15e3;
|
|
62
97
|
function killProcessTree(pid, platform = process.platform, spawnFn = spawn) {
|
|
@@ -87,8 +122,8 @@ function killAllCommands() {
|
|
|
87
122
|
}
|
|
88
123
|
var backgrounds = /* @__PURE__ */ new Map();
|
|
89
124
|
var nextBackgroundId = 1;
|
|
90
|
-
function startBackground(command, cwd, env) {
|
|
91
|
-
const child = spawnChild(command, cwd, env);
|
|
125
|
+
function startBackground(command, cwd, env, shell) {
|
|
126
|
+
const child = spawnChild(command, cwd, env, shell);
|
|
92
127
|
const task = {
|
|
93
128
|
id: nextBackgroundId++,
|
|
94
129
|
command: Array.isArray(command) ? command.join(" ") : command,
|
|
@@ -159,8 +194,14 @@ function renderBackgroundTasks() {
|
|
|
159
194
|
return `Background tasks:
|
|
160
195
|
${lines.join("\n")}`;
|
|
161
196
|
}
|
|
162
|
-
function spawnChild(command, cwd, env) {
|
|
163
|
-
|
|
197
|
+
function spawnChild(command, cwd, env, shell) {
|
|
198
|
+
if (Array.isArray(command)) {
|
|
199
|
+
return spawn(command[0], command.slice(1), { cwd, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
|
|
200
|
+
}
|
|
201
|
+
if (shell) {
|
|
202
|
+
return spawn(shell.file, shell.args(command), { cwd, shell: false, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
|
|
203
|
+
}
|
|
204
|
+
return spawn(command, { cwd, shell: true, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
|
|
164
205
|
}
|
|
165
206
|
var NETWORK_PATTERNS = [
|
|
166
207
|
/\b(curl|wget|ftp|scp|sftp|rsync|lynx|telnet)\b/i,
|
|
@@ -196,7 +237,7 @@ function offlineEnv(env = process.env) {
|
|
|
196
237
|
}
|
|
197
238
|
function runCommand(command, opts) {
|
|
198
239
|
return new Promise((resolve) => {
|
|
199
|
-
const child = spawnChild(command, opts.cwd, opts.env);
|
|
240
|
+
const child = spawnChild(command, opts.cwd, opts.env, opts.shell ?? defaultShell());
|
|
200
241
|
if (!exitHookInstalled) {
|
|
201
242
|
process.on("exit", killAllCommands);
|
|
202
243
|
exitHookInstalled = true;
|
|
@@ -264,13 +305,20 @@ var BASH_SCHEMA = z.object({
|
|
|
264
305
|
task_id: z.number().int().optional().describe("Poll a background task started with background: true (omit command)"),
|
|
265
306
|
kill: z.boolean().optional().describe("With task_id: stop the background task")
|
|
266
307
|
});
|
|
308
|
+
var SHELL_NOTE = {
|
|
309
|
+
bash: "Shell: Git Bash. Unix tools such as tail, grep, ls, sed and head are available.",
|
|
310
|
+
powershell: "Shell: Windows PowerShell 5.1. Unix tools such as tail, grep, ls, sed and head are NOT installed; use PowerShell equivalents (Select-Object -Last 40, Select-String, Get-ChildItem, Get-Content)."
|
|
311
|
+
};
|
|
267
312
|
function createBashTool(options = {}) {
|
|
268
313
|
const offline = options.networkPolicy === "offline";
|
|
269
314
|
const sandbox = options.sandbox === true;
|
|
270
315
|
const platform = options.platform ?? process.platform;
|
|
316
|
+
const shell = resolveShell({ platform, env: process.env, exists: existsSync2, ...options.shellDeps });
|
|
271
317
|
const childEnv = offline ? offlineEnv() : void 0;
|
|
318
|
+
const shellNote = shell ? `
|
|
319
|
+
${SHELL_NOTE[shell.name]}` : "";
|
|
272
320
|
const description = `${offline ? `${BASH_DESCRIPTION}
|
|
273
|
-
Network access is off (networkPolicy "offline"): internet commands such as curl, wget, git fetch/push/clone, package installs (npm, pip, ...), gh, and docker pull are blocked.` : BASH_DESCRIPTION}${sandbox ? "\nCommands run inside an OS sandbox: file writes are limited to the working directory and temp areas." : ""}`;
|
|
321
|
+
Network access is off (networkPolicy "offline"): internet commands such as curl, wget, git fetch/push/clone, package installs (npm, pip, ...), gh, and docker pull are blocked.` : BASH_DESCRIPTION}${sandbox ? "\nCommands run inside an OS sandbox: file writes are limited to the working directory and temp areas." : ""}${shellNote}`;
|
|
274
322
|
return defineTool({
|
|
275
323
|
name: "bash",
|
|
276
324
|
description,
|
|
@@ -310,7 +358,7 @@ Network access is off (networkPolicy "offline"): internet commands such as curl,
|
|
|
310
358
|
}
|
|
311
359
|
if (input.background) {
|
|
312
360
|
if (!input.command) return { output: 'The "command" argument is required to start a background task.', isError: true };
|
|
313
|
-
const task = startBackground(exec, ctx.cwd, childEnv);
|
|
361
|
+
const task = startBackground(exec, ctx.cwd, childEnv, shell);
|
|
314
362
|
return {
|
|
315
363
|
output: `Background task #${task.id} started: ${input.command}
|
|
316
364
|
Poll it with {task_id: ${task.id}}; stop it with {task_id: ${task.id}, kill: true}.`
|
|
@@ -323,7 +371,8 @@ Poll it with {task_id: ${task.id}}; stop it with {task_id: ${task.id}, kill: tru
|
|
|
323
371
|
cwd: ctx.cwd,
|
|
324
372
|
timeoutMs: input.timeout_ms ?? 12e4,
|
|
325
373
|
signal: ctx.signal,
|
|
326
|
-
env: childEnv
|
|
374
|
+
env: childEnv,
|
|
375
|
+
shell
|
|
327
376
|
});
|
|
328
377
|
const status = r.timedOut ? `[stopped: timeout after ${Math.round((input.timeout_ms ?? 12e4) / 1e3)} seconds]` : r.aborted ? "[cancelled by the user]" : `[exit code ${r.exitCode}]`;
|
|
329
378
|
return { output: `${r.output.trimEnd()}
|
|
@@ -353,12 +402,12 @@ var BUILTIN_AGENTS = [
|
|
|
353
402
|
];
|
|
354
403
|
|
|
355
404
|
// src/context.ts
|
|
356
|
-
import { existsSync, readFileSync } from "fs";
|
|
405
|
+
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
357
406
|
import { dirname, join } from "path";
|
|
358
407
|
var FILES = ["AGENTS.md", "BCCLI.md"];
|
|
359
408
|
function readIf(path) {
|
|
360
409
|
try {
|
|
361
|
-
return
|
|
410
|
+
return existsSync3(path) ? readFileSync(path, "utf8").trim() : void 0;
|
|
362
411
|
} catch {
|
|
363
412
|
return void 0;
|
|
364
413
|
}
|
|
@@ -382,7 +431,7 @@ ${text}`);
|
|
|
382
431
|
}
|
|
383
432
|
function isGitRepo(cwd) {
|
|
384
433
|
for (let dir = cwd; ; dir = dirname(dir)) {
|
|
385
|
-
if (
|
|
434
|
+
if (existsSync3(join(dir, ".git"))) return true;
|
|
386
435
|
if (dirname(dir) === dir) return false;
|
|
387
436
|
}
|
|
388
437
|
}
|
|
@@ -426,7 +475,7 @@ ${instructions}` : ""}`;
|
|
|
426
475
|
}
|
|
427
476
|
|
|
428
477
|
// src/extensions.ts
|
|
429
|
-
import { existsSync as
|
|
478
|
+
import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
430
479
|
import { basename, join as join2 } from "path";
|
|
431
480
|
function parseFrontmatter(text) {
|
|
432
481
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text);
|
|
@@ -461,7 +510,7 @@ function loadSkills(r) {
|
|
|
461
510
|
for (const dir of dirs(r, "skills")) {
|
|
462
511
|
for (const entry of list(dir)) {
|
|
463
512
|
const file = join2(dir, entry, "SKILL.md");
|
|
464
|
-
if (!
|
|
513
|
+
if (!existsSync4(file)) continue;
|
|
465
514
|
const { data } = parseFrontmatter(readFileSync2(file, "utf8"));
|
|
466
515
|
const name = str(data.name) || entry;
|
|
467
516
|
byName.set(name, { name, description: str(data.description) ?? "", dir: join2(dir, entry), file });
|
|
@@ -590,12 +639,12 @@ async function runHooks(hooks, event, payload = {}, opts = {}) {
|
|
|
590
639
|
}
|
|
591
640
|
|
|
592
641
|
// src/slash/memory.ts
|
|
593
|
-
import { appendFileSync, existsSync as
|
|
642
|
+
import { appendFileSync, existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
594
643
|
function instructionFiles(cwd, home) {
|
|
595
|
-
return instructionPaths(cwd, home).filter((path) =>
|
|
644
|
+
return instructionPaths(cwd, home).filter((path) => existsSync5(path)).map((path) => ({ path, lines: readFileSync3(path, "utf8").split("\n").filter(Boolean).length }));
|
|
596
645
|
}
|
|
597
646
|
function appendMemory(file, text) {
|
|
598
|
-
const prefix =
|
|
647
|
+
const prefix = existsSync5(file) && !readFileSync3(file, "utf8").endsWith("\n") ? "\n" : "";
|
|
599
648
|
appendFileSync(file, `${prefix}- ${text.trim()}
|
|
600
649
|
`);
|
|
601
650
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EQQTTE2K.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveWorktree,
|
|
7
7
|
runPrint
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BUHWQU3V.js";
|
|
9
9
|
import {
|
|
10
10
|
helpText,
|
|
11
11
|
parseCliArgs
|
|
@@ -15,9 +15,9 @@ import {
|
|
|
15
15
|
} from "./chunk-DSFHN5CH.js";
|
|
16
16
|
import {
|
|
17
17
|
createRuntime
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-M4IYXI3V.js";
|
|
19
19
|
import "./chunk-3HCOAJEQ.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-DBHDZ5EP.js";
|
|
21
21
|
import "./chunk-GAFJEQTJ.js";
|
|
22
22
|
import "./chunk-JROUQ5YS.js";
|
|
23
23
|
import "./chunk-LN32JIZR.js";
|
|
@@ -90,16 +90,16 @@ async function main() {
|
|
|
90
90
|
return runModelsCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), fetch: globalThis.fetch });
|
|
91
91
|
}
|
|
92
92
|
if (args.command === "update") {
|
|
93
|
-
const { runUpdateCommand } = await import("./update-
|
|
93
|
+
const { runUpdateCommand } = await import("./update-VBDEHHMR.js");
|
|
94
94
|
return runUpdateCommand({ env: process.env });
|
|
95
95
|
}
|
|
96
96
|
if (args.command === "acp") {
|
|
97
|
-
const { runtimeAgent, runAcp } = await import("./acp-
|
|
97
|
+
const { runtimeAgent, runAcp } = await import("./acp-SZWZ5EE4.js");
|
|
98
98
|
await runAcp(process.stdin, process.stdout, { cwd, newAgent: (c) => runtimeAgent(c) });
|
|
99
99
|
return 0;
|
|
100
100
|
}
|
|
101
101
|
if (args.command === "serve") {
|
|
102
|
-
const { startServe } = await import("./serve-
|
|
102
|
+
const { startServe } = await import("./serve-KQ35P4W3.js");
|
|
103
103
|
const handle = await startServe({ port: args.port, host: args.host, token: args.token, cwd, env: process.env });
|
|
104
104
|
process.stderr.write(`bccli serve ${handle.url} \u2014 Authorization: Bearer ${handle.token}
|
|
105
105
|
`);
|
|
@@ -135,13 +135,13 @@ async function main() {
|
|
|
135
135
|
if (!process.stdin.isTTY) throw new ConfigError(t('Interactive mode needs a terminal. For scripts/CI use: bccli -p "task"'));
|
|
136
136
|
if (rt.config.updateCheck !== "off" && !process.env.BCCLI_NO_UPDATE_CHECK) {
|
|
137
137
|
try {
|
|
138
|
-
const { checkForUpdate } = await import("./update-
|
|
138
|
+
const { checkForUpdate } = await import("./update-VBDEHHMR.js");
|
|
139
139
|
const update = await checkForUpdate({ home: rt.home, fetch: globalThis.fetch, now: /* @__PURE__ */ new Date() });
|
|
140
140
|
if (update) console.error(update);
|
|
141
141
|
} catch {
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
const { startInteractive } = await import("./ui-
|
|
144
|
+
const { startInteractive } = await import("./ui-S4QFJJIB.js");
|
|
145
145
|
return startInteractive(rt, { initialPrompt: args.prompt, resume: args.resume, version: VERSION });
|
|
146
146
|
}
|
|
147
147
|
main().then(
|
package/dist/sdk.js
CHANGED
|
@@ -1900,6 +1900,7 @@ import { z as z8 } from "zod";
|
|
|
1900
1900
|
|
|
1901
1901
|
// src/tools/bash.ts
|
|
1902
1902
|
import { spawn as spawn2 } from "child_process";
|
|
1903
|
+
import { existsSync as existsSync3 } from "fs";
|
|
1903
1904
|
import { z } from "zod";
|
|
1904
1905
|
|
|
1905
1906
|
// src/tools/sandbox.ts
|
|
@@ -1949,6 +1950,40 @@ function sandboxArgv(command, opts) {
|
|
|
1949
1950
|
return void 0;
|
|
1950
1951
|
}
|
|
1951
1952
|
|
|
1953
|
+
// src/tools/shell.ts
|
|
1954
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1955
|
+
import { win32 } from "path";
|
|
1956
|
+
var PS_PRELUDE = "[Console]::OutputEncoding=[Text.Encoding]::UTF8; $OutputEncoding=[Text.Encoding]::UTF8; ";
|
|
1957
|
+
var PS_EPILOGUE = "\nif ($LASTEXITCODE -ne $null) { exit $LASTEXITCODE } elseif (-not $?) { exit 1 }";
|
|
1958
|
+
function gitBashCandidates(env) {
|
|
1959
|
+
const roots = [env.ProgramW6432, env.ProgramFiles, env["ProgramFiles(x86)"], env.LOCALAPPDATA && win32.join(env.LOCALAPPDATA, "Programs")];
|
|
1960
|
+
const fromRoots = roots.filter((root) => !!root).map((root) => win32.join(root, "Git", "bin", "bash.exe"));
|
|
1961
|
+
const fromPath = (env.PATH ?? env.Path ?? "").split(";").filter(Boolean).map((dir) => win32.join(dir, "..", "bin", "bash.exe"));
|
|
1962
|
+
return [...fromRoots, ...fromPath];
|
|
1963
|
+
}
|
|
1964
|
+
function resolveShell(deps) {
|
|
1965
|
+
if (deps.platform !== "win32") return void 0;
|
|
1966
|
+
const bash = gitBashCandidates(deps.env).find((candidate) => deps.exists(candidate));
|
|
1967
|
+
if (bash) return { name: "bash", file: bash, args: (command) => ["-c", command] };
|
|
1968
|
+
return {
|
|
1969
|
+
name: "powershell",
|
|
1970
|
+
file: "powershell.exe",
|
|
1971
|
+
args: (command) => [
|
|
1972
|
+
"-NoProfile",
|
|
1973
|
+
"-NonInteractive",
|
|
1974
|
+
"-ExecutionPolicy",
|
|
1975
|
+
"Bypass",
|
|
1976
|
+
"-EncodedCommand",
|
|
1977
|
+
Buffer.from(PS_PRELUDE + command + PS_EPILOGUE, "utf16le").toString("base64")
|
|
1978
|
+
]
|
|
1979
|
+
};
|
|
1980
|
+
}
|
|
1981
|
+
var cachedDefault = null;
|
|
1982
|
+
function defaultShell() {
|
|
1983
|
+
if (cachedDefault === null) cachedDefault = resolveShell({ platform: process.platform, env: process.env, exists: existsSync2 });
|
|
1984
|
+
return cachedDefault;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1952
1987
|
// src/tools/types.ts
|
|
1953
1988
|
function defineTool(tool) {
|
|
1954
1989
|
return tool;
|
|
@@ -1984,8 +2019,8 @@ function killAllCommands() {
|
|
|
1984
2019
|
}
|
|
1985
2020
|
var backgrounds = /* @__PURE__ */ new Map();
|
|
1986
2021
|
var nextBackgroundId = 1;
|
|
1987
|
-
function startBackground(command, cwd, env) {
|
|
1988
|
-
const child = spawnChild(command, cwd, env);
|
|
2022
|
+
function startBackground(command, cwd, env, shell) {
|
|
2023
|
+
const child = spawnChild(command, cwd, env, shell);
|
|
1989
2024
|
const task = {
|
|
1990
2025
|
id: nextBackgroundId++,
|
|
1991
2026
|
command: Array.isArray(command) ? command.join(" ") : command,
|
|
@@ -2046,8 +2081,14 @@ ${task.tail}` : task.head + task.tail;
|
|
|
2046
2081
|
return `${body.trimEnd()}
|
|
2047
2082
|
${backgroundStatus(task)}`.trimStart();
|
|
2048
2083
|
}
|
|
2049
|
-
function spawnChild(command, cwd, env) {
|
|
2050
|
-
|
|
2084
|
+
function spawnChild(command, cwd, env, shell) {
|
|
2085
|
+
if (Array.isArray(command)) {
|
|
2086
|
+
return spawn2(command[0], command.slice(1), { cwd, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
|
|
2087
|
+
}
|
|
2088
|
+
if (shell) {
|
|
2089
|
+
return spawn2(shell.file, shell.args(command), { cwd, shell: false, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
|
|
2090
|
+
}
|
|
2091
|
+
return spawn2(command, { cwd, shell: true, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
|
|
2051
2092
|
}
|
|
2052
2093
|
var NETWORK_PATTERNS = [
|
|
2053
2094
|
/\b(curl|wget|ftp|scp|sftp|rsync|lynx|telnet)\b/i,
|
|
@@ -2083,7 +2124,7 @@ function offlineEnv(env = process.env) {
|
|
|
2083
2124
|
}
|
|
2084
2125
|
function runCommand(command, opts) {
|
|
2085
2126
|
return new Promise((resolve4) => {
|
|
2086
|
-
const child = spawnChild(command, opts.cwd, opts.env);
|
|
2127
|
+
const child = spawnChild(command, opts.cwd, opts.env, opts.shell ?? defaultShell());
|
|
2087
2128
|
if (!exitHookInstalled) {
|
|
2088
2129
|
process.on("exit", killAllCommands);
|
|
2089
2130
|
exitHookInstalled = true;
|
|
@@ -2151,13 +2192,20 @@ var BASH_SCHEMA = z.object({
|
|
|
2151
2192
|
task_id: z.number().int().optional().describe("Poll a background task started with background: true (omit command)"),
|
|
2152
2193
|
kill: z.boolean().optional().describe("With task_id: stop the background task")
|
|
2153
2194
|
});
|
|
2195
|
+
var SHELL_NOTE = {
|
|
2196
|
+
bash: "Shell: Git Bash. Unix tools such as tail, grep, ls, sed and head are available.",
|
|
2197
|
+
powershell: "Shell: Windows PowerShell 5.1. Unix tools such as tail, grep, ls, sed and head are NOT installed; use PowerShell equivalents (Select-Object -Last 40, Select-String, Get-ChildItem, Get-Content)."
|
|
2198
|
+
};
|
|
2154
2199
|
function createBashTool(options = {}) {
|
|
2155
2200
|
const offline = options.networkPolicy === "offline";
|
|
2156
2201
|
const sandbox = options.sandbox === true;
|
|
2157
2202
|
const platform = options.platform ?? process.platform;
|
|
2203
|
+
const shell = resolveShell({ platform, env: process.env, exists: existsSync3, ...options.shellDeps });
|
|
2158
2204
|
const childEnv = offline ? offlineEnv() : void 0;
|
|
2205
|
+
const shellNote = shell ? `
|
|
2206
|
+
${SHELL_NOTE[shell.name]}` : "";
|
|
2159
2207
|
const description = `${offline ? `${BASH_DESCRIPTION}
|
|
2160
|
-
Network access is off (networkPolicy "offline"): internet commands such as curl, wget, git fetch/push/clone, package installs (npm, pip, ...), gh, and docker pull are blocked.` : BASH_DESCRIPTION}${sandbox ? "\nCommands run inside an OS sandbox: file writes are limited to the working directory and temp areas." : ""}`;
|
|
2208
|
+
Network access is off (networkPolicy "offline"): internet commands such as curl, wget, git fetch/push/clone, package installs (npm, pip, ...), gh, and docker pull are blocked.` : BASH_DESCRIPTION}${sandbox ? "\nCommands run inside an OS sandbox: file writes are limited to the working directory and temp areas." : ""}${shellNote}`;
|
|
2161
2209
|
return defineTool({
|
|
2162
2210
|
name: "bash",
|
|
2163
2211
|
description,
|
|
@@ -2197,7 +2245,7 @@ Network access is off (networkPolicy "offline"): internet commands such as curl,
|
|
|
2197
2245
|
}
|
|
2198
2246
|
if (input.background) {
|
|
2199
2247
|
if (!input.command) return { output: 'The "command" argument is required to start a background task.', isError: true };
|
|
2200
|
-
const task = startBackground(exec, ctx.cwd, childEnv);
|
|
2248
|
+
const task = startBackground(exec, ctx.cwd, childEnv, shell);
|
|
2201
2249
|
return {
|
|
2202
2250
|
output: `Background task #${task.id} started: ${input.command}
|
|
2203
2251
|
Poll it with {task_id: ${task.id}}; stop it with {task_id: ${task.id}, kill: true}.`
|
|
@@ -2210,7 +2258,8 @@ Poll it with {task_id: ${task.id}}; stop it with {task_id: ${task.id}, kill: tru
|
|
|
2210
2258
|
cwd: ctx.cwd,
|
|
2211
2259
|
timeoutMs: input.timeout_ms ?? 12e4,
|
|
2212
2260
|
signal: ctx.signal,
|
|
2213
|
-
env: childEnv
|
|
2261
|
+
env: childEnv,
|
|
2262
|
+
shell
|
|
2214
2263
|
});
|
|
2215
2264
|
const status = r.timedOut ? `[stopped: timeout after ${Math.round((input.timeout_ms ?? 12e4) / 1e3)} seconds]` : r.aborted ? "[cancelled by the user]" : `[exit code ${r.exitCode}]`;
|
|
2216
2265
|
return { output: `${r.output.trimEnd()}
|
|
@@ -2926,7 +2975,7 @@ function createReadTool(options = {}) {
|
|
|
2926
2975
|
var readTool = createReadTool({ vision: true });
|
|
2927
2976
|
|
|
2928
2977
|
// src/tools/write.ts
|
|
2929
|
-
import { existsSync as
|
|
2978
|
+
import { existsSync as existsSync4 } from "fs";
|
|
2930
2979
|
import { mkdir, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
2931
2980
|
import { dirname } from "path";
|
|
2932
2981
|
import { z as z7 } from "zod";
|
|
@@ -2941,16 +2990,16 @@ var writeTool = defineTool({
|
|
|
2941
2990
|
target: (input) => input.path,
|
|
2942
2991
|
async validate(input, ctx) {
|
|
2943
2992
|
const abs = resolvePath(ctx.cwd, input.path);
|
|
2944
|
-
return
|
|
2993
|
+
return existsSync4(abs) && !ctx.readFiles.has(abs) ? `${input.path} already exists. Read it with read before overwriting it.` : void 0;
|
|
2945
2994
|
},
|
|
2946
2995
|
async preview(input, ctx) {
|
|
2947
2996
|
const abs = resolvePath(ctx.cwd, input.path);
|
|
2948
|
-
const old =
|
|
2997
|
+
const old = existsSync4(abs) ? await readFile4(abs, "utf8") : "";
|
|
2949
2998
|
return formatDiff(diffLines(old, input.content));
|
|
2950
2999
|
},
|
|
2951
3000
|
async run(input, ctx) {
|
|
2952
3001
|
const abs = resolvePath(ctx.cwd, input.path);
|
|
2953
|
-
if (
|
|
3002
|
+
if (existsSync4(abs) && !ctx.readFiles.has(abs)) {
|
|
2954
3003
|
return { output: `${input.path} already exists. Read it with read before overwriting it.`, isError: true };
|
|
2955
3004
|
}
|
|
2956
3005
|
try {
|
|
@@ -3428,7 +3477,7 @@ ${t("This model may not support tool calling. Try another model with /model.")}`
|
|
|
3428
3477
|
};
|
|
3429
3478
|
|
|
3430
3479
|
// src/checkpoints.ts
|
|
3431
|
-
import { existsSync as
|
|
3480
|
+
import { existsSync as existsSync5, statSync } from "fs";
|
|
3432
3481
|
import { readFile as readFile5, rm, writeFile as writeFile3 } from "fs/promises";
|
|
3433
3482
|
var MAX_TURNS = 20;
|
|
3434
3483
|
var MAX_BYTES2 = 2 * 1024 * 1024;
|
|
@@ -3466,7 +3515,7 @@ var CheckpointStore = class {
|
|
|
3466
3515
|
if (!this.current) this.beginTurn();
|
|
3467
3516
|
const turn = this.current;
|
|
3468
3517
|
if (turn.has(path)) return;
|
|
3469
|
-
if (!
|
|
3518
|
+
if (!existsSync5(path)) turn.set(path, null);
|
|
3470
3519
|
else if (statSync(path).size > MAX_BYTES2) turn.set(path, "skipped");
|
|
3471
3520
|
else turn.set(path, await readFile5(path));
|
|
3472
3521
|
while (this.turns() > MAX_TURNS) this.history.shift();
|
|
@@ -3534,7 +3583,7 @@ var CheckpointStore = class {
|
|
|
3534
3583
|
continue;
|
|
3535
3584
|
}
|
|
3536
3585
|
try {
|
|
3537
|
-
if (!
|
|
3586
|
+
if (!existsSync5(path)) into.set(path, null);
|
|
3538
3587
|
else if (statSync(path).size > MAX_BYTES2) into.set(path, "skipped");
|
|
3539
3588
|
else into.set(path, await readFile5(path));
|
|
3540
3589
|
} catch {
|
|
@@ -3593,7 +3642,7 @@ import { z as z9 } from "zod";
|
|
|
3593
3642
|
|
|
3594
3643
|
// src/mcp/config.ts
|
|
3595
3644
|
import { createHash } from "crypto";
|
|
3596
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
3645
|
+
import { chmodSync as chmodSync2, existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
3597
3646
|
import { dirname as dirname2, join as join3, resolve as resolve3 } from "path";
|
|
3598
3647
|
var ENV_REF = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
|
|
3599
3648
|
function expandEnvVars(config, env) {
|
|
@@ -3616,14 +3665,14 @@ function expandEnvVars(config, env) {
|
|
|
3616
3665
|
|
|
3617
3666
|
// src/mcp/oauth.ts
|
|
3618
3667
|
import { spawn as spawn3 } from "child_process";
|
|
3619
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
3668
|
+
import { chmodSync as chmodSync3, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3620
3669
|
import { createServer } from "http";
|
|
3621
3670
|
import { dirname as dirname3, join as join4 } from "path";
|
|
3622
3671
|
import { auth } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
3623
3672
|
var oauthStorePath = (home) => join4(home, "mcp-oauth.json");
|
|
3624
3673
|
function readStore(home) {
|
|
3625
3674
|
const path = oauthStorePath(home);
|
|
3626
|
-
if (!
|
|
3675
|
+
if (!existsSync7(path)) return {};
|
|
3627
3676
|
try {
|
|
3628
3677
|
return JSON.parse(readFileSync4(path, "utf8"));
|
|
3629
3678
|
} catch {
|
|
@@ -3887,12 +3936,12 @@ var McpManager = class {
|
|
|
3887
3936
|
import { homedir as homedir2 } from "os";
|
|
3888
3937
|
|
|
3889
3938
|
// src/context.ts
|
|
3890
|
-
import { existsSync as
|
|
3939
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
3891
3940
|
import { dirname as dirname4, join as join5 } from "path";
|
|
3892
3941
|
var FILES = ["AGENTS.md", "BCCLI.md"];
|
|
3893
3942
|
function readIf(path) {
|
|
3894
3943
|
try {
|
|
3895
|
-
return
|
|
3944
|
+
return existsSync8(path) ? readFileSync5(path, "utf8").trim() : void 0;
|
|
3896
3945
|
} catch {
|
|
3897
3946
|
return void 0;
|
|
3898
3947
|
}
|
|
@@ -3916,7 +3965,7 @@ ${text}`);
|
|
|
3916
3965
|
}
|
|
3917
3966
|
function isGitRepo(cwd) {
|
|
3918
3967
|
for (let dir = cwd; ; dir = dirname4(dir)) {
|
|
3919
|
-
if (
|
|
3968
|
+
if (existsSync8(join5(dir, ".git"))) return true;
|
|
3920
3969
|
if (dirname4(dir) === dir) return false;
|
|
3921
3970
|
}
|
|
3922
3971
|
}
|
|
@@ -3960,7 +4009,7 @@ ${instructions}` : ""}`;
|
|
|
3960
4009
|
}
|
|
3961
4010
|
|
|
3962
4011
|
// src/extensions.ts
|
|
3963
|
-
import { existsSync as
|
|
4012
|
+
import { existsSync as existsSync9, readdirSync, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
|
|
3964
4013
|
import { basename, join as join6 } from "path";
|
|
3965
4014
|
function parseFrontmatter(text) {
|
|
3966
4015
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text);
|
|
@@ -3995,7 +4044,7 @@ function loadSkills(r) {
|
|
|
3995
4044
|
for (const dir of dirs(r, "skills")) {
|
|
3996
4045
|
for (const entry of list(dir)) {
|
|
3997
4046
|
const file = join6(dir, entry, "SKILL.md");
|
|
3998
|
-
if (!
|
|
4047
|
+
if (!existsSync9(file)) continue;
|
|
3999
4048
|
const { data } = parseFrontmatter(readFileSync6(file, "utf8"));
|
|
4000
4049
|
const name = str(data.name) || entry;
|
|
4001
4050
|
byName.set(name, { name, description: str(data.description) ?? "", dir: join6(dir, entry), file });
|
|
@@ -4102,7 +4151,7 @@ async function addProviderKey(providerId, key, deps) {
|
|
|
4102
4151
|
|
|
4103
4152
|
// src/session.ts
|
|
4104
4153
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
4105
|
-
import { appendFileSync, existsSync as
|
|
4154
|
+
import { appendFileSync, existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync7, rmSync, statSync as statSync3 } from "fs";
|
|
4106
4155
|
import { join as join8 } from "path";
|
|
4107
4156
|
function projectDir(home, cwd) {
|
|
4108
4157
|
const slug = cwd.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(-100) || "root";
|
|
@@ -4132,7 +4181,7 @@ var Session = class _Session {
|
|
|
4132
4181
|
}
|
|
4133
4182
|
static list(home, cwd) {
|
|
4134
4183
|
const dir = projectDir(home, cwd);
|
|
4135
|
-
if (!
|
|
4184
|
+
if (!existsSync10(dir)) return [];
|
|
4136
4185
|
return readdirSync2(dir).filter((f) => f.endsWith(".jsonl")).map((f) => {
|
|
4137
4186
|
const session = new _Session(join8(dir, f));
|
|
4138
4187
|
const first = session.load().find((m) => m.role === "user");
|
|
@@ -4153,7 +4202,7 @@ var Session = class _Session {
|
|
|
4153
4202
|
this.write({ t: "reset" });
|
|
4154
4203
|
}
|
|
4155
4204
|
load() {
|
|
4156
|
-
if (!
|
|
4205
|
+
if (!existsSync10(this.file)) return [];
|
|
4157
4206
|
let messages = [];
|
|
4158
4207
|
for (const line of readFileSync7(this.file, "utf8").split("\n")) {
|
|
4159
4208
|
if (!line.trim()) continue;
|
|
@@ -4403,14 +4452,14 @@ function createTodoTool(store) {
|
|
|
4403
4452
|
}
|
|
4404
4453
|
|
|
4405
4454
|
// src/tools/memory.ts
|
|
4406
|
-
import { existsSync as
|
|
4455
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
4407
4456
|
import { join as join9 } from "path";
|
|
4408
4457
|
import { z as z15 } from "zod";
|
|
4409
4458
|
|
|
4410
4459
|
// src/slash/memory.ts
|
|
4411
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
4460
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
4412
4461
|
function appendMemory(file, text) {
|
|
4413
|
-
const prefix =
|
|
4462
|
+
const prefix = existsSync11(file) && !readFileSync9(file, "utf8").endsWith("\n") ? "\n" : "";
|
|
4414
4463
|
appendFileSync2(file, `${prefix}- ${text.trim()}
|
|
4415
4464
|
`);
|
|
4416
4465
|
}
|
|
@@ -4430,7 +4479,7 @@ function createSaveMemoryTool(opts) {
|
|
|
4430
4479
|
const content = input.content.trim();
|
|
4431
4480
|
if (!content) return { output: "Memory content is empty.", isError: true };
|
|
4432
4481
|
const file = input.scope === "global" ? join9(opts.home, "BCCLI.md") : join9(ctx.cwd, "AGENTS.md");
|
|
4433
|
-
if (
|
|
4482
|
+
if (existsSync12(file)) {
|
|
4434
4483
|
const lines = readFileSync10(file, "utf8").split("\n");
|
|
4435
4484
|
if (lines.some((line) => line.trim() === `- ${content}`)) {
|
|
4436
4485
|
return { output: `Already saved to ${file}.` };
|
|
@@ -4711,7 +4760,7 @@ function createDiagnosticsTool(servers) {
|
|
|
4711
4760
|
}
|
|
4712
4761
|
|
|
4713
4762
|
// src/plugins.ts
|
|
4714
|
-
import { existsSync as
|
|
4763
|
+
import { existsSync as existsSync13 } from "fs";
|
|
4715
4764
|
import { createRequire } from "module";
|
|
4716
4765
|
import { isAbsolute as isAbsolute3, join as join11 } from "path";
|
|
4717
4766
|
import { z as z18 } from "zod";
|
|
@@ -4742,7 +4791,7 @@ function loadPlugins(specs, opts) {
|
|
|
4742
4791
|
} catch {
|
|
4743
4792
|
throw new ConfigError(t("Plugin not found: {spec}", { spec }));
|
|
4744
4793
|
}
|
|
4745
|
-
if (!
|
|
4794
|
+
if (!existsSync13(file)) throw new ConfigError(t("Plugin not found: {spec}", { spec }));
|
|
4746
4795
|
let mod;
|
|
4747
4796
|
try {
|
|
4748
4797
|
mod = require_(file);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EQQTTE2K.js";
|
|
5
5
|
import {
|
|
6
6
|
LOOPBACK_BIND,
|
|
7
7
|
MAX_FRAME_BYTES,
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
} from "./chunk-AS7VV7D3.js";
|
|
14
14
|
import {
|
|
15
15
|
createRuntime
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-M4IYXI3V.js";
|
|
17
17
|
import "./chunk-3HCOAJEQ.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-DBHDZ5EP.js";
|
|
19
19
|
import "./chunk-GAFJEQTJ.js";
|
|
20
20
|
import "./chunk-JROUQ5YS.js";
|
|
21
21
|
import {
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createRuntime,
|
|
4
4
|
lunaPtcAutoEnabled
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M4IYXI3V.js";
|
|
6
6
|
import "./chunk-3HCOAJEQ.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-DBHDZ5EP.js";
|
|
8
8
|
import "./chunk-GAFJEQTJ.js";
|
|
9
9
|
import "./chunk-JROUQ5YS.js";
|
|
10
10
|
import "./chunk-LN32JIZR.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
toolLabel,
|
|
10
10
|
verifyFollowup,
|
|
11
11
|
worktreeListText
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BUHWQU3V.js";
|
|
13
13
|
import {
|
|
14
14
|
BUILTIN_AGENTS,
|
|
15
15
|
appendMemory,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
renderBackgroundTasks,
|
|
22
22
|
runHooks,
|
|
23
23
|
validateGlobPattern
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-DBHDZ5EP.js";
|
|
25
25
|
import {
|
|
26
26
|
nextMode
|
|
27
27
|
} from "./chunk-GAFJEQTJ.js";
|