byterover-cli 1.4.0 → 1.6.0
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.md +193 -12
- package/dist/core/domain/cipher/process/types.d.ts +1 -1
- package/dist/core/domain/entities/provider-config.d.ts +92 -0
- package/dist/core/domain/entities/provider-config.js +181 -0
- package/dist/core/domain/entities/provider-registry.d.ts +55 -0
- package/dist/core/domain/entities/provider-registry.js +74 -0
- package/dist/core/domain/errors/headless-prompt-error.d.ts +11 -0
- package/dist/core/domain/errors/headless-prompt-error.js +18 -0
- package/dist/core/interfaces/cipher/i-content-generator.d.ts +30 -0
- package/dist/core/interfaces/cipher/i-content-generator.js +12 -1
- package/dist/core/interfaces/cipher/message-factory.d.ts +4 -1
- package/dist/core/interfaces/cipher/message-factory.js +5 -0
- package/dist/core/interfaces/cipher/message-types.d.ts +19 -1
- package/dist/core/interfaces/i-cogit-pull-service.d.ts +0 -1
- package/dist/core/interfaces/i-memory-retrieval-service.d.ts +0 -1
- package/dist/core/interfaces/i-memory-storage-service.d.ts +0 -2
- package/dist/core/interfaces/i-provider-config-store.d.ts +88 -0
- package/dist/core/interfaces/i-provider-config-store.js +1 -0
- package/dist/core/interfaces/i-provider-keychain-store.d.ts +33 -0
- package/dist/core/interfaces/i-provider-keychain-store.js +1 -0
- package/dist/core/interfaces/i-space-service.d.ts +1 -2
- package/dist/core/interfaces/i-team-service.d.ts +1 -2
- package/dist/core/interfaces/i-user-service.d.ts +1 -2
- package/dist/core/interfaces/usecase/i-curate-use-case.d.ts +2 -0
- package/dist/core/interfaces/usecase/i-init-use-case.d.ts +9 -3
- package/dist/core/interfaces/usecase/i-login-use-case.d.ts +4 -1
- package/dist/core/interfaces/usecase/i-pull-use-case.d.ts +5 -3
- package/dist/core/interfaces/usecase/i-push-use-case.d.ts +6 -4
- package/dist/core/interfaces/usecase/i-query-use-case.d.ts +2 -0
- package/dist/core/interfaces/usecase/i-status-use-case.d.ts +1 -0
- package/dist/infra/cipher/agent/service-initializer.d.ts +1 -1
- package/dist/infra/cipher/agent/service-initializer.js +0 -1
- package/dist/infra/cipher/file-system/file-system-service.js +5 -5
- package/dist/infra/cipher/http/internal-llm-http-service.d.ts +40 -1
- package/dist/infra/cipher/http/internal-llm-http-service.js +153 -4
- package/dist/infra/cipher/llm/formatters/gemini-formatter.js +8 -1
- package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +2 -3
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +20 -11
- package/dist/infra/cipher/llm/generators/openrouter-content-generator.d.ts +1 -0
- package/dist/infra/cipher/llm/generators/openrouter-content-generator.js +26 -0
- package/dist/infra/cipher/llm/internal-llm-service.d.ts +13 -0
- package/dist/infra/cipher/llm/internal-llm-service.js +75 -4
- package/dist/infra/cipher/llm/model-capabilities.d.ts +74 -0
- package/dist/infra/cipher/llm/model-capabilities.js +157 -0
- package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +35 -1
- package/dist/infra/cipher/llm/openrouter-llm-service.js +216 -28
- package/dist/infra/cipher/llm/stream-processor.d.ts +22 -2
- package/dist/infra/cipher/llm/stream-processor.js +78 -4
- package/dist/infra/cipher/llm/thought-parser.d.ts +1 -1
- package/dist/infra/cipher/llm/thought-parser.js +5 -5
- package/dist/infra/cipher/llm/transformers/openrouter-stream-transformer.d.ts +49 -0
- package/dist/infra/cipher/llm/transformers/openrouter-stream-transformer.js +272 -0
- package/dist/infra/cipher/llm/transformers/reasoning-extractor.d.ts +71 -0
- package/dist/infra/cipher/llm/transformers/reasoning-extractor.js +253 -0
- package/dist/infra/cipher/process/process-service.js +1 -1
- package/dist/infra/cipher/session/chat-session.d.ts +2 -0
- package/dist/infra/cipher/session/chat-session.js +13 -2
- package/dist/infra/cipher/storage/message-storage-service.js +4 -0
- package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +3 -3
- package/dist/infra/cipher/tools/implementations/task-tool.js +1 -1
- package/dist/infra/cogit/http-cogit-pull-service.js +1 -1
- package/dist/infra/cogit/http-cogit-push-service.js +0 -1
- package/dist/infra/http/authenticated-http-client.d.ts +1 -3
- package/dist/infra/http/authenticated-http-client.js +1 -5
- package/dist/infra/http/openrouter-api-client.d.ts +148 -0
- package/dist/infra/http/openrouter-api-client.js +161 -0
- package/dist/infra/mcp/tools/task-result-waiter.js +9 -1
- package/dist/infra/memory/http-memory-retrieval-service.js +1 -1
- package/dist/infra/memory/http-memory-storage-service.js +2 -2
- package/dist/infra/process/agent-worker.js +178 -70
- package/dist/infra/process/inline-agent-executor.d.ts +32 -0
- package/dist/infra/process/inline-agent-executor.js +259 -0
- package/dist/infra/process/transport-handlers.d.ts +25 -4
- package/dist/infra/process/transport-handlers.js +57 -10
- package/dist/infra/repl/commands/connectors-command.js +2 -2
- package/dist/infra/repl/commands/index.js +5 -0
- package/dist/infra/repl/commands/model-command.d.ts +13 -0
- package/dist/infra/repl/commands/model-command.js +212 -0
- package/dist/infra/repl/commands/provider-command.d.ts +13 -0
- package/dist/infra/repl/commands/provider-command.js +181 -0
- package/dist/infra/repl/transport-client-helper.js +6 -2
- package/dist/infra/space/http-space-service.d.ts +1 -1
- package/dist/infra/space/http-space-service.js +2 -2
- package/dist/infra/storage/file-provider-config-store.d.ts +83 -0
- package/dist/infra/storage/file-provider-config-store.js +157 -0
- package/dist/infra/storage/provider-keychain-store.d.ts +37 -0
- package/dist/infra/storage/provider-keychain-store.js +75 -0
- package/dist/infra/storage/token-store.d.ts +4 -3
- package/dist/infra/storage/token-store.js +6 -5
- package/dist/infra/team/http-team-service.d.ts +1 -1
- package/dist/infra/team/http-team-service.js +2 -2
- package/dist/infra/terminal/headless-terminal.d.ts +91 -0
- package/dist/infra/terminal/headless-terminal.js +211 -0
- package/dist/infra/transport/socket-io-transport-client.d.ts +20 -0
- package/dist/infra/transport/socket-io-transport-client.js +88 -1
- package/dist/infra/usecase/curate-use-case.d.ts +40 -1
- package/dist/infra/usecase/curate-use-case.js +176 -15
- package/dist/infra/usecase/init-use-case.d.ts +27 -5
- package/dist/infra/usecase/init-use-case.js +200 -34
- package/dist/infra/usecase/login-use-case.d.ts +10 -8
- package/dist/infra/usecase/login-use-case.js +35 -2
- package/dist/infra/usecase/pull-use-case.d.ts +19 -5
- package/dist/infra/usecase/pull-use-case.js +71 -13
- package/dist/infra/usecase/push-use-case.d.ts +18 -5
- package/dist/infra/usecase/push-use-case.js +81 -14
- package/dist/infra/usecase/query-use-case.d.ts +21 -0
- package/dist/infra/usecase/query-use-case.js +114 -29
- package/dist/infra/usecase/space-list-use-case.js +1 -1
- package/dist/infra/usecase/space-switch-use-case.js +2 -2
- package/dist/infra/usecase/status-use-case.d.ts +36 -0
- package/dist/infra/usecase/status-use-case.js +185 -48
- package/dist/infra/user/http-user-service.d.ts +1 -1
- package/dist/infra/user/http-user-service.js +2 -2
- package/dist/oclif/commands/curate.d.ts +6 -1
- package/dist/oclif/commands/curate.js +24 -3
- package/dist/oclif/commands/init.d.ts +18 -0
- package/dist/oclif/commands/init.js +129 -0
- package/dist/oclif/commands/login.d.ts +9 -0
- package/dist/oclif/commands/login.js +45 -0
- package/dist/oclif/commands/pull.d.ts +16 -0
- package/dist/oclif/commands/pull.js +78 -0
- package/dist/oclif/commands/push.d.ts +17 -0
- package/dist/oclif/commands/push.js +87 -0
- package/dist/oclif/commands/query.d.ts +6 -1
- package/dist/oclif/commands/query.js +29 -4
- package/dist/oclif/commands/status.d.ts +5 -1
- package/dist/oclif/commands/status.js +17 -5
- package/dist/resources/tools/bash_exec.txt +1 -1
- package/dist/tui/components/api-key-dialog.d.ts +39 -0
- package/dist/tui/components/api-key-dialog.js +94 -0
- package/dist/tui/components/execution/execution-changes.d.ts +3 -1
- package/dist/tui/components/execution/execution-changes.js +4 -4
- package/dist/tui/components/execution/execution-content.d.ts +1 -1
- package/dist/tui/components/execution/execution-content.js +4 -12
- package/dist/tui/components/execution/execution-input.js +1 -1
- package/dist/tui/components/execution/execution-progress.d.ts +10 -13
- package/dist/tui/components/execution/execution-progress.js +70 -17
- package/dist/tui/components/execution/execution-reasoning.d.ts +16 -0
- package/dist/tui/components/execution/execution-reasoning.js +34 -0
- package/dist/tui/components/execution/execution-tool.d.ts +23 -0
- package/dist/tui/components/execution/execution-tool.js +125 -0
- package/dist/tui/components/execution/expanded-log-view.js +3 -3
- package/dist/tui/components/execution/log-item.d.ts +2 -0
- package/dist/tui/components/execution/log-item.js +6 -4
- package/dist/tui/components/index.d.ts +2 -0
- package/dist/tui/components/index.js +2 -0
- package/dist/tui/components/inline-prompts/inline-select.js +3 -2
- package/dist/tui/components/model-dialog.d.ts +63 -0
- package/dist/tui/components/model-dialog.js +89 -0
- package/dist/tui/components/onboarding/onboarding-flow.js +8 -2
- package/dist/tui/components/provider-dialog.d.ts +27 -0
- package/dist/tui/components/provider-dialog.js +31 -0
- package/dist/tui/components/reasoning-text.d.ts +26 -0
- package/dist/tui/components/reasoning-text.js +49 -0
- package/dist/tui/components/selectable-list.d.ts +54 -0
- package/dist/tui/components/selectable-list.js +180 -0
- package/dist/tui/components/streaming-text.d.ts +30 -0
- package/dist/tui/components/streaming-text.js +52 -0
- package/dist/tui/contexts/tasks-context.d.ts +15 -0
- package/dist/tui/contexts/tasks-context.js +224 -40
- package/dist/tui/contexts/theme-context.d.ts +1 -0
- package/dist/tui/contexts/theme-context.js +3 -2
- package/dist/tui/hooks/use-activity-logs.js +7 -1
- package/dist/tui/hooks/use-auth-polling.js +1 -1
- package/dist/tui/types/messages.d.ts +32 -5
- package/dist/tui/utils/index.d.ts +1 -1
- package/dist/tui/utils/index.js +1 -1
- package/dist/tui/utils/log.d.ts +0 -9
- package/dist/tui/utils/log.js +2 -53
- package/dist/tui/views/command-view.js +4 -1
- package/dist/utils/environment-detector.d.ts +15 -0
- package/dist/utils/environment-detector.js +62 -1
- package/oclif.manifest.json +287 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,8 +12,11 @@ Command-line interface for ByteRover, featuring an interactive REPL with a moder
|
|
|
12
12
|
* [Quick Start](#quick-start)
|
|
13
13
|
* [Interactive REPL](#interactive-repl)
|
|
14
14
|
* [Keyboard Shortcuts](#keyboard-shortcuts)
|
|
15
|
+
* [CLI Commands](#cli-commands)
|
|
16
|
+
* [Headless Mode](#headless-mode)
|
|
15
17
|
* [What is Context Tree?](#what-is-context-tree)
|
|
16
18
|
* [Supported AI Agents](#supported-ai-agents)
|
|
19
|
+
* [LLM Providers](#llm-providers) (BETA)
|
|
17
20
|
* [Slash Commands Reference](#slash-commands-reference)
|
|
18
21
|
* [Authentication](#authentication)
|
|
19
22
|
* [Configuration](#configuration)
|
|
@@ -51,7 +54,7 @@ brv --version
|
|
|
51
54
|
|
|
52
55
|
Visit [**ByteRover Docs**](https://docs.byterover.dev) for more information.
|
|
53
56
|
|
|
54
|
-
Get started with ByteRover CLI
|
|
57
|
+
Get started with ByteRover CLI:
|
|
55
58
|
|
|
56
59
|
### 1. Start the REPL
|
|
57
60
|
|
|
@@ -91,6 +94,14 @@ ByteRover automatically configures the best connector for your installed agents:
|
|
|
91
94
|
- **MCP tools** for most other agents (universal protocol)
|
|
92
95
|
- Switch connector types anytime via `/connectors`
|
|
93
96
|
|
|
97
|
+
### 5. (Optional) Connect an LLM Provider
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
/provider
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
ByteRover works out of the box with its built-in LLM provider. To use your own models, connect to [OpenRouter](https://openrouter.ai/keys) for access to 200+ models. See [LLM Providers](#llm-providers) for details.
|
|
104
|
+
|
|
94
105
|
You're now ready to use ByteRover! Try `/status` to see your project's current state.
|
|
95
106
|
|
|
96
107
|
## Interactive REPL
|
|
@@ -115,7 +126,7 @@ The terminal UI includes:
|
|
|
115
126
|
- **Streaming Output**: Live responses with markdown rendering (headings, lists, blockquotes, code blocks)
|
|
116
127
|
- **Reasoning Display**: View agent thinking process with streamed reasoning blocks
|
|
117
128
|
- **File References**: Type `@` in curate mode to browse and attach files
|
|
118
|
-
- **PDF Support**: Reference and extract text from PDF files using `@` (
|
|
129
|
+
- **PDF Support**: Reference and extract text from PDF files using `@` (100 pages default, 200 max)
|
|
119
130
|
- **Dynamic Domains**: Automatically creates new knowledge domains as your context tree grows
|
|
120
131
|
- **Session Persistence**: Sessions auto-resume after restart
|
|
121
132
|
- **Expandable Views**: Press `Ctrl+O` to expand messages or logs to full-screen with vim-style navigation
|
|
@@ -133,17 +144,123 @@ The terminal UI includes:
|
|
|
133
144
|
| `/` | Show command suggestions |
|
|
134
145
|
| `@` | Browse files (in curate mode) |
|
|
135
146
|
|
|
136
|
-
|
|
147
|
+
## CLI Commands
|
|
137
148
|
|
|
138
|
-
In the REPL,
|
|
149
|
+
In addition to the interactive REPL, ByteRover CLI provides direct command-line commands for automation and scripting.
|
|
150
|
+
|
|
151
|
+
### Authentication
|
|
152
|
+
|
|
153
|
+
| Command | Description |
|
|
154
|
+
|---------|-------------|
|
|
155
|
+
| `brv login -k <key>` | Authenticate with an API key |
|
|
139
156
|
|
|
157
|
+
**Example:**
|
|
158
|
+
```bash
|
|
159
|
+
brv login --api-key your-api-key
|
|
140
160
|
```
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
161
|
+
|
|
162
|
+
Get your API key at [app.byterover.dev/settings/keys](https://app.byterover.dev/settings/keys).
|
|
163
|
+
|
|
164
|
+
### Project Commands
|
|
165
|
+
|
|
166
|
+
| Command | Description |
|
|
167
|
+
|---------|-------------|
|
|
168
|
+
| `brv init` | Initialize a project with ByteRover |
|
|
169
|
+
| `brv status [dir]` | Show CLI status and project information |
|
|
170
|
+
|
|
171
|
+
**Init flags:**
|
|
172
|
+
- `-f, --force`: Force re-initialization without confirmation
|
|
173
|
+
- `--headless`: Run in headless mode (requires `--team` and `--space`)
|
|
174
|
+
- `--team <id|name>`: Team ID or name
|
|
175
|
+
- `--space <id|name>`: Space ID or name
|
|
176
|
+
- `--format <text|json>`: Output format (default: text)
|
|
177
|
+
|
|
178
|
+
**Status flags:**
|
|
179
|
+
- `-f, --format <text|json>`: Output format (default: text)
|
|
180
|
+
- `--headless`: Run in headless mode
|
|
181
|
+
|
|
182
|
+
### Context Operations
|
|
183
|
+
|
|
184
|
+
| Command | Description |
|
|
185
|
+
|---------|-------------|
|
|
186
|
+
| `brv query <question>` | Query the context tree |
|
|
187
|
+
| `brv curate [context]` | Curate context to the context tree |
|
|
188
|
+
|
|
189
|
+
**Note:** `query` and `curate` require a running `brv` instance in another terminal.
|
|
190
|
+
|
|
191
|
+
**Query flags:**
|
|
192
|
+
- `--headless`: Run in headless mode
|
|
193
|
+
- `--format <text|json>`: Output format (default: text)
|
|
194
|
+
|
|
195
|
+
**Curate flags:**
|
|
196
|
+
- `-f, --files <path>`: Include specific files (max 5, can be repeated)
|
|
197
|
+
- `--headless`: Run in headless mode
|
|
198
|
+
- `--format <text|json>`: Output format (default: text)
|
|
199
|
+
|
|
200
|
+
### Cloud Sync
|
|
201
|
+
|
|
202
|
+
| Command | Description |
|
|
203
|
+
|---------|-------------|
|
|
204
|
+
| `brv push` | Push context tree to ByteRover cloud |
|
|
205
|
+
| `brv pull` | Pull context tree from ByteRover cloud |
|
|
206
|
+
|
|
207
|
+
**Push flags:**
|
|
208
|
+
- `-b, --branch <name>`: ByteRover branch name (default: main, not Git branch)
|
|
209
|
+
- `-y, --yes`: Skip confirmation prompt
|
|
210
|
+
- `--headless`: Run in headless mode (auto-skips confirmation)
|
|
211
|
+
- `--format <text|json>`: Output format (default: text)
|
|
212
|
+
|
|
213
|
+
**Pull flags:**
|
|
214
|
+
- `-b, --branch <name>`: ByteRover branch name (default: main, not Git branch)
|
|
215
|
+
- `--headless`: Run in headless mode
|
|
216
|
+
- `--format <text|json>`: Output format (default: text)
|
|
217
|
+
|
|
218
|
+
## Headless Mode
|
|
219
|
+
|
|
220
|
+
ByteRover CLI supports headless mode for automation, CI/CD pipelines, and scripting. Headless mode disables interactive prompts and supports machine-readable JSON output.
|
|
221
|
+
|
|
222
|
+
### Supported Commands
|
|
223
|
+
|
|
224
|
+
The following commands support `--headless` mode:
|
|
225
|
+
- `brv init` (requires `--team` and `--space`)
|
|
226
|
+
- `brv status`
|
|
227
|
+
- `brv query`
|
|
228
|
+
- `brv curate`
|
|
229
|
+
- `brv push` (auto-skips confirmation)
|
|
230
|
+
- `brv pull`
|
|
231
|
+
|
|
232
|
+
### Output Formats
|
|
233
|
+
|
|
234
|
+
Use `--format` to control output:
|
|
235
|
+
- `text` (default): Human-readable text output
|
|
236
|
+
- `json`: NDJSON (newline-delimited JSON) for machine parsing
|
|
237
|
+
|
|
238
|
+
### CI/CD Examples
|
|
239
|
+
|
|
240
|
+
**Initialize a project in CI:**
|
|
241
|
+
```bash
|
|
242
|
+
brv login --api-key $BRV_API_KEY
|
|
243
|
+
brv init --headless --team "my-team" --space "my-space" --format json
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Push context tree after tests pass:**
|
|
247
|
+
```bash
|
|
248
|
+
brv push --headless --format json -y
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Query context in a script:**
|
|
252
|
+
```bash
|
|
253
|
+
brv query "What are the API endpoints?" --headless --format json
|
|
144
254
|
```
|
|
145
255
|
|
|
146
|
-
|
|
256
|
+
### JSON Output Structure
|
|
257
|
+
|
|
258
|
+
JSON output uses NDJSON format with message types:
|
|
259
|
+
- `log`: Progress messages
|
|
260
|
+
- `output`: Main output content
|
|
261
|
+
- `error`: Error messages
|
|
262
|
+
- `warning`: Warning messages
|
|
263
|
+
- `result`: Final operation result
|
|
147
264
|
|
|
148
265
|
## What is Context Tree?
|
|
149
266
|
|
|
@@ -203,6 +320,48 @@ ByteRover supports four connector types:
|
|
|
203
320
|
- All others (16 agents): MCP connector
|
|
204
321
|
- Rules: Available for all agents as fallback
|
|
205
322
|
|
|
323
|
+
## LLM Providers (BETA)
|
|
324
|
+
|
|
325
|
+
ByteRover uses LLMs internally to power `/curate` and `/query` operations. By default, the built-in ByteRover provider is used with no configuration required. You can optionally connect to OpenRouter to access 200+ models.
|
|
326
|
+
|
|
327
|
+
### Available Providers
|
|
328
|
+
|
|
329
|
+
| Provider | API Key Required | Models |
|
|
330
|
+
|----------|-----------------|--------|
|
|
331
|
+
| **ByteRover** (default) | No | Built-in internal model |
|
|
332
|
+
| **OpenRouter** | Yes | 200+ models from Anthropic, OpenAI, Google, Meta, and more |
|
|
333
|
+
|
|
334
|
+
### Connecting a Provider
|
|
335
|
+
|
|
336
|
+
Use `/provider` (aliases: `/providers`, `/connect`) to switch providers:
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
/provider
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
This opens an interactive prompt showing all available providers with their connection status.
|
|
343
|
+
|
|
344
|
+
### Selecting a Model
|
|
345
|
+
|
|
346
|
+
When connected to OpenRouter, use `/model` (alias: `/models`) to browse and select models:
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
/model
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
The model browser shows:
|
|
353
|
+
- **Pricing**: Input/output cost per million tokens (e.g., `$3.00/$15.00/M`)
|
|
354
|
+
- **Context window**: Maximum token capacity (e.g., `200K ctx`)
|
|
355
|
+
- **Free models**: Marked with `[Free]`
|
|
356
|
+
- **Favorites and recents**: Starred and recently used models appear first
|
|
357
|
+
|
|
358
|
+
### OpenRouter Setup
|
|
359
|
+
|
|
360
|
+
1. Get an API key at [openrouter.ai/keys](https://openrouter.ai/keys)
|
|
361
|
+
2. Run `/provider` and select **OpenRouter**
|
|
362
|
+
3. Paste your API key when prompted (stored securely in system keychain)
|
|
363
|
+
4. Run `/model` to select a model (default: `anthropic/claude-3.5-sonnet`)
|
|
364
|
+
|
|
206
365
|
## Slash Commands Reference
|
|
207
366
|
|
|
208
367
|
### Core Workflow
|
|
@@ -279,6 +438,15 @@ ByteRover supports four connector types:
|
|
|
279
438
|
**Reset options:**
|
|
280
439
|
- `-y, --yes`: Skip confirmation prompt
|
|
281
440
|
|
|
441
|
+
### LLM Providers (BETA)
|
|
442
|
+
|
|
443
|
+
| Command | Description |
|
|
444
|
+
|---------|-------------|
|
|
445
|
+
| `/provider` | Connect to and switch between LLM providers |
|
|
446
|
+
| `/model` | Select a model from the active provider (OpenRouter) |
|
|
447
|
+
|
|
448
|
+
**Aliases:** `/providers` and `/connect` for `/provider`; `/models` for `/model`
|
|
449
|
+
|
|
282
450
|
### Session Management
|
|
283
451
|
|
|
284
452
|
| Command | Description |
|
|
@@ -288,7 +456,7 @@ ByteRover supports four connector types:
|
|
|
288
456
|
**Options:**
|
|
289
457
|
- `-y, --yes`: Skip confirmation prompt
|
|
290
458
|
|
|
291
|
-
**Note:** Sessions are stateful and auto-resume after restart. Use `/new` to start fresh—this clears conversation history but does NOT affect the context tree.
|
|
459
|
+
**Note:** Sessions are stateful and auto-resume after restart (retained for 30 days). Use `/new` to start fresh—this clears conversation history but does NOT affect the context tree.
|
|
292
460
|
|
|
293
461
|
### Project Setup
|
|
294
462
|
|
|
@@ -308,16 +476,29 @@ ByteRover supports four connector types:
|
|
|
308
476
|
|
|
309
477
|
## Authentication
|
|
310
478
|
|
|
311
|
-
ByteRover CLI
|
|
479
|
+
ByteRover CLI supports two authentication methods to suit different workflows.
|
|
480
|
+
|
|
481
|
+
### Authentication Methods
|
|
482
|
+
|
|
483
|
+
**1. OAuth 2.0 (Interactive)**
|
|
484
|
+
- Use `/login` in the REPL
|
|
485
|
+
- Opens browser for secure OAuth flow with PKCE
|
|
486
|
+
- Best for: Local development, interactive use
|
|
487
|
+
|
|
488
|
+
**2. API Key (Non-interactive)**
|
|
489
|
+
- Use `brv login --api-key <key>`
|
|
490
|
+
- No browser required
|
|
491
|
+
- Best for: CI/CD, automation, headless environments
|
|
492
|
+
- Get your key at [app.byterover.dev/settings/keys](https://app.byterover.dev/settings/keys)
|
|
312
493
|
|
|
313
|
-
### How
|
|
494
|
+
### How OAuth Works
|
|
314
495
|
|
|
315
496
|
1. Run `/login` in the REPL to start authentication
|
|
316
497
|
2. Your browser opens to the ByteRover authorization page
|
|
317
498
|
3. After successful login, tokens are securely stored in your system keychain
|
|
318
499
|
4. All subsequent commands automatically use your stored credentials
|
|
319
500
|
|
|
320
|
-
### Security
|
|
501
|
+
### Security Features
|
|
321
502
|
|
|
322
503
|
- **PKCE flow**: Prevents authorization code interception attacks
|
|
323
504
|
- **System keychain**: Tokens stored in macOS Keychain, Windows Credential Manager, or Linux Secret Service
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Configuration Entity
|
|
3
|
+
*
|
|
4
|
+
* Stores user's provider preferences and connection state.
|
|
5
|
+
* Non-sensitive data (API keys stored separately in keychain).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Configuration for a single connected provider.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConnectedProviderConfig {
|
|
11
|
+
/** Currently active model for this provider */
|
|
12
|
+
readonly activeModel?: string;
|
|
13
|
+
/** When the provider was connected */
|
|
14
|
+
readonly connectedAt: string;
|
|
15
|
+
/** User's favorite models (for quick access) */
|
|
16
|
+
readonly favoriteModels: readonly string[];
|
|
17
|
+
/** Recently used models (last 10) */
|
|
18
|
+
readonly recentModels: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parameters for creating a ProviderConfig.
|
|
22
|
+
*/
|
|
23
|
+
export interface ProviderConfigParams {
|
|
24
|
+
/** Currently active provider ID */
|
|
25
|
+
readonly activeProvider: string;
|
|
26
|
+
/** Configuration for each connected provider */
|
|
27
|
+
readonly providers: Readonly<Record<string, ConnectedProviderConfig>>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Default configuration when no providers are connected.
|
|
31
|
+
*/
|
|
32
|
+
export declare const DEFAULT_PROVIDER_CONFIG: ProviderConfigParams;
|
|
33
|
+
/**
|
|
34
|
+
* Represents the provider configuration for the CLI.
|
|
35
|
+
* Tracks which providers are connected and user preferences.
|
|
36
|
+
*/
|
|
37
|
+
export declare class ProviderConfig {
|
|
38
|
+
readonly activeProvider: string;
|
|
39
|
+
readonly providers: Readonly<Record<string, ConnectedProviderConfig>>;
|
|
40
|
+
private constructor();
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new ProviderConfig with default values.
|
|
43
|
+
*/
|
|
44
|
+
static createDefault(): ProviderConfig;
|
|
45
|
+
/**
|
|
46
|
+
* Deserializes config from JSON format.
|
|
47
|
+
* Returns default config for invalid JSON structure.
|
|
48
|
+
*/
|
|
49
|
+
static fromJson(json: unknown): ProviderConfig;
|
|
50
|
+
/**
|
|
51
|
+
* Get the active model for a provider.
|
|
52
|
+
*/
|
|
53
|
+
getActiveModel(providerId: string): string | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Get favorite models for a provider.
|
|
56
|
+
*/
|
|
57
|
+
getFavoriteModels(providerId: string): readonly string[];
|
|
58
|
+
/**
|
|
59
|
+
* Get recent models for a provider.
|
|
60
|
+
*/
|
|
61
|
+
getRecentModels(providerId: string): readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* Check if a provider is connected.
|
|
64
|
+
*/
|
|
65
|
+
isProviderConnected(providerId: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Serializes the config to JSON format.
|
|
68
|
+
*/
|
|
69
|
+
toJson(): ProviderConfigParams;
|
|
70
|
+
/**
|
|
71
|
+
* Create a new config with the active model changed for a provider.
|
|
72
|
+
*/
|
|
73
|
+
withActiveModel(providerId: string, modelId: string): ProviderConfig;
|
|
74
|
+
/**
|
|
75
|
+
* Create a new config with the active provider changed.
|
|
76
|
+
*/
|
|
77
|
+
withActiveProvider(providerId: string): ProviderConfig;
|
|
78
|
+
/**
|
|
79
|
+
* Create a new config with a model toggled as favorite.
|
|
80
|
+
*/
|
|
81
|
+
withFavoriteToggled(providerId: string, modelId: string): ProviderConfig;
|
|
82
|
+
/**
|
|
83
|
+
* Create a new config with a provider connected.
|
|
84
|
+
*/
|
|
85
|
+
withProviderConnected(providerId: string, options?: {
|
|
86
|
+
activeModel?: string;
|
|
87
|
+
}): ProviderConfig;
|
|
88
|
+
/**
|
|
89
|
+
* Create a new config with a provider disconnected.
|
|
90
|
+
*/
|
|
91
|
+
withProviderDisconnected(providerId: string): ProviderConfig;
|
|
92
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Configuration Entity
|
|
3
|
+
*
|
|
4
|
+
* Stores user's provider preferences and connection state.
|
|
5
|
+
* Non-sensitive data (API keys stored separately in keychain).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Type guard for ProviderConfig JSON validation.
|
|
9
|
+
*/
|
|
10
|
+
const isProviderConfigJson = (json) => {
|
|
11
|
+
if (typeof json !== 'object' || json === null)
|
|
12
|
+
return false;
|
|
13
|
+
const obj = json;
|
|
14
|
+
if (typeof obj.activeProvider !== 'string')
|
|
15
|
+
return false;
|
|
16
|
+
if (typeof obj.providers !== 'object' || obj.providers === null)
|
|
17
|
+
return false;
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Default configuration when no providers are connected.
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_PROVIDER_CONFIG = {
|
|
24
|
+
activeProvider: 'byterover',
|
|
25
|
+
providers: {},
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Maximum number of recent models to track.
|
|
29
|
+
*/
|
|
30
|
+
const MAX_RECENT_MODELS = 10;
|
|
31
|
+
/**
|
|
32
|
+
* Represents the provider configuration for the CLI.
|
|
33
|
+
* Tracks which providers are connected and user preferences.
|
|
34
|
+
*/
|
|
35
|
+
export class ProviderConfig {
|
|
36
|
+
activeProvider;
|
|
37
|
+
providers;
|
|
38
|
+
constructor(params) {
|
|
39
|
+
this.activeProvider = params.activeProvider;
|
|
40
|
+
this.providers = params.providers;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a new ProviderConfig with default values.
|
|
44
|
+
*/
|
|
45
|
+
static createDefault() {
|
|
46
|
+
return new ProviderConfig(DEFAULT_PROVIDER_CONFIG);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Deserializes config from JSON format.
|
|
50
|
+
* Returns default config for invalid JSON structure.
|
|
51
|
+
*/
|
|
52
|
+
static fromJson(json) {
|
|
53
|
+
if (!isProviderConfigJson(json)) {
|
|
54
|
+
return ProviderConfig.createDefault();
|
|
55
|
+
}
|
|
56
|
+
return new ProviderConfig(json);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the active model for a provider.
|
|
60
|
+
*/
|
|
61
|
+
getActiveModel(providerId) {
|
|
62
|
+
return this.providers[providerId]?.activeModel;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get favorite models for a provider.
|
|
66
|
+
*/
|
|
67
|
+
getFavoriteModels(providerId) {
|
|
68
|
+
return this.providers[providerId]?.favoriteModels ?? [];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get recent models for a provider.
|
|
72
|
+
*/
|
|
73
|
+
getRecentModels(providerId) {
|
|
74
|
+
return this.providers[providerId]?.recentModels ?? [];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if a provider is connected.
|
|
78
|
+
*/
|
|
79
|
+
isProviderConnected(providerId) {
|
|
80
|
+
return providerId in this.providers;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Serializes the config to JSON format.
|
|
84
|
+
*/
|
|
85
|
+
toJson() {
|
|
86
|
+
return {
|
|
87
|
+
activeProvider: this.activeProvider,
|
|
88
|
+
providers: this.providers,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create a new config with the active model changed for a provider.
|
|
93
|
+
*/
|
|
94
|
+
withActiveModel(providerId, modelId) {
|
|
95
|
+
const existingConfig = this.providers[providerId];
|
|
96
|
+
if (!existingConfig) {
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
// Add to recent models (at the front, deduplicated)
|
|
100
|
+
const recentModels = [
|
|
101
|
+
modelId,
|
|
102
|
+
...existingConfig.recentModels.filter((m) => m !== modelId),
|
|
103
|
+
].slice(0, MAX_RECENT_MODELS);
|
|
104
|
+
const newProviderConfig = {
|
|
105
|
+
...existingConfig,
|
|
106
|
+
activeModel: modelId,
|
|
107
|
+
recentModels,
|
|
108
|
+
};
|
|
109
|
+
return new ProviderConfig({
|
|
110
|
+
...this.toJson(),
|
|
111
|
+
providers: {
|
|
112
|
+
...this.providers,
|
|
113
|
+
[providerId]: newProviderConfig,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create a new config with the active provider changed.
|
|
119
|
+
*/
|
|
120
|
+
withActiveProvider(providerId) {
|
|
121
|
+
return new ProviderConfig({
|
|
122
|
+
...this.toJson(),
|
|
123
|
+
activeProvider: providerId,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Create a new config with a model toggled as favorite.
|
|
128
|
+
*/
|
|
129
|
+
withFavoriteToggled(providerId, modelId) {
|
|
130
|
+
const existingConfig = this.providers[providerId];
|
|
131
|
+
if (!existingConfig) {
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
const isFavorite = existingConfig.favoriteModels.includes(modelId);
|
|
135
|
+
const favoriteModels = isFavorite
|
|
136
|
+
? existingConfig.favoriteModels.filter((m) => m !== modelId)
|
|
137
|
+
: [...existingConfig.favoriteModels, modelId];
|
|
138
|
+
const newProviderConfig = {
|
|
139
|
+
...existingConfig,
|
|
140
|
+
favoriteModels,
|
|
141
|
+
};
|
|
142
|
+
return new ProviderConfig({
|
|
143
|
+
...this.toJson(),
|
|
144
|
+
providers: {
|
|
145
|
+
...this.providers,
|
|
146
|
+
[providerId]: newProviderConfig,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Create a new config with a provider connected.
|
|
152
|
+
*/
|
|
153
|
+
withProviderConnected(providerId, options) {
|
|
154
|
+
const existingConfig = this.providers[providerId];
|
|
155
|
+
const newProviderConfig = {
|
|
156
|
+
activeModel: options?.activeModel ?? existingConfig?.activeModel,
|
|
157
|
+
connectedAt: existingConfig?.connectedAt ?? new Date().toISOString(),
|
|
158
|
+
favoriteModels: existingConfig?.favoriteModels ?? [],
|
|
159
|
+
recentModels: existingConfig?.recentModels ?? [],
|
|
160
|
+
};
|
|
161
|
+
return new ProviderConfig({
|
|
162
|
+
...this.toJson(),
|
|
163
|
+
providers: {
|
|
164
|
+
...this.providers,
|
|
165
|
+
[providerId]: newProviderConfig,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Create a new config with a provider disconnected.
|
|
171
|
+
*/
|
|
172
|
+
withProviderDisconnected(providerId) {
|
|
173
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
174
|
+
const { [providerId]: _removed, ...remainingProviders } = this.providers;
|
|
175
|
+
const newActiveProvider = this.activeProvider === providerId ? 'byterover' : this.activeProvider;
|
|
176
|
+
return new ProviderConfig({
|
|
177
|
+
activeProvider: newActiveProvider,
|
|
178
|
+
providers: remainingProviders,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Registry
|
|
3
|
+
*
|
|
4
|
+
* Defines available LLM providers that can be connected to byterover-cli.
|
|
5
|
+
* Inspired by OpenCode's provider system.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Definition for an LLM provider.
|
|
9
|
+
*/
|
|
10
|
+
export interface ProviderDefinition {
|
|
11
|
+
/** URL where users can get an API key */
|
|
12
|
+
readonly apiKeyUrl?: string;
|
|
13
|
+
/** API base URL (empty for internal providers) */
|
|
14
|
+
readonly baseUrl: string;
|
|
15
|
+
/** Category for grouping in UI */
|
|
16
|
+
readonly category: 'other' | 'popular';
|
|
17
|
+
/** Default model to use when first connected */
|
|
18
|
+
readonly defaultModel?: string;
|
|
19
|
+
/** Short description */
|
|
20
|
+
readonly description: string;
|
|
21
|
+
/** Default headers for API requests */
|
|
22
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
23
|
+
/** Unique provider identifier */
|
|
24
|
+
readonly id: string;
|
|
25
|
+
/** Endpoint to fetch available models */
|
|
26
|
+
readonly modelsEndpoint: string;
|
|
27
|
+
/** Display name */
|
|
28
|
+
readonly name: string;
|
|
29
|
+
/** Priority for display order (lower = higher priority) */
|
|
30
|
+
readonly priority: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Registry of all available providers.
|
|
34
|
+
* Order by priority for consistent display.
|
|
35
|
+
*/
|
|
36
|
+
export declare const PROVIDER_REGISTRY: Readonly<Record<string, ProviderDefinition>>;
|
|
37
|
+
/**
|
|
38
|
+
* Get all providers sorted by priority.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getProvidersSortedByPriority(): ProviderDefinition[];
|
|
41
|
+
/**
|
|
42
|
+
* Get providers grouped by category.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getProvidersGroupedByCategory(): {
|
|
45
|
+
other: ProviderDefinition[];
|
|
46
|
+
popular: ProviderDefinition[];
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Get a provider by ID.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getProviderById(id: string): ProviderDefinition | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a provider requires an API key.
|
|
54
|
+
*/
|
|
55
|
+
export declare function providerRequiresApiKey(id: string): boolean;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Registry
|
|
3
|
+
*
|
|
4
|
+
* Defines available LLM providers that can be connected to byterover-cli.
|
|
5
|
+
* Inspired by OpenCode's provider system.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Registry of all available providers.
|
|
9
|
+
* Order by priority for consistent display.
|
|
10
|
+
*/
|
|
11
|
+
export const PROVIDER_REGISTRY = {
|
|
12
|
+
byterover: {
|
|
13
|
+
baseUrl: '',
|
|
14
|
+
category: 'popular',
|
|
15
|
+
description: 'Internal ByteRover LLM',
|
|
16
|
+
headers: {},
|
|
17
|
+
id: 'byterover',
|
|
18
|
+
modelsEndpoint: '',
|
|
19
|
+
name: 'ByteRover',
|
|
20
|
+
priority: 0,
|
|
21
|
+
},
|
|
22
|
+
openrouter: {
|
|
23
|
+
apiKeyUrl: 'https://openrouter.ai/keys',
|
|
24
|
+
baseUrl: 'https://openrouter.ai/api/v1',
|
|
25
|
+
category: 'popular',
|
|
26
|
+
defaultModel: 'anthropic/claude-3.5-sonnet',
|
|
27
|
+
description: 'Access 200+ models',
|
|
28
|
+
headers: {
|
|
29
|
+
'HTTP-Referer': 'https://byterover.dev',
|
|
30
|
+
'X-Title': 'byterover-cli',
|
|
31
|
+
},
|
|
32
|
+
id: 'openrouter',
|
|
33
|
+
modelsEndpoint: '/models',
|
|
34
|
+
name: 'OpenRouter',
|
|
35
|
+
priority: 1,
|
|
36
|
+
},
|
|
37
|
+
// Future providers can be added here:
|
|
38
|
+
// anthropic: { ... },
|
|
39
|
+
// openai: { ... },
|
|
40
|
+
// google: { ... },
|
|
41
|
+
// groq: { ... },
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Get all providers sorted by priority.
|
|
45
|
+
*/
|
|
46
|
+
export function getProvidersSortedByPriority() {
|
|
47
|
+
return Object.values(PROVIDER_REGISTRY).sort((a, b) => a.priority - b.priority);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get providers grouped by category.
|
|
51
|
+
*/
|
|
52
|
+
export function getProvidersGroupedByCategory() {
|
|
53
|
+
const providers = getProvidersSortedByPriority();
|
|
54
|
+
return {
|
|
55
|
+
other: providers.filter((p) => p.category === 'other'),
|
|
56
|
+
popular: providers.filter((p) => p.category === 'popular'),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get a provider by ID.
|
|
61
|
+
*/
|
|
62
|
+
export function getProviderById(id) {
|
|
63
|
+
return PROVIDER_REGISTRY[id];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if a provider requires an API key.
|
|
67
|
+
*/
|
|
68
|
+
export function providerRequiresApiKey(id) {
|
|
69
|
+
const provider = getProviderById(id);
|
|
70
|
+
if (!provider)
|
|
71
|
+
return false;
|
|
72
|
+
// Internal providers (empty baseUrl) don't need API keys
|
|
73
|
+
return provider.baseUrl.length > 0;
|
|
74
|
+
}
|