@botconnector/bccli 0.4.0-beta.5 → 0.4.0-beta.51

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.
Files changed (58) hide show
  1. package/README.md +97 -2
  2. package/dist/acp-NWP4FFTG.js +182 -0
  3. package/dist/args-2R45YZ42.js +13 -0
  4. package/dist/{chunk-U7DLMVPZ.js → chunk-2QYHSESB.js} +2 -1
  5. package/dist/{chunk-UESQNU4A.js → chunk-4WVIPZFV.js} +14 -9
  6. package/dist/chunk-7F3IWBPQ.js +191 -0
  7. package/dist/chunk-DP7EBW53.js +341 -0
  8. package/dist/{chunk-SJH3YLW4.js → chunk-F6ACN47V.js} +60 -6
  9. package/dist/chunk-FTFVW7XD.js +235 -0
  10. package/dist/{chunk-ELML4KVQ.js → chunk-GAFJEQTJ.js} +32 -2
  11. package/dist/{chunk-NGLKANMD.js → chunk-H73FO5YK.js} +24 -2
  12. package/dist/chunk-KD2LMIS4.js +145 -0
  13. package/dist/chunk-KIZC5XV4.js +2141 -0
  14. package/dist/chunk-N7KP6RNP.js +76 -0
  15. package/dist/chunk-NDEJUL44.js +361 -0
  16. package/dist/chunk-PSO7R5AD.js +10 -0
  17. package/dist/chunk-QXOV4DUZ.js +56 -0
  18. package/dist/chunk-QZKLZELZ.js +64 -0
  19. package/dist/chunk-R4BJBTWC.js +940 -0
  20. package/dist/chunk-SNKVS26H.js +63 -0
  21. package/dist/chunk-TQWCM5RO.js +231 -0
  22. package/dist/chunk-VU5HNQHX.js +8 -0
  23. package/dist/chunk-XLC6T4SX.js +500 -0
  24. package/dist/chunk-YIYX3FFS.js +733 -0
  25. package/dist/cli.js +157 -1281
  26. package/dist/completion-OV3MW2N4.js +125 -0
  27. package/dist/{config-NPSYFAFD.js → config-AZZFOXKV.js} +5 -2
  28. package/dist/config-H5A7XHHK.js +30 -0
  29. package/dist/ghBotCli-7WDYF4L7.js +677 -0
  30. package/dist/integrationCli-ZMTSILYF.js +685 -0
  31. package/dist/login-W4Y6WHLV.js +16 -0
  32. package/dist/{mcpCli-Q2H63ISP.js → mcpCli-5QISTOFK.js} +42 -9
  33. package/dist/modelsCli-FZMBD4OE.js +36 -0
  34. package/dist/npmRunner-LU43GM3W.js +46 -0
  35. package/dist/oauthLogin-VESMXG4M.js +210 -0
  36. package/dist/pluginsCli-GEHR7FQR.js +284 -0
  37. package/dist/prCli-JXA7DJW4.js +72 -0
  38. package/dist/providerCli-EUZGKP5F.js +15 -0
  39. package/dist/sdk.js +5486 -0
  40. package/dist/serve-6KX4MXHC.js +178 -0
  41. package/dist/serve-YSUJD57D.js +515 -0
  42. package/dist/session-F6MG3UCU.js +12 -0
  43. package/dist/setup-LLWREJQH.js +24 -0
  44. package/dist/statsCli-H4HEY5ID.js +353 -0
  45. package/dist/transferCli-2XUKBG2L.js +71 -0
  46. package/dist/ui-6HJVYI46.js +2370 -0
  47. package/dist/update-O4WCLKOO.js +109 -0
  48. package/package.json +24 -3
  49. package/dist/args-FCLPQ7TO.js +0 -11
  50. package/dist/chunk-5O4HD7IU.js +0 -253
  51. package/dist/chunk-C5AFWX7H.js +0 -328
  52. package/dist/chunk-GW36UMHZ.js +0 -52
  53. package/dist/chunk-RZUJYAQV.js +0 -112
  54. package/dist/chunk-UN7QXPCB.js +0 -82
  55. package/dist/login-F4G5QXOU.js +0 -9
  56. package/dist/providerCli-MXV6PD6F.js +0 -11
  57. package/dist/session-7UB77CEG.js +0 -9
  58. package/dist/ui-RYTSKEIA.js +0 -1344
