@botconnector/bccli 0.4.0-beta.1 → 0.4.0-beta.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/cli.js CHANGED
@@ -1,16 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- HELP_TEXT,
4
- parseCliArgs
5
- } from "./chunk-M7INIL2C.js";
6
- import {
7
- addProviderKey,
8
- createProvider,
9
- listAllModels
10
- } from "./chunk-5ISYVAXI.js";
11
- import {
12
- runLogin
13
- } from "./chunk-QH7XXNHU.js";
14
2
  import {
15
3
  BUILTIN_AGENTS,
16
4
  buildSystemPrompt,
@@ -20,13 +8,26 @@ import {
20
8
  loadSkills,
21
9
  parseFrontmatter,
22
10
  runPrint
23
- } from "./chunk-OSWQPSA4.js";
11
+ } from "./chunk-KV27KTOX.js";
12
+ import {
13
+ HELP_TEXT,
14
+ parseCliArgs
15
+ } from "./chunk-BJ337ABK.js";
24
16
  import {
25
17
  Permissions
26
18
  } from "./chunk-ELML4KVQ.js";
19
+ import {
20
+ addProviderKey,
21
+ createProvider,
22
+ listAllModels
23
+ } from "./chunk-U7GK73CK.js";
27
24
  import {
28
25
  providerName
29
- } from "./chunk-5C6NQFSI.js";
26
+ } from "./chunk-7S6JXQCH.js";
27
+ import "./chunk-CLN4Z5E3.js";
28
+ import {
29
+ runLogin
30
+ } from "./chunk-IOWDWOXS.js";
30
31
  import {
31
32
  Session,
32
33
  pruneSessions
@@ -36,7 +37,7 @@ import {
36
37
  bccliHome,
37
38
  loadConfig,
38
39
  resolveModel
39
- } from "./chunk-Z5JM76EL.js";
40
+ } from "./chunk-2MGINW4O.js";
40
41
 
41
42
  // src/tools/index.ts
42
43
  import { z as z8 } from "zod";
