@botconnector/bccli 0.4.8 → 0.4.10
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-VEXFXT5P.js → acp-L4WGVJTY.js} +2 -2
- package/dist/{args-6XMUZDAK.js → args-EW7XJVQN.js} +4 -4
- package/dist/args.d.ts +6 -0
- package/dist/{chunk-OETLWNGS.js → chunk-24KDXQZT.js} +1 -1
- package/dist/{chunk-OUJRD7GG.js → chunk-3K66L37W.js} +8 -3
- package/dist/{chunk-CSIQDFEF.js → chunk-3PUWH62K.js} +1 -1
- package/dist/{chunk-WSSJH765.js → chunk-4WI5ON64.js} +1 -1
- package/dist/{chunk-KREGVQ63.js → chunk-5QCCV2JM.js} +11 -11
- package/dist/{chunk-RRECJTOG.js → chunk-67REFMSY.js} +1 -1
- package/dist/{chunk-TLCFBQ6E.js → chunk-6N2BBLIT.js} +2 -2
- package/dist/{chunk-EAR2C6TS.js → chunk-6RVAPAE5.js} +1 -1
- package/dist/{chunk-2YG6L3YO.js → chunk-7HDBPDAD.js} +2 -2
- package/dist/{chunk-O6NTUSSE.js → chunk-CBD52BYV.js} +1 -1
- package/dist/{chunk-Z2ELYJ5O.js → chunk-CIEPLTGS.js} +10 -3
- package/dist/{chunk-XCVYR5BK.js → chunk-ED5TTYQU.js} +12 -1
- package/dist/{chunk-62UTSCWF.js → chunk-MPYSYTSO.js} +1 -1
- package/dist/{chunk-AWBEZY4D.js → chunk-PGDYPOQW.js} +7 -5
- package/dist/{chunk-HPYI7L4W.js → chunk-SXRQ2Q7A.js} +4 -4
- package/dist/{chunk-DRJSANKH.js → chunk-USFXL5BS.js} +4 -2
- package/dist/{chunk-EOJNFGOP.js → chunk-VXRW5SYP.js} +74 -15
- package/dist/{chunk-6H6MPG7L.js → chunk-ZWXKBFKW.js} +7 -7
- package/dist/cli.js +39 -39
- package/dist/{completion-FETH4OGC.js → completion-GEFRIQWV.js} +1 -1
- package/dist/{config-RVMC23W3.js → config-JKMYKNAT.js} +2 -2
- package/dist/{config-KR5JI5RA.js → config-JLOH5M6B.js} +3 -3
- package/dist/{ghBotCli-Z6GWXCJ6.js → ghBotCli-WEVS6S6O.js} +14 -14
- package/dist/{integrationCli-GPRR6J6W.js → integrationCli-PKMICTHC.js} +2 -2
- package/dist/{login-DFSN77L3.js → login-2TZRODUL.js} +4 -4
- package/dist/{mcpCli-64P3SVUE.js → mcpCli-TAPKYGHO.js} +22 -7
- package/dist/{modelsCli-PFQY3G2Q.js → modelsCli-6PK7V2QZ.js} +6 -6
- package/dist/{oauthLogin-NR22NWEV.js → oauthLogin-UI34LQZU.js} +1 -1
- package/dist/{pluginsCli-UKRJ3AHN.js → pluginsCli-RCF33U5J.js} +6 -2
- package/dist/{prCli-6FCI36AJ.js → prCli-24PMW7NS.js} +1 -1
- package/dist/print.d.ts +1 -0
- package/dist/providerCli-XA4LTWRD.js +15 -0
- package/dist/sdk.js +93 -15
- package/dist/{serve-DTTFDRUY.js → serve-7BFCIEPJ.js} +27 -16
- package/dist/{serve-PKUTKQQT.js → serve-XNJI67DU.js} +3 -3
- package/dist/session-VAPIHHUG.js +12 -0
- package/dist/setup-GPIMZOWE.js +24 -0
- package/dist/{statsCli-FR7GOKWO.js → statsCli-QDHE4TKB.js} +1 -1
- package/dist/{transferCli-GIE4MEJ4.js → transferCli-7OKKYGG2.js} +4 -4
- package/dist/{ui-NZVOCQSU.js → ui-SZAIIJC5.js} +12 -12
- package/dist/{update-W2D2XJVP.js → update-JSNVVXPS.js} +2 -2
- package/package.json +1 -1
- package/dist/providerCli-PBSZECBM.js +0 -15
- package/dist/session-XABMBIIF.js +0 -12
- package/dist/setup-CLPQLTM7.js +0 -24
|
@@ -180,8 +180,8 @@ function runtimeAgent(cwd, allowAll = false) {
|
|
|
180
180
|
return {
|
|
181
181
|
async run(text, onChunk, signal, io) {
|
|
182
182
|
if (!rt) {
|
|
183
|
-
const { parseCliArgs } = await import("./args-
|
|
184
|
-
const { createRuntime } = await import("./setup-
|
|
183
|
+
const { parseCliArgs } = await import("./args-EW7XJVQN.js");
|
|
184
|
+
const { createRuntime } = await import("./setup-GPIMZOWE.js");
|
|
185
185
|
rt = createRuntime({ cwd, args: { ...parseCliArgs([]), allowAll } });
|
|
186
186
|
}
|
|
187
187
|
if (io && !allowAll) rt.agent.askPermission = (req) => io.askPermission(req);
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
helpText,
|
|
4
4
|
parseCliArgs
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CIEPLTGS.js";
|
|
6
6
|
import "./chunk-WFZKJY3R.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-6RVAPAE5.js";
|
|
8
|
+
import "./chunk-USFXL5BS.js";
|
|
9
|
+
import "./chunk-ED5TTYQU.js";
|
|
10
10
|
export {
|
|
11
11
|
helpText,
|
|
12
12
|
parseCliArgs
|
package/dist/args.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ export interface CliArgs {
|
|
|
5
5
|
command: 'run' | 'login' | 'models' | 'update' | 'acp' | 'serve' | 'plugins' | 'gh-bot' | 'provider' | 'mcp' | 'connect' | 'disconnect' | 'integrations' | 'completion' | 'stats' | 'export' | 'import' | 'pr';
|
|
6
6
|
subArgs: string[];
|
|
7
7
|
url?: string;
|
|
8
|
+
/** `bccli mcp add <name> --command <cmd>`: server stdio, bukan HTTP. */
|
|
9
|
+
stdioCommand?: string;
|
|
10
|
+
/** Argumen untuk server stdio (dipisah spasi). */
|
|
11
|
+
stdioArgs?: string;
|
|
8
12
|
name?: string;
|
|
9
13
|
keyEnv?: string;
|
|
10
14
|
values: string[];
|
|
@@ -16,6 +20,8 @@ export interface CliArgs {
|
|
|
16
20
|
continue: boolean;
|
|
17
21
|
resume: boolean;
|
|
18
22
|
allowAll: boolean;
|
|
23
|
+
/** `-p` untuk CI: kegagalan tool apa pun membuat exit code 1. */
|
|
24
|
+
failOnToolError: boolean;
|
|
19
25
|
allowedTools: string[];
|
|
20
26
|
worktree?: string;
|
|
21
27
|
outputFormat?: 'text' | 'json' | 'stream-json';
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runCommand,
|
|
4
4
|
runHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3PUWH62K.js";
|
|
6
6
|
import {
|
|
7
7
|
ConfigError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-USFXL5BS.js";
|
|
9
9
|
import {
|
|
10
10
|
t
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ED5TTYQU.js";
|
|
12
12
|
|
|
13
13
|
// src/verify.ts
|
|
14
14
|
var MAX_VERIFY_ROUNDS = 2;
|
|
@@ -90,6 +90,7 @@ async function runPrint(rt, prompt, io = { out: process.stdout, err: process.std
|
|
|
90
90
|
case "toolEnd":
|
|
91
91
|
if (event.isError) io.err.write(` \u2717 ${event.output.split("\n")[0]}
|
|
92
92
|
`);
|
|
93
|
+
if (event.isError && opts.failOnToolError) failed = true;
|
|
93
94
|
if ((event.tool === "edit" || event.tool === "write") && !event.isError) edited = true;
|
|
94
95
|
if (format === "stream-json") emit({ type: "tool_result", tool: toolNames.get(event.id), isError: !!event.isError, output: event.output });
|
|
95
96
|
break;
|
|
@@ -125,6 +126,9 @@ async function runPrint(rt, prompt, io = { out: process.stdout, err: process.std
|
|
|
125
126
|
const controller = new AbortController();
|
|
126
127
|
const onSigint = () => controller.abort();
|
|
127
128
|
process.once("SIGINT", onSigint);
|
|
129
|
+
const onSigbreak = () => controller.abort();
|
|
130
|
+
const useSigbreak = process.platform === "win32";
|
|
131
|
+
if (useSigbreak) process.once("SIGBREAK", onSigbreak);
|
|
128
132
|
const start = await runHooks(rt.config.hooks, "SessionStart", {}, { env: rt.env, cwd: rt.cwd });
|
|
129
133
|
for (const warning of start.warnings) io.err.write(`${warning}
|
|
130
134
|
`);
|
|
@@ -153,6 +157,7 @@ async function runPrint(rt, prompt, io = { out: process.stdout, err: process.std
|
|
|
153
157
|
}
|
|
154
158
|
} finally {
|
|
155
159
|
process.off("SIGINT", onSigint);
|
|
160
|
+
if (useSigbreak) process.off("SIGBREAK", onSigbreak);
|
|
156
161
|
}
|
|
157
162
|
const stop = await runHooks(rt.config.hooks, "Stop", {}, { env: rt.env, cwd: rt.cwd });
|
|
158
163
|
for (const warning of stop.warnings) io.err.write(`${warning}
|
|
@@ -24,11 +24,11 @@ import {
|
|
|
24
24
|
resolvePath,
|
|
25
25
|
runHooks,
|
|
26
26
|
validateGlobPattern
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-3PUWH62K.js";
|
|
28
28
|
import {
|
|
29
29
|
createWebSearchTool,
|
|
30
30
|
fetchTool
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-4WI5ON64.js";
|
|
32
32
|
import {
|
|
33
33
|
defineTool
|
|
34
34
|
} from "./chunk-PSO7R5AD.js";
|
|
@@ -37,39 +37,39 @@ import {
|
|
|
37
37
|
} from "./chunk-WFZKJY3R.js";
|
|
38
38
|
import {
|
|
39
39
|
addProviderKey
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-PGDYPOQW.js";
|
|
41
41
|
import {
|
|
42
42
|
listAllModels
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-SXRQ2Q7A.js";
|
|
44
44
|
import {
|
|
45
45
|
providerName
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-MPYSYTSO.js";
|
|
47
47
|
import {
|
|
48
48
|
FileOAuthProvider,
|
|
49
49
|
hasStoredTokens
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-67REFMSY.js";
|
|
51
51
|
import {
|
|
52
52
|
Session
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-24KDXQZT.js";
|
|
54
54
|
import {
|
|
55
55
|
completionAssistantMessage,
|
|
56
56
|
createProvider,
|
|
57
57
|
hasPendingProgrammaticReplay,
|
|
58
58
|
imageUserMessage,
|
|
59
59
|
withFallbackProvider
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-VXRW5SYP.js";
|
|
61
61
|
import {
|
|
62
62
|
expandEnvVars
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-7HDBPDAD.js";
|
|
64
64
|
import {
|
|
65
65
|
ConfigError,
|
|
66
66
|
bccliHome,
|
|
67
67
|
loadConfig,
|
|
68
68
|
resolveModel
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-USFXL5BS.js";
|
|
70
70
|
import {
|
|
71
71
|
t
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-ED5TTYQU.js";
|
|
73
73
|
|
|
74
74
|
// src/textToolCalls.ts
|
|
75
75
|
var PAIR = /(?:<arg_key>\s*|`)?([A-Za-z_]\w*)(?:\s*<\/arg_key>)?`?\s*(?:=\s*`|<arg_value>)([\s\S]*?)<\/arg_value>/g;
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
REASONING_LEVELS,
|
|
7
7
|
isReasoningLevel
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6RVAPAE5.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-USFXL5BS.js";
|
|
12
12
|
import {
|
|
13
13
|
parseLang,
|
|
14
14
|
t
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ED5TTYQU.js";
|
|
16
16
|
|
|
17
17
|
// src/args.ts
|
|
18
18
|
import { parseArgs } from "util";
|
|
@@ -112,6 +112,7 @@ Options:
|
|
|
112
112
|
-r, --resume pick a session to continue
|
|
113
113
|
--allow-all run all tools without asking for permission
|
|
114
114
|
--allowed-tools <a,b> tools allowed without asking: bash, edit, fetch
|
|
115
|
+
--fail-on-tool-error with -p: exit 1 when any tool call fails (for CI)
|
|
115
116
|
-w, --worktree <name> run in git worktree ../<repo>.worktrees/<name> (created, or reused if it exists)
|
|
116
117
|
--output-format <fmt> text | json | stream-json for -p (machine-readable output)
|
|
117
118
|
--permission-mode <mode> default | acceptEdits | plan | allowAll
|
|
@@ -137,6 +138,9 @@ function parseCliArgs(argv) {
|
|
|
137
138
|
continue: { type: "boolean", short: "c" },
|
|
138
139
|
resume: { type: "boolean", short: "r" },
|
|
139
140
|
"allow-all": { type: "boolean" },
|
|
141
|
+
command: { type: "string" },
|
|
142
|
+
args: { type: "string" },
|
|
143
|
+
"fail-on-tool-error": { type: "boolean" },
|
|
140
144
|
"allowed-tools": { type: "string" },
|
|
141
145
|
worktree: { type: "string", short: "w" },
|
|
142
146
|
"output-format": { type: "string" },
|
|
@@ -210,6 +214,7 @@ function parseCliArgs(argv) {
|
|
|
210
214
|
continue: !!values.continue,
|
|
211
215
|
resume: !!values.resume,
|
|
212
216
|
allowAll: !!values["allow-all"],
|
|
217
|
+
failOnToolError: !!values["fail-on-tool-error"],
|
|
213
218
|
allowedTools: (values["allowed-tools"] ?? "").split(",").map((s) => s.trim()).filter(Boolean),
|
|
214
219
|
worktree: values.worktree,
|
|
215
220
|
outputFormat,
|
|
@@ -221,6 +226,8 @@ function parseCliArgs(argv) {
|
|
|
221
226
|
logout: !!values.logout,
|
|
222
227
|
subArgs: ["models", "plugins", "gh-bot", "provider", "mcp", "connect", "disconnect", "integrations", "completion", "stats", "export", "import", "pr"].includes(command) ? rest : [],
|
|
223
228
|
url: values.url,
|
|
229
|
+
stdioCommand: values.command,
|
|
230
|
+
stdioArgs: values.args,
|
|
224
231
|
name: values.name,
|
|
225
232
|
keyEnv: values["key-env"],
|
|
226
233
|
values: values.value ?? [],
|
|
@@ -136,6 +136,7 @@ Options:
|
|
|
136
136
|
-r, --resume pick a session to continue
|
|
137
137
|
--allow-all run all tools without asking for permission
|
|
138
138
|
--allowed-tools <a,b> tools allowed without asking: bash, edit, fetch
|
|
139
|
+
--fail-on-tool-error with -p: exit 1 when any tool call fails (for CI)
|
|
139
140
|
-w, --worktree <name> run in git worktree ../<repo>.worktrees/<name> (created, or reused if it exists)
|
|
140
141
|
--output-format <fmt> text | json | stream-json for -p (machine-readable output)
|
|
141
142
|
--permission-mode <mode> default | acceptEdits | plan | allowAll
|
|
@@ -166,6 +167,7 @@ Opsi:
|
|
|
166
167
|
-r, --resume pilih sesi untuk dilanjutkan
|
|
167
168
|
--allow-all jalankan semua alat tanpa minta izin
|
|
168
169
|
--allowed-tools <a,b> alat yang boleh tanpa izin: bash, edit, fetch
|
|
170
|
+
--fail-on-tool-error dengan -p: keluar 1 bila ada tool gagal (untuk CI)
|
|
169
171
|
-w, --worktree <name> jalankan di git worktree ../<repo>.worktrees/<name> (dibuat, atau dipakai ulang jika ada)
|
|
170
172
|
--output-format <fmt> text | json | stream-json untuk -p (output mesin)
|
|
171
173
|
--permission-mode <mode> default | acceptEdits | plan | allowAll
|
|
@@ -224,6 +226,7 @@ Opsi:
|
|
|
224
226
|
'npm removed the files of {name} but the config entry {entry} remains: {reason}. bccli will refuse to start while that entry is listed \u2014 fix the config error at {path}, then run "bccli plugins remove {name}" again (safe to repeat), or delete the entry manually.': 'npm sudah menghapus file {name} tetapi entry config {entry} tertinggal: {reason}. bccli menolak start selama entry itu terdaftar \u2014 perbaiki error config di {path}, lalu jalankan lagi "bccli plugins remove {name}" (aman diulang), atau hapus entry secara manual.',
|
|
225
227
|
"Skipping malformed entry: {entry} \u2014 fix it manually in {path}.": "Melewatkan entry rusak: {entry} \u2014 perbaiki manual di {path}.",
|
|
226
228
|
"No managed plugins to update.": "Tidak ada plugin terelola untuk diperbarui.",
|
|
229
|
+
"No plugins are installed. Install one with: bccli plugins install <spec>": "Belum ada plugin terpasang. Pasang dengan: bccli plugins install <spec>",
|
|
227
230
|
"update requires a plugin name or no argument: bccli plugins update [name]": "update butuh nama plugin atau tanpa argumen: bccli plugins update [nama]",
|
|
228
231
|
"{name} updated to latest.": "{name} diperbarui ke versi terbaru.",
|
|
229
232
|
"Use either --key or --logout, not both.": "Pakai --key atau --logout, jangan keduanya.",
|
|
@@ -281,6 +284,13 @@ Opsi:
|
|
|
281
284
|
"No API key for {id} yet. Run `bccli login` or set the env var {env}.": "API key untuk {id} belum ada. Jalankan `bccli login` atau set env {env}.",
|
|
282
285
|
"Error from the provider: {message}": "Error dari provider: {message}",
|
|
283
286
|
"Cannot connect to {url}: {error}": "Tidak bisa terhubung ke {url}: {error}",
|
|
287
|
+
"The API key was rejected. Check the key for this provider (bccli login) or its API key environment variable.": "Kunci API ditolak. Periksa kunci provider ini (bccli login) atau env var kuncinya.",
|
|
288
|
+
"Model or endpoint not found. Check the model name and the provider base URL.": "Model atau endpoint tidak ditemukan. Periksa nama model dan base URL provider.",
|
|
289
|
+
"Rate limit reached. Wait a moment, or switch model with /model.": "Batas laju tercapai. Tunggu sebentar, atau ganti model dengan /model.",
|
|
290
|
+
"The provider is having trouble. Try again, or switch model with /model.": "Penyedia sedang bermasalah. Coba lagi, atau ganti model dengan /model.",
|
|
291
|
+
"The provider did not respond within {seconds}s. Check the connection, then try again.": "Penyedia tidak merespons dalam {seconds} detik. Periksa koneksi, lalu coba lagi.",
|
|
292
|
+
"The provider stopped sending data for {seconds}s. The answer above may be incomplete; try again.": "Penyedia berhenti mengirim data selama {seconds} detik. Jawaban di atas mungkin tidak lengkap; coba lagi.",
|
|
293
|
+
"The response ended before it finished (no finish_reason or [DONE]). The answer above is incomplete; try again.": "Respons berakhir sebelum selesai (tanpa finish_reason atau [DONE]). Jawaban di atas tidak lengkap; coba lagi.",
|
|
284
294
|
"{status} from {url}: {message}": "{status} dari {url}: {message}",
|
|
285
295
|
"Request failed": "Permintaan gagal",
|
|
286
296
|
"Connection closed before the response finished.": "Koneksi ditutup sebelum respons selesai.",
|
|
@@ -305,7 +315,8 @@ Opsi:
|
|
|
305
315
|
"Usage: bccli mcp {action} <name>": "Pemakaian: bccli mcp {action} <nama>",
|
|
306
316
|
"{name} removed.": "{name} dihapus.",
|
|
307
317
|
"{name} installed ({url}).": "{name} terpasang ({url}).",
|
|
308
|
-
"{name}
|
|
318
|
+
"{name} installed (stdio: {command}).": "{name} terpasang (stdio: {command}).",
|
|
319
|
+
"{name} is not in the catalog. For another server use: bccli mcp add {name} --url <url> (HTTP) or bccli mcp add {name} --command <cmd> (stdio).": "{name} tidak ada di katalog. Untuk server lain pakai: bccli mcp add {name} --url <url> (HTTP) atau bccli mcp add {name} --command <cmd> (stdio).",
|
|
309
320
|
"{name} installed. Active in the next bccli session.": "{name} terpasang. Aktif di sesi bccli berikutnya.",
|
|
310
321
|
"control a browser (open pages, click, fill forms, screenshot)": "kontrol browser (buka halaman, klik, isi form, screenshot)",
|
|
311
322
|
"up-to-date library documentation": "dokumentasi library terbaru",
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
listAllModels
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SXRQ2Q7A.js";
|
|
5
5
|
import {
|
|
6
6
|
hasKey,
|
|
7
7
|
providerName,
|
|
8
8
|
removeGlobalProvider,
|
|
9
9
|
writeGlobalConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-MPYSYTSO.js";
|
|
11
11
|
import {
|
|
12
12
|
PRESETS,
|
|
13
13
|
loadConfig,
|
|
14
14
|
saveCredential
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-USFXL5BS.js";
|
|
16
16
|
import {
|
|
17
17
|
t
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ED5TTYQU.js";
|
|
19
19
|
|
|
20
20
|
// src/providerCli.ts
|
|
21
21
|
async function addProviderKey(providerId, key, deps) {
|
|
@@ -49,7 +49,8 @@ async function runProviderCommand(args, deps) {
|
|
|
49
49
|
return 1;
|
|
50
50
|
}
|
|
51
51
|
const preset = PRESETS.find((p) => p.id === id);
|
|
52
|
-
|
|
52
|
+
const createdEntry = !preset && !config.providers[id];
|
|
53
|
+
if (createdEntry) {
|
|
53
54
|
if (!args.url) {
|
|
54
55
|
deps.err(t("{id} is not a preset. For a custom provider add --url <OpenAI-compatible base URL>.", { id }));
|
|
55
56
|
return 1;
|
|
@@ -63,6 +64,7 @@ async function runProviderCommand(args, deps) {
|
|
|
63
64
|
const key = needsKey ? await deps.readSecret(t("API key for {id} (leave empty if not needed): ", { id })) : "";
|
|
64
65
|
const result = await addProviderKey(id, key, deps);
|
|
65
66
|
if (!result.ok) {
|
|
67
|
+
if (createdEntry) removeGlobalProvider(id, deps.env);
|
|
66
68
|
deps.err(result.error);
|
|
67
69
|
return 1;
|
|
68
70
|
}
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
import {
|
|
3
3
|
hasKey,
|
|
4
4
|
providerName
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MPYSYTSO.js";
|
|
6
6
|
import {
|
|
7
7
|
createProvider
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VXRW5SYP.js";
|
|
9
9
|
import {
|
|
10
10
|
PRESETS,
|
|
11
11
|
readCredentials
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-USFXL5BS.js";
|
|
13
13
|
import {
|
|
14
14
|
t
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ED5TTYQU.js";
|
|
16
16
|
|
|
17
17
|
// src/models.ts
|
|
18
18
|
function order(ids) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
t
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ED5TTYQU.js";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
7
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
@@ -339,7 +339,9 @@ function resolveModel(config, modelRef, env = process.env) {
|
|
|
339
339
|
if (!provider) {
|
|
340
340
|
throw new ConfigError(t('Provider "{id}" is not in the config. Available: {list}', { id: providerId, list: Object.keys(config.providers).join(", ") }));
|
|
341
341
|
}
|
|
342
|
-
const
|
|
342
|
+
const untrusted = config.projectProviders?.includes(providerId) ?? false;
|
|
343
|
+
const stored = untrusted ? void 0 : readCredentials(env)[providerId];
|
|
344
|
+
const apiKey = stored || (provider.apiKeyEnv ? env[provider.apiKeyEnv] : void 0) || void 0;
|
|
343
345
|
if (provider.apiKeyEnv && !apiKey) {
|
|
344
346
|
throw new ConfigError(t("No API key for {id} yet. Run `bccli login` or set the env var {env}.", { id: providerId, env: provider.apiKeyEnv }));
|
|
345
347
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
reasoningPayload
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6RVAPAE5.js";
|
|
5
5
|
import {
|
|
6
6
|
t
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ED5TTYQU.js";
|
|
8
8
|
|
|
9
9
|
// src/provider.ts
|
|
10
10
|
import OpenAI from "openai";
|
|
@@ -78,6 +78,17 @@ function outputReasoningSummary(items) {
|
|
|
78
78
|
}).map((part) => part && typeof part === "object" && "text" in part && typeof part.text === "string" ? part.text : "").filter(Boolean).join("\n");
|
|
79
79
|
}
|
|
80
80
|
var retryable = (status) => status === 429 || status >= 500;
|
|
81
|
+
function httpIdleMs() {
|
|
82
|
+
const raw = Number(process.env.BCCLI_HTTP_IDLE_TIMEOUT_MS);
|
|
83
|
+
return Number.isFinite(raw) && raw > 0 ? raw : 6e4;
|
|
84
|
+
}
|
|
85
|
+
function statusHint(status) {
|
|
86
|
+
if (status === 401 || status === 403) return t("The API key was rejected. Check the key for this provider (bccli login) or its API key environment variable.");
|
|
87
|
+
if (status === 404) return t("Model or endpoint not found. Check the model name and the provider base URL.");
|
|
88
|
+
if (status === 429) return t("Rate limit reached. Wait a moment, or switch model with /model.");
|
|
89
|
+
if (status >= 500) return t("The provider is having trouble. Try again, or switch model with /model.");
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
81
92
|
function detectRepetition(text) {
|
|
82
93
|
const tail = text.slice(-600);
|
|
83
94
|
for (let len = 1; len <= 12; len++) {
|
|
@@ -120,7 +131,7 @@ var toUsage = (u) => u ? {
|
|
|
120
131
|
...u.prompt_tokens_details?.cached_tokens != null ? { cachedInputTokens: u.prompt_tokens_details.cached_tokens } : {},
|
|
121
132
|
...u.prompt_tokens_details?.cache_write_tokens != null ? { cacheWriteTokens: u.prompt_tokens_details.cache_write_tokens } : {}
|
|
122
133
|
} : void 0;
|
|
123
|
-
async function readStream(res, onText, onThinking) {
|
|
134
|
+
async function readStream(res, onText, onThinking, signal) {
|
|
124
135
|
let text = "";
|
|
125
136
|
let thinking = "";
|
|
126
137
|
const splitter = new ThinkSplitter();
|
|
@@ -137,6 +148,7 @@ async function readStream(res, onText, onThinking) {
|
|
|
137
148
|
};
|
|
138
149
|
let usage;
|
|
139
150
|
let finishReason;
|
|
151
|
+
let sawDone = false;
|
|
140
152
|
const calls = [];
|
|
141
153
|
const byIndex = /* @__PURE__ */ new Map();
|
|
142
154
|
let current;
|
|
@@ -146,7 +158,11 @@ async function readStream(res, onText, onThinking) {
|
|
|
146
158
|
const handle = (line) => {
|
|
147
159
|
if (!line.startsWith("data:")) return;
|
|
148
160
|
const data = line.slice(5).trim();
|
|
149
|
-
if (!data
|
|
161
|
+
if (!data) return;
|
|
162
|
+
if (data === "[DONE]") {
|
|
163
|
+
sawDone = true;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
150
166
|
let event;
|
|
151
167
|
try {
|
|
152
168
|
event = JSON.parse(data);
|
|
@@ -175,18 +191,45 @@ async function readStream(res, onText, onThinking) {
|
|
|
175
191
|
if (tc.function?.arguments) target.arguments += tc.function.arguments;
|
|
176
192
|
}
|
|
177
193
|
};
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
const iterator = res.body[Symbol.asyncIterator]();
|
|
195
|
+
const idle = httpIdleMs();
|
|
196
|
+
const onAbort = () => void iterator.return?.();
|
|
197
|
+
if (signal?.aborted) onAbort();
|
|
198
|
+
else signal?.addEventListener("abort", onAbort);
|
|
199
|
+
try {
|
|
200
|
+
for (; ; ) {
|
|
201
|
+
let timer;
|
|
202
|
+
const stalled = new Promise((_, reject) => {
|
|
203
|
+
timer = setTimeout(
|
|
204
|
+
() => reject(new ProviderError(t("The provider stopped sending data for {seconds}s. The answer above may be incomplete; try again.", { seconds: String(Math.round(idle / 1e3)) }))),
|
|
205
|
+
idle
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
let step;
|
|
209
|
+
try {
|
|
210
|
+
step = await Promise.race([iterator.next(), stalled]);
|
|
211
|
+
} finally {
|
|
212
|
+
if (timer) clearTimeout(timer);
|
|
213
|
+
}
|
|
214
|
+
if (step.done) break;
|
|
215
|
+
buffer += decoder.decode(step.value, { stream: true });
|
|
216
|
+
let newline = buffer.indexOf("\n");
|
|
217
|
+
while (newline >= 0 && loopAt < 0) {
|
|
218
|
+
handle(buffer.slice(0, newline).trim());
|
|
219
|
+
buffer = buffer.slice(newline + 1);
|
|
220
|
+
newline = buffer.indexOf("\n");
|
|
221
|
+
}
|
|
222
|
+
if (loopAt >= 0) return { text: text.slice(0, loopAt), toolCalls: [], thinking: thinking || void 0, usage, finishReason: "repetition" };
|
|
185
223
|
}
|
|
186
|
-
|
|
224
|
+
} finally {
|
|
225
|
+
signal?.removeEventListener("abort", onAbort);
|
|
226
|
+
void iterator.return?.();
|
|
187
227
|
}
|
|
188
228
|
handle(buffer.trim());
|
|
189
229
|
emit(splitter.flush());
|
|
230
|
+
if (!sawDone && !finishReason) {
|
|
231
|
+
throw new ProviderError(t("The response ended before it finished (no finish_reason or [DONE]). The answer above is incomplete; try again."));
|
|
232
|
+
}
|
|
190
233
|
const toolCalls = calls.map((call, index) => ({ ...call, id: call.id || `call_${index}` }));
|
|
191
234
|
return { text, toolCalls, thinking: thinking || void 0, usage, finishReason };
|
|
192
235
|
}
|
|
@@ -882,12 +925,26 @@ function createProvider(options) {
|
|
|
882
925
|
await sleep(delay, signal);
|
|
883
926
|
}
|
|
884
927
|
let res;
|
|
928
|
+
const idleAbort = new AbortController();
|
|
929
|
+
const forwardAbort = () => idleAbort.abort(signal?.reason);
|
|
930
|
+
if (signal?.aborted) forwardAbort();
|
|
931
|
+
else signal?.addEventListener("abort", forwardAbort);
|
|
932
|
+
const idle = httpIdleMs();
|
|
933
|
+
const headerTimer = setTimeout(() => idleAbort.abort(new Error("idle-timeout")), idle);
|
|
885
934
|
try {
|
|
886
|
-
res = await doFetch(`${baseURL}${path}`, { method: "POST", headers, body: JSON.stringify(body), signal });
|
|
935
|
+
res = await doFetch(`${baseURL}${path}`, { method: "POST", headers, body: JSON.stringify(body), signal: idleAbort.signal });
|
|
887
936
|
} catch (error) {
|
|
888
937
|
if (signal?.aborted) throw error;
|
|
938
|
+
if (idleAbort.signal.aborted) {
|
|
939
|
+
throw new ProviderError(
|
|
940
|
+
t("The provider did not respond within {seconds}s. Check the connection, then try again.", { seconds: String(Math.round(idle / 1e3)) })
|
|
941
|
+
);
|
|
942
|
+
}
|
|
889
943
|
lastError = new ProviderError(t("Cannot connect to {url}: {error}", { url: baseURL, error: error.message }));
|
|
890
944
|
continue;
|
|
945
|
+
} finally {
|
|
946
|
+
clearTimeout(headerTimer);
|
|
947
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
891
948
|
}
|
|
892
949
|
if (res.ok) return res;
|
|
893
950
|
const retryHeader = res.headers.get("retry-after");
|
|
@@ -896,7 +953,9 @@ function createProvider(options) {
|
|
|
896
953
|
if (Number.isFinite(secs) && secs > 0 && secs <= 30) retryAfterWaitMs = Math.ceil(secs * 1e3);
|
|
897
954
|
}
|
|
898
955
|
const text = await res.text().catch(() => "");
|
|
899
|
-
|
|
956
|
+
const raw = t("{status} from {url}: {message}", { status: res.status, url: baseURL, message: errorMessage(text) });
|
|
957
|
+
const hint = statusHint(res.status);
|
|
958
|
+
lastError = new ProviderError(hint ? `${hint} (${raw})` : raw, res.status);
|
|
900
959
|
const deterministicQuota429 = res.status === 429 && /"code"\s*:\s*"(?:luna_monthly_quota_exhausted|plan_allowance_exhausted)"/i.test(text);
|
|
901
960
|
if (!retryable(res.status) || deterministicQuota429) throw lastError;
|
|
902
961
|
}
|
|
@@ -946,7 +1005,7 @@ function createProvider(options) {
|
|
|
946
1005
|
);
|
|
947
1006
|
if ((res.headers.get("content-type") ?? "").includes("application/json")) return readJson(res, onText, onThinking);
|
|
948
1007
|
if (!res.body) throw new ProviderError(t("Empty response from the provider"));
|
|
949
|
-
return readStream(res, onText, onThinking);
|
|
1008
|
+
return readStream(res, onText, onThinking, signal);
|
|
950
1009
|
},
|
|
951
1010
|
async listModels() {
|
|
952
1011
|
const res = await doFetch(`${baseURL}/models`, { headers });
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
defaultOpen
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-67REFMSY.js";
|
|
5
5
|
import {
|
|
6
6
|
removeCredential,
|
|
7
7
|
saveCredential
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-USFXL5BS.js";
|
|
9
9
|
import {
|
|
10
10
|
t
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ED5TTYQU.js";
|
|
12
12
|
|
|
13
13
|
// src/login.ts
|
|
14
14
|
function readSecret(prompt) {
|
|
@@ -91,8 +91,8 @@ function defaultLoginDeps() {
|
|
|
91
91
|
fetch: globalThis.fetch,
|
|
92
92
|
// Wiring NYATA jalur lama: persis runLogin lama (provider add + prompt key).
|
|
93
93
|
legacyAdd: async (providerId, targetCwd) => {
|
|
94
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
95
|
-
const { parseCliArgs: parse } = await import("./args-
|
|
94
|
+
const { runProviderCommand } = await import("./providerCli-XA4LTWRD.js");
|
|
95
|
+
const { parseCliArgs: parse } = await import("./args-EW7XJVQN.js");
|
|
96
96
|
return runProviderCommand(parse(["provider", "add", providerId]), {
|
|
97
97
|
env: process.env,
|
|
98
98
|
cwd: targetCwd,
|
|
@@ -117,12 +117,12 @@ async function runLogin(providerId, cwd, args, deps) {
|
|
|
117
117
|
);
|
|
118
118
|
return 1;
|
|
119
119
|
}
|
|
120
|
-
const { runOauthLogout } = await import("./oauthLogin-
|
|
120
|
+
const { runOauthLogout } = await import("./oauthLogin-UI34LQZU.js");
|
|
121
121
|
return runOauthLogout({ out: deps.out, err: deps.err, env: deps.env, removeCredential: deps.removeCredential });
|
|
122
122
|
}
|
|
123
123
|
if (args.key) return deps.legacyAdd(providerId, cwd);
|
|
124
124
|
if (providerId === "openrouter") {
|
|
125
|
-
const { runOauthLogin } = await import("./oauthLogin-
|
|
125
|
+
const { runOauthLogin } = await import("./oauthLogin-UI34LQZU.js");
|
|
126
126
|
return runOauthLogin({
|
|
127
127
|
out: deps.out,
|
|
128
128
|
err: deps.err,
|