@botconnector/bccli 0.4.0-beta.9 → 0.4.1
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/README.en.md +253 -0
- package/README.md +93 -6
- package/dist/abort.d.ts +5 -0
- package/dist/acp-3PHBAI64.js +182 -0
- package/dist/acp.d.ts +27 -0
- package/dist/agent.d.ts +143 -0
- package/dist/agents.d.ts +4 -0
- package/dist/args-W6BNKY7K.js +13 -0
- package/dist/args.d.ts +51 -0
- package/dist/budget.d.ts +23 -0
- package/dist/checkpoints.d.ts +34 -0
- package/dist/{chunk-BFZXRKW5.js → chunk-24JN75FZ.js} +29 -7
- package/dist/chunk-45SDLMTV.js +341 -0
- package/dist/chunk-75BECX4F.js +56 -0
- package/dist/{chunk-SJH3YLW4.js → chunk-BC7UXFE4.js} +69 -6
- package/dist/chunk-BGXNR74O.js +733 -0
- package/dist/chunk-BKGFA2PT.js +8 -0
- package/dist/{chunk-CLN4Z5E3.js → chunk-BLOYFIAD.js} +6 -3
- package/dist/chunk-BXQQCUAC.js +145 -0
- package/dist/chunk-FLQPE4S5.js +373 -0
- package/dist/chunk-GN4W3T6E.js +76 -0
- package/dist/{chunk-7S6JXQCH.js → chunk-JHPGOAXU.js} +2 -1
- package/dist/chunk-MFHCQQEN.js +201 -0
- package/dist/chunk-MHIYLXJC.js +143 -0
- package/dist/chunk-PSO7R5AD.js +10 -0
- package/dist/chunk-PZRKU4UM.js +2143 -0
- package/dist/chunk-QZKLZELZ.js +64 -0
- package/dist/chunk-R5RE46CW.js +231 -0
- package/dist/chunk-UZWJQF67.js +500 -0
- package/dist/{chunk-DX7CZTBB.js → chunk-WI22M2ID.js} +14 -9
- package/dist/chunk-WNACAUDK.js +946 -0
- package/dist/chunk-XV7ZVL4J.js +235 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +150 -1382
- package/dist/clipboardImage.d.ts +17 -0
- package/dist/commands.d.ts +16 -0
- package/dist/completion-HPPFDAPB.js +125 -0
- package/dist/completion.d.ts +14 -0
- package/dist/{config-YUNKPCNB.js → config-DIDLDONU.js} +5 -2
- package/dist/config-IU76CPK2.js +34 -0
- package/dist/config.d.ts +97 -0
- package/dist/context.d.ts +13 -0
- package/dist/contextWindow.d.ts +3 -0
- package/dist/diff.d.ts +7 -0
- package/dist/exit.d.ts +9 -0
- package/dist/extensions.d.ts +34 -0
- package/dist/ghBotCli-E3VPHNZY.js +677 -0
- package/dist/ghBotCli.d.ts +9 -0
- package/dist/ghBotDispatch.d.ts +68 -0
- package/dist/ghBotRunner.d.ts +82 -0
- package/dist/ghBotServe.d.ts +21 -0
- package/dist/ghBotWebhook.d.ts +45 -0
- package/dist/hooks.d.ts +27 -0
- package/dist/i18n/id.d.ts +1 -0
- package/dist/i18n.d.ts +16 -0
- package/dist/integrationCli-Q2YPDTPG.js +685 -0
- package/dist/integrationCli.d.ts +9 -0
- package/dist/keybinds.d.ts +22 -0
- package/dist/login-FP3BB44A.js +16 -0
- package/dist/login.d.ts +19 -0
- package/dist/lsp.d.ts +47 -0
- package/dist/mcp/catalog.d.ts +14 -0
- package/dist/mcp/config.d.ts +36 -0
- package/dist/mcp/manager.d.ts +34 -0
- package/dist/mcp/oauth.d.ts +82 -0
- package/dist/{mcpCli-DZWQPTOS.js → mcpCli-SNBDUWJN.js} +42 -9
- package/dist/mcpCli.d.ts +3 -0
- package/dist/mcpServer/serve.d.ts +8 -0
- package/dist/mcpServer/server.d.ts +19 -0
- package/dist/models.d.ts +13 -0
- package/dist/modelsCli-CZ2HNGKR.js +36 -0
- package/dist/modelsCli.d.ts +15 -0
- package/dist/npmRunner-LU43GM3W.js +46 -0
- package/dist/npmRunner.d.ts +21 -0
- package/dist/oauthLogin-6FWQABJ7.js +210 -0
- package/dist/oauthLogin.d.ts +47 -0
- package/dist/permissions.d.ts +30 -0
- package/dist/pluginSpec.d.ts +25 -0
- package/dist/plugins.d.ts +45 -0
- package/dist/pluginsCli-LPIUUDWB.js +284 -0
- package/dist/pluginsCli.d.ts +16 -0
- package/dist/prCli-5IMV3VNQ.js +78 -0
- package/dist/prCli.d.ts +33 -0
- package/dist/presets.d.ts +8 -0
- package/dist/print.d.ts +14 -0
- package/dist/provider.d.ts +140 -0
- package/dist/providerCli-NMUFXAAS.js +15 -0
- package/dist/providerCli.d.ts +17 -0
- package/dist/providers.d.ts +6 -0
- package/dist/reasoning.d.ts +12 -0
- package/dist/repomap.d.ts +10 -0
- package/dist/sdk.d.ts +57 -0
- package/dist/sdk.js +5571 -0
- package/dist/serve-KWOECK5W.js +178 -0
- package/dist/serve-X2ZV4S5U.js +521 -0
- package/dist/serve.d.ts +37 -0
- package/dist/serveHeartbeat.d.ts +14 -0
- package/dist/serveProtocol.d.ts +47 -0
- package/dist/session-GKEXDJKZ.js +12 -0
- package/dist/session.d.ts +30 -0
- package/dist/setup-OV3NWQN5.js +24 -0
- package/dist/setup.d.ts +74 -0
- package/dist/slash/copy.d.ts +1 -0
- package/dist/slash/diff.d.ts +1 -0
- package/dist/slash/doctor.d.ts +18 -0
- package/dist/slash/export.d.ts +2 -0
- package/dist/slash/info.d.ts +45 -0
- package/dist/slash/memory.d.ts +10 -0
- package/dist/statsCli-CF3R7ATL.js +353 -0
- package/dist/statsCli.d.ts +62 -0
- package/dist/textToolCalls.d.ts +6 -0
- package/dist/thinking.d.ts +17 -0
- package/dist/tokenBudget.d.ts +22 -0
- package/dist/tools/bash.d.ts +52 -0
- package/dist/tools/diagnostics.d.ts +5 -0
- package/dist/tools/edit.d.ts +7 -0
- package/dist/tools/fetch.d.ts +41 -0
- package/dist/tools/glob.d.ts +5 -0
- package/dist/tools/globSafety.d.ts +7 -0
- package/dist/tools/grep.d.ts +13 -0
- package/dist/tools/ignore.d.ts +2 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/memory.d.ts +13 -0
- package/dist/tools/paths.d.ts +2 -0
- package/dist/tools/plan.d.ts +10 -0
- package/dist/tools/read.d.ts +16 -0
- package/dist/tools/repomap.d.ts +2 -0
- package/dist/tools/sandbox.d.ts +12 -0
- package/dist/tools/shell.d.ts +18 -0
- package/dist/tools/skill.d.ts +3 -0
- package/dist/tools/task.d.ts +28 -0
- package/dist/tools/todo.d.ts +13 -0
- package/dist/tools/types.d.ts +52 -0
- package/dist/tools/websearch.d.ts +9 -0
- package/dist/tools/write.d.ts +5 -0
- package/dist/transferCli-YUFPI6AH.js +71 -0
- package/dist/transferCli.d.ts +23 -0
- package/dist/ui/App.d.ts +7 -0
- package/dist/ui/DiffView.d.ts +3 -0
- package/dist/ui/EditableText.d.ts +7 -0
- package/dist/ui/LinePrompt.d.ts +6 -0
- package/dist/ui/ListPicker.d.ts +11 -0
- package/dist/ui/Markdown.d.ts +8 -0
- package/dist/ui/McpMenu.d.ts +11 -0
- package/dist/ui/ModelPicker.d.ts +6 -0
- package/dist/ui/PermissionPrompt.d.ts +5 -0
- package/dist/ui/PlanApproval.d.ts +5 -0
- package/dist/ui/PromptInput.d.ts +18 -0
- package/dist/ui/ProviderMenu.d.ts +10 -0
- package/dist/ui/Spinner.d.ts +4 -0
- package/dist/ui/StatusBar.d.ts +9 -0
- package/dist/ui/TodoList.d.ts +4 -0
- package/dist/ui/ToolBlock.d.ts +14 -0
- package/dist/ui/complete.d.ts +1 -0
- package/dist/ui/focusReport.d.ts +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/lineEdit.d.ts +42 -0
- package/dist/ui/replay.d.ts +4 -0
- package/dist/ui/table.d.ts +20 -0
- package/dist/ui/theme.d.ts +5 -0
- package/dist/ui/thinkingMouse.d.ts +33 -0
- package/dist/ui/transcript.d.ts +55 -0
- package/dist/ui/vim.d.ts +26 -0
- package/dist/ui-IVIFNUCC.js +2367 -0
- package/dist/update-TZ2G6KQ3.js +145 -0
- package/dist/update.d.ts +30 -0
- package/dist/verify.d.ts +16 -0
- package/dist/version.d.ts +1 -0
- package/dist/webBudget.d.ts +25 -0
- package/dist/worktree.d.ts +12 -0
- package/package.json +42 -8
- package/dist/args-JPVSGCGY.js +0 -12
- package/dist/chunk-2MGINW4O.js +0 -114
- package/dist/chunk-ELML4KVQ.js +0 -76
- package/dist/chunk-ISGBGFSU.js +0 -52
- package/dist/chunk-KV27KTOX.js +0 -254
- package/dist/chunk-U7GK73CK.js +0 -341
- package/dist/chunk-ZYCYTEKD.js +0 -96
- package/dist/integrationCli-BGT5UZU4.js +0 -223
- package/dist/login-6K32PIXV.js +0 -9
- package/dist/providerCli-Q7LRM2NP.js +0 -12
- package/dist/session-7UB77CEG.js +0 -9
- package/dist/ui-6GTQUJOE.js +0 -1415
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
VERSION
|
|
4
|
+
} from "./chunk-BKGFA2PT.js";
|
|
5
|
+
import {
|
|
6
|
+
t
|
|
7
|
+
} from "./chunk-UZWJQF67.js";
|
|
8
|
+
|
|
9
|
+
// src/update.ts
|
|
10
|
+
import { spawnSync } from "child_process";
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
|
|
12
|
+
import { dirname, join } from "path";
|
|
13
|
+
var REGISTRY_URL = "https://registry.npmjs.org/-/package/@botconnector/bccli/dist-tags";
|
|
14
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
15
|
+
function splitVersion(v) {
|
|
16
|
+
const i = v.indexOf("-");
|
|
17
|
+
const coreStr = i < 0 ? v : v.slice(0, i);
|
|
18
|
+
const preStr = i < 0 ? "" : v.slice(i + 1);
|
|
19
|
+
return {
|
|
20
|
+
core: coreStr.split(".").map((p) => Number.parseInt(p, 10) || 0),
|
|
21
|
+
pre: preStr ? preStr.split(".") : []
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function compareVersions(a, b) {
|
|
25
|
+
const A = splitVersion(a);
|
|
26
|
+
const B = splitVersion(b);
|
|
27
|
+
for (let i = 0; i < Math.max(A.core.length, B.core.length); i++) {
|
|
28
|
+
const x = A.core[i] ?? 0;
|
|
29
|
+
const y = B.core[i] ?? 0;
|
|
30
|
+
if (x !== y) return x < y ? -1 : 1;
|
|
31
|
+
}
|
|
32
|
+
if (!A.pre.length && !B.pre.length) return 0;
|
|
33
|
+
if (!A.pre.length) return 1;
|
|
34
|
+
if (!B.pre.length) return -1;
|
|
35
|
+
for (let i = 0; i < Math.max(A.pre.length, B.pre.length); i++) {
|
|
36
|
+
const x = A.pre[i];
|
|
37
|
+
const y = B.pre[i];
|
|
38
|
+
if (x === void 0) return -1;
|
|
39
|
+
if (y === void 0) return 1;
|
|
40
|
+
const nx = Number.parseInt(x, 10);
|
|
41
|
+
const ny = Number.parseInt(y, 10);
|
|
42
|
+
if (String(nx) === x && String(ny) === y) {
|
|
43
|
+
if (nx !== ny) return nx < ny ? -1 : 1;
|
|
44
|
+
} else if (x !== y) {
|
|
45
|
+
return x < y ? -1 : 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
function channelFor(version) {
|
|
51
|
+
return version.includes("-") ? "next" : "latest";
|
|
52
|
+
}
|
|
53
|
+
function cachePath(home) {
|
|
54
|
+
return join(home, "update-check.json");
|
|
55
|
+
}
|
|
56
|
+
function readCache(home) {
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(readFileSync(cachePath(home), "utf8"));
|
|
59
|
+
return typeof parsed?.checkedAt === "string" ? parsed : void 0;
|
|
60
|
+
} catch {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function writeCache(home, cache) {
|
|
65
|
+
mkdirSync(home, { recursive: true });
|
|
66
|
+
const tmp = `${cachePath(home)}.tmp`;
|
|
67
|
+
writeFileSync(tmp, JSON.stringify(cache));
|
|
68
|
+
renameSync(tmp, cachePath(home));
|
|
69
|
+
}
|
|
70
|
+
function dueForCheck(cache, now, intervalMs = CHECK_INTERVAL_MS) {
|
|
71
|
+
if (!cache) return true;
|
|
72
|
+
const at = Date.parse(cache.checkedAt);
|
|
73
|
+
if (!Number.isFinite(at)) return true;
|
|
74
|
+
return now.getTime() - at >= intervalMs;
|
|
75
|
+
}
|
|
76
|
+
function updateNotice(current, latest) {
|
|
77
|
+
if (!latest || latest.length > 64 || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(latest) || compareVersions(current, latest) >= 0) return void 0;
|
|
78
|
+
return t("A new bccli is available: {latest} (you have {current}). Run: bccli update", { latest, current });
|
|
79
|
+
}
|
|
80
|
+
function notifyOnce(home, cache) {
|
|
81
|
+
const message = updateNotice(VERSION, cache?.latest);
|
|
82
|
+
if (!message || !cache?.latest || cache.notified === cache.latest) return void 0;
|
|
83
|
+
writeCache(home, { ...cache, notified: cache.latest });
|
|
84
|
+
return message;
|
|
85
|
+
}
|
|
86
|
+
async function checkForUpdate(deps) {
|
|
87
|
+
try {
|
|
88
|
+
const cached = readCache(deps.home);
|
|
89
|
+
if (!dueForCheck(cached, deps.now)) return notifyOnce(deps.home, cached);
|
|
90
|
+
const res = await deps.fetch(REGISTRY_URL, { signal: AbortSignal.timeout(deps.timeoutMs ?? 3e3) });
|
|
91
|
+
if (!res.ok) return notifyOnce(deps.home, cached);
|
|
92
|
+
const tags = await res.json();
|
|
93
|
+
const latest = tags[channelFor(VERSION)] ?? tags.latest;
|
|
94
|
+
const updated = { checkedAt: deps.now.toISOString(), latest, notified: cached?.notified };
|
|
95
|
+
writeCache(deps.home, updated);
|
|
96
|
+
return notifyOnce(deps.home, updated);
|
|
97
|
+
} catch {
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function updateSpawnCommand(version, platform = process.platform, nodeExecPath = process.execPath, targetVersion) {
|
|
102
|
+
const spec = `@botconnector/bccli@${targetVersion ?? channelFor(version)}`;
|
|
103
|
+
if (platform !== "win32") return { command: "npm", args: ["i", "-g", spec] };
|
|
104
|
+
const npmCli = join(dirname(nodeExecPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
105
|
+
return { command: nodeExecPath, args: [npmCli, "i", "-g", spec], npmCli };
|
|
106
|
+
}
|
|
107
|
+
async function runUpdateCommand(deps) {
|
|
108
|
+
const current = deps.env.BCCLI_VERSION_OVERRIDE ?? VERSION;
|
|
109
|
+
let target;
|
|
110
|
+
try {
|
|
111
|
+
const response = await (deps.fetch ?? fetch)(REGISTRY_URL, {
|
|
112
|
+
signal: AbortSignal.timeout(8e3),
|
|
113
|
+
cache: "no-store",
|
|
114
|
+
headers: { "cache-control": "no-cache" }
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
117
|
+
const tags = await response.json();
|
|
118
|
+
target = tags[channelFor(current)];
|
|
119
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(target ?? "")) throw new Error("invalid registry version");
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error(`Could not verify BCCLI update version: ${String(error)}. No changes made.`);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
if (compareVersions(target, current) <= 0) {
|
|
125
|
+
console.log(`BCCLI ${current} is already up to date (registry: ${target}); no changes made.`);
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
const spec = updateSpawnCommand(current, deps.platform, deps.nodeExecPath, target);
|
|
129
|
+
if (spec.npmCli && !existsSync(spec.npmCli)) {
|
|
130
|
+
console.error(`npm CLI was not found at ${spec.npmCli}. Update manually with: npm install -g @botconnector/bccli@${channelFor(deps.env.BCCLI_VERSION_OVERRIDE ?? VERSION)}`);
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
133
|
+
const r = (deps.spawn ?? spawnSync)(spec.command, spec.args, { stdio: "inherit", env: deps.env, shell: false });
|
|
134
|
+
if (r.error) console.error(`BCCLI update failed: ${r.error.message}. Try: npm install -g @botconnector/bccli@${channelFor(deps.env.BCCLI_VERSION_OVERRIDE ?? VERSION)}`);
|
|
135
|
+
return typeof r.status === "number" ? r.status : 1;
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
channelFor,
|
|
139
|
+
checkForUpdate,
|
|
140
|
+
compareVersions,
|
|
141
|
+
dueForCheck,
|
|
142
|
+
runUpdateCommand,
|
|
143
|
+
updateNotice,
|
|
144
|
+
updateSpawnCommand
|
|
145
|
+
};
|
package/dist/update.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
export interface UpdateCache {
|
|
3
|
+
checkedAt: string;
|
|
4
|
+
latest?: string;
|
|
5
|
+
notified?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Simplified semver: numeric cores, prerelease sorts below release, numeric prerelease parts compare numerically. */
|
|
8
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
9
|
+
export declare function channelFor(version: string): 'next' | 'latest';
|
|
10
|
+
export declare function dueForCheck(cache: UpdateCache | undefined, now: Date, intervalMs?: number): boolean;
|
|
11
|
+
export declare function updateNotice(current: string, latest: string | undefined): string | undefined;
|
|
12
|
+
/** Best-effort registry check with a 24h cache; never throws, never blocks startup for long. */
|
|
13
|
+
export declare function checkForUpdate(deps: {
|
|
14
|
+
home: string;
|
|
15
|
+
fetch: typeof fetch;
|
|
16
|
+
now: Date;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
}): Promise<string | undefined>;
|
|
19
|
+
export declare function updateSpawnCommand(version: string, platform?: NodeJS.Platform, nodeExecPath?: string, targetVersion?: string): {
|
|
20
|
+
command: string;
|
|
21
|
+
args: string[];
|
|
22
|
+
npmCli?: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function runUpdateCommand(deps: {
|
|
25
|
+
env: NodeJS.ProcessEnv;
|
|
26
|
+
spawn?: typeof spawnSync;
|
|
27
|
+
platform?: NodeJS.Platform;
|
|
28
|
+
nodeExecPath?: string;
|
|
29
|
+
fetch?: typeof fetch;
|
|
30
|
+
}): Promise<number>;
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { runCommand } from './tools/bash';
|
|
2
|
+
export interface VerifyFailure {
|
|
3
|
+
cmd: string;
|
|
4
|
+
exitCode: number;
|
|
5
|
+
output: string;
|
|
6
|
+
}
|
|
7
|
+
/** Fix rounds per user turn; keeps a failing verify command from looping forever. */
|
|
8
|
+
export declare const MAX_VERIFY_ROUNDS = 2;
|
|
9
|
+
export declare function runVerify(commands: string[], opts: {
|
|
10
|
+
cwd: string;
|
|
11
|
+
env: NodeJS.ProcessEnv;
|
|
12
|
+
signal: AbortSignal;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
run?: typeof runCommand;
|
|
15
|
+
}): Promise<VerifyFailure[]>;
|
|
16
|
+
export declare function verifyFollowup(failures: VerifyFailure[], maxBytes?: number): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION: string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ChatMessage } from './provider';
|
|
2
|
+
export declare const isStub: (content: string) => boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Replaces old `fetch` results with a one-line stub, in one batch and only once they add up to more than
|
|
5
|
+
* PRUNE_MIN_TOKENS, so the prompt prefix (and its cache) changes rarely. The newest KEEP_TOKENS worth stay intact.
|
|
6
|
+
*/
|
|
7
|
+
export declare function pruneOldFetches(messages: ChatMessage[]): boolean;
|
|
8
|
+
export interface WebBudgetLimits {
|
|
9
|
+
perTurn?: number;
|
|
10
|
+
sessionChars?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class WebBudget {
|
|
13
|
+
private fetches;
|
|
14
|
+
private chars;
|
|
15
|
+
private readonly perTurn;
|
|
16
|
+
private readonly sessionChars;
|
|
17
|
+
constructor(limits?: WebBudgetLimits);
|
|
18
|
+
startTurn(): void;
|
|
19
|
+
/** Gives back a reservation, e.g. when the fetch was served from cache and cost nothing. */
|
|
20
|
+
refund(): void;
|
|
21
|
+
reset(): void;
|
|
22
|
+
/** Reserves one fetch; returns the refusal to show the model when over budget. */
|
|
23
|
+
take(): string | undefined;
|
|
24
|
+
record(chars: number): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface WorktreePlan {
|
|
2
|
+
path: string;
|
|
3
|
+
created: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolve (creating when needed) the sibling worktree for `-w <name>`: always derived from the
|
|
7
|
+
* MAIN checkout, so running inside an existing worktree nests nothing. The returned path becomes
|
|
8
|
+
* the session cwd, so config, prompts, sessions, and permissions all follow it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveWorktree(cwd: string, name: string, bin?: string): Promise<WorktreePlan>;
|
|
11
|
+
/** Read-only status for /worktree: what exists and how to remove it safely. */
|
|
12
|
+
export declare function worktreeListText(cwd: string, bin?: string): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botconnector/bccli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "BCCLI — BotConnector AI coding agent for the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,26 +18,60 @@
|
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "tsup",
|
|
21
|
+
"build": "tsup && tsc -p tsconfig.build.json",
|
|
22
22
|
"typecheck": "tsc --noEmit",
|
|
23
|
-
"lint": "biome lint src test",
|
|
24
|
-
"test": "vitest run"
|
|
23
|
+
"lint": "biome lint --error-on-warnings src test",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"coverage": "vitest run --coverage"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
28
29
|
"diff": "^9.0.0",
|
|
29
|
-
"fast-glob": "^3.3.3",
|
|
30
30
|
"ink": "^7.1.1",
|
|
31
|
+
"openai": "^7.27.0",
|
|
31
32
|
"react": "^19.3.0",
|
|
33
|
+
"undici": "^8.12.1",
|
|
34
|
+
"ws": "^8.22.0",
|
|
35
|
+
"yaml": "^2.9.1",
|
|
32
36
|
"zod": "^4.6.5"
|
|
33
37
|
},
|
|
34
38
|
"devDependencies": {
|
|
35
39
|
"@biomejs/biome": "^2.5.14",
|
|
36
40
|
"@types/node": "^26.6.3",
|
|
37
41
|
"@types/react": "^19.3.0",
|
|
42
|
+
"@types/ws": "^8.18.2",
|
|
43
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
38
44
|
"ink-testing-library": "^4.0.0",
|
|
39
|
-
"tsup": "^
|
|
45
|
+
"tsup": "^9.0.0",
|
|
40
46
|
"typescript": "^7.0.2",
|
|
41
47
|
"vitest": "^5.0.2"
|
|
42
|
-
}
|
|
48
|
+
},
|
|
49
|
+
"overrides": {
|
|
50
|
+
"esbuild": "0.28.2"
|
|
51
|
+
},
|
|
52
|
+
"main": "dist/sdk.js",
|
|
53
|
+
"types": "dist/sdk.d.ts",
|
|
54
|
+
"exports": {
|
|
55
|
+
".": {
|
|
56
|
+
"types": "./dist/sdk.d.ts",
|
|
57
|
+
"default": "./dist/sdk.js"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"keywords": [
|
|
61
|
+
"bccli",
|
|
62
|
+
"ai",
|
|
63
|
+
"coding-agent",
|
|
64
|
+
"agent",
|
|
65
|
+
"cli",
|
|
66
|
+
"tui",
|
|
67
|
+
"terminal",
|
|
68
|
+
"mcp",
|
|
69
|
+
"openai",
|
|
70
|
+
"indonesia"
|
|
71
|
+
],
|
|
72
|
+
"author": "BotConnector (https://botconnector.id)",
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/farijarifriyanto-debug/bccli/issues"
|
|
75
|
+
},
|
|
76
|
+
"homepage": "https://github.com/farijarifriyanto-debug/bccli#readme"
|
|
43
77
|
}
|
package/dist/args-JPVSGCGY.js
DELETED
package/dist/chunk-2MGINW4O.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/presets.ts
|
|
4
|
-
var PRESETS = [
|
|
5
|
-
{ id: "bc-cloud", name: "BotConnector Cloud", baseURL: "https://api.botconnector.id/v1", apiKeyEnv: "BOTCONNECTOR_API_KEY" },
|
|
6
|
-
{ id: "openrouter", name: "OpenRouter", baseURL: "https://openrouter.ai/api/v1", apiKeyEnv: "OPENROUTER_API_KEY" },
|
|
7
|
-
{ id: "openai", name: "OpenAI", baseURL: "https://api.openai.com/v1", apiKeyEnv: "OPENAI_API_KEY" },
|
|
8
|
-
{ id: "gemini", name: "Google Gemini", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", apiKeyEnv: "GEMINI_API_KEY" },
|
|
9
|
-
{ id: "deepseek", name: "DeepSeek", baseURL: "https://api.deepseek.com/v1", apiKeyEnv: "DEEPSEEK_API_KEY" },
|
|
10
|
-
{ id: "groq", name: "Groq", baseURL: "https://api.groq.com/openai/v1", apiKeyEnv: "GROQ_API_KEY" },
|
|
11
|
-
{ id: "ollama-cloud", name: "Ollama Cloud", baseURL: "https://ollama.com/v1", apiKeyEnv: "OLLAMA_API_KEY" },
|
|
12
|
-
{ id: "ollama", name: "Ollama lokal", baseURL: "http://127.0.0.1:11434/v1", local: true },
|
|
13
|
-
{ id: "lmstudio", name: "LM Studio lokal", baseURL: "http://127.0.0.1:1234/v1", local: true }
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
// src/config.ts
|
|
17
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
18
|
-
import { homedir } from "os";
|
|
19
|
-
import { join } from "path";
|
|
20
|
-
var ConfigError = class extends Error {
|
|
21
|
-
};
|
|
22
|
-
var DEFAULT_CONFIG = {
|
|
23
|
-
model: "bc-cloud/glm-5.3-flash",
|
|
24
|
-
permissionMode: "default",
|
|
25
|
-
reasoning: "auto",
|
|
26
|
-
providers: Object.fromEntries(PRESETS.map((p) => [p.id, { baseURL: p.baseURL, apiKeyEnv: p.apiKeyEnv }])),
|
|
27
|
-
allow: []
|
|
28
|
-
};
|
|
29
|
-
function bccliHome(env = process.env) {
|
|
30
|
-
return env.BCCLI_HOME ?? join(homedir(), ".bccli");
|
|
31
|
-
}
|
|
32
|
-
function readJsonConfig(path) {
|
|
33
|
-
if (!existsSync(path)) return {};
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
36
|
-
} catch (error) {
|
|
37
|
-
throw new ConfigError(`Config tidak valid: ${path} (${error.message})`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function untrustedProviders(project, known) {
|
|
41
|
-
const out = {};
|
|
42
|
-
for (const [id, provider] of Object.entries(project.providers ?? {})) {
|
|
43
|
-
if (known[id] || typeof provider?.baseURL !== "string") continue;
|
|
44
|
-
out[id] = { baseURL: provider.baseURL };
|
|
45
|
-
}
|
|
46
|
-
return out;
|
|
47
|
-
}
|
|
48
|
-
function loadConfig(cwd, env = process.env) {
|
|
49
|
-
const global = readJsonConfig(join(bccliHome(env), "config.json"));
|
|
50
|
-
const project = readJsonConfig(join(cwd, ".bccli", "config.json"));
|
|
51
|
-
const known = { ...DEFAULT_CONFIG.providers, ...global.providers };
|
|
52
|
-
const fromProject = untrustedProviders(project, known);
|
|
53
|
-
return {
|
|
54
|
-
model: project.model ?? global.model ?? DEFAULT_CONFIG.model,
|
|
55
|
-
permissionMode: global.permissionMode ?? DEFAULT_CONFIG.permissionMode,
|
|
56
|
-
reasoning: global.reasoning ?? DEFAULT_CONFIG.reasoning,
|
|
57
|
-
providers: { ...known, ...fromProject },
|
|
58
|
-
projectProviders: Object.keys(fromProject),
|
|
59
|
-
allow: [...global.allow ?? []]
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function readCredentials(env = process.env) {
|
|
63
|
-
const path = join(bccliHome(env), "credentials");
|
|
64
|
-
if (!existsSync(path)) return {};
|
|
65
|
-
try {
|
|
66
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
67
|
-
} catch {
|
|
68
|
-
return {};
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function saveCredential(providerId, key, env = process.env) {
|
|
72
|
-
const home = bccliHome(env);
|
|
73
|
-
mkdirSync(home, { recursive: true });
|
|
74
|
-
const path = join(home, "credentials");
|
|
75
|
-
writeFileSync(path, JSON.stringify({ ...readCredentials(env), [providerId]: key }, null, 2), { mode: 384 });
|
|
76
|
-
chmodSync(path, 384);
|
|
77
|
-
}
|
|
78
|
-
function resolveModel(config, modelRef, env = process.env) {
|
|
79
|
-
const slash = modelRef.indexOf("/");
|
|
80
|
-
if (slash <= 0 || slash === modelRef.length - 1) {
|
|
81
|
-
throw new ConfigError(`Model harus berformat provider/model, contoh bc-cloud/glm-5.3-flash (dapat: ${modelRef})`);
|
|
82
|
-
}
|
|
83
|
-
const providerId = modelRef.slice(0, slash);
|
|
84
|
-
const provider = config.providers[providerId];
|
|
85
|
-
if (!provider) {
|
|
86
|
-
throw new ConfigError(`Provider "${providerId}" tidak ada di config. Tersedia: ${Object.keys(config.providers).join(", ")}`);
|
|
87
|
-
}
|
|
88
|
-
const apiKey = (provider.apiKeyEnv ? env[provider.apiKeyEnv] : void 0) || readCredentials(env)[providerId] || void 0;
|
|
89
|
-
if (provider.apiKeyEnv && !apiKey) {
|
|
90
|
-
throw new ConfigError(`API key untuk ${providerId} belum ada. Jalankan \`bccli login\` atau set env ${provider.apiKeyEnv}.`);
|
|
91
|
-
}
|
|
92
|
-
return { providerId, model: modelRef.slice(slash + 1), baseURL: provider.baseURL.replace(/\/+$/, ""), apiKey };
|
|
93
|
-
}
|
|
94
|
-
function removeCredential(providerId, env = process.env) {
|
|
95
|
-
const creds = readCredentials(env);
|
|
96
|
-
if (!(providerId in creds)) return false;
|
|
97
|
-
delete creds[providerId];
|
|
98
|
-
const path = join(bccliHome(env), "credentials");
|
|
99
|
-
writeFileSync(path, JSON.stringify(creds, null, 2), { mode: 384 });
|
|
100
|
-
chmodSync(path, 384);
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export {
|
|
105
|
-
PRESETS,
|
|
106
|
-
ConfigError,
|
|
107
|
-
bccliHome,
|
|
108
|
-
readJsonConfig,
|
|
109
|
-
loadConfig,
|
|
110
|
-
readCredentials,
|
|
111
|
-
saveCredential,
|
|
112
|
-
resolveModel,
|
|
113
|
-
removeCredential
|
|
114
|
-
};
|
package/dist/chunk-ELML4KVQ.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/permissions.ts
|
|
4
|
-
import { isAbsolute, relative, resolve, sep } from "path";
|
|
5
|
-
var MODE_ORDER = ["default", "acceptEdits", "plan", "allowAll"];
|
|
6
|
-
function nextMode(mode) {
|
|
7
|
-
return MODE_ORDER[(MODE_ORDER.indexOf(mode) + 1) % MODE_ORDER.length];
|
|
8
|
-
}
|
|
9
|
-
var TWO_WORD = /* @__PURE__ */ new Set(["npm", "npx", "pnpm", "yarn", "bun", "git", "cargo", "go", "docker", "python", "python3", "uv", "make"]);
|
|
10
|
-
function commandKey(segment) {
|
|
11
|
-
const words = segment.trim().split(/\s+/);
|
|
12
|
-
return TWO_WORD.has(words[0]) && words[1] ? `${words[0]} ${words[1]}` : words[0];
|
|
13
|
-
}
|
|
14
|
-
var Permissions = class {
|
|
15
|
-
constructor(mode, rules = [], cwd = process.cwd()) {
|
|
16
|
-
this.mode = mode;
|
|
17
|
-
this.cwd = cwd;
|
|
18
|
-
this.rules = new Set(rules);
|
|
19
|
-
this.configRules = new Set(rules);
|
|
20
|
-
}
|
|
21
|
-
mode;
|
|
22
|
-
cwd;
|
|
23
|
-
rules;
|
|
24
|
-
configRules;
|
|
25
|
-
/** Edits may only be auto-allowed inside the project and outside .git. */
|
|
26
|
-
editInProject(target) {
|
|
27
|
-
const rel = relative(this.cwd, resolve(this.cwd, target));
|
|
28
|
-
if (!rel || rel.startsWith("..") || isAbsolute(rel)) return false;
|
|
29
|
-
return !rel.split(sep).includes(".git") && !rel.split("/").includes(".git");
|
|
30
|
-
}
|
|
31
|
-
/** Rules that "[a] allow for this session" would add; undefined when it must always be asked. */
|
|
32
|
-
rulesFor(req) {
|
|
33
|
-
if (req.kind === "edit") return this.editInProject(req.target) ? ["edit(project)"] : void 0;
|
|
34
|
-
if (req.kind === "fetch") {
|
|
35
|
-
try {
|
|
36
|
-
return [`fetch(${new URL(req.target).hostname})`];
|
|
37
|
-
} catch {
|
|
38
|
-
return void 0;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (req.kind === "bash") {
|
|
42
|
-
if (/`|\$\(|[<>]|^\s*[({]/.test(req.target)) return void 0;
|
|
43
|
-
const segments = req.target.split(/&&|\|\||[;&|\n]/).map((s) => s.trim()).filter(Boolean);
|
|
44
|
-
if (!segments.length) return void 0;
|
|
45
|
-
return [...new Set(segments.map((s) => `bash(${commandKey(s)})`))];
|
|
46
|
-
}
|
|
47
|
-
if (req.kind === "mcp") return [`mcp(${req.tool})`];
|
|
48
|
-
return [];
|
|
49
|
-
}
|
|
50
|
-
check(req) {
|
|
51
|
-
if (req.kind === "read") return "allow";
|
|
52
|
-
if (this.mode === "allowAll") return "allow";
|
|
53
|
-
if (this.mode === "plan") return "deny";
|
|
54
|
-
if (this.rules.has(req.kind)) return "allow";
|
|
55
|
-
const needed = this.rulesFor(req);
|
|
56
|
-
if (!needed) return "ask";
|
|
57
|
-
if (req.kind === "edit" && this.mode === "acceptEdits") return "allow";
|
|
58
|
-
return needed.every((rule) => this.rules.has(rule)) ? "allow" : "ask";
|
|
59
|
-
}
|
|
60
|
-
list() {
|
|
61
|
-
return [...this.rules].map((rule) => ({ rule, source: this.configRules.has(rule) ? "config" : "session" }));
|
|
62
|
-
}
|
|
63
|
-
/** Removes a session grant; rules from config/flags stay until the user edits them. */
|
|
64
|
-
revoke(rule) {
|
|
65
|
-
if (!this.configRules.has(rule)) this.rules.delete(rule);
|
|
66
|
-
}
|
|
67
|
-
allowForSession(req) {
|
|
68
|
-
for (const rule of this.rulesFor(req) ?? []) this.rules.add(rule);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export {
|
|
73
|
-
MODE_ORDER,
|
|
74
|
-
nextMode,
|
|
75
|
-
Permissions
|
|
76
|
-
};
|
package/dist/chunk-ISGBGFSU.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/login.ts
|
|
4
|
-
function readSecret(prompt) {
|
|
5
|
-
return new Promise((resolve) => {
|
|
6
|
-
process.stdout.write(prompt);
|
|
7
|
-
const stdin = process.stdin;
|
|
8
|
-
if (!stdin.isTTY) {
|
|
9
|
-
let data = "";
|
|
10
|
-
stdin.on("data", (d) => {
|
|
11
|
-
data += d;
|
|
12
|
-
});
|
|
13
|
-
stdin.on("end", () => resolve(data.trim()));
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
let value = "";
|
|
17
|
-
stdin.setRawMode(true);
|
|
18
|
-
stdin.resume();
|
|
19
|
-
const onData = (buffer) => {
|
|
20
|
-
for (const ch of buffer.toString()) {
|
|
21
|
-
if (ch === "\r" || ch === "\n") {
|
|
22
|
-
stdin.setRawMode(false);
|
|
23
|
-
stdin.pause();
|
|
24
|
-
stdin.off("data", onData);
|
|
25
|
-
process.stdout.write("\n");
|
|
26
|
-
resolve(value.trim());
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (ch === "") process.exit(130);
|
|
30
|
-
if (ch === "\x7F" || ch === "\b") value = value.slice(0, -1);
|
|
31
|
-
else value += ch;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
stdin.on("data", onData);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
async function runLogin(providerId, cwd) {
|
|
38
|
-
const { runProviderCommand } = await import("./providerCli-Q7LRM2NP.js");
|
|
39
|
-
const { parseCliArgs } = await import("./args-JPVSGCGY.js");
|
|
40
|
-
return runProviderCommand(parseCliArgs(["provider", "add", providerId]), {
|
|
41
|
-
env: process.env,
|
|
42
|
-
cwd,
|
|
43
|
-
out: (s) => console.log(s),
|
|
44
|
-
err: (s) => console.error(s),
|
|
45
|
-
readSecret
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export {
|
|
50
|
-
readSecret,
|
|
51
|
-
runLogin
|
|
52
|
-
};
|