@@ -6,10 +6,36 @@ var MODE_ORDER = ["default", "acceptEdits", "plan", "allowAll"];
6
6
  function nextMode(mode) {
7
7
  return MODE_ORDER[(MODE_ORDER.indexOf(mode) + 1) % MODE_ORDER.length];
8
8
  }
9
- var TWO_WORD = /* @__PURE__ */ new Set(["npm", "npx", "pnpm", "yarn", "bun", "git", "cargo", "go", "docker", "python", "python3", "uv", "make"]);
9
+ var ALWAYS_ASK_COMMANDS = /* @__PURE__ */ new Set(["sudo", "sh", "bash", "zsh", "su"]);
10
+ function isAlwaysAsk(segment) {
11
+ const words = segment.trim().split(/\s+/);
12
+ const first = words[0] ?? "";
13
+ if (ALWAYS_ASK_COMMANDS.has(first)) return true;
14
+ const flags = words.slice(1).filter((w) => w.startsWith("-"));
15
+ if (first === "rm" && flags.some((w) => w.includes("r"))) return true;
16
+ if (first === "chmod" && flags.some((w) => w.includes("R"))) return true;
17
+ if (first === "kill" && words.slice(1).includes("-9")) return true;
18
+ if (first === "git" && words[1] === "push") {
19
+ return words.slice(2).some((w) => w === "-f" || w === "--force" || w.startsWith("--force="));
20
+ }
21
+ return false;
22
+ }
10
23
  function commandKey(segment) {
11
24
  const words = segment.trim().split(/\s+/);
12
- return TWO_WORD.has(words[0]) && words[1] ? `${words[0]} ${words[1]}` : words[0];
25
+ return words[1] ? `${words[0]} ${words[1]}` : words[0];
26
+ }
27
+ function requiresSensitiveToolApproval(req) {
28
+ const target = req.target.trim();
29
+ if (req.kind === "read" || req.kind === "edit") {
30
+ return /(?:^|[/\\])(?:\.env(?:\..*)?|\.ssh|\.aws|\.config\/gcloud|secrets?|credentials?)(?:[/\\]|$)/i.test(target) || /(?:id_rsa|id_ed25519|\.pem|\.p12|\.key)$/i.test(target);
31
+ }
32
+ if (req.kind === "bash") {
33
+ return /\b(?:rm\s+-[a-z]*r[a-z]*f[a-z]*\s|rm\s+-[a-z]*f[a-z]*r[a-z]*\s|mkfs(?:\.|\s)|wipefs\b|shred\s|git\s+push\s+(?:--force|-f)\b|docker\s+(?:system\s+prune|volume\s+rm)|kubectl\s+delete\b|drop\s+(?:database|table)|npm\s+publish\b)/i.test(target) || /\b(?:deploy-service\.sh|aws\s+secretsmanager|cat\s+[^;&|]*\.env\b)/i.test(target);
34
+ }
35
+ if (req.kind === "mcp") {
36
+ return /(?:delete|remove|revoke|transfer|send_email|publish|deploy|execute_command|run_command|read_secret)/i.test(req.tool);
37
+ }
38
+ return false;
13
39
  }
