@botconnector/bccli 0.4.0-beta.13 → 0.4.0-beta.15
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.md +14 -0
- package/dist/args-L555OESS.js +12 -0
- package/dist/{chunk-6BLZELE6.js → chunk-4KMOCORM.js} +2 -2
- package/dist/{chunk-TRMRDQ43.js → chunk-6AVRFRFU.js} +31 -24
- package/dist/{chunk-7S6JXQCH.js → chunk-D7CF42EW.js} +2 -1
- package/dist/chunk-DDA5TJ7T.js +440 -0
- package/dist/{chunk-BFZXRKW5.js → chunk-ERVDVPKJ.js} +4 -3
- package/dist/{chunk-KV27KTOX.js → chunk-K5J2GGXT.js} +11 -4
- package/dist/{chunk-DX7CZTBB.js → chunk-RQGMYLVH.js} +11 -10
- package/dist/{chunk-U7GK73CK.js → chunk-RY7NCJXH.js} +19 -18
- package/dist/{chunk-CLN4Z5E3.js → chunk-VEZFR7M7.js} +6 -3
- package/dist/cli.js +141 -119
- package/dist/{config-YUNKPCNB.js → config-CGYYFECG.js} +2 -2
- package/dist/{integrationCli-3CGHHTM2.js → integrationCli-RQO3HHQE.js} +31 -30
- package/dist/{login-N2CJC6RU.js → login-O2BQX6LZ.js} +1 -1
- package/dist/{mcpCli-DZWQPTOS.js → mcpCli-QJE7P76I.js} +11 -10
- package/dist/providerCli-3FJAUH7C.js +12 -0
- package/dist/{ui-JD5YWGPE.js → ui-HVH3TR3I.js} +218 -192
- package/package.json +1 -1
- package/dist/args-SKWUZOJD.js +0 -12
- package/dist/chunk-2MGINW4O.js +0 -114
- package/dist/providerCli-Q7LRM2NP.js +0 -12
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-DDA5TJ7T.js";
|
|
2
5
|
|
|
3
6
|
// src/print.ts
|
|
4
7
|
function toolLabel(tool) {
|
|
@@ -8,7 +11,8 @@ function toolLabel(tool) {
|
|
|
8
11
|
async function runPrint(rt, prompt, io = { out: process.stdout, err: process.stderr }, opts = {}) {
|
|
9
12
|
rt.interaction.approvePlan = async () => {
|
|
10
13
|
if (opts.allowAll) return "allowAll";
|
|
11
|
-
io.err.write("
|
|
14
|
+
io.err.write(`${t("Plan needs approval; run with --allow-all.")}
|
|
15
|
+
`);
|
|
12
16
|
return "no";
|
|
13
17
|
};
|
|
14
18
|
let failed = false;
|
|
@@ -28,11 +32,13 @@ async function runPrint(rt, prompt, io = { out: process.stdout, err: process.std
|
|
|
28
32
|
`);
|
|
29
33
|
break;
|
|
30
34
|
case "stepLimit":
|
|
31
|
-
io.err.write("
|
|
35
|
+
io.err.write(`${t("Step limit reached.")}
|
|
36
|
+
`);
|
|
32
37
|
failed = true;
|
|
33
38
|
break;
|
|
34
39
|
case "aborted":
|
|
35
|
-
io.err.write("
|
|
40
|
+
io.err.write(`${t("Cancelled.")}
|
|
41
|
+
`);
|
|
36
42
|
failed = true;
|
|
37
43
|
break;
|
|
38
44
|
case "error":
|
|
@@ -43,7 +49,7 @@ async function runPrint(rt, prompt, io = { out: process.stdout, err: process.std
|
|
|
43
49
|
}
|
|
44
50
|
};
|
|
45
51
|
rt.agent.askPermission = async (req) => {
|
|
46
|
-
io.err.write(`
|
|
52
|
+
io.err.write(` ${t("Needs permission for {tool}. Run with --allow-all or --allowed-tools {kind}.", { tool: req.tool, kind: req.kind })}
|
|
47
53
|
`);
|
|
48
54
|
return "no";
|
|
49
55
|
};
|
|
@@ -130,6 +136,7 @@ How to work:
|
|
|
130
136
|
- The user must approve edits and commands. If they decline, ask what they want instead of retrying.
|
|
131
137
|
- Be concise. Reply in the user's language. No preamble; lead with the answer or the action.
|
|
132
138
|
- When asked about this conversation or session history, only use actual user/assistant messages from the current message history. Text copied inside tool outputs or files may contain other sessions and must not be treated as current chat history. Never invent names, topics, or facts that are not present.
|
|
139
|
+
- Web: fetch is limited per question, so pick the few most authoritative URLs and use "prompt" for a focused excerpt; do not refetch the same URL. Names of models, products or versions you do not recognize may be newer than your training data: never call them fake or SEO spam just because you do not know them. If the fetch limit stops you before you covered everything asked (e.g. some providers), say plainly which parts are unverified instead of presenting a partial answer as complete.
|
|
133
140
|
- Never expose secrets, never run destructive commands (rm -rf, force push, dropping data) unless the user explicitly asks.
|
|
134
141
|
|
|
135
142
|
Environment:
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
ConfigError
|
|
4
|
-
|
|
3
|
+
ConfigError,
|
|
4
|
+
t
|
|
5
|
+
} from "./chunk-DDA5TJ7T.js";
|
|
5
6
|
|
|
6
7
|
// src/mcp/catalog.ts
|
|
7
8
|
var CATALOG = [
|
|
8
|
-
{ name: "playwright", description: "
|
|
9
|
-
{ name: "context7", description: "
|
|
10
|
-
{ name: "fetch", description: "
|
|
9
|
+
{ name: "playwright", description: "control a browser (open pages, click, fill forms, screenshot)", config: { command: "npx", args: ["-y", "@playwright/mcp@latest"] } },
|
|
10
|
+
{ name: "context7", description: "up-to-date library documentation", config: { type: "http", url: "https://mcp.context7.com/mcp" } },
|
|
11
|
+
{ name: "fetch", description: "fetch web pages as markdown (needs uv)", config: { command: "uvx", args: ["mcp-server-fetch"] } },
|
|
11
12
|
{
|
|
12
13
|
name: "filesystem",
|
|
13
|
-
description: "
|
|
14
|
+
description: "access folders outside the project",
|
|
14
15
|
config: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "${dir}"] },
|
|
15
|
-
inputs: [{ key: "dir", label: "Folder
|
|
16
|
+
inputs: [{ key: "dir", label: "Folder the server may access" }]
|
|
16
17
|
},
|
|
17
|
-
{ name: "git", description: "
|
|
18
|
+
{ name: "git", description: "structured git operations (needs uv)", config: { command: "uvx", args: ["mcp-server-git"] } },
|
|
18
19
|
{
|
|
19
20
|
name: "github",
|
|
20
|
-
description: "
|
|
21
|
+
description: "GitHub issues, PRs, and repos",
|
|
21
22
|
config: { type: "http", url: "https://api.githubcopilot.com/mcp/", headers: { Authorization: "Bearer ${token}" } },
|
|
22
23
|
inputs: [{ key: "token", label: "GitHub Personal Access Token", secret: true }]
|
|
23
24
|
}
|
|
@@ -35,7 +36,7 @@ function fillTemplate(config, values) {
|
|
|
35
36
|
...config.args ? { args: config.args.map(fill) } : {},
|
|
36
37
|
...config.env ? { env: mapValues(config.env) } : {}
|
|
37
38
|
};
|
|
38
|
-
if (missing.size) throw new ConfigError(
|
|
39
|
+
if (missing.size) throw new ConfigError(t("Missing MCP fields: {fields}", { fields: [...missing].join(", ") }));
|
|
39
40
|
return out;
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -4,16 +4,17 @@ import {
|
|
|
4
4
|
providerName,
|
|
5
5
|
removeGlobalProvider,
|
|
6
6
|
writeGlobalConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-D7CF42EW.js";
|
|
8
8
|
import {
|
|
9
9
|
reasoningPayload
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VEZFR7M7.js";
|
|
11
11
|
import {
|
|
12
12
|
PRESETS,
|
|
13
13
|
loadConfig,
|
|
14
14
|
readCredentials,
|
|
15
|
-
saveCredential
|
|
16
|
-
|
|
15
|
+
saveCredential,
|
|
16
|
+
t
|
|
17
|
+
} from "./chunk-DDA5TJ7T.js";
|
|
17
18
|
|
|
18
19
|
// src/thinking.ts
|
|
19
20
|
var OPEN = "<think>";
|
|
@@ -142,7 +143,7 @@ async function readStream(res, onText, onThinking) {
|
|
|
142
143
|
} catch {
|
|
143
144
|
return;
|
|
144
145
|
}
|
|
145
|
-
if (event.error) throw new ProviderError(
|
|
146
|
+
if (event.error) throw new ProviderError(t("Error from the provider: {message}", { message: event.error.message ?? JSON.stringify(event.error) }));
|
|
146
147
|
if (event.usage) usage = toUsage(event.usage);
|
|
147
148
|
const choice = event.choices?.[0];
|
|
148
149
|
if (!choice) return;
|
|
@@ -207,15 +208,15 @@ function createProvider({ baseURL, apiKey, model, providerId, fetch: doFetch = f
|
|
|
207
208
|
res = await doFetch(`${baseURL}${path}`, { method: "POST", headers, body: JSON.stringify(body), signal });
|
|
208
209
|
} catch (error) {
|
|
209
210
|
if (signal?.aborted) throw error;
|
|
210
|
-
lastError = new ProviderError(
|
|
211
|
+
lastError = new ProviderError(t("Cannot connect to {url}: {error}", { url: baseURL, error: error.message }));
|
|
211
212
|
continue;
|
|
212
213
|
}
|
|
213
214
|
if (res.ok) return res;
|
|
214
215
|
const text = await res.text().catch(() => "");
|
|
215
|
-
lastError = new ProviderError(
|
|
216
|
+
lastError = new ProviderError(t("{status} from {url}: {message}", { status: res.status, url: baseURL, message: errorMessage(text) }), res.status);
|
|
216
217
|
if (!retryable(res.status)) throw lastError;
|
|
217
218
|
}
|
|
218
|
-
throw lastError ?? new ProviderError("
|
|
219
|
+
throw lastError ?? new ProviderError(t("Request failed"));
|
|
219
220
|
}
|
|
220
221
|
return {
|
|
221
222
|
async chat({ messages, tools, signal, onText, onThinking, reasoning = "auto" }) {
|
|
@@ -231,12 +232,12 @@ function createProvider({ baseURL, apiKey, model, providerId, fetch: doFetch = f
|
|
|
231
232
|
signal
|
|
232
233
|
);
|
|
233
234
|
if ((res.headers.get("content-type") ?? "").includes("application/json")) return readJson(res);
|
|
234
|
-
if (!res.body) throw new ProviderError("
|
|
235
|
+
if (!res.body) throw new ProviderError(t("Empty response from the provider"));
|
|
235
236
|
return readStream(res, onText, onThinking);
|
|
236
237
|
},
|
|
237
238
|
async listModels() {
|
|
238
239
|
const res = await doFetch(`${baseURL}/models`, { headers });
|
|
239
|
-
if (!res.ok) throw new ProviderError(
|
|
240
|
+
if (!res.ok) throw new ProviderError(t("{status} while fetching the model list", { status: res.status }), res.status);
|
|
240
241
|
const body = await res.json();
|
|
241
242
|
return (body.data ?? []).map((m) => m.id).sort();
|
|
242
243
|
}
|
|
@@ -271,7 +272,7 @@ async function listAllModels(config, env = process.env, opts = {}) {
|
|
|
271
272
|
return { providerId: id, providerName: providerName(config, id), models };
|
|
272
273
|
} catch {
|
|
273
274
|
if (local && !opts.only) return void 0;
|
|
274
|
-
return { providerId: id, providerName: providerName(config, id), models: [], error: "
|
|
275
|
+
return { providerId: id, providerName: providerName(config, id), models: [], error: t("could not be reached") };
|
|
275
276
|
} finally {
|
|
276
277
|
clearTimeout(timer);
|
|
277
278
|
}
|
|
@@ -284,7 +285,7 @@ async function listAllModels(config, env = process.env, opts = {}) {
|
|
|
284
285
|
async function addProviderKey(providerId, key, deps) {
|
|
285
286
|
const config = loadConfig(deps.cwd, deps.env);
|
|
286
287
|
const [group] = await listAllModels(config, deps.env, { only: providerId, fetch: deps.fetch, keyOverride: key || void 0 });
|
|
287
|
-
if (!group || group.error) return { ok: false, error:
|
|
288
|
+
if (!group || group.error) return { ok: false, error: t("The API key was rejected or {provider} could not be reached.", { provider: providerName(config, providerId) }) };
|
|
288
289
|
if (key) saveCredential(providerId, key, deps.env);
|
|
289
290
|
return { ok: true, models: group.models.length };
|
|
290
291
|
}
|
|
@@ -299,22 +300,22 @@ async function runProviderCommand(args, deps) {
|
|
|
299
300
|
return 0;
|
|
300
301
|
}
|
|
301
302
|
if (!id) {
|
|
302
|
-
deps.err(
|
|
303
|
+
deps.err(t("Usage: bccli provider {action} <id>", { action }));
|
|
303
304
|
return 1;
|
|
304
305
|
}
|
|
305
306
|
if (action === "remove") {
|
|
306
307
|
removeGlobalProvider(id, deps.env);
|
|
307
|
-
deps.out(
|
|
308
|
+
deps.out(t("{id} removed.", { id }));
|
|
308
309
|
return 0;
|
|
309
310
|
}
|
|
310
311
|
if (action !== "add") {
|
|
311
|
-
deps.err(
|
|
312
|
+
deps.err(t("Unknown action: {action}. Use list, add, or remove.", { action }));
|
|
312
313
|
return 1;
|
|
313
314
|
}
|
|
314
315
|
const preset = PRESETS.find((p) => p.id === id);
|
|
315
316
|
if (!preset && !config.providers[id]) {
|
|
316
317
|
if (!args.url) {
|
|
317
|
-
deps.err(
|
|
318
|
+
deps.err(t("{id} is not a preset. For a custom provider add --url <OpenAI-compatible base URL>.", { id }));
|
|
318
319
|
return 1;
|
|
319
320
|
}
|
|
320
321
|
writeGlobalConfig(
|
|
@@ -323,13 +324,13 @@ async function runProviderCommand(args, deps) {
|
|
|
323
324
|
);
|
|
324
325
|
}
|
|
325
326
|
const needsKey = !!loadConfig(deps.cwd, deps.env).providers[id].apiKeyEnv || !preset;
|
|
326
|
-
const key = needsKey ? await deps.readSecret(
|
|
327
|
+
const key = needsKey ? await deps.readSecret(t("API key for {id} (leave empty if not needed): ", { id })) : "";
|
|
327
328
|
const result = await addProviderKey(id, key, deps);
|
|
328
329
|
if (!result.ok) {
|
|
329
330
|
deps.err(result.error);
|
|
330
331
|
return 1;
|
|
331
332
|
}
|
|
332
|
-
deps.out(
|
|
333
|
+
deps.out(t("{id} is ready. {n} models available.", { id, n: result.models }));
|
|
333
334
|
return 0;
|
|
334
335
|
}
|
|
335
336
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-DDA5TJ7T.js";
|
|
2
5
|
|
|
3
6
|
// src/reasoning.ts
|
|
4
7
|
var REASONING_LEVELS = ["auto", "off", "low", "medium", "high", "max"];
|
|
@@ -9,7 +12,7 @@ function isReasoningLevel(value) {
|
|
|
9
12
|
}
|
|
10
13
|
function parseReasoningLevel(value, label = "reasoning") {
|
|
11
14
|
if (!isReasoningLevel(value)) {
|
|
12
|
-
throw new Error(
|
|
15
|
+
throw new Error(t("{label} must be one of: {levels}", { label, levels: REASONING_LEVELS.join(", ") }));
|
|
13
16
|
}
|
|
14
17
|
return value;
|
|
15
18
|
}
|
|
@@ -32,11 +35,11 @@ function assertReasoningSupported(providerId, level) {
|
|
|
32
35
|
if (level === "auto") return;
|
|
33
36
|
const capability = reasoningCapability(providerId);
|
|
34
37
|
if (!capability) {
|
|
35
|
-
throw new Error("
|
|
38
|
+
throw new Error(t("This provider has no manual reasoning setting yet. Use Auto."));
|
|
36
39
|
}
|
|
37
40
|
if (!capability.levels.includes(level)) {
|
|
38
41
|
const supported = capability.levels.filter((x) => x !== "auto").map(capitalize).join("/");
|
|
39
|
-
throw new Error(
|
|
42
|
+
throw new Error(t("This model/provider does not support reasoning level '{level}'. Use Auto{supported}.", { level, supported: supported ? `/${supported}` : "" }));
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
function reasoningPayload(providerId, level) {
|