@@ -300,6 +301,20 @@ async function readCapped(res) {
300
301
  function htmlToText(html) {
301
302
  return html.replace(/<(script|style|noscript)[\s\S]*?<\/\1>/gi, "").replace(/<(br|\/p|\/div|\/h[1-6]|\/li|\/tr)\s*\/?>/gi, "\n").replace(/<[^>]+>/g, "").replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&").split("\n").map((l) => l.replace(/\s+/g, " ").trim()).filter(Boolean).join("\n");
302
303
  }
304
+ function describeFetchError(error) {
305
+ const cause = error.cause;
306
+ const code = cause?.code ?? "";
307
+ const detail = cause?.message ?? error.message;
308
+ if (error.name === "TimeoutError") return "tidak ada jawaban dalam 30 detik";
309
+ if (code === "ENOTFOUND" || code === "EAI_AGAIN") return `${detail} \u2014 DNS tidak menemukan host (salah ketik, offline, atau diblokir DNS/ISP)`;
310
+ if (/CERT|SELF_SIGNED|UNABLE_TO/.test(code)) {
311
+ return `${detail} \u2014 sertifikat TLS ditolak; sering karena antivirus/proxy yang memeriksa HTTPS. Coba jalankan dengan NODE_OPTIONS=--use-system-ca`;
312
+ }
313
+ if (/ECONNRESET|ECONNREFUSED|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|UND_ERR_CONNECT_TIMEOUT|UND_ERR_SOCKET/.test(code)) {
314
+ return `${detail} \u2014 koneksi gagal (firewall, proxy, atau situs diblokir jaringan)`;
315
+ }
316
+ return code ? `${detail} (${code})` : detail;
317
+ }
303
318
  var fetchTool = defineTool({
304
319
  name: "fetch",
305
320
  description: "Fetch a URL (http/https). HTML is converted to plain text. Max 50k characters.",
@@ -327,12 +342,12 @@ var fetchTool = defineTool({
327
342
  url = next;
328
343
  }
329
344
  } catch (error) {
330
- return { output: `Gagal mengambil ${input.url}: ${error.message}`, isError: true };
345
+ return { output: `Gagal mengambil ${input.url}: ${describeFetchError(error)}`, isError: true };
331
346
  }
332
347
  if (!res) return { output: `Gagal mengambil ${input.url}`, isError: true };
333
348
  const { text: body, truncated } = await readCapped(res);
334
- if (!res.ok) return { output: `HTTP ${res.status} dari ${input.url}: ${body.slice(0, 500)}`, isError: true };
335
349
  const text = (res.headers.get("content-type") ?? "").includes("html") ? htmlToText(body) : body;
350
+ if (!res.ok) return { output: `HTTP ${res.status} dari ${input.url}: ${text.slice(0, 500)}`, isError: true };
336
351
  const clipped = text.length > MAX_CHARS || truncated ? `${text.slice(0, MAX_CHARS)}
337
352
  \u2026 [dipotong]` : text;
338
353
  const display = truncated ? "lebih dari 5 MB, dipotong" : `${text.length} karakter`;
@@ -521,6 +536,71 @@ function toolDefinitions(tools) {
521
536
  });
522
537
  }
523
538
 
539
+ // src/textToolCalls.ts
540
+ var PAIR = /(?:<arg_key>\s*|`)?([A-Za-z_]\w*)(?:\s*<\/arg_key>)?`?\s*(?:=\s*`|<arg_value>)([\s\S]*?)<\/arg_value>/g;
541
+ var CALL_START = /<tool_call>|\n?[^\n]*\bTool call list\b[^\n]*|\n\s*\d+\.\s*Tool:/g;
542
+ function coerce(value, type) {
543
+ const types = Array.isArray(type) ? type : [type];
544
+ const v = value.trim();
545
+ if ((types.includes("integer") || types.includes("number")) && v !== "" && !Number.isNaN(Number(v))) return Number(v);
546
+ if (types.includes("boolean") && /^(true|false)$/i.test(v)) return v.toLowerCase() === "true";
547
+ if ((types.includes("object") || types.includes("array")) && /^[[{]/.test(v)) {
548
+ try {
549
+ return JSON.parse(v);
550
+ } catch {
551
+ }
552
+ }
553
+ return value.replace(/^\n+|\n+$/g, "");
554
+ }
555
+ function pickTool(name, keys, tools) {
556
+ const named = name && tools.find((t) => t.function.name === name);
557
+ if (named) return named;
558
+ let best;
559
+ let bestScore = 0;
560
+ let tie = false;
561
+ for (const t of tools) {
562
+ const params = t.function.parameters;
563
+ const props = Object.keys(params.properties ?? {});
564
+ if (!(params.required ?? []).every((r) => keys.includes(r))) continue;
565
+ const score = keys.filter((k) => props.includes(k)).length;
566
+ if (score > bestScore) [best, bestScore, tie] = [t, score, false];
567
+ else if (score === bestScore && score > 0) tie = true;
568
+ }
569
+ return tie ? void 0 : best;
570
+ }
571
+ function recoverTextToolCalls(text, tools) {
572
+ if (!/<\/arg_value>|<tool_call>/.test(text)) return null;
573
+ const starts = [...text.matchAll(CALL_START)].map((m) => m.index ?? 0);
574
+ const firstPair = text.search(PAIR);
575
+ const cut = Math.min(...[...starts, firstPair].filter((i) => i >= 0));
576
+ const bounds = starts.filter((i) => i >= cut);
577
+ if (!bounds.length || bounds[0] > cut) bounds.unshift(cut);
578
+ const toolCalls = [];
579
+ bounds.forEach((start, n) => {
580
+ const segment = text.slice(start, bounds[n + 1] ?? text.length);
581
+ const name = /<tool_call>\s*([A-Za-z_][\w.-]*)/.exec(segment)?.[1] ?? /Tool:\s*`?([A-Za-z_][\w.-]*)`?/.exec(segment)?.[1];
582
+ let args = [];
583
+ const flush = () => {
584
+ if (!args.length) return;
585
+ const keys = args.map(([k]) => k);
586
+ const tool = pickTool(name, keys, tools);
587
+ if (tool) {
588
+ const props = tool.function.parameters.properties ?? {};
589
+ const input = Object.fromEntries(args.filter(([k]) => k in props).map(([k, v]) => [k, coerce(v, props[k].type)]));
590
+ toolCalls.push({ id: `text_call_${toolCalls.length}`, name: tool.function.name, arguments: JSON.stringify(input) });
591
+ }
592
+ args = [];
593
+ };
594
+ for (const m of segment.matchAll(PAIR)) {
595
+ if (args.some(([k]) => k === m[1])) flush();
596
+ args.push([m[1], m[2]]);
597
+ }
598
+ flush();
599
+ });
600
+ if (!toolCalls.length) return null;
601
+ return { text: text.slice(0, cut).trim(), toolCalls };
602
+ }
603
+
524
604
  // src/agent.ts
525
605
  var estimateTokens = (text) => Math.ceil(text.length / 4);
526
606
  var COMPACT_PROMPT = "Summarize the conversation so far for yourself so you can continue the work with no other context. Include: the user goals, decisions made, files touched and their current state, commands run and results, the task in progress and the next step. Be concise but complete.";
@@ -537,6 +617,7 @@ var Agent = class {
537
617
  this.maxSteps = opts.maxSteps ?? 50;
538
618
  this.contextWindow = opts.contextWindow ?? 128e3;
539
619
  this.systemPrompt = opts.systemPrompt;
620
+ this.reasoning = opts.reasoning ?? "auto";
540
621
  }
541
622
  opts;
542
623
  provider;
@@ -546,6 +627,7 @@ var Agent = class {
546
627
  lastInputTokens = 0;
547
628
  onEvent = () => {
548
629
  };
630
+ reasoning;
549
631
  askPermission = async () => "no";
550
632
  tools;
551
633
  definitions;
@@ -595,7 +677,8 @@ var Agent = class {
595
677
  messages: [{ role: "system", content: this.systemPrompt }, ...this.messages, { role: "user", content: COMPACT_PROMPT }],
596
678
  // Some gateways reject tool_calls in history when no tools are declared.
597
679
  tools: this.definitions,
598
- signal
680
+ signal,
681
+ reasoning: this.reasoning
599
682
  });
600
683
  this.clear();
601
684
  this.push({ role: "user", content: `Ringkasan percakapan sebelumnya:
@@ -615,12 +698,21 @@ ${completion.text}` });
615
698
  await this.compact(signal);
616
699
  this.push({ role: "user", content: `Lanjutkan tugas ini sesuai ringkasan di atas: ${text}` });
617
700
  }
618
- const completion = await this.provider.chat({
701
+ let completion = await this.provider.chat({
619
702
  messages: [{ role: "system", content: this.systemPrompt }, ...this.messages],
620
703
  tools: this.turnDefinitions,
621
704
  signal,
622
- onText: (delta) => this.onEvent({ type: "text", delta })
705
+ onText: (delta) => this.onEvent({ type: "text", delta }),
706
+ onThinking: (delta) => this.onEvent({ type: "thinking", delta }),
707
+ reasoning: this.reasoning
623
708
  });
709
+ if (!completion.toolCalls.length && completion.finishReason !== "repetition") {
710
+ const recovered = recoverTextToolCalls(completion.text, this.turnDefinitions);
711
+ if (recovered) {
712
+ completion = { ...completion, ...recovered };
713
+ this.onEvent({ type: "textReplace", text: recovered.text });
714
+ }
715
+ }
624
716
  const usage = completion.usage ?? {
625
717
  inputTokens: estimateTokens(this.systemPrompt) + estimateTokens(JSON.stringify(this.messages)),
626
718
  outputTokens: estimateTokens(completion.text) + (completion.toolCalls.length ? estimateTokens(JSON.stringify(completion.toolCalls)) : 0)
@@ -819,8 +911,8 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"
819
911
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
820
912
  import { z as z9 } from "zod";
821
913
  function mcpToolName(server, tool, taken) {
822
- const clean = (s) => s.replace(/[^A-Za-z0-9_-]+/g, "_");
823
- const base = `mcp__${clean(server)}__${clean(tool)}`.slice(0, 64);
914
+ const clean2 = (s) => s.replace(/[^A-Za-z0-9_-]+/g, "_");
915
+ const base = `mcp__${clean2(server)}__${clean2(tool)}`.slice(0, 64);
824
916
  let name = base;
825
917
  for (let n = 2; taken.has(name); n++) name = `${base.slice(0, 64 - String(n).length - 1)}_${n}`;
826
918
  taken.add(name);
@@ -965,8 +1057,69 @@ ${body}`, display: skill.description.slice(0, 60) };
965
1057
  });