14
40
  var Permissions = class {
15
41
  constructor(mode, rules = [], cwd = process.cwd()) {
@@ -30,6 +56,7 @@ var Permissions = class {
30
56
  }
31
57
  /** Rules that "[a] allow for this session" would add; undefined when it must always be asked. */
32
58
  rulesFor(req) {
59
+ if (process.env.BC_TOOL_POLICY_ENFORCE === "true" && requiresSensitiveToolApproval(req)) return void 0;
33
60
  if (req.kind === "edit") return this.editInProject(req.target) ? ["edit(project)"] : void 0;
34
61
  if (req.kind === "fetch") {
35
62
  try {
@@ -42,12 +69,15 @@ var Permissions = class {
42
69
  if (/`|\$\(|[<>]|^\s*[({]/.test(req.target)) return void 0;
43
70
  const segments = req.target.split(/&&|\|\||[;&|\n]/).map((s) => s.trim()).filter(Boolean);
44
71
  if (!segments.length) return void 0;
72
+ if (segments.some(isAlwaysAsk)) return void 0;
45
73
  return [...new Set(segments.map((s) => `bash(${commandKey(s)})`))];
46
74
  }
47
75
  if (req.kind === "mcp") return [`mcp(${req.tool})`];
48
76
  return [];
49
77
  }
50
78
  check(req) {
79
+ if (this.mode === "plan" && req.kind !== "read") return "deny";
80
+ if (process.env.BC_TOOL_POLICY_ENFORCE === "true" && requiresSensitiveToolApproval(req)) return "ask";
51
81
  if (req.kind === "read") return "allow";
52
82
  if (this.mode === "allowAll") return "allow";
53
83
  if (this.mode === "plan") return "deny";
@@ -1,12 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigError
4
- } from "./chunk-RZUJYAQV.js";
4
+ } from "./chunk-NDEJUL44.js";
5
+ import {
6
+ t
7
+ } from "./chunk-XLC6T4SX.js";
5
8
 
6
9
  // src/mcp/config.ts
7
10
  import { createHash } from "crypto";
8
11
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
9
12
  import { dirname, join, resolve } from "path";
13
+ var ENV_REF = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
14
+ function expandEnvVars(config, env) {
15
+ const expand = (value) => value.replace(ENV_REF, (match, name, fallback) => {
16
+ const resolved = env[name];
17
+ if (resolved !== void 0) return resolved;
18
+ return fallback !== void 0 ? fallback : match;
19
+ });
20
+ const expandMap = (map) => Object.fromEntries(Object.entries(map).map(([k, v]) => [k, expand(v)]));
21
+ if (config.type === "http") {
22
+ return { ...config, url: expand(config.url), ...config.headers ? { headers: expandMap(config.headers) } : {} };
23
+ }
24
+ return {
25
+ ...config,
26
+ command: expand(config.command),
27
+ ...config.args ? { args: config.args.map(expand) } : {},
28
+ ...config.env ? { env: expandMap(config.env) } : {}
29
+ };
30
+ }
10
31
  var globalMcpPath = (home) => join(home, "mcp.json");
11
32
  var projectMcpPath = (cwd) => join(cwd, ".bccli", "mcp.json");
12
33
  var trustPath = (home) => join(home, "trusted-mcp.json");
@@ -15,7 +36,7 @@ function readJson(path, fallback) {
15
36
  try {
16
37
  return JSON.parse(readFileSync(path, "utf8"));
17
38
  } catch (error) {
18
- throw new ConfigError(`File MCP tidak valid: ${path} (${error.message})`);
39
+ throw new ConfigError(t("Invalid MCP file: {path} ({error})", { path, error: error.message }));
19
40
  }
20
41
  }
21
42
  function writePrivate(path, data) {
@@ -58,6 +79,7 @@ function serversToStart(home, cwd) {
58
79
  }
59
80
 
60
81
  export {
82
+ expandEnvVars,
61
83
  globalMcpPath,
62
84
  projectMcpPath,
63
85
  readMcpFile,
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ defaultOpen
4
+ } from "./chunk-7F3IWBPQ.js";
5
+ import {
6
+ removeCredential,
7
+ saveCredential
8
+ } from "./chunk-NDEJUL44.js";
9
+ import {
10
+ t
11
+ } from "./chunk-XLC6T4SX.js";
12
+
13
+ // src/login.ts
14
+ function readSecret(prompt) {
15
+ return new Promise((resolve) => {
16
+ process.stdout.write(prompt);
17
+ const stdin = process.stdin;
18
+ if (!stdin.isTTY) {
19
+ let data = "";
20
+ stdin.on("data", (d) => {
21
+ data += d;
22
+ });
23
+ stdin.on("end", () => resolve(data.trim()));
24
+ return;
25
+ }
26
+ let value = "";
27
+ stdin.setRawMode(true);
28
+ stdin.resume();
29
+ const onData = (buffer) => {
30
+ for (const ch of buffer.toString()) {
31
+ if (ch === "\r" || ch === "\n") {
32
+ stdin.setRawMode(false);
33
+ stdin.pause();
34
+ stdin.off("data", onData);
35
+ process.stdout.write("\n");
36
+ resolve(value.trim());
37
+ return;
38
+ }
39
+ if (ch === "") process.exit(130);
40
+ if (ch === "\x7F" || ch === "\b") value = value.slice(0, -1);
41
+ else value += ch;
42
+ }
43
+ };
44
+ stdin.on("data", onData);
45
+ });
46
+ }
47
+ function readLine(prompt) {
48
+ return new Promise((resolve) => {
49
+ process.stdout.write(prompt);
50
+ const stdin = process.stdin;
51
+ if (!stdin.isTTY) {
52
+ let data = "";
53
+ stdin.on("data", (d) => {
54
+ data += d;
55
+ });
56
+ stdin.on("end", () => resolve(data.trim()));
57
+ return;
58
+ }
59
+ let value = "";
60
+ stdin.setRawMode(true);
61
+ stdin.resume();
62
+ const onData = (buffer) => {
63
+ for (const ch of buffer.toString()) {
64
+ const code = ch.charCodeAt(0);
65
+ if (code === 13 || code === 10) {
66
+ stdin.setRawMode(false);
67
+ stdin.pause();
68
+ stdin.off("data", onData);
69
+ process.stdout.write("\n");
70
+ resolve(value.trim());
71
+ return;
72
+ }
73
+ if (code === 3) process.exit(130);
74
+ if (code === 127 || code === 8) value = value.slice(0, -1);
75
+ else value += ch;
76
+ }
77
+ };
78
+ stdin.on("data", onData);
79
+ });
80
+ }
81
+ function defaultLoginDeps() {
82
+ return {
83
+ out: (s) => console.log(s),
84
+ err: (s) => console.error(s),
85
+ env: process.env,
86
+ isTTY: process.stdin.isTTY ?? false,
87
+ open: (url) => defaultOpen(new URL(url)),
88
+ readLine,
89
+ saveCredential: (id, key) => saveCredential(id, key, process.env),
90
+ removeCredential: (id) => removeCredential(id, process.env),
91
+ fetch: globalThis.fetch,
92
+ // Wiring NYATA jalur lama: persis runLogin lama (provider add + prompt key).
93
+ legacyAdd: async (providerId, targetCwd) => {
94
+ const { runProviderCommand } = await import("./providerCli-EUZGKP5F.js");
95
+ const { parseCliArgs: parse } = await import("./args-2R45YZ42.js");
96
+ return runProviderCommand(parse(["provider", "add", providerId]), {
97
+ env: process.env,
98
+ cwd: targetCwd,
99
+ out: (s) => console.log(s),
100
+ err: (s) => console.error(s),
101
+ readSecret
102
+ });
103
+ }
104
+ };
105
+ }
106
+ async function runLogin(providerId, cwd, args, deps) {
107
+ if (args.key && args.logout) {
108
+ deps.err(t("Use either --key or --logout, not both."));
109
+ return 1;
110
+ }
111
+ if (args.logout) {
112
+ if (providerId !== "openrouter") {
113
+ deps.err(
114
+ t("Logout is not supported for {id}; use bccli provider remove {id} to delete its stored key and config.", {
115
+ id: providerId
116
+ })
117
+ );
118
+ return 1;
119
+ }
120
+ const { runOauthLogout } = await import("./oauthLogin-VESMXG4M.js");
121
+ return runOauthLogout({ out: deps.out, err: deps.err, env: deps.env, removeCredential: deps.removeCredential });
122
+ }
123
+ if (args.key) return deps.legacyAdd(providerId, cwd);
124
+ if (providerId === "openrouter") {
125
+ const { runOauthLogin } = await import("./oauthLogin-VESMXG4M.js");
126
+ return runOauthLogin({
127
+ out: deps.out,
128
+ err: deps.err,
129
+ env: deps.env,
130
+ isTTY: deps.isTTY,
131
+ open: deps.open,
132
+ readLine: deps.readLine,
133
+ saveCredential: deps.saveCredential,
134
+ fetch: deps.fetch
135
+ });
136
+ }
137
+ return deps.legacyAdd(providerId, cwd);
138
+ }
139
+
140
+ export {
141
+ readSecret,
142
+ readLine,
143
+ defaultLoginDeps,
144
+ runLogin
145
+ };