@botconnector/bccli 0.4.0-beta.50 → 0.4.0-beta.52
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 +237 -0
- package/README.md +24 -1
- package/dist/acp-CH5CYAGX.js +182 -0
- package/dist/{args-2R45YZ42.js → args-44YOL5QJ.js} +4 -4
- package/dist/{chunk-H73FO5YK.js → chunk-2Y3QHA6B.js} +2 -2
- package/dist/{chunk-EUCSCUYP.js → chunk-6R2PPFNJ.js} +1 -1
- package/dist/{chunk-2QYHSESB.js → chunk-AWGB5Q44.js} +1 -1
- package/dist/{chunk-FTFVW7XD.js → chunk-BHVJIVEF.js} +3 -3
- package/dist/{chunk-KIZC5XV4.js → chunk-CCE6EISW.js} +10 -10
- package/dist/{chunk-YIYX3FFS.js → chunk-FIW4AJH7.js} +1 -1
- package/dist/{chunk-R4BJBTWC.js → chunk-GMKDCZES.js} +2 -2
- package/dist/{chunk-F6ACN47V.js → chunk-HPMYPOCZ.js} +1 -1
- package/dist/{chunk-4WVIPZFV.js → chunk-ILBXVGMJ.js} +2 -2
- package/dist/{chunk-TQWCM5RO.js → chunk-KDZT3TSG.js} +3 -3
- package/dist/{chunk-XLC6T4SX.js → chunk-LUTJZME3.js} +1 -2
- package/dist/{chunk-KD2LMIS4.js → chunk-MYJ7JVSE.js} +6 -6
- package/dist/{chunk-NDEJUL44.js → chunk-N74AEPNA.js} +2 -2
- package/dist/{chunk-QXOV4DUZ.js → chunk-QB45QGNJ.js} +5 -5
- package/dist/{chunk-N7KP6RNP.js → chunk-YALWYJLE.js} +4 -4
- package/dist/{chunk-DP7EBW53.js → chunk-YATYUXV7.js} +1 -1
- package/dist/{chunk-SNKVS26H.js → chunk-Z7TGZMYK.js} +1 -1
- package/dist/cli.js +38 -38
- package/dist/{completion-OV3MW2N4.js → completion-OZ6UDMOX.js} +1 -1
- package/dist/{config-AZZFOXKV.js → config-KY5HCYJG.js} +3 -3
- package/dist/{config-H5A7XHHK.js → config-UUKS6MAS.js} +2 -2
- package/dist/{ghBotCli-7WDYF4L7.js → ghBotCli-2LLP6VRD.js} +13 -13
- package/dist/{integrationCli-ZMTSILYF.js → integrationCli-UX4QNT3G.js} +2 -2
- package/dist/{login-W4Y6WHLV.js → login-MMC3MKNY.js} +3 -3
- package/dist/{mcpCli-5QISTOFK.js → mcpCli-SQBUXLGD.js} +5 -5
- package/dist/{modelsCli-FZMBD4OE.js → modelsCli-OKAJOI4B.js} +6 -6
- package/dist/{oauthLogin-VESMXG4M.js → oauthLogin-4YKTBX7B.js} +2 -2
- package/dist/{pluginsCli-GEHR7FQR.js → pluginsCli-KFRFZCFG.js} +2 -2
- package/dist/{prCli-JXA7DJW4.js → prCli-FITKBEUT.js} +1 -1
- package/dist/providerCli-5YZY7GFZ.js +15 -0
- package/dist/sdk.js +3 -4
- package/dist/{serve-6KX4MXHC.js → serve-BHU5LDXB.js} +3 -3
- package/dist/{serve-XDHMB7TO.js → serve-GNXXNI6U.js} +14 -14
- package/dist/session-LFDUVEPY.js +12 -0
- package/dist/setup-VWBBGF6G.js +24 -0
- package/dist/{statsCli-H4HEY5ID.js → statsCli-SVJAWOSZ.js} +1 -1
- package/dist/{transferCli-2XUKBG2L.js → transferCli-RE374MK3.js} +4 -4
- package/dist/{ui-6HJVYI46.js → ui-XDLB6OW7.js} +12 -17
- package/dist/{update-IQR346E5.js → update-4SHBDS75.js} +2 -2
- package/package.json +1 -1
- package/dist/acp-V5RP42VB.js +0 -114
- package/dist/providerCli-EUZGKP5F.js +0 -15
- package/dist/session-F6MG3UCU.js +0 -12
- package/dist/setup-LLWREJQH.js +0 -24
package/README.en.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# BCCLI
|
|
2
|
+
|
|
3
|
+
[English](README.en.md) · **Bahasa Indonesia**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@botconnector/bccli)
|
|
6
|
+
[](https://www.npmjs.com/package/@botconnector/bccli)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://botconnector.id/id/download)
|
|
10
|
+
|
|
11
|
+
An AI coding agent from [BotConnector](https://botconnector.id/) that works in your terminal: it reads code,
|
|
12
|
+
edits files, and runs commands — with your permission.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
*Real session recording: BCCLI creates `hello.js` and runs it with `node`.*
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# one-line install (macOS / Linux / WSL2) — provisions a portable Node if needed, no sudo
|
|
20
|
+
curl -fsSL https://raw.githubusercontent.com/farijarifriyanto-debug/bccli/main/install.sh | bash
|
|
21
|
+
|
|
22
|
+
# or manual, if you already have Node.js 22+
|
|
23
|
+
npm i -g @botconnector/bccli@next # latest beta, requires Node.js 22+
|
|
24
|
+
bccli login # store your BotConnector Cloud API key
|
|
25
|
+
cd your-project && bccli
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
| Command | What it does |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `bccli` | interactive mode |
|
|
33
|
+
| `bccli -p "task"` | one-shot task (scripts/CI) |
|
|
34
|
+
| `bccli -p "task" --output-format json` | final result as a single JSON object; `stream-json` = JSONL events per stage (tool_use/tool_result/message/result) for CI |
|
|
35
|
+
| `bccli -c` / `bccli -r` | continue last session / pick a session |
|
|
36
|
+
| `bccli -m provider/model` | choose a model |
|
|
37
|
+
| `bccli --reasoning <auto\|off\|low\|medium\|high\|max>` | set reasoning level for this invocation |
|
|
38
|
+
| `bccli models` | list models |
|
|
39
|
+
|
|
40
|
+
In-session commands (type `/` for suggestions, ↑↓ to select, Enter to run):
|
|
41
|
+
|
|
42
|
+
| Command | What it does |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `/help` | list commands and shortcuts |
|
|
45
|
+
| `/model` | switch model |
|
|
46
|
+
| `/reasoning` | pick Auto / Off / Low / Medium / High / Max |
|
|
47
|
+
| `/provider` | add/select an AI provider |
|
|
48
|
+
| `/language` | change display language (`en` / `id`) |
|
|
49
|
+
| `/mcp` | install/manage MCP servers |
|
|
50
|
+
| `/new` | new session (old sessions are kept) |
|
|
51
|
+
| `/resume` | continue another session in this folder |
|
|
52
|
+
| `/session` | info about this session |
|
|
53
|
+
| `/status` | version, model, permission mode, MCP, context |
|
|
54
|
+
| `/permissions` | view/revoke permissions |
|
|
55
|
+
| `/undo` | undo the last file-edit turn |
|
|
56
|
+
| `/diff` | git diff of the project |
|
|
57
|
+
| `/copy` | copy the last answer |
|
|
58
|
+
| `/export` | save the conversation to markdown |
|
|
59
|
+
| `/memory` | project instructions (/memory <text>, /memory global <text>) |
|
|
60
|
+
| `/init` | create/update AGENTS.md for this project |
|
|
61
|
+
| `/agents` | list subagents |
|
|
62
|
+
| `/skills` | list skills and custom commands |
|
|
63
|
+
| `/doctor` | check installation health |
|
|
64
|
+
| `/login` | store the active provider's API key |
|
|
65
|
+
| `/logout` | remove the active provider's API key |
|
|
66
|
+
| `/clear` | start a fresh conversation |
|
|
67
|
+
| `/compact` | compact the conversation |
|
|
68
|
+
| `/cost` | token usage for this session |
|
|
69
|
+
| `/exit` | quit |
|
|
70
|
+
|
|
71
|
+
`/undo` only reverts file edit/write tool changes (not bash commands), one turn at a time, up to 20 turns back.
|
|
72
|
+
Shift+Tab cycles permission modes: `default` → `acceptEdits` → `plan` → `allowAll`.
|
|
73
|
+
|
|
74
|
+
`-p` mode never prompts: permission-requiring tools are refused unless you pass
|
|
75
|
+
`--allow-all` or `--allowed-tools bash,edit,fetch`.
|
|
76
|
+
|
|
77
|
+
## Language
|
|
78
|
+
|
|
79
|
+
BCCLI's UI (help, messages, permission prompts) is **English by default**. Indonesian stays available:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
bccli --lang id # one-off
|
|
83
|
+
BCCLI_LANG=id bccli # via environment
|
|
84
|
+
/language id # inside a session; stored in ~/.bccli/config.json ("language")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Priority order: `--lang`, then `BCCLI_LANG`, then `language` in config, then English. The model answers in
|
|
88
|
+
the language you write; tool messages the model reads (tool output, errors) are always English so they
|
|
89
|
+
don't distort the reply language.
|
|
90
|
+
|
|
91
|
+
## Providers
|
|
92
|
+
|
|
93
|
+
`/provider` in a session (or `bccli provider add <id>`) adds a provider with just an API key:
|
|
94
|
+
|
|
95
|
+
| Id | Provider |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `bc-cloud` | BotConnector Cloud (default) |
|
|
98
|
+
| `openrouter` | OpenRouter |
|
|
99
|
+
| `openai` | OpenAI |
|
|
100
|
+
| `gemini` | Google Gemini |
|
|
101
|
+
| `deepseek` | DeepSeek |
|
|
102
|
+
| `groq` | Groq |
|
|
103
|
+
| `ollama-cloud` | Ollama Cloud |
|
|
104
|
+
| `ollama` | local Ollama (no key) |
|
|
105
|
+
| `lmstudio` | local LM Studio (no key) |
|
|
106
|
+
|
|
107
|
+
Any other OpenAI-compatible provider: pick **Custom…** in `/provider`, or
|
|
108
|
+
`bccli provider add corp --url https://corp.example/v1 --name "Corp"`.
|
|
109
|
+
|
|
110
|
+
`/model` lists models from **every** provider that has a key, grouped by provider;
|
|
111
|
+
type to filter. Your choice is saved as the default.
|
|
112
|
+
|
|
113
|
+
Reasoning can be set via `bccli --reasoning <auto|off|low|medium|high|max>` or `/reasoning`.
|
|
114
|
+
**Auto** uses the model/provider default and BCCLI sends no reasoning override. BCCLI never
|
|
115
|
+
silently lowers or raises reasoning effort. Manual levels pass through when the provider/model
|
|
116
|
+
contract supports them; unsupported levels produce a clear error instead of a silent downgrade.
|
|
117
|
+
|
|
118
|
+
`.bccli/config.json` inside a project may only pick a `model` and add new keyless providers —
|
|
119
|
+
the `reasoning` preference is read only from the user config `~/.bccli/config.json`, never from a
|
|
120
|
+
cloned repo — permissions (`permissionMode`, `allow`) and existing providers are configured only
|
|
121
|
+
from `~/.bccli/config.json`, so a cloned repo cannot grant itself full permissions or steal API keys.
|
|
122
|
+
|
|
123
|
+
## External agent integrations
|
|
124
|
+
|
|
125
|
+
BCCLI can set up BotConnector as a provider for other agents:
|
|
126
|
+
|
|
127
|
+
| Command | What it does |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `bccli integrations` | show integration status |
|
|
130
|
+
| `bccli connect opencode` | connect OpenCode to BotConnector |
|
|
131
|
+
| `bccli connect aider` | connect Aider to BotConnector |
|
|
132
|
+
| `bccli connect cline` | connect Cline CLI to BotConnector |
|
|
133
|
+
| `bccli connect deepseek-harness` / `bccli connect dsh` | connect DeepSeek Harness to BotConnector |
|
|
134
|
+
| `bccli connect codex` | create Codex Responses API profile + BotConnector launcher |
|
|
135
|
+
| `bccli connect claude-code` | create a Claude Code launcher via Anthropic Messages compatibility |
|
|
136
|
+
| `bccli connect cursor` | guided Cursor setup + Base URL override warning |
|
|
137
|
+
| `bccli connect openai-cli` | create an OpenAI CLI launcher for BotConnector |
|
|
138
|
+
| `bccli connect openai-sdk` | create an env profile for the OpenAI Python/Node SDK |
|
|
139
|
+
| `bccli connect openai-compatible` | create a universal OpenAI-compatible env profile |
|
|
140
|
+
| `bccli disconnect <agent>` | restore the config from before the integration |
|
|
141
|
+
|
|
142
|
+
OpenCode uses the global config `~/.config/opencode/opencode.json`. BCCLI fetches the BotConnector
|
|
143
|
+
model catalog on connect, preserves other providers' config, and stores secrets in a separate file
|
|
144
|
+
under `~/.bccli/integrations/`.
|
|
145
|
+
Aider uses `~/.aider.conf.yml` pointing at a separate BCCLI env file; BCCLI refuses to overwrite
|
|
146
|
+
existing Aider OpenAI/env-file settings.
|
|
147
|
+
|
|
148
|
+
Cline uses an `openai-compatible` provider in `~/.cline/data/settings/providers.json`. If that slot
|
|
149
|
+
is taken by another endpoint, BCCLI refuses to overwrite it. Cline itself stores provider API keys
|
|
150
|
+
in that file.
|
|
151
|
+
|
|
152
|
+
DeepSeek Harness uses a custom `botconnector` provider in `$DSH_HOME/settings.yaml` with
|
|
153
|
+
`api: openai-completions` and `apiKeyEnv: BOTCONNECTOR_API_KEY`; the key goes in the BCCLI block of
|
|
154
|
+
`$DSH_HOME/.env`. Other DSH providers are kept. After connecting, run the web profile with
|
|
155
|
+
`dsh web` (same as `dsh --profile web`); bare `dsh` without a profile is rejected by DSH 0.1.x.
|
|
156
|
+
|
|
157
|
+
Codex uses a profile `$CODEX_HOME/botconnector.config.toml` with `wire_api = "responses"` and a BCCLI
|
|
158
|
+
launcher that reads the key from BCCLI storage at runtime. Claude Code gets an isolated launcher with
|
|
159
|
+
`ANTHROPIC_BASE_URL=https://api.botconnector.id` and the `/v1/messages` compatibility endpoint +
|
|
160
|
+
token counting. Codex and Claude Code primary login/config are not overwritten.
|
|
161
|
+
|
|
162
|
+
External agents call BotConnector directly, so model discovery does not use BCCLI-specific identity.
|
|
163
|
+
Access restricted to BCCLI/Web App (for example Luna launch access) is not automatically inherited.
|
|
164
|
+
Before changing external config, BCCLI makes a backup so `disconnect` can restore it.
|
|
165
|
+
|
|
166
|
+
## Internet
|
|
167
|
+
|
|
168
|
+
- `web_search`: web search with no permission prompt. Uses your BotConnector Cloud account when a key
|
|
169
|
+
is present, otherwise goes straight to Keenable (free, no key). Results are titles, URLs, and short
|
|
170
|
+
snippets, so they are token-efficient.
|
|
171
|
+
- `fetch`: open one URL from this machine (permission required per host).
|
|
172
|
+
|
|
173
|
+
## MCP
|
|
174
|
+
|
|
175
|
+
`/mcp` (or `bccli mcp add <name>`) installs servers from the catalog:
|
|
176
|
+
`playwright`, `context7`, `fetch`, `filesystem`, `git`, `github`. Other remote servers:
|
|
177
|
+
`bccli mcp add name --url https://…`. Stored in `~/.bccli/mcp.json` (`mcpServers` format, same as
|
|
178
|
+
Claude Code). All MCP tools always require permission.
|
|
179
|
+
|
|
180
|
+
A `.bccli/mcp.json` inside a repo is not executed until you approve it (asked once per folder).
|
|
181
|
+
|
|
182
|
+
`bccli mcp serve` runs a stdio MCP server with your BotConnector tools
|
|
183
|
+
(`bc_search`, `bc_fetch`, `bc_models`, `bc_chat`) for Claude Code, Cursor, opencode, and other MCP
|
|
184
|
+
hosts. Requires `bccli login` (or `BOTCONNECTOR_API_KEY`):
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
claude mcp add botconnector -- npx -y @botconnector/bccli mcp serve
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Subagents
|
|
191
|
+
|
|
192
|
+
The agent can delegate work via the `task` tool:
|
|
193
|
+
- `explore` — read & search only, can run in parallel;
|
|
194
|
+
- `general` — all tools (edits/commands still ask permission);
|
|
195
|
+
- custom — `.bccli/agents/name.md` or `.claude/agents/name.md`:
|
|
196
|
+
|
|
197
|
+
```markdown
|
|
198
|
+
---
|
|
199
|
+
name: reviewer
|
|
200
|
+
description: review code changes
|
|
201
|
+
tools: [read, grep, glob]
|
|
202
|
+
model: openrouter/qwen/qwen3-coder
|
|
203
|
+
---
|
|
204
|
+
You are a code reviewer. Report real bugs only.
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Skills & custom commands
|
|
208
|
+
|
|
209
|
+
- Skills: folders containing `SKILL.md` in `~/.bccli/skills/`, `.bccli/skills/`, `~/.claude/skills/`,
|
|
210
|
+
`.claude/skills/` — used automatically when relevant, or via `/skill-name`.
|
|
211
|
+
- Commands: `commands/name.md` in the same folders → `/name arguments` (`$ARGUMENTS` is replaced).
|
|
212
|
+
|
|
213
|
+
## Todos & plan mode
|
|
214
|
+
|
|
215
|
+
Tasks with ≥ 3 steps show a checklist above the input box. In plan mode (Shift+Tab),
|
|
216
|
+
the agent only reads and then proposes a plan; `[a]` approves with automatic edits,
|
|
217
|
+
`[y]` approves asking at each step, `[n]` asks for revisions.
|
|
218
|
+
|
|
219
|
+
Project instructions are read from `AGENTS.md` and `BCCLI.md`.
|
|
220
|
+
|
|
221
|
+
## Development
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npm install
|
|
225
|
+
npm test && npm run typecheck && npm run lint && npm run build
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
CI (`ci.yml`) runs the same on Linux, macOS, and Windows.
|
|
229
|
+
Releases: bump `version` in `package.json`, then push a `v<version>` tag — `release.yml`
|
|
230
|
+
runs tests, a smoke test against BotConnector Cloud, and `npm publish --provenance`.
|
|
231
|
+
|
|
232
|
+
## Learn more
|
|
233
|
+
|
|
234
|
+
- [Download & BCCLI guide](https://botconnector.id/id/download)
|
|
235
|
+
- [BotConnector Developer API](https://botconnector.id/id/developers/api) — OpenAI SDK-compatible endpoint
|
|
236
|
+
- [Switchboard](https://github.com/farijarifriyanto-debug/switchboard) — BotConnector's open source agent harness
|
|
237
|
+
- [Contributing](CONTRIBUTING.md)
|
package/README.md
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
# BCCLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Bahasa Indonesia** · [English](README.en.md)
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@botconnector/bccli)
|
|
6
|
+
[](https://www.npmjs.com/package/@botconnector/bccli)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://botconnector.id/id/download)
|
|
10
|
+
|
|
11
|
+
Agent AI coding dari [BotConnector](https://botconnector.id/) yang bekerja di terminal: membaca kode, mengedit file,
|
|
4
12
|
dan menjalankan perintah — dengan izin kamu.
|
|
5
13
|
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
*Rekaman sesi asli: BCCLI membuat file `hello.js` lalu menjalankannya dengan `node`.*
|
|
17
|
+
|
|
6
18
|
```bash
|
|
19
|
+
# install satu baris (macOS / Linux / WSL2) — pasang Node portable bila perlu, tanpa sudo
|
|
20
|
+
curl -fsSL https://raw.githubusercontent.com/farijarifriyanto-debug/bccli/main/install.sh | bash
|
|
21
|
+
|
|
22
|
+
# atau manual, bila Node.js 22+ sudah terpasang
|
|
7
23
|
npm i -g @botconnector/bccli@next # beta terbaru, butuh Node.js 22+
|
|
8
24
|
bccli login # simpan API key BotConnector Cloud
|
|
9
25
|
cd project-kamu && bccli
|
|
@@ -209,3 +225,10 @@ npm test && npm run typecheck && npm run lint && npm run build
|
|
|
209
225
|
CI (`ci.yml`) menjalankan hal yang sama di Linux, macOS, dan Windows.
|
|
210
226
|
Rilis: naikkan `version` di `package.json`, lalu push tag `v<version>` — `release.yml`
|
|
211
227
|
menjalankan test, smoke test ke BotConnector Cloud, dan `npm publish --provenance`.
|
|
228
|
+
|
|
229
|
+
## Pelajari lebih lanjut
|
|
230
|
+
|
|
231
|
+
- [Unduh & panduan BCCLI](https://botconnector.id/id/download)
|
|
232
|
+
- [Developer API BotConnector](https://botconnector.id/id/developers/api) — endpoint kompatibel OpenAI SDK
|
|
233
|
+
- [Switchboard](https://github.com/farijarifriyanto-debug/switchboard) — harness agent open source dari BotConnector
|
|
234
|
+
- [Berkontribusi](CONTRIBUTING.md)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/acp.ts
|
|
4
|
+
var ACP_PROTOCOL_VERSION = 1;
|
|
5
|
+
var TOOL_KINDS = {
|
|
6
|
+
read: "read",
|
|
7
|
+
repo_map: "read",
|
|
8
|
+
edit: "edit",
|
|
9
|
+
write: "edit",
|
|
10
|
+
grep: "search",
|
|
11
|
+
glob: "search",
|
|
12
|
+
bash: "execute",
|
|
13
|
+
powershell: "execute",
|
|
14
|
+
fetch: "fetch",
|
|
15
|
+
web_search: "fetch"
|
|
16
|
+
};
|
|
17
|
+
var kindOf = (tool) => TOOL_KINDS[tool] ?? "other";
|
|
18
|
+
var titleOf = (tool, target) => (target ? `${tool}: ${target}` : tool).slice(0, 200);
|
|
19
|
+
var MAX_OUTPUT = 4e3;
|
|
20
|
+
var PERMISSION_OPTIONS = [
|
|
21
|
+
{ optionId: "allow", name: "Allow", kind: "allow_once" },
|
|
22
|
+
{ optionId: "allow_session", name: "Allow for this session", kind: "allow_always" },
|
|
23
|
+
{ optionId: "reject", name: "Reject", kind: "reject_once" }
|
|
24
|
+
];
|
|
25
|
+
var ANSWERS = { allow: "yes", allow_session: "session", reject: "no" };
|
|
26
|
+
function runAcp(input, output, opts) {
|
|
27
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
28
|
+
const awaiting = /* @__PURE__ */ new Map();
|
|
29
|
+
let nextSession = 1;
|
|
30
|
+
let nextRequest = 1;
|
|
31
|
+
const write = (msg) => {
|
|
32
|
+
output.write(`${JSON.stringify(msg)}
|
|
33
|
+
`);
|
|
34
|
+
};
|
|
35
|
+
const reply = (id, result) => write({ jsonrpc: "2.0", id, result });
|
|
36
|
+
const replyError = (id, code, message) => write({ jsonrpc: "2.0", id, error: { code, message } });
|
|
37
|
+
const update = (sessionId, body) => write({ jsonrpc: "2.0", method: "session/update", params: { sessionId, update: body } });
|
|
38
|
+
const ioFor = (sid, session) => ({
|
|
39
|
+
toolStart(id, tool, target) {
|
|
40
|
+
session.open.push({ id, tool, target });
|
|
41
|
+
update(sid, { sessionUpdate: "tool_call", toolCallId: id, title: titleOf(tool, target), kind: kindOf(tool), status: "in_progress", rawInput: { target } });
|
|
42
|
+
},
|
|
43
|
+
toolEnd(id, output2, isError) {
|
|
44
|
+
session.open = session.open.filter((c) => c.id !== id);
|
|
45
|
+
const text = output2.length > MAX_OUTPUT ? `${output2.slice(0, MAX_OUTPUT)}
|
|
46
|
+
[truncated]` : output2;
|
|
47
|
+
update(sid, {
|
|
48
|
+
sessionUpdate: "tool_call_update",
|
|
49
|
+
toolCallId: id,
|
|
50
|
+
status: isError ? "failed" : "completed",
|
|
51
|
+
...text ? { content: [{ type: "content", content: { type: "text", text } }] } : {}
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
askPermission(req) {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const requestId = nextRequest++;
|
|
57
|
+
const call = [...session.open].reverse().find((c) => c.tool === req.tool && c.target === req.target);
|
|
58
|
+
const settle = (answer) => {
|
|
59
|
+
session.pending.delete(settle);
|
|
60
|
+
awaiting.delete(requestId);
|
|
61
|
+
resolve(answer);
|
|
62
|
+
};
|
|
63
|
+
session.pending.add(settle);
|
|
64
|
+
awaiting.set(requestId, (message) => {
|
|
65
|
+
const outcome = message.result?.outcome;
|
|
66
|
+
settle(outcome?.outcome === "selected" ? ANSWERS[outcome.optionId ?? ""] ?? "no" : "no");
|
|
67
|
+
});
|
|
68
|
+
write({
|
|
69
|
+
jsonrpc: "2.0",
|
|
70
|
+
id: requestId,
|
|
71
|
+
method: "session/request_permission",
|
|
72
|
+
params: {
|
|
73
|
+
sessionId: sid,
|
|
74
|
+
toolCall: { toolCallId: call?.id ?? `permission-${requestId}`, title: titleOf(req.tool, req.target), kind: kindOf(req.tool), status: "pending" },
|
|
75
|
+
options: PERMISSION_OPTIONS
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const handle = async (msg) => {
|
|
82
|
+
const { id, method, params } = msg ?? {};
|
|
83
|
+
if (method === void 0 && id !== void 0 && (msg.result !== void 0 || msg.error !== void 0)) {
|
|
84
|
+
awaiting.get(id)?.(msg);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (method === "initialize") {
|
|
88
|
+
return reply(id, {
|
|
89
|
+
protocolVersion: ACP_PROTOCOL_VERSION,
|
|
90
|
+
agentCapabilities: {
|
|
91
|
+
loadSession: false,
|
|
92
|
+
promptCapabilities: { image: false, audio: false, embeddedContext: false }
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (method === "session/new") {
|
|
97
|
+
const sessionId = `s${nextSession++}`;
|
|
98
|
+
sessions.set(sessionId, { controller: null, pending: /* @__PURE__ */ new Set(), open: [] });
|
|
99
|
+
return reply(id, { sessionId });
|
|
100
|
+
}
|
|
101
|
+
if (method === "session/cancel") {
|
|
102
|
+
const session = sessions.get(params?.sessionId ?? "");
|
|
103
|
+
session?.controller?.abort();
|
|
104
|
+
for (const settle of [...session?.pending ?? []]) settle("no");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (method === "session/prompt") {
|
|
108
|
+
const sid = params?.sessionId ?? "";
|
|
109
|
+
const session = sessions.get(sid);
|
|
110
|
+
if (!session) return replyError(id, -32602, "Unknown session");
|
|
111
|
+
const text = (params?.prompt ?? []).filter((p) => p?.type === "text").map((p) => String(p.text ?? "")).join("\n");
|
|
112
|
+
const controller = new AbortController();
|
|
113
|
+
session.controller = controller;
|
|
114
|
+
let cancelled = false;
|
|
115
|
+
controller.signal.addEventListener("abort", () => {
|
|
116
|
+
cancelled = true;
|
|
117
|
+
});
|
|
118
|
+
try {
|
|
119
|
+
session.agent ??= opts.newAgent(params?.cwd ?? opts.cwd);
|
|
120
|
+
await session.agent.run(text, (chunk) => update(sid, { sessionUpdate: "agent_message_chunk", content: { type: "text", text: chunk } }), controller.signal, ioFor(sid, session));
|
|
121
|
+
} catch (e) {
|
|
122
|
+
if (cancelled) return reply(id, { stopReason: "cancelled" });
|
|
123
|
+
return replyError(id, -32603, e.message);
|
|
124
|
+
} finally {
|
|
125
|
+
session.controller = null;
|
|
126
|
+
session.open = [];
|
|
127
|
+
}
|
|
128
|
+
return reply(id, { stopReason: cancelled ? "cancelled" : "end_turn" });
|
|
129
|
+
}
|
|
130
|
+
if (id !== void 0) return replyError(id, -32601, "Method not found");
|
|
131
|
+
};
|
|
132
|
+
return new Promise((resolve) => {
|
|
133
|
+
let buf = "";
|
|
134
|
+
const onData = (chunk) => {
|
|
135
|
+
buf += chunk.toString();
|
|
136
|
+
let idx = buf.indexOf("\n");
|
|
137
|
+
while (idx >= 0) {
|
|
138
|
+
const line = buf.slice(0, idx);
|
|
139
|
+
buf = buf.slice(idx + 1);
|
|
140
|
+
idx = buf.indexOf("\n");
|
|
141
|
+
if (!line.trim()) continue;
|
|
142
|
+
let msg;
|
|
143
|
+
try {
|
|
144
|
+
msg = JSON.parse(line);
|
|
145
|
+
} catch {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
void handle(msg);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const onEnd = () => {
|
|
152
|
+
input.removeListener("data", onData);
|
|
153
|
+
resolve();
|
|
154
|
+
};
|
|
155
|
+
input.on("data", onData);
|
|
156
|
+
input.on("end", onEnd);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function runtimeAgent(cwd, allowAll = false) {
|
|
160
|
+
let rt;
|
|
161
|
+
return {
|
|
162
|
+
async run(text, onChunk, signal, io) {
|
|
163
|
+
if (!rt) {
|
|
164
|
+
const { parseCliArgs } = await import("./args-44YOL5QJ.js");
|
|
165
|
+
const { createRuntime } = await import("./setup-VWBBGF6G.js");
|
|
166
|
+
rt = createRuntime({ cwd, args: { ...parseCliArgs([]), allowAll } });
|
|
167
|
+
}
|
|
168
|
+
if (io && !allowAll) rt.agent.askPermission = (req) => io.askPermission(req);
|
|
169
|
+
rt.agent.onEvent = (event) => {
|
|
170
|
+
if (event.type === "text") onChunk(event.delta);
|
|
171
|
+
else if (event.type === "toolStart") io?.toolStart(event.id, event.tool, event.target);
|
|
172
|
+
else if (event.type === "toolEnd") io?.toolEnd(event.id, event.output, event.isError);
|
|
173
|
+
};
|
|
174
|
+
await rt.agent.run(text, signal);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export {
|
|
179
|
+
ACP_PROTOCOL_VERSION,
|
|
180
|
+
runAcp,
|
|
181
|
+
runtimeAgent
|
|
182
|
+
};
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
helpText,
|
|
4
4
|
parseCliArgs
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BHVJIVEF.js";
|
|
6
6
|
import "./chunk-GAFJEQTJ.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-Z7TGZMYK.js";
|
|
8
|
+
import "./chunk-N74AEPNA.js";
|
|
9
|
+
import "./chunk-LUTJZME3.js";
|
|
10
10
|
export {
|
|
11
11
|
helpText,
|
|
12
12
|
parseCliArgs
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
REASONING_LEVELS,
|
|
7
7
|
isReasoningLevel
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-Z7TGZMYK.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-N74AEPNA.js";
|
|
12
12
|
import {
|
|
13
13
|
parseLang,
|
|
14
14
|
t
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-LUTJZME3.js";
|
|
16
16
|
|
|
17
17
|
// src/args.ts
|
|
18
18
|
import { parseArgs } from "util";
|
|
@@ -20,11 +20,11 @@ import {
|
|
|
20
20
|
parseFrontmatter,
|
|
21
21
|
runHooks,
|
|
22
22
|
validateGlobPattern
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-FIW4AJH7.js";
|
|
24
24
|
import {
|
|
25
25
|
createWebSearchTool,
|
|
26
26
|
fetchTool
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-YATYUXV7.js";
|
|
28
28
|
import {
|
|
29
29
|
defineTool
|
|
30
30
|
} from "./chunk-PSO7R5AD.js";
|
|
@@ -33,38 +33,38 @@ import {
|
|
|
33
33
|
} from "./chunk-GAFJEQTJ.js";
|
|
34
34
|
import {
|
|
35
35
|
addProviderKey
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-YALWYJLE.js";
|
|
37
37
|
import {
|
|
38
38
|
listAllModels
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-QB45QGNJ.js";
|
|
40
40
|
import {
|
|
41
41
|
providerName
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-AWGB5Q44.js";
|
|
43
43
|
import {
|
|
44
44
|
FileOAuthProvider,
|
|
45
45
|
hasStoredTokens
|
|
46
46
|
} from "./chunk-7F3IWBPQ.js";
|
|
47
47
|
import {
|
|
48
48
|
Session
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-HPMYPOCZ.js";
|
|
50
50
|
import {
|
|
51
51
|
completionAssistantMessage,
|
|
52
52
|
createProvider,
|
|
53
53
|
hasPendingProgrammaticReplay,
|
|
54
54
|
imageUserMessage
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-GMKDCZES.js";
|
|
56
56
|
import {
|
|
57
57
|
expandEnvVars
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-2Y3QHA6B.js";
|
|
59
59
|
import {
|
|
60
60
|
ConfigError,
|
|
61
61
|
bccliHome,
|
|
62
62
|
loadConfig,
|
|
63
63
|
resolveModel
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-N74AEPNA.js";
|
|
65
65
|
import {
|
|
66
66
|
t
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-LUTJZME3.js";
|
|
68
68
|
|
|
69
69
|
// src/textToolCalls.ts
|
|
70
70
|
var PAIR = /(?:<arg_key>\s*|`)?([A-Za-z_]\w*)(?:\s*<\/arg_key>)?`?\s*(?:=\s*`|<arg_value>)([\s\S]*?)<\/arg_value>/g;
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runCommand,
|
|
4
4
|
runHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FIW4AJH7.js";
|
|
6
6
|
import {
|
|
7
7
|
ConfigError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-N74AEPNA.js";
|
|
9
9
|
import {
|
|
10
10
|
t
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LUTJZME3.js";
|
|
12
12
|
|
|
13
13
|
// src/verify.ts
|
|
14
14
|
var MAX_VERIFY_ROUNDS = 2;
|
|
@@ -239,7 +239,7 @@ Opsi:
|
|
|
239
239
|
"OpenRouter exchange failed ({status}): {detail}. Your stored credential was not changed.": "Pertukaran OpenRouter gagal ({status}): {detail}. Credential tersimpan tidak berubah.",
|
|
240
240
|
"The key was created on your OpenRouter account but could not be saved locally ({reason}). Manage it (copy or revoke) at {dashboard}, then run bccli login openrouter again.": "Key sudah dibuat di akun OpenRouter kamu tetapi gagal disimpan lokal ({reason}). Kelola (salin atau cabut) di {dashboard}, lalu jalankan bccli login openrouter lagi.",
|
|
241
241
|
"Logged in: openrouter credential saved.": "Login berhasil: credential openrouter tersimpan.",
|
|
242
|
-
"Note: {env} is set in the environment
|
|
242
|
+
"Note: {env} is also set in the environment; the stored credential takes priority and {env} is only the fallback.": "Catatan: {env} juga ter-set di environment; credential tersimpan lebih diutamakan dan {env} hanya cadangan.",
|
|
243
243
|
"Verify with: bccli models openrouter (your key is never printed).": "Verifikasi dengan: bccli models openrouter (key kamu tidak pernah dicetak).",
|
|
244
244
|
"openrouter credential removed.": "credential openrouter dihapus.",
|
|
245
245
|
"openrouter credential was not stored.": "credential openrouter tidak tersimpan.",
|
|
@@ -388,7 +388,6 @@ Opsi:
|
|
|
388
388
|
"Could not write {file}: {error}": "Gagal menulis {file}: {error}",
|
|
389
389
|
"Added to {file}.": "Ditambahkan ke {file}.",
|
|
390
390
|
"API key for {provider}": "API key untuk {provider}",
|
|
391
|
-
"Key for {provider} saved, but {env} in the environment takes precedence and is still used.": "Key {provider} tersimpan, tapi {env} di environment lebih diutamakan dan tetap dipakai.",
|
|
392
391
|
"Key for {provider} saved \xB7 {n} models.": "Key {provider} tersimpan \xB7 {n} model.",
|
|
393
392
|
"Stored key deleted, but {env} is still set in the environment and is still used.": "Key tersimpan dihapus, tapi {env} masih ada di environment dan tetap dipakai.",
|
|
394
393
|
"No stored key; {env} is still set in the environment and is still used.": "Tidak ada key tersimpan; {env} masih ada di environment dan tetap dipakai.",
|