@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
package/dist/chunk-KV27KTOX.js
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/print.ts
|
|
4
|
-
function toolLabel(tool) {
|
|
5
|
-
if (tool === "web_search") return "Search";
|
|
6
|
-
return tool.charAt(0).toUpperCase() + tool.slice(1);
|
|
7
|
-
}
|
|
8
|
-
async function runPrint(rt, prompt, io = { out: process.stdout, err: process.stderr }, opts = {}) {
|
|
9
|
-
rt.interaction.approvePlan = async () => {
|
|
10
|
-
if (opts.allowAll) return "allowAll";
|
|
11
|
-
io.err.write("Rencana butuh persetujuan; jalankan dengan --allow-all.\n");
|
|
12
|
-
return "no";
|
|
13
|
-
};
|
|
14
|
-
let failed = false;
|
|
15
|
-
let wroteText = false;
|
|
16
|
-
rt.agent.onEvent = (event) => {
|
|
17
|
-
switch (event.type) {
|
|
18
|
-
case "text":
|
|
19
|
-
io.out.write(event.delta);
|
|
20
|
-
wroteText = true;
|
|
21
|
-
break;
|
|
22
|
-
case "toolStart":
|
|
23
|
-
io.err.write(`\u23BF ${toolLabel(event.tool)} ${event.target}
|
|
24
|
-
`);
|
|
25
|
-
break;
|
|
26
|
-
case "toolEnd":
|
|
27
|
-
if (event.isError) io.err.write(` \u2717 ${event.output.split("\n")[0]}
|
|
28
|
-
`);
|
|
29
|
-
break;
|
|
30
|
-
case "stepLimit":
|
|
31
|
-
io.err.write("Batas langkah tercapai.\n");
|
|
32
|
-
failed = true;
|
|
33
|
-
break;
|
|
34
|
-
case "aborted":
|
|
35
|
-
io.err.write("Dibatalkan.\n");
|
|
36
|
-
failed = true;
|
|
37
|
-
break;
|
|
38
|
-
case "error":
|
|
39
|
-
io.err.write(`Error: ${event.message}
|
|
40
|
-
`);
|
|
41
|
-
failed = true;
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
rt.agent.askPermission = async (req) => {
|
|
46
|
-
io.err.write(` Butuh izin untuk ${req.tool}. Jalankan dengan --allow-all atau --allowed-tools ${req.kind}.
|
|
47
|
-
`);
|
|
48
|
-
return "no";
|
|
49
|
-
};
|
|
50
|
-
const controller = new AbortController();
|
|
51
|
-
const onSigint = () => controller.abort();
|
|
52
|
-
process.once("SIGINT", onSigint);
|
|
53
|
-
try {
|
|
54
|
-
await rt.agent.run(prompt, controller.signal);
|
|
55
|
-
} finally {
|
|
56
|
-
process.off("SIGINT", onSigint);
|
|
57
|
-
}
|
|
58
|
-
if (wroteText) io.out.write("\n");
|
|
59
|
-
return failed ? 1 : 0;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// src/agents.ts
|
|
63
|
-
var EXPLORE_PROMPT = "You are a read-only research agent working for another agent. Search and read the codebase to answer the request. You cannot edit files or run commands. Reply with a concise report: the answer, the relevant file paths with line numbers, and nothing else.";
|
|
64
|
-
var GENERAL_PROMPT = "You are an agent handling a delegated task for another agent. Complete the task end to end with the tools you have, verify the result, and reply with a short report of what you did and what you found.";
|
|
65
|
-
var BUILTIN_AGENTS = [
|
|
66
|
-
{
|
|
67
|
-
name: "explore",
|
|
68
|
-
description: "Read-only: search and read code to answer a question (fast, safe, can run in parallel).",
|
|
69
|
-
tools: ["read", "grep", "glob"],
|
|
70
|
-
prompt: EXPLORE_PROMPT,
|
|
71
|
-
maxSteps: 30
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: "general",
|
|
75
|
-
description: "Full tools: carry out a self-contained sub-task (edits and commands still need user permission).",
|
|
76
|
-
prompt: GENERAL_PROMPT,
|
|
77
|
-
maxSteps: 50
|
|
78
|
-
}
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
// src/context.ts
|
|
82
|
-
import { existsSync, readFileSync } from "fs";
|
|
83
|
-
import { dirname, join } from "path";
|
|
84
|
-
var FILES = ["AGENTS.md", "BCCLI.md"];
|
|
85
|
-
function readIf(path) {
|
|
86
|
-
try {
|
|
87
|
-
return existsSync(path) ? readFileSync(path, "utf8").trim() : void 0;
|
|
88
|
-
} catch {
|
|
89
|
-
return void 0;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function instructionPaths(cwd, home) {
|
|
93
|
-
const dirs2 = [];
|
|
94
|
-
for (let dir = cwd; ; dir = dirname(dir)) {
|
|
95
|
-
dirs2.unshift(dir);
|
|
96
|
-
if (dirname(dir) === dir) break;
|
|
97
|
-
}
|
|
98
|
-
return [join(home, "BCCLI.md"), ...dirs2.flatMap((dir) => FILES.map((name) => join(dir, name)))];
|
|
99
|
-
}
|
|
100
|
-
function loadInstructions(cwd, home) {
|
|
101
|
-
const parts = [];
|
|
102
|
-
for (const path of instructionPaths(cwd, home)) {
|
|
103
|
-
const text = readIf(path);
|
|
104
|
-
if (text) parts.push(`# ${path}
|
|
105
|
-
${text}`);
|
|
106
|
-
}
|
|
107
|
-
return parts.join("\n\n");
|
|
108
|
-
}
|
|
109
|
-
function isGitRepo(cwd) {
|
|
110
|
-
for (let dir = cwd; ; dir = dirname(dir)) {
|
|
111
|
-
if (existsSync(join(dir, ".git"))) return true;
|
|
112
|
-
if (dirname(dir) === dir) return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
function buildSystemPrompt(opts) {
|
|
116
|
-
const instructions = loadInstructions(opts.cwd, opts.home);
|
|
117
|
-
const skills = (opts.skills ?? []).slice(0, 50);
|
|
118
|
-
const skillText = skills.length ? `
|
|
119
|
-
|
|
120
|
-
Skills (load one with the skill tool when it matches the task):
|
|
121
|
-
${skills.map((s) => `- ${s.name}: ${s.description.slice(0, 200)}`).join("\n")}` : "";
|
|
122
|
-
return `You are BCCLI, a coding agent by BotConnector running in the user's terminal. You help with software engineering tasks by reading code, editing files, and running commands with the tools provided.
|
|
123
|
-
|
|
124
|
-
How to work:
|
|
125
|
-
- Understand before changing: read the relevant files and search the codebase first. Never guess file contents.
|
|
126
|
-
- Always read a file before editing it. Make the smallest correct change; match the existing style.
|
|
127
|
-
- For tasks with 3 or more steps, keep a todo list with todo_write and update it as you go.
|
|
128
|
-
- In plan mode you can only read and search. When the plan is ready, call exit_plan with it and wait for approval.
|
|
129
|
-
- Verify your work: run the tests, build or the command that proves the change works, and report the real result.
|
|
130
|
-
- The user must approve edits and commands. If they decline, ask what they want instead of retrying.
|
|
131
|
-
- Be concise. Reply in the user's language. No preamble; lead with the answer or the action.
|
|
132
|
-
- 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.
|
|
133
|
-
- Never expose secrets, never run destructive commands (rm -rf, force push, dropping data) unless the user explicitly asks.
|
|
134
|
-
|
|
135
|
-
Environment:
|
|
136
|
-
- Working directory: ${opts.cwd}
|
|
137
|
-
- Git repository: ${isGitRepo(opts.cwd) ? "yes" : "no"}
|
|
138
|
-
- Platform: ${opts.platform ?? process.platform}
|
|
139
|
-
- Date: ${opts.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
140
|
-
- Model: ${opts.model}${skillText}${instructions ? `
|
|
141
|
-
|
|
142
|
-
Project and user instructions (follow them):
|
|
143
|
-
|
|
144
|
-
${instructions}` : ""}`;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// src/extensions.ts
|
|
148
|
-
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
149
|
-
import { basename, join as join2 } from "path";
|
|
150
|
-
function parseFrontmatter(text) {
|
|
151
|
-
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text);
|
|
152
|
-
if (!match) return { data: {}, body: text };
|
|
153
|
-
const data = {};
|
|
154
|
-
for (const line of match[1].split(/\r?\n/)) {
|
|
155
|
-
const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
|
|
156
|
-
if (!kv) continue;
|
|
157
|
-
let value = kv[2].trim();
|
|
158
|
-
if (value.startsWith("[") && value.endsWith("]")) {
|
|
159
|
-
data[kv[1]] = value.slice(1, -1).split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
if (/^(["']).*\1$/.test(value)) value = value.slice(1, -1);
|
|
163
|
-
data[kv[1]] = value;
|
|
164
|
-
}
|
|
165
|
-
return { data, body: text.slice(match[0].length) };
|
|
166
|
-
}
|
|
167
|
-
var str = (v) => Array.isArray(v) ? v.join(", ") : v;
|
|
168
|
-
function dirs(r, kind) {
|
|
169
|
-
return [join2(r.userHome, ".claude", kind), join2(r.home, kind), join2(r.cwd, ".claude", kind), join2(r.cwd, ".bccli", kind)];
|
|
170
|
-
}
|
|
171
|
-
function list(dir) {
|
|
172
|
-
try {
|
|
173
|
-
return readdirSync(dir).sort();
|
|
174
|
-
} catch {
|
|
175
|
-
return [];
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function loadSkills(r) {
|
|
179
|
-
const byName = /* @__PURE__ */ new Map();
|
|
180
|
-
for (const dir of dirs(r, "skills")) {
|
|
181
|
-
for (const entry of list(dir)) {
|
|
182
|
-
const file = join2(dir, entry, "SKILL.md");
|
|
183
|
-
if (!existsSync2(file)) continue;
|
|
184
|
-
const { data } = parseFrontmatter(readFileSync2(file, "utf8"));
|
|
185
|
-
const name = str(data.name) || entry;
|
|
186
|
-
byName.set(name, { name, description: str(data.description) ?? "", dir: join2(dir, entry), file });
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return [...byName.values()];
|
|
190
|
-
}
|
|
191
|
-
function loadCommands(r) {
|
|
192
|
-
const byName = /* @__PURE__ */ new Map();
|
|
193
|
-
for (const dir of dirs(r, "commands")) {
|
|
194
|
-
for (const entry of list(dir)) {
|
|
195
|
-
const file = join2(dir, entry);
|
|
196
|
-
if (!entry.endsWith(".md") || !statSync(file).isFile()) continue;
|
|
197
|
-
const { data, body } = parseFrontmatter(readFileSync2(file, "utf8"));
|
|
198
|
-
const def = { name: basename(entry, ".md"), body: body.trim() };
|
|
199
|
-
if (data.description) def.description = str(data.description);
|
|
200
|
-
if (data["argument-hint"]) def.argumentHint = str(data["argument-hint"]);
|
|
201
|
-
byName.set(def.name, def);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return [...byName.values()];
|
|
205
|
-
}
|
|
206
|
-
function loadAgentDefs(r) {
|
|
207
|
-
const byName = /* @__PURE__ */ new Map();
|
|
208
|
-
for (const dir of dirs(r, "agents")) {
|
|
209
|
-
for (const entry of list(dir)) {
|
|
210
|
-
if (!entry.endsWith(".md")) continue;
|
|
211
|
-
const { data, body } = parseFrontmatter(readFileSync2(join2(dir, entry), "utf8"));
|
|
212
|
-
const name = str(data.name) || basename(entry, ".md");
|
|
213
|
-
const def = { name, description: str(data.description) ?? "", prompt: body.trim() };
|
|
214
|
-
if (data.tools)
|
|
215
|
-
def.tools = Array.isArray(data.tools) ? data.tools : String(data.tools).split(",").map((s) => s.trim()).filter(Boolean);
|
|
216
|
-
if (data.model) def.model = str(data.model);
|
|
217
|
-
byName.set(name, def);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return [...byName.values()];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// src/tools/ignore.ts
|
|
224
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
225
|
-
import { join as join3 } from "path";
|
|
226
|
-
function ignorePatterns(root) {
|
|
227
|
-
const patterns = ["**/node_modules/**", "**/.git/**"];
|
|
228
|
-
let lines = [];
|
|
229
|
-
try {
|
|
230
|
-
lines = readFileSync3(join3(root, ".gitignore"), "utf8").split(/\r?\n/);
|
|
231
|
-
} catch {
|
|
232
|
-
return patterns;
|
|
233
|
-
}
|
|
234
|
-
for (const raw of lines) {
|
|
235
|
-
const line = raw.trim();
|
|
236
|
-
if (!line || line.startsWith("#") || line.startsWith("!")) continue;
|
|
237
|
-
const p = line.replace(/^\//, "").replace(/\/$/, "");
|
|
238
|
-
patterns.push(`**/${p}`, `**/${p}/**`);
|
|
239
|
-
}
|
|
240
|
-
return patterns;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export {
|
|
244
|
-
toolLabel,
|
|
245
|
-
runPrint,
|
|
246
|
-
ignorePatterns,
|
|
247
|
-
BUILTIN_AGENTS,
|
|
248
|
-
instructionPaths,
|
|
249
|
-
buildSystemPrompt,
|
|
250
|
-
parseFrontmatter,
|
|
251
|
-
loadSkills,
|
|
252
|
-
loadCommands,
|
|
253
|
-
loadAgentDefs
|
|
254
|
-
};
|
package/dist/chunk-U7GK73CK.js
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
hasKey,
|
|
4
|
-
providerName,
|
|
5
|
-
removeGlobalProvider,
|
|
6
|
-
writeGlobalConfig
|
|
7
|
-
} from "./chunk-7S6JXQCH.js";
|
|
8
|
-
import {
|
|
9
|
-
reasoningPayload
|
|
10
|
-
} from "./chunk-CLN4Z5E3.js";
|
|
11
|
-
import {
|
|
12
|
-
PRESETS,
|
|
13
|
-
loadConfig,
|
|
14
|
-
readCredentials,
|
|
15
|
-
saveCredential
|
|
16
|
-
} from "./chunk-2MGINW4O.js";
|
|
17
|
-
|
|
18
|
-
// src/thinking.ts
|
|
19
|
-
var OPEN = "<think>";
|
|
20
|
-
var CLOSE = "</think>";
|
|
21
|
-
function partialTag(text, tag) {
|
|
22
|
-
for (let n = Math.min(tag.length - 1, text.length); n > 0; n--) if (tag.startsWith(text.slice(-n))) return n;
|
|
23
|
-
return 0;
|
|
24
|
-
}
|
|
25
|
-
var ThinkSplitter = class {
|
|
26
|
-
inside = false;
|
|
27
|
-
held = "";
|
|
28
|
-
push(delta) {
|
|
29
|
-
let rest = this.held + delta;
|
|
30
|
-
this.held = "";
|
|
31
|
-
let text = "";
|
|
32
|
-
let thinking = "";
|
|
33
|
-
while (rest) {
|
|
34
|
-
const tag = this.inside ? CLOSE : OPEN;
|
|
35
|
-
const at = rest.indexOf(tag);
|
|
36
|
-
if (at >= 0) {
|
|
37
|
-
if (this.inside) thinking += rest.slice(0, at);
|
|
38
|
-
else text += rest.slice(0, at);
|
|
39
|
-
rest = rest.slice(at + tag.length);
|
|
40
|
-
this.inside = !this.inside;
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
const keep = partialTag(rest, tag);
|
|
44
|
-
const out = rest.slice(0, rest.length - keep);
|
|
45
|
-
if (this.inside) thinking += out;
|
|
46
|
-
else text += out;
|
|
47
|
-
this.held = rest.slice(rest.length - keep);
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
return { text, thinking };
|
|
51
|
-
}
|
|
52
|
-
/** Whatever was held back as a possible tag start is plain text after all. */
|
|
53
|
-
flush() {
|
|
54
|
-
const held = this.held;
|
|
55
|
-
this.held = "";
|
|
56
|
-
return this.inside ? { text: "", thinking: held } : { text: held, thinking: "" };
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
function splitThinking(text) {
|
|
60
|
-
const s = new ThinkSplitter();
|
|
61
|
-
const a = s.push(text);
|
|
62
|
-
const b = s.flush();
|
|
63
|
-
return { text: a.text + b.text, thinking: a.thinking + b.thinking };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/provider.ts
|
|
67
|
-
var ProviderError = class extends Error {
|
|
68
|
-
constructor(message, status) {
|
|
69
|
-
super(message);
|
|
70
|
-
this.status = status;
|
|
71
|
-
}
|
|
72
|
-
status;
|
|
73
|
-
};
|
|
74
|
-
var retryable = (status) => status === 429 || status >= 500;
|
|
75
|
-
function detectRepetition(text) {
|
|
76
|
-
const tail = text.slice(-600);
|
|
77
|
-
for (let len = 1; len <= 12; len++) {
|
|
78
|
-
const unit = tail.slice(-len);
|
|
79
|
-
if (unit.length < len || !unit.trim()) continue;
|
|
80
|
-
let i = tail.length;
|
|
81
|
-
let count = 0;
|
|
82
|
-
while (i >= len && tail.slice(i - len, i) === unit) {
|
|
83
|
-
count++;
|
|
84
|
-
i -= len;
|
|
85
|
-
}
|
|
86
|
-
if (count >= 20 && count * len >= 300) return text.length - count * len;
|
|
87
|
-
}
|
|
88
|
-
return -1;
|
|
89
|
-
}
|
|
90
|
-
function sleep(ms, signal) {
|
|
91
|
-
return new Promise((resolve, reject) => {
|
|
92
|
-
const timer = setTimeout(resolve, ms);
|
|
93
|
-
signal?.addEventListener(
|
|
94
|
-
"abort",
|
|
95
|
-
() => {
|
|
96
|
-
clearTimeout(timer);
|
|
97
|
-
reject(signal.reason);
|
|
98
|
-
},
|
|
99
|
-
{ once: true }
|
|
100
|
-
);
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
function errorMessage(body) {
|
|
104
|
-
try {
|
|
105
|
-
const parsed = JSON.parse(body);
|
|
106
|
-
return parsed?.error?.message ?? parsed?.message ?? body.slice(0, 300);
|
|
107
|
-
} catch {
|
|
108
|
-
return body.slice(0, 300);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
var toUsage = (u) => u ? { inputTokens: u.prompt_tokens ?? 0, outputTokens: u.completion_tokens ?? 0 } : void 0;
|
|
112
|
-
async function readStream(res, onText, onThinking) {
|
|
113
|
-
let text = "";
|
|
114
|
-
let thinking = "";
|
|
115
|
-
const splitter = new ThinkSplitter();
|
|
116
|
-
const emit = (part) => {
|
|
117
|
-
if (part.thinking) {
|
|
118
|
-
thinking += part.thinking;
|
|
119
|
-
onThinking?.(part.thinking);
|
|
120
|
-
}
|
|
121
|
-
if (part.text) {
|
|
122
|
-
text += part.text;
|
|
123
|
-
onText?.(part.text);
|
|
124
|
-
if (loopAt < 0) loopAt = detectRepetition(text);
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
let usage;
|
|
128
|
-
let finishReason;
|
|
129
|
-
const calls = [];
|
|
130
|
-
const byIndex = /* @__PURE__ */ new Map();
|
|
131
|
-
let current;
|
|
132
|
-
const decoder = new TextDecoder();
|
|
133
|
-
let buffer = "";
|
|
134
|
-
let loopAt = -1;
|
|
135
|
-
const handle = (line) => {
|
|
136
|
-
if (!line.startsWith("data:")) return;
|
|
137
|
-
const data = line.slice(5).trim();
|
|
138
|
-
if (!data || data === "[DONE]") return;
|
|
139
|
-
let event;
|
|
140
|
-
try {
|
|
141
|
-
event = JSON.parse(data);
|
|
142
|
-
} catch {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
if (event.error) throw new ProviderError(`Error dari provider: ${event.error.message ?? JSON.stringify(event.error)}`);
|
|
146
|
-
if (event.usage) usage = toUsage(event.usage);
|
|
147
|
-
const choice = event.choices?.[0];
|
|
148
|
-
if (!choice) return;
|
|
149
|
-
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
150
|
-
const delta = choice.delta ?? {};
|
|
151
|
-
const reasoning = delta.reasoning_content || delta.reasoning;
|
|
152
|
-
if (reasoning) emit({ text: "", thinking: reasoning });
|
|
153
|
-
if (delta.content) emit(splitter.push(delta.content));
|
|
154
|
-
for (const tc of delta.tool_calls ?? []) {
|
|
155
|
-
let target = tc.index !== void 0 ? byIndex.get(tc.index) : current;
|
|
156
|
-
if (!target || tc.index === void 0 && tc.id && target.id && target.id !== tc.id) {
|
|
157
|
-
target = { id: "", name: "", arguments: "" };
|
|
158
|
-
calls.push(target);
|
|
159
|
-
if (tc.index !== void 0) byIndex.set(tc.index, target);
|
|
160
|
-
}
|
|
161
|
-
current = target;
|
|
162
|
-
if (tc.id) target.id = tc.id;
|
|
163
|
-
if (tc.function?.name && !target.name) target.name = tc.function.name;
|
|
164
|
-
if (tc.function?.arguments) target.arguments += tc.function.arguments;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
for await (const chunk of res.body) {
|
|
168
|
-
buffer += decoder.decode(chunk, { stream: true });
|
|
169
|
-
let newline = buffer.indexOf("\n");
|
|
170
|
-
while (newline >= 0 && loopAt < 0) {
|
|
171
|
-
handle(buffer.slice(0, newline).trim());
|
|
172
|
-
buffer = buffer.slice(newline + 1);
|
|
173
|
-
newline = buffer.indexOf("\n");
|
|
174
|
-
}
|
|
175
|
-
if (loopAt >= 0) return { text: text.slice(0, loopAt), toolCalls: [], thinking: thinking || void 0, usage, finishReason: "repetition" };
|
|
176
|
-
}
|
|
177
|
-
handle(buffer.trim());
|
|
178
|
-
emit(splitter.flush());
|
|
179
|
-
const toolCalls = calls.map((call, index) => ({ ...call, id: call.id || `call_${index}` }));
|
|
180
|
-
return { text, toolCalls, thinking: thinking || void 0, usage, finishReason };
|
|
181
|
-
}
|
|
182
|
-
async function readJson(res) {
|
|
183
|
-
const body = await res.json();
|
|
184
|
-
const choice = body.choices?.[0];
|
|
185
|
-
const toolCalls = (choice?.message?.tool_calls ?? []).map((tc, i) => ({
|
|
186
|
-
id: tc.id || `call_${i}`,
|
|
187
|
-
name: tc.function?.name ?? "",
|
|
188
|
-
arguments: tc.function?.arguments ?? ""
|
|
189
|
-
}));
|
|
190
|
-
const split = splitThinking(choice?.message?.content ?? "");
|
|
191
|
-
const thinking = (choice?.message?.reasoning_content || choice?.message?.reasoning || "") + split.thinking;
|
|
192
|
-
return { text: split.text, toolCalls, thinking: thinking || void 0, usage: toUsage(body.usage), finishReason: choice?.finish_reason };
|
|
193
|
-
}
|
|
194
|
-
function createProvider({ baseURL, apiKey, model, providerId, fetch: doFetch = fetch, retryDelayMs = 1e3 }) {
|
|
195
|
-
const headers = { "content-type": "application/json" };
|
|
196
|
-
if (apiKey) headers.authorization = `Bearer ${apiKey}`;
|
|
197
|
-
if (/^https:\/\/api\.botconnector\.id\/v1\/?$/.test(baseURL) && apiKey?.startsWith("bc_live_")) {
|
|
198
|
-
headers["x-botconnector-client"] = "bccli";
|
|
199
|
-
headers["x-botconnector-client-version"] = "0.4.0";
|
|
200
|
-
}
|
|
201
|
-
async function post(path, body, signal) {
|
|
202
|
-
let lastError;
|
|
203
|
-
for (let attempt = 0; attempt < 4; attempt++) {
|
|
204
|
-
if (attempt > 0) await sleep(retryDelayMs * 2 ** (attempt - 1), signal);
|
|
205
|
-
let res;
|
|
206
|
-
try {
|
|
207
|
-
res = await doFetch(`${baseURL}${path}`, { method: "POST", headers, body: JSON.stringify(body), signal });
|
|
208
|
-
} catch (error) {
|
|
209
|
-
if (signal?.aborted) throw error;
|
|
210
|
-
lastError = new ProviderError(`Tidak bisa terhubung ke ${baseURL}: ${error.message}`);
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if (res.ok) return res;
|
|
214
|
-
const text = await res.text().catch(() => "");
|
|
215
|
-
lastError = new ProviderError(`${res.status} dari ${baseURL}: ${errorMessage(text)}`, res.status);
|
|
216
|
-
if (!retryable(res.status)) throw lastError;
|
|
217
|
-
}
|
|
218
|
-
throw lastError ?? new ProviderError("Permintaan gagal");
|
|
219
|
-
}
|
|
220
|
-
return {
|
|
221
|
-
async chat({ messages, tools, signal, onText, onThinking, reasoning = "auto" }) {
|
|
222
|
-
let reasoningOverride;
|
|
223
|
-
try {
|
|
224
|
-
reasoningOverride = reasoningPayload(providerId, reasoning);
|
|
225
|
-
} catch (error) {
|
|
226
|
-
throw new ProviderError(error.message);
|
|
227
|
-
}
|
|
228
|
-
const res = await post(
|
|
229
|
-
"/chat/completions",
|
|
230
|
-
{ model, messages, stream: true, stream_options: { include_usage: true }, ...tools?.length ? { tools } : {}, ...reasoningOverride },
|
|
231
|
-
signal
|
|
232
|
-
);
|
|
233
|
-
if ((res.headers.get("content-type") ?? "").includes("application/json")) return readJson(res);
|
|
234
|
-
if (!res.body) throw new ProviderError("Respons provider kosong");
|
|
235
|
-
return readStream(res, onText, onThinking);
|
|
236
|
-
},
|
|
237
|
-
async listModels() {
|
|
238
|
-
const res = await doFetch(`${baseURL}/models`, { headers });
|
|
239
|
-
if (!res.ok) throw new ProviderError(`${res.status} saat mengambil daftar model`, res.status);
|
|
240
|
-
const body = await res.json();
|
|
241
|
-
return (body.data ?? []).map((m) => m.id).sort();
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// src/models.ts
|
|
247
|
-
function order(ids) {
|
|
248
|
-
const presetIds = PRESETS.map((p) => p.id);
|
|
249
|
-
const presets = presetIds.filter((id) => ids.includes(id));
|
|
250
|
-
const custom = ids.filter((id) => !presetIds.includes(id)).sort();
|
|
251
|
-
return [...presets, ...custom];
|
|
252
|
-
}
|
|
253
|
-
async function listAllModels(config, env = process.env, opts = {}) {
|
|
254
|
-
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
255
|
-
const baseFetch = opts.fetch ?? fetch;
|
|
256
|
-
const untrusted = new Set(config.projectProviders ?? []);
|
|
257
|
-
const ids = order(Object.keys(config.providers)).filter((id) => opts.only ? id === opts.only : !untrusted.has(id) && hasKey(config, id, env));
|
|
258
|
-
const results = await Promise.all(
|
|
259
|
-
ids.map(async (id) => {
|
|
260
|
-
const provider = config.providers[id];
|
|
261
|
-
const apiKey = (opts.keyOverride && id === opts.only ? opts.keyOverride : void 0) || (provider.apiKeyEnv ? env[provider.apiKeyEnv] : void 0) || readCredentials(env)[id] || void 0;
|
|
262
|
-
const local = !provider.apiKeyEnv;
|
|
263
|
-
const timedFetch = ((input, init) => baseFetch(input, { ...init, signal: AbortSignal.timeout(timeoutMs) }));
|
|
264
|
-
const list = createProvider({ baseURL: provider.baseURL.replace(/\/+$/, ""), apiKey, model: "", fetch: timedFetch }).listModels();
|
|
265
|
-
let timer;
|
|
266
|
-
const timeout = new Promise((_, reject) => {
|
|
267
|
-
timer = setTimeout(() => reject(new Error("timeout")), timeoutMs);
|
|
268
|
-
});
|
|
269
|
-
try {
|
|
270
|
-
const models = await Promise.race([list, timeout]);
|
|
271
|
-
return { providerId: id, providerName: providerName(config, id), models };
|
|
272
|
-
} catch {
|
|
273
|
-
if (local && !opts.only) return void 0;
|
|
274
|
-
return { providerId: id, providerName: providerName(config, id), models: [], error: "tidak bisa dihubungi" };
|
|
275
|
-
} finally {
|
|
276
|
-
clearTimeout(timer);
|
|
277
|
-
}
|
|
278
|
-
})
|
|
279
|
-
);
|
|
280
|
-
return results.filter((g) => !!g);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// src/providerCli.ts
|
|
284
|
-
async function addProviderKey(providerId, key, deps) {
|
|
285
|
-
const config = loadConfig(deps.cwd, deps.env);
|
|
286
|
-
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: `API key ditolak atau ${providerName(config, providerId)} tidak bisa dihubungi.` };
|
|
288
|
-
if (key) saveCredential(providerId, key, deps.env);
|
|
289
|
-
return { ok: true, models: group.models.length };
|
|
290
|
-
}
|
|
291
|
-
async function runProviderCommand(args, deps) {
|
|
292
|
-
const [action = "list", id] = args.subArgs;
|
|
293
|
-
const config = loadConfig(deps.cwd, deps.env);
|
|
294
|
-
if (action === "list") {
|
|
295
|
-
for (const pid of Object.keys(config.providers)) {
|
|
296
|
-
const mark = hasKey(config, pid, deps.env) ? "\u2713" : "\u25CB";
|
|
297
|
-
deps.out(`${mark} ${pid.padEnd(14)} ${providerName(config, pid).padEnd(20)} ${config.providers[pid].baseURL}`);
|
|
298
|
-
}
|
|
299
|
-
return 0;
|
|
300
|
-
}
|
|
301
|
-
if (!id) {
|
|
302
|
-
deps.err(`Pemakaian: bccli provider ${action} <id>`);
|
|
303
|
-
return 1;
|
|
304
|
-
}
|
|
305
|
-
if (action === "remove") {
|
|
306
|
-
removeGlobalProvider(id, deps.env);
|
|
307
|
-
deps.out(`${id} dihapus.`);
|
|
308
|
-
return 0;
|
|
309
|
-
}
|
|
310
|
-
if (action !== "add") {
|
|
311
|
-
deps.err(`Aksi tidak dikenal: ${action}. Pakai list, add, atau remove.`);
|
|
312
|
-
return 1;
|
|
313
|
-
}
|
|
314
|
-
const preset = PRESETS.find((p) => p.id === id);
|
|
315
|
-
if (!preset && !config.providers[id]) {
|
|
316
|
-
if (!args.url) {
|
|
317
|
-
deps.err(`${id} bukan preset. Untuk provider custom tambahkan --url <base URL OpenAI-compatible>.`);
|
|
318
|
-
return 1;
|
|
319
|
-
}
|
|
320
|
-
writeGlobalConfig(
|
|
321
|
-
{ providers: { [id]: { baseURL: args.url, ...args.name ? { name: args.name } : {}, ...args.keyEnv ? { apiKeyEnv: args.keyEnv } : {} } } },
|
|
322
|
-
deps.env
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
const needsKey = !!loadConfig(deps.cwd, deps.env).providers[id].apiKeyEnv || !preset;
|
|
326
|
-
const key = needsKey ? await deps.readSecret(`API key untuk ${id} (kosongkan bila tidak perlu): `) : "";
|
|
327
|
-
const result = await addProviderKey(id, key, deps);
|
|
328
|
-
if (!result.ok) {
|
|
329
|
-
deps.err(result.error);
|
|
330
|
-
return 1;
|
|
331
|
-
}
|
|
332
|
-
deps.out(`${id} siap. ${result.models} model tersedia.`);
|
|
333
|
-
return 0;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export {
|
|
337
|
-
createProvider,
|
|
338
|
-
listAllModels,
|
|
339
|
-
addProviderKey,
|
|
340
|
-
runProviderCommand
|
|
341
|
-
};
|
package/dist/chunk-ZYCYTEKD.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
MODE_ORDER
|
|
4
|
-
} from "./chunk-ELML4KVQ.js";
|
|
5
|
-
import {
|
|
6
|
-
REASONING_LEVELS,
|
|
7
|
-
isReasoningLevel
|
|
8
|
-
} from "./chunk-CLN4Z5E3.js";
|
|
9
|
-
import {
|
|
10
|
-
ConfigError
|
|
11
|
-
} from "./chunk-2MGINW4O.js";
|
|
12
|
-
|
|
13
|
-
// src/args.ts
|
|
14
|
-
import { parseArgs } from "util";
|
|
15
|
-
var HELP_TEXT = `BCCLI \u2014 agent AI BotConnector di terminal
|
|
16
|
-
|
|
17
|
-
Pemakaian:
|
|
18
|
-
bccli [tugas] mode interaktif (opsional langsung dengan tugas)
|
|
19
|
-
bccli -p "tugas" jalankan satu tugas tanpa interaksi (skrip/CI)
|
|
20
|
-
bccli login [provider] simpan API key (default: bc-cloud)
|
|
21
|
-
bccli models daftar model dari provider aktif
|
|
22
|
-
bccli provider list|add <id>|remove <id> kelola provider (custom: --url <url> [--name N] [--key-env ENV])
|
|
23
|
-
bccli mcp list|add <nama>|remove <nama> kelola server MCP (katalog, atau --url <url>)
|
|
24
|
-
bccli integrations lihat status integrasi agent eksternal
|
|
25
|
-
bccli connect <agent> hubungkan BotConnector ke agent (opencode, aider)
|
|
26
|
-
bccli disconnect <agent> lepas integrasi dan pulihkan config sebelumnya
|
|
27
|
-
|
|
28
|
-
Opsi:
|
|
29
|
-
-m, --model <provider/model> pilih model, contoh bc-cloud/glm-5.3-flash
|
|
30
|
-
--reasoning <level> auto | off | low | medium | high | max
|
|
31
|
-
-c, --continue lanjutkan sesi terakhir di folder ini
|
|
32
|
-
-r, --resume pilih sesi untuk dilanjutkan
|
|
33
|
-
--allow-all jalankan semua alat tanpa minta izin
|
|
34
|
-
--allowed-tools <a,b> alat yang boleh tanpa izin: bash, edit, fetch
|
|
35
|
-
--permission-mode <mode> default | acceptEdits | plan | allowAll
|
|
36
|
-
-v, --version versi
|
|
37
|
-
-h, --help bantuan ini`;
|
|
38
|
-
function parseCliArgs(argv) {
|
|
39
|
-
const { values, positionals } = parseArgs({
|
|
40
|
-
args: argv,
|
|
41
|
-
allowPositionals: true,
|
|
42
|
-
options: {
|
|
43
|
-
print: { type: "boolean", short: "p" },
|
|
44
|
-
model: { type: "string", short: "m" },
|
|
45
|
-
reasoning: { type: "string" },
|
|
46
|
-
continue: { type: "boolean", short: "c" },
|
|
47
|
-
resume: { type: "boolean", short: "r" },
|
|
48
|
-
"allow-all": { type: "boolean" },
|
|
49
|
-
"allowed-tools": { type: "string" },
|
|
50
|
-
"permission-mode": { type: "string" },
|
|
51
|
-
help: { type: "boolean", short: "h" },
|
|
52
|
-
version: { type: "boolean", short: "v" },
|
|
53
|
-
url: { type: "string" },
|
|
54
|
-
name: { type: "string" },
|
|
55
|
-
"key-env": { type: "string" },
|
|
56
|
-
value: { type: "string", multiple: true }
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
const reasoning = values.reasoning;
|
|
60
|
-
if (reasoning && !isReasoningLevel(reasoning)) {
|
|
61
|
-
throw new ConfigError(`--reasoning harus salah satu dari: ${REASONING_LEVELS.join(", ")}`);
|
|
62
|
-
}
|
|
63
|
-
const mode = values["permission-mode"];
|
|
64
|
-
if (mode && !MODE_ORDER.includes(mode)) {
|
|
65
|
-
throw new ConfigError(`--permission-mode harus salah satu dari: ${MODE_ORDER.join(", ")}`);
|
|
66
|
-
}
|
|
67
|
-
const [first, ...rest] = positionals;
|
|
68
|
-
const SUBCOMMANDS = ["login", "models", "provider", "mcp", "connect", "disconnect", "integrations"];
|
|
69
|
-
const command = SUBCOMMANDS.includes(first) ? first : "run";
|
|
70
|
-
const words = command === "run" ? positionals : rest;
|
|
71
|
-
return {
|
|
72
|
-
command,
|
|
73
|
-
prompt: command === "run" && words.length ? words.join(" ") : void 0,
|
|
74
|
-
print: !!values.print,
|
|
75
|
-
model: values.model,
|
|
76
|
-
reasoning,
|
|
77
|
-
continue: !!values.continue,
|
|
78
|
-
resume: !!values.resume,
|
|
79
|
-
allowAll: !!values["allow-all"],
|
|
80
|
-
allowedTools: (values["allowed-tools"] ?? "").split(",").map((s) => s.trim()).filter(Boolean),
|
|
81
|
-
permissionMode: mode,
|
|
82
|
-
help: !!values.help,
|
|
83
|
-
version: !!values.version,
|
|
84
|
-
loginProvider: command === "login" ? rest[0] ?? "bc-cloud" : void 0,
|
|
85
|
-
subArgs: ["provider", "mcp", "connect", "disconnect", "integrations"].includes(command) ? rest : [],
|
|
86
|
-
url: values.url,
|
|
87
|
-
name: values.name,
|
|
88
|
-
keyEnv: values["key-env"],
|
|
89
|
-
values: values.value ?? []
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export {
|
|
94
|
-
HELP_TEXT,
|
|
95
|
-
parseCliArgs
|
|
96
|
-
};
|