966
1058
  }
967
1059
 
968
- // src/tools/task.ts
1060
+ // src/tools/websearch.ts
969
1061
  import { z as z12 } from "zod";
1062
+ var clean = (items, max) => (Array.isArray(items) ? items : []).filter((r) => typeof r?.url === "string" && /^https?:\/\//.test(r.url)).slice(0, max).map((r) => ({
1063
+ title: String(r.title || r.url).slice(0, 200),
1064
+ url: r.url,
1065
+ snippet: String(r.snippet || r.description || "").replace(/\s+/g, " ").trim().slice(0, 600)
1066
+ }));
1067
+ async function postJson(url, body, headers, signal) {
1068
+ const res = await fetch(url, {
1069
+ method: "POST",
1070
+ headers: { "content-type": "application/json", ...headers },
1071
+ body: JSON.stringify(body),
1072
+ signal: AbortSignal.any([signal, AbortSignal.timeout(3e4)])
1073
+ });
1074
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1075
+ return res.json();
1076
+ }
1077
+ function createWebSearchTool(opts) {
1078
+ const keenableURL = opts.keenableURL ?? "https://api.keenable.ai/v1/search/public";
1079
+ return defineTool({
1080
+ name: "web_search",
1081
+ description: "Search the web. Returns titles, URLs and short snippets. Use it to find the right pages instead of guessing URLs; then fetch a result URL when you need the full page.",
1082
+ schema: z12.object({
1083
+ query: z12.string().min(1).max(500).describe("Search query"),
1084
+ max_results: z12.number().int().min(1).max(10).optional().describe("Number of results (default 6)")
1085
+ }),
1086
+ kind: "read",
1087
+ target: (input) => input.query,
1088
+ parallelSafe: () => true,
1089
+ async run(input, ctx) {
1090
+ const max = input.max_results ?? 6;
1091
+ const errors = [];
1092
+ let results = [];
1093
+ const bc = opts.botconnector();
1094
+ if (bc) {
1095
+ try {
1096
+ const data = await postJson(`${bc.baseURL.replace(/\/+$/, "")}/web/search`, { query: input.query, max_results: max }, { authorization: `Bearer ${bc.apiKey}` }, ctx.signal);
1097
+ results = clean(data.results, max);
1098
+ } catch (error) {
1099
+ errors.push(`BotConnector: ${error.message}`);
1100
+ }
1101
+ }
1102
+ if (!results.length) {
1103
+ try {
1104
+ const data = await postJson(keenableURL, { query: input.query }, { "x-keenable-title": "BotConnector" }, ctx.signal);
1105
+ results = clean(data.results, max);
1106
+ } catch (error) {
1107
+ errors.push(`Keenable: ${error.message}`);
1108
+ }
1109
+ }
1110
+ if (!results.length) {
1111
+ return { output: errors.length ? `Web search gagal (${errors.join("; ")}).` : "Tidak ada hasil.", isError: errors.length > 0 };
1112
+ }
1113
+ const output = results.map((r, i) => `${i + 1}. ${r.title}
1114
+ ${r.url}${r.snippet ? `
1115
+ ${r.snippet}` : ""}`).join("\n");
1116
+ return { output, display: `${results.length} hasil` };
1117
+ }
1118
+ });
1119
+ }
1120
+
1121
+ // src/tools/task.ts
1122
+ import { z as z13 } from "zod";
970
1123
  function createTaskTool(opts) {
971
1124
  const byName = new Map(opts.agents.map((a) => [a.name, a]));
972
1125
  const list = opts.agents.map((a) => `- ${a.name}: ${a.description}`).join("\n");
@@ -974,10 +1127,10 @@ function createTaskTool(opts) {
974
1127
  name: "task",
975
1128
  description: `Delegate a self-contained sub-task to a subagent. It starts with an empty context and returns only its final report. Available agents:
976
1129
  ${list}`,
977
- schema: z12.object({
978
- agent: z12.string().describe("Agent name"),
979
- description: z12.string().describe("3-6 word summary shown to the user"),
980
- prompt: z12.string().describe("Full instructions; the subagent sees nothing else")
1130
+ schema: z13.object({
1131
+ agent: z13.string().describe("Agent name"),
1132
+ description: z13.string().describe("3-6 word summary shown to the user"),
1133
+ prompt: z13.string().describe("Full instructions; the subagent sees nothing else")
981
1134
  }),
982
1135
  kind: "read",
983
1136
  target: (input) => `[${input.agent}] ${input.description}`,
@@ -1013,6 +1166,7 @@ ${def.prompt}`,
1013
1166
  cwd: opts.cwd,
1014
1167
  maxSteps: def.maxSteps ?? 50,
1015
1168
  label: def.name,
1169
+ reasoning: opts.reasoning?.() ?? "auto",
1016
1170
  // Subagent edits belong to the parent's turn so /undo reverts them too.
1017
1171
  checkpoint: ctx.checkpoint
1018
1172
  });
@@ -1041,7 +1195,7 @@ ${def.prompt}`,
1041
1195
  }
1042
1196
 
1043
1197
  // src/tools/todo.ts
1044
- import { z as z13 } from "zod";
1198
+ import { z as z14 } from "zod";
1045
1199
  var TodoStore = class {
1046
1200
  items = [];
1047
1201
  listeners = /* @__PURE__ */ new Set();
@@ -1058,8 +1212,8 @@ function createTodoTool(store) {
1058
1212
  return defineTool({
1059
1213
  name: "todo_write",
1060
1214
  description: "Write the task list for multi-step work (3+ steps). Send the whole list every time; exactly one item in_progress while working. Mark items completed as soon as they are done.",
1061
- schema: z13.object({
1062
- todos: z13.array(z13.object({ content: z13.string(), status: z13.enum(["pending", "in_progress", "completed"]) }))
1215
+ schema: z14.object({
1216
+ todos: z14.array(z14.object({ content: z14.string(), status: z14.enum(["pending", "in_progress", "completed"]) }))
1063
1217
  }),
1064
1218
  kind: "read",
1065
1219
  target: (input) => `${input.todos.length} item`,
@@ -1081,9 +1235,10 @@ function createRuntime(opts) {
1081
1235
  const home = bccliHome(env);
1082
1236
  let config = loadConfig(opts.cwd, env);
1083
1237
  let modelRef = opts.args.model ?? config.model;
1238
+ let reasoning = opts.args.reasoning ?? config.reasoning;
1084
1239
  const makeProvider = (ref) => {
1085
1240
  const resolved = resolveModel(config, ref, env);
1086
- return opts.provider ?? createProvider({ baseURL: resolved.baseURL, apiKey: resolved.apiKey, model: resolved.model });
1241
+ return opts.provider ?? createProvider({ baseURL: resolved.baseURL, apiKey: resolved.apiKey, model: resolved.model, providerId: resolved.providerId });
1087
1242
  };
1088
1243
  const provider = makeProvider(modelRef);
1089
1244
  const mode = opts.args.allowAll ? "allowAll" : opts.args.permissionMode ?? config.permissionMode;
@@ -1107,7 +1262,17 @@ function createRuntime(opts) {
1107
1262
  }
1108
1263
  }
1109
1264
  const systemPrompt = buildSystemPrompt({ cwd: opts.cwd, home, model: modelRef, skills });
1110
- const baseTools = [...ALL_TOOLS, createSkillTool(skills), createTodoTool(todos), createExitPlanTool({ permissions, interaction })];
1265
+ const webSearch = createWebSearchTool({
1266
+ botconnector: () => {
1267
+ try {
1268
+ const bc = resolveModel(config, "bc-cloud/search", env);
1269
+ return bc.apiKey ? { baseURL: bc.baseURL, apiKey: bc.apiKey } : void 0;
1270
+ } catch {
1271
+ return void 0;
1272
+ }
1273
+ }
1274
+ });
1275
+ const baseTools = [...ALL_TOOLS, webSearch, createSkillTool(skills), createTodoTool(todos), createExitPlanTool({ permissions, interaction })];
1111
1276
  const task = createTaskTool({
1112
1277
  agents: [...BUILTIN_AGENTS, ...agentDefs],
1113
1278
  // Subagents get whatever the main agent has right now (incl. MCP tools), minus task itself.
@@ -1116,7 +1281,8 @@ function createRuntime(opts) {
1116
1281
  provider: () => agent.provider,
1117
1282
  providerFor: makeProvider,
1118
1283
  systemPrompt,
1119
- cwd: opts.cwd
1284
+ cwd: opts.cwd,
1285
+ reasoning: () => reasoning
1120
1286
  });
1121
1287
  const agent = new Agent({
1122
1288
  provider,
@@ -1125,6 +1291,7 @@ function createRuntime(opts) {
1125
1291
  systemPrompt,
1126
1292
  cwd: opts.cwd,
1127
1293
  history,
1294
+ reasoning,
1128
1295
  onMessage: (m) => session.append(m),
1129
1296
  onReset: () => session.reset(),
1130
1297
  onTurnStart: () => checkpoints.beginTurn(),
@@ -1166,6 +1333,9 @@ function createRuntime(opts) {
1166
1333
  get modelRef() {
1167
1334
  return modelRef;
1168
1335
  },
1336
+ get reasoning() {
1337
+ return reasoning;
1338
+ },
1169
1339
  agent,
1170
1340
  get session() {
1171
1341
  return session;
@@ -1173,6 +1343,8 @@ function createRuntime(opts) {
1173
1343
  resume(previous) {
1174
1344
  session = previous;
1175
1345
  agent.load(previous.load());
1346
+ agent.totalUsage = { inputTokens: 0, outputTokens: 0 };
1347
+ todos.set([]);
1176
1348
  checkpoints.clear();
1177
1349
  },
1178
1350
  newSession() {
@@ -1193,12 +1365,16 @@ function createRuntime(opts) {
1193
1365
  setModel(ref) {
1194
1366
  agent.provider = makeProvider(ref);
1195
1367
  modelRef = ref;
1368
+ },
1369
+ setReasoning(level) {
1370
+ reasoning = level;
1371
+ agent.reasoning = level;
1196
1372
  }
1197
1373
  };
1198
1374
  }
1199
1375
 
1200
1376
  // src/version.ts
1201
- var VERSION = true ? "0.4.0-beta.1" : "0.0.0-dev";
1377
+ var VERSION = true ? "0.4.0-beta.10" : "0.0.0-dev";
1202
1378
 
1203
1379
  // src/cli.ts
1204
1380
  async function main() {
@@ -1214,15 +1390,25 @@ async function main() {
1214
1390
  const cwd = process.cwd();
1215
1391
  if (args.command === "login") return runLogin(args.loginProvider ?? "bc-cloud", cwd);
1216
1392
  if (args.command === "mcp") {
1217
- const { runMcpCommand } = await import("./mcpCli-BV3IGR47.js");
1218
- const { readSecret } = await import("./login-FTMR64IA.js");
1393
+ const { runMcpCommand } = await import("./mcpCli-DZWQPTOS.js");
1394
+ const { readSecret } = await import("./login-4C262MEI.js");
1219
1395
  return runMcpCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
1220
1396
  }
1221
1397
  if (args.command === "provider") {
1222
- const { runProviderCommand } = await import("./providerCli-SJRCBSRE.js");
1223
- const { readSecret } = await import("./login-FTMR64IA.js");
1398
+ const { runProviderCommand } = await import("./providerCli-Q7LRM2NP.js");
1399
+ const { readSecret } = await import("./login-4C262MEI.js");
1224
1400
  return runProviderCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
1225
1401
  }
1402
+ if (args.command === "connect" || args.command === "disconnect" || args.command === "integrations") {
1403
+ const { runIntegrationCommand } = await import("./integrationCli-GEIMUL3M.js");
1404
+ return runIntegrationCommand(args, {
1405
+ env: process.env,
1406
+ cwd,
1407
+ out: (s) => console.log(s),
1408
+ err: (s) => console.error(s),
1409
+ fetch: globalThis.fetch
1410
+ });
1411
+ }
1226
1412
  if (args.command === "models") {
1227
1413
  const config = loadConfig(cwd);
1228
1414
  const resolved = resolveModel(config, args.model ?? config.model);
@@ -1237,7 +1423,7 @@ async function main() {
1237
1423
  }
1238
1424
  if (args.print) {
1239
1425
  if (!args.prompt) throw new ConfigError('Mode -p butuh tugas, contoh: bccli -p "jelaskan repo ini"');
1240
- const { serversToStart } = await import("./config-XPWPGNZJ.js");
1426
+ const { serversToStart } = await import("./config-YUNKPCNB.js");
1241
1427
  const plan = serversToStart(rt.home, cwd);
1242
1428
  for (const s of plan.needTrust) {
1243
1429
  console.error(`Server MCP project "${s.name}" dilewati (belum diizinkan; jalankan bccli interaktif sekali untuk menyetujuinya).`);
@@ -1250,7 +1436,7 @@ async function main() {
1250
1436
  }
1251
1437
  }
1252
1438
  if (!process.stdin.isTTY) throw new ConfigError('Mode interaktif butuh terminal. Untuk skrip/CI pakai: bccli -p "tugas"');
1253
- const { startInteractive } = await import("./ui-LWZ75D7H.js");
1439
+ const { startInteractive } = await import("./ui-6GTQUJOE.js");
1254
1440
  return startInteractive(rt, { initialPrompt: args.prompt, resume: args.resume, version: VERSION });
1255
1441
  }
1256
1442
  main().then(
@@ -8,8 +8,8 @@ import {
8
8
  removeGlobalServer,
9
9
  serversToStart,
10
10
  setProjectTrust
11
- } from "./chunk-XQLXE666.js";
12
- import "./chunk-Z5JM76EL.js";
11
+ } from "./chunk-BFZXRKW5.js";
12
+ import "./chunk-2MGINW4O.js";
13
13
  export {
14
14
  addGlobalServer,
15
15
  globalMcpPath,