byterover-cli 0.1.1 → 0.2.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.md +37 -27
- package/bin/dev.cmd +1 -1
- package/bin/dev.js +1 -1
- package/bin/run.cmd +1 -1
- package/bin/run.js +1 -1
- package/dist/commands/add.js +1 -1
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +73 -27
- package/dist/commands/logout.d.ts +16 -0
- package/dist/commands/logout.js +61 -0
- package/dist/commands/push.d.ts +5 -5
- package/dist/commands/push.js +11 -11
- package/dist/commands/retrieve.d.ts +2 -2
- package/dist/commands/retrieve.js +3 -3
- package/dist/commands/space/list.js +10 -5
- package/dist/commands/space/switch.js +8 -7
- package/dist/commands/status.js +5 -5
- package/dist/config/environment.d.ts +3 -2
- package/dist/config/environment.js +5 -3
- package/dist/constants.d.ts +8 -1
- package/dist/constants.js +8 -1
- package/dist/core/domain/entities/{br-config.d.ts → brv-config.d.ts} +5 -5
- package/dist/core/domain/entities/{br-config.js → brv-config.js} +5 -5
- package/dist/core/domain/entities/event.d.ts +1 -1
- package/dist/core/domain/entities/event.js +1 -0
- package/dist/core/interfaces/i-playbook-service.d.ts +1 -1
- package/dist/core/interfaces/i-project-config-store.d.ts +10 -10
- package/dist/core/interfaces/i-rule-template-service.d.ts +0 -4
- package/dist/core/interfaces/i-rule-template-service.js +1 -4
- package/dist/hooks/init/welcome.d.ts +3 -0
- package/dist/hooks/init/welcome.js +31 -0
- package/dist/infra/ace/ace-file-utils.js +2 -2
- package/dist/infra/ace/file-bullet-content-store.d.ts +4 -4
- package/dist/infra/ace/file-bullet-content-store.js +7 -7
- package/dist/infra/ace/file-delta-store.d.ts +1 -1
- package/dist/infra/ace/file-delta-store.js +1 -1
- package/dist/infra/ace/file-executor-output-store.d.ts +1 -1
- package/dist/infra/ace/file-executor-output-store.js +1 -1
- package/dist/infra/ace/file-playbook-store.d.ts +3 -3
- package/dist/infra/ace/file-playbook-store.js +6 -6
- package/dist/infra/ace/file-reflection-store.d.ts +1 -1
- package/dist/infra/ace/file-reflection-store.js +1 -1
- package/dist/infra/config/file-config-store.d.ts +6 -8
- package/dist/infra/config/file-config-store.js +10 -11
- package/dist/infra/playbook/file-playbook-service.d.ts +0 -1
- package/dist/infra/playbook/file-playbook-service.js +7 -8
- package/dist/infra/rule/constants.d.ts +4 -0
- package/dist/infra/rule/constants.js +4 -0
- package/dist/infra/rule/rule-template-service.js +1 -1
- package/dist/infra/rule/rule-writer-service.js +1 -5
- package/dist/templates/README.md +5 -5
- package/dist/templates/sections/command-reference.md +41 -23
- package/dist/templates/sections/workflow.md +11 -12
- package/oclif.manifest.json +44 -4
- package/package.json +9 -8
package/README.md
CHANGED
|
@@ -6,6 +6,14 @@ Command-line interface for ByteRover, enabling seamless team/space management, a
|
|
|
6
6
|
[](https://npmjs.org/package/byterover-cli)
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
|
|
9
|
+
## Important
|
|
10
|
+
|
|
11
|
+
Starting with version **0.2.0**, the ByteRover CLI command has been renamed from `br` to `brv` to avoid conflicts with [broot](https://github.com/Canop/broot), another popular CLI tool that also uses the `br` command.
|
|
12
|
+
|
|
13
|
+
This is a **breaking change** that requires action from existing users.
|
|
14
|
+
|
|
15
|
+
Please check the migration guide [here](https://docs.byterover.dev/beta/migration-br-brv).
|
|
16
|
+
|
|
9
17
|
## Table of Contents
|
|
10
18
|
|
|
11
19
|
* [Installation](#installation)
|
|
@@ -40,17 +48,19 @@ npm install -g byterover-cli
|
|
|
40
48
|
### Verify installation
|
|
41
49
|
|
|
42
50
|
```bash
|
|
43
|
-
|
|
51
|
+
brv --version
|
|
44
52
|
```
|
|
45
53
|
|
|
46
54
|
## Quick Start
|
|
47
55
|
|
|
56
|
+
Visit [**ByteRover's Beta Docs**](https://docs.byterover.dev/beta) for more information.
|
|
57
|
+
|
|
48
58
|
Get started with ByteRover CLI in three simple steps:
|
|
49
59
|
|
|
50
60
|
### 1. Authenticate
|
|
51
61
|
|
|
52
62
|
```bash
|
|
53
|
-
|
|
63
|
+
brv login
|
|
54
64
|
```
|
|
55
65
|
|
|
56
66
|
This opens your browser to complete OAuth authentication. Your credentials are securely stored in the system keychain.
|
|
@@ -58,8 +68,8 @@ This opens your browser to complete OAuth authentication. Your credentials are s
|
|
|
58
68
|
### 2. Initialize a project
|
|
59
69
|
|
|
60
70
|
```bash
|
|
61
|
-
cd your
|
|
62
|
-
|
|
71
|
+
cd to/your/project
|
|
72
|
+
brv init
|
|
63
73
|
```
|
|
64
74
|
|
|
65
75
|
Select a space from your available spaces and configure your project.
|
|
@@ -100,14 +110,14 @@ If you're using a coding agent like Claude Code:
|
|
|
100
110
|
|
|
101
111
|
```bash
|
|
102
112
|
# Complete ACE workflow in a single command
|
|
103
|
-
|
|
113
|
+
brv complete "auth-feature" \
|
|
104
114
|
"Implemented JWT authentication with secure token handling" \
|
|
105
115
|
"Successfully added OAuth2 authentication" \
|
|
106
116
|
--tool-usage "Read:src/auth.ts,Edit:src/auth.ts,Bash:npm test" \
|
|
107
117
|
--feedback "All tests passed, auth works correctly"
|
|
108
118
|
```
|
|
109
119
|
|
|
110
|
-
For comprehensive ACE instructions for coding agents, check the corresponding coding agents' instruction files after `
|
|
120
|
+
For comprehensive ACE instructions for coding agents, check the corresponding coding agents' instruction files after `brv init` or `brv gen-rules`.
|
|
111
121
|
|
|
112
122
|
## Essential Commands
|
|
113
123
|
|
|
@@ -115,46 +125,46 @@ For comprehensive ACE instructions for coding agents, check the corresponding co
|
|
|
115
125
|
|
|
116
126
|
```bash
|
|
117
127
|
# Log in to ByteRover
|
|
118
|
-
|
|
128
|
+
brv login
|
|
119
129
|
|
|
120
130
|
# Check your authentication and project status
|
|
121
|
-
|
|
131
|
+
brv status
|
|
122
132
|
```
|
|
123
133
|
|
|
124
134
|
### Project Setup
|
|
125
135
|
|
|
126
136
|
```bash
|
|
127
137
|
# Initialize project with ByteRover
|
|
128
|
-
|
|
138
|
+
brv init
|
|
129
139
|
|
|
130
140
|
# List available spaces
|
|
131
|
-
|
|
141
|
+
brv space list
|
|
132
142
|
|
|
133
143
|
# Switch to a different space or team
|
|
134
|
-
|
|
144
|
+
brv space switch
|
|
135
145
|
```
|
|
136
146
|
|
|
137
147
|
### Memory Operations
|
|
138
148
|
|
|
139
149
|
```bash
|
|
140
150
|
# Retrieve memories from ByteRover (outputs to stdout for agent context)
|
|
141
|
-
|
|
142
|
-
|
|
151
|
+
brv retrieve --query "authentication best practices"
|
|
152
|
+
brv retrieve -q "error handling" -n "src/auth/login.ts,src/auth/oauth.ts"
|
|
143
153
|
|
|
144
154
|
# Push your playbook to ByteRover's memory storage
|
|
145
|
-
|
|
155
|
+
brv push
|
|
146
156
|
```
|
|
147
157
|
|
|
148
158
|
### For Coding Agents
|
|
149
159
|
|
|
150
160
|
```bash
|
|
151
161
|
# Complete ACE workflow (recommended for agents)
|
|
152
|
-
|
|
162
|
+
brv complete <hint> <reasoning> <answer> \
|
|
153
163
|
--tool-usage <tools> \
|
|
154
164
|
--feedback <feedback>
|
|
155
165
|
|
|
156
166
|
# Generate agent rules (sets up ACE workflow for your coding agent)
|
|
157
|
-
|
|
167
|
+
brv gen-rules
|
|
158
168
|
```
|
|
159
169
|
|
|
160
170
|
## Authentication
|
|
@@ -163,7 +173,7 @@ ByteRover CLI uses **OAuth 2.0 with PKCE** (Proof Key for Code Exchange) for sec
|
|
|
163
173
|
|
|
164
174
|
### How it works
|
|
165
175
|
|
|
166
|
-
1. Run `
|
|
176
|
+
1. Run `brv login` to start authentication
|
|
167
177
|
2. Your browser opens to the ByteRover authorization page
|
|
168
178
|
3. After successful login, tokens are securely stored in your system keychain
|
|
169
179
|
4. All subsequent commands automatically use your stored credentials
|
|
@@ -179,7 +189,7 @@ ByteRover CLI uses **OAuth 2.0 with PKCE** (Proof Key for Code Exchange) for sec
|
|
|
179
189
|
|
|
180
190
|
### Project Configuration
|
|
181
191
|
|
|
182
|
-
When you run `
|
|
192
|
+
When you run `brv init`, a configuration file is created at `.brv/config.json` in your project directory containing:
|
|
183
193
|
|
|
184
194
|
- **Space ID**: The ByteRover workspace/space associated with this project
|
|
185
195
|
- **User information**: Your user ID and email
|
|
@@ -187,17 +197,17 @@ When you run `br init`, a configuration file is created at `.br/config.json` in
|
|
|
187
197
|
|
|
188
198
|
### ACE File Structure
|
|
189
199
|
|
|
190
|
-
ACE stores all outputs in `.
|
|
200
|
+
ACE stores all outputs in `.brv/ace/`:
|
|
191
201
|
|
|
192
202
|
```
|
|
193
|
-
.
|
|
203
|
+
.brv/ace/
|
|
194
204
|
├── playbook.json # Your living knowledge base
|
|
195
205
|
├── executor-outputs/ # Coding task outputs
|
|
196
206
|
├── reflections/ # Task analysis and feedback
|
|
197
207
|
└── deltas/ # Playbook updates
|
|
198
208
|
```
|
|
199
209
|
|
|
200
|
-
**Note**: When you run `
|
|
210
|
+
**Note**: When you run `brv push`, the playbook is uploaded to ByteRover's memory storage, and local ACE files are automatically cleaned up to keep your workspace organized.
|
|
201
211
|
|
|
202
212
|
## Getting Help
|
|
203
213
|
|
|
@@ -205,20 +215,20 @@ ACE stores all outputs in `.br/ace/`:
|
|
|
205
215
|
|
|
206
216
|
```bash
|
|
207
217
|
# Get general help
|
|
208
|
-
|
|
218
|
+
brv --help
|
|
209
219
|
|
|
210
220
|
# Get help for a specific command
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
221
|
+
brv login --help
|
|
222
|
+
brv init --help
|
|
223
|
+
brv push --help
|
|
214
224
|
```
|
|
215
225
|
|
|
216
226
|
### Support
|
|
217
227
|
|
|
218
228
|
If you encounter issues or have questions:
|
|
219
229
|
|
|
220
|
-
1. Check the command help: `
|
|
221
|
-
2. Review your status: `
|
|
230
|
+
1. Check the command help: `brv [command] --help`
|
|
231
|
+
2. Review your status: `brv status`
|
|
222
232
|
3. Contact ByteRover support
|
|
223
233
|
|
|
224
234
|
---
|
package/bin/dev.cmd
CHANGED
package/bin/dev.js
CHANGED
package/bin/run.cmd
CHANGED
package/bin/run.js
CHANGED
package/dist/commands/add.js
CHANGED
|
@@ -62,7 +62,7 @@ export default class Add extends Command {
|
|
|
62
62
|
this.log(` Section: ${section}`);
|
|
63
63
|
const contentDisplay = content.length > 200 ? `${content.slice(0, 200)}...` : content;
|
|
64
64
|
this.log(` Content: ${contentDisplay}`);
|
|
65
|
-
this.log('\nTip: Use `
|
|
65
|
+
this.log('\nTip: Use `brv status` to view and update bullets later');
|
|
66
66
|
const confirmed = await confirm({
|
|
67
67
|
default: true,
|
|
68
68
|
message: 'Add this bullet?',
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -6,10 +6,16 @@ import type { IProjectConfigStore } from '../core/interfaces/i-project-config-st
|
|
|
6
6
|
import type { ISpaceService } from '../core/interfaces/i-space-service.js';
|
|
7
7
|
import type { ITeamService } from '../core/interfaces/i-team-service.js';
|
|
8
8
|
import type { ITokenStore } from '../core/interfaces/i-token-store.js';
|
|
9
|
+
import { BrvConfig } from '../core/domain/entities/brv-config.js';
|
|
9
10
|
import { ITrackingService } from '../core/interfaces/i-tracking-service.js';
|
|
10
11
|
export default class Init extends Command {
|
|
11
12
|
static description: string;
|
|
12
13
|
static examples: string[];
|
|
14
|
+
static flags: {
|
|
15
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
};
|
|
17
|
+
protected cleanupBeforeReInitialization(): Promise<void>;
|
|
18
|
+
protected confirmReInitialization(config: BrvConfig): Promise<boolean>;
|
|
13
19
|
protected createServices(): {
|
|
14
20
|
playbookService: IPlaybookService;
|
|
15
21
|
projectConfigStore: IProjectConfigStore;
|
package/dist/commands/init.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { select } from '@inquirer/prompts';
|
|
2
|
-
import { Command, ux } from '@oclif/core';
|
|
1
|
+
import { confirm, select } from '@inquirer/prompts';
|
|
2
|
+
import { Command, Flags, ux } from '@oclif/core';
|
|
3
|
+
import { rm } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
3
5
|
import { getCurrentConfig } from '../config/environment.js';
|
|
4
|
-
import {
|
|
6
|
+
import { BRV_DIR, PROJECT_CONFIG_FILE } from '../constants.js';
|
|
7
|
+
import { BrvConfig } from '../core/domain/entities/brv-config.js';
|
|
5
8
|
import { ProjectConfigStore } from '../infra/config/file-config-store.js';
|
|
6
9
|
import { FilePlaybookService } from '../infra/playbook/file-playbook-service.js';
|
|
7
10
|
import { HttpSpaceService } from '../infra/space/http-space-service.js';
|
|
@@ -9,12 +12,47 @@ import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
|
|
|
9
12
|
import { HttpTeamService } from '../infra/team/http-team-service.js';
|
|
10
13
|
import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
|
|
11
14
|
export default class Init extends Command {
|
|
12
|
-
static description =
|
|
15
|
+
static description = `Initialize a project with ByteRover (creates ${BRV_DIR}/${PROJECT_CONFIG_FILE} with team/space selection and initializes ACE playbook)`;
|
|
13
16
|
static examples = [
|
|
14
17
|
'<%= config.bin %> <%= command.id %>',
|
|
15
18
|
'# Re-initialize if config exists (will show current config and exit):\n<%= config.bin %> <%= command.id %>',
|
|
16
19
|
'# Full workflow: login then initialize:\n<%= config.bin %> login\n<%= config.bin %> <%= command.id %>',
|
|
17
20
|
];
|
|
21
|
+
static flags = {
|
|
22
|
+
force: Flags.boolean({
|
|
23
|
+
char: 'f',
|
|
24
|
+
default: false,
|
|
25
|
+
description: 'Force re-initialization without confirmation prompt',
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async cleanupBeforeReInitialization() {
|
|
29
|
+
const brvDir = join(process.cwd(), BRV_DIR);
|
|
30
|
+
this.log('\n Cleaning up existing ByteRover directory...');
|
|
31
|
+
ux.action.start(` Removing ${BRV_DIR}/`);
|
|
32
|
+
try {
|
|
33
|
+
await rm(brvDir, { force: true, recursive: true });
|
|
34
|
+
ux.action.stop('✓');
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
ux.action.stop('✗');
|
|
38
|
+
this.error(`Failed to remove ${BRV_DIR}/: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async confirmReInitialization(config) {
|
|
42
|
+
this.log('\n Project is already initialized');
|
|
43
|
+
this.log(` Team: ${config.teamName}`);
|
|
44
|
+
this.log(` Space: ${config.spaceName}`);
|
|
45
|
+
this.log(` Config: ${join(process.cwd(), BRV_DIR, PROJECT_CONFIG_FILE)}`);
|
|
46
|
+
this.log('\n Re-initializing will:');
|
|
47
|
+
this.log(` - Remove the entire ${BRV_DIR}/ directory and all its contents`);
|
|
48
|
+
this.log(' - Allow you to select a new team/space');
|
|
49
|
+
this.log(' - Create a fresh configuration and ACE playbook');
|
|
50
|
+
this.log(' - Regenerate rule instructions\n');
|
|
51
|
+
return confirm({
|
|
52
|
+
default: false,
|
|
53
|
+
message: 'Continue with re-initialization?',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
18
56
|
createServices() {
|
|
19
57
|
const envConfig = getCurrentConfig();
|
|
20
58
|
const tokenStore = new KeychainTokenStore();
|
|
@@ -61,37 +99,49 @@ export default class Init extends Command {
|
|
|
61
99
|
return selectedTeam;
|
|
62
100
|
}
|
|
63
101
|
async run() {
|
|
102
|
+
const { flags } = await this.parse(Init);
|
|
64
103
|
try {
|
|
65
104
|
const { playbookService, projectConfigStore, spaceService, teamService, tokenStore, trackingService } = this.createServices();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
105
|
+
const alreadyInitialized = await projectConfigStore.exists();
|
|
106
|
+
if (alreadyInitialized) {
|
|
107
|
+
const currentConfig = await projectConfigStore.read();
|
|
108
|
+
if (currentConfig === undefined) {
|
|
109
|
+
this.error('Configuration file exists but cannot be read. Please check .brv/config.json');
|
|
110
|
+
}
|
|
111
|
+
if (!flags.force) {
|
|
112
|
+
const confirmed = await this.confirmReInitialization(currentConfig);
|
|
113
|
+
if (!confirmed) {
|
|
114
|
+
this.log('\nCancelled. Project configuration unchanged.');
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await this.cleanupBeforeReInitialization();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.error(`Failed to clean up existing data: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
123
|
+
}
|
|
124
|
+
this.log('\n'); // Spacing before continuing with init flow
|
|
73
125
|
}
|
|
74
126
|
this.log('Initializing ByteRover project...\n');
|
|
75
|
-
// 2. Load and validate authentication token
|
|
76
127
|
const token = await tokenStore.load();
|
|
77
128
|
if (token === undefined) {
|
|
78
|
-
this.error('Not authenticated. Please run "
|
|
129
|
+
this.error('Not authenticated. Please run "brv login" first.');
|
|
79
130
|
}
|
|
80
131
|
if (!token.isValid()) {
|
|
81
|
-
this.error('Authentication token expired. Please run "
|
|
132
|
+
this.error('Authentication token expired. Please run "brv login" again.');
|
|
82
133
|
}
|
|
83
|
-
// 3. Fetch all teams with spinner
|
|
84
134
|
ux.action.start('Fetching all teams');
|
|
85
135
|
const teamResult = await teamService.getTeams(token.accessToken, token.sessionKey, { fetchAll: true });
|
|
86
136
|
ux.action.stop();
|
|
87
137
|
const { teams } = teamResult;
|
|
88
138
|
if (teams.length === 0) {
|
|
89
|
-
this.
|
|
139
|
+
this.log('No teams found.');
|
|
140
|
+
this.log(`Please visit ${getCurrentConfig().webAppUrl} to create your first team.`);
|
|
141
|
+
return;
|
|
90
142
|
}
|
|
91
|
-
// 4. Prompt for team selection
|
|
92
143
|
this.log();
|
|
93
144
|
const selectedTeam = await this.promptForTeamSelection(teams);
|
|
94
|
-
// 5. Fetch all spaces for the selected team with spinner
|
|
95
145
|
ux.action.start('Fetching all spaces');
|
|
96
146
|
const spaceResult = await spaceService.getSpaces(token.accessToken, token.sessionKey, selectedTeam.id, {
|
|
97
147
|
fetchAll: true,
|
|
@@ -99,15 +149,14 @@ export default class Init extends Command {
|
|
|
99
149
|
ux.action.stop();
|
|
100
150
|
const { spaces } = spaceResult;
|
|
101
151
|
if (spaces.length === 0) {
|
|
102
|
-
this.
|
|
152
|
+
this.log(`No spaces found in team "${selectedTeam.getDisplayName()}"`);
|
|
153
|
+
this.log(`Please visit ${getCurrentConfig().webAppUrl} to create your first space for ${selectedTeam.getDisplayName()}.`);
|
|
154
|
+
return;
|
|
103
155
|
}
|
|
104
|
-
// 6. Prompt for space selection
|
|
105
156
|
this.log();
|
|
106
157
|
const selectedSpace = await this.promptForSpaceSelection(spaces);
|
|
107
|
-
|
|
108
|
-
const config = BrConfig.fromSpace(selectedSpace);
|
|
158
|
+
const config = BrvConfig.fromSpace(selectedSpace);
|
|
109
159
|
await projectConfigStore.write(config);
|
|
110
|
-
// 8. Initialize ACE playbook
|
|
111
160
|
this.log('\nInitializing ACE context...');
|
|
112
161
|
try {
|
|
113
162
|
const playbookPath = await playbookService.initialize();
|
|
@@ -117,16 +166,13 @@ export default class Init extends Command {
|
|
|
117
166
|
// Warn but don't fail if ACE init fails
|
|
118
167
|
this.warn(`ACE initialization skipped: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
119
168
|
}
|
|
120
|
-
// 9. Generate rules
|
|
121
169
|
this.log(`\nGenerate rule instructions for coding agents to work with ByteRover correctly`);
|
|
122
170
|
this.log();
|
|
123
171
|
await this.config.runCommand('gen-rules');
|
|
124
|
-
// Track space initialization
|
|
125
172
|
await trackingService.track('space:init');
|
|
126
|
-
// 10. Display success
|
|
127
173
|
this.log(`\n✓ Project initialized successfully!`);
|
|
128
174
|
this.log(`✓ Connected to space: ${selectedSpace.getDisplayName()}`);
|
|
129
|
-
this.log(`✓ Configuration saved to:
|
|
175
|
+
this.log(`✓ Configuration saved to: ${BRV_DIR}/${PROJECT_CONFIG_FILE}`);
|
|
130
176
|
}
|
|
131
177
|
catch (error) {
|
|
132
178
|
this.error(error instanceof Error ? error.message : 'Initialization failed');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { ITokenStore } from '../core/interfaces/i-token-store.js';
|
|
3
|
+
import type { ITrackingService } from '../core/interfaces/i-tracking-service.js';
|
|
4
|
+
export default class Logout extends Command {
|
|
5
|
+
static description: string;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
};
|
|
10
|
+
protected confirmLogout(userEmail: string): Promise<boolean>;
|
|
11
|
+
protected createServices(): {
|
|
12
|
+
tokenStore: ITokenStore;
|
|
13
|
+
trackingService: ITrackingService;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import { Command, Flags } from '@oclif/core';
|
|
3
|
+
import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
|
|
4
|
+
import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
|
|
5
|
+
export default class Logout extends Command {
|
|
6
|
+
static description = 'Log out of ByteRover CLI and clear authentication (does not affect local project files)';
|
|
7
|
+
static examples = ['<%= config.bin %> <%= command.id %>', '<%= config.bin %> <%= command.id %> --yes'];
|
|
8
|
+
static flags = {
|
|
9
|
+
yes: Flags.boolean({
|
|
10
|
+
char: 'y',
|
|
11
|
+
default: false,
|
|
12
|
+
description: 'Skip confirmation prompt',
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
async confirmLogout(userEmail) {
|
|
16
|
+
return confirm({
|
|
17
|
+
// Pressing 'Enter' = Yes
|
|
18
|
+
default: true,
|
|
19
|
+
message: `Logging out ${userEmail}. Are you sure?`,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
createServices() {
|
|
23
|
+
const tokenStore = new KeychainTokenStore();
|
|
24
|
+
const trackingService = new MixpanelTrackingService(tokenStore);
|
|
25
|
+
return {
|
|
26
|
+
tokenStore,
|
|
27
|
+
trackingService,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async run() {
|
|
31
|
+
const { flags } = await this.parse(Logout);
|
|
32
|
+
const { tokenStore, trackingService } = this.createServices();
|
|
33
|
+
try {
|
|
34
|
+
const token = await tokenStore.load();
|
|
35
|
+
if (token === undefined) {
|
|
36
|
+
this.log('You are not currently logged in.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!flags.yes) {
|
|
40
|
+
const confirmed = await this.confirmLogout(token.userEmail);
|
|
41
|
+
if (!confirmed) {
|
|
42
|
+
this.log('Logout cancelled.');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await trackingService.track('auth:signed_out');
|
|
48
|
+
}
|
|
49
|
+
catch { }
|
|
50
|
+
await tokenStore.clear();
|
|
51
|
+
this.log('Successfully logged out.');
|
|
52
|
+
this.log("Run 'brv login' to authenticate again.");
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error instanceof Error && error.message.includes('keychain')) {
|
|
56
|
+
this.error('Unable to access system keychain. Please check your system permissions and try again.');
|
|
57
|
+
}
|
|
58
|
+
this.error(error instanceof Error ? error.message : 'Logout failed');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/commands/push.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import type { AuthToken } from '../core/domain/entities/auth-token.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrvConfig } from '../core/domain/entities/brv-config.js';
|
|
4
4
|
import type { PresignedUrl } from '../core/domain/entities/presigned-url.js';
|
|
5
5
|
import type { PresignedUrlsResponse } from '../core/domain/entities/presigned-urls-response.js';
|
|
6
6
|
import type { IMemoryStorageService } from '../core/interfaces/i-memory-storage-service.js';
|
|
@@ -15,10 +15,10 @@ export default class Push extends Command {
|
|
|
15
15
|
branch: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
17
|
};
|
|
18
|
-
protected checkProjectInit(projectConfigStore: IProjectConfigStore): Promise<
|
|
18
|
+
protected checkProjectInit(projectConfigStore: IProjectConfigStore): Promise<BrvConfig>;
|
|
19
19
|
protected cleanUpLocalFiles(playbookStore: IPlaybookStore): Promise<void>;
|
|
20
|
-
protected confirmPush(projectConfig:
|
|
21
|
-
protected confirmUpload(memoryService: IMemoryStorageService, token: AuthToken, projectConfig:
|
|
20
|
+
protected confirmPush(projectConfig: BrvConfig, branch: string, fileCount: number): Promise<boolean>;
|
|
21
|
+
protected confirmUpload(memoryService: IMemoryStorageService, token: AuthToken, projectConfig: BrvConfig, requestId: string): Promise<void>;
|
|
22
22
|
protected createServices(): {
|
|
23
23
|
memoryService: IMemoryStorageService;
|
|
24
24
|
playbookStore: IPlaybookStore;
|
|
@@ -26,7 +26,7 @@ export default class Push extends Command {
|
|
|
26
26
|
tokenStore: ITokenStore;
|
|
27
27
|
trackingService: ITrackingService;
|
|
28
28
|
};
|
|
29
|
-
protected getPresignedUrls(memoryService: IMemoryStorageService, token: AuthToken, projectConfig:
|
|
29
|
+
protected getPresignedUrls(memoryService: IMemoryStorageService, token: AuthToken, projectConfig: BrvConfig): Promise<PresignedUrlsResponse>;
|
|
30
30
|
protected loadPlaybookContent(playbookStore: IPlaybookStore): Promise<string>;
|
|
31
31
|
run(): Promise<void>;
|
|
32
32
|
protected uploadFiles(memoryService: IMemoryStorageService, presignedUrls: ReadonlyArray<PresignedUrl>, playbookContent: string): Promise<void>;
|
package/dist/commands/push.js
CHANGED
|
@@ -2,7 +2,7 @@ import { confirm } from '@inquirer/prompts';
|
|
|
2
2
|
import { Command, Flags, ux } from '@oclif/core';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { getCurrentConfig } from '../config/environment.js';
|
|
5
|
-
import { ACE_DIR,
|
|
5
|
+
import { ACE_DIR, BRV_DIR, BULLETS_DIR, DEFAULT_BRANCH, DELTAS_DIR, EXECUTOR_OUTPUTS_DIR, PLAYBOOK_FILE, REFLECTIONS_DIR, } from '../constants.js';
|
|
6
6
|
import { FilePlaybookStore } from '../infra/ace/file-playbook-store.js';
|
|
7
7
|
import { ProjectConfigStore } from '../infra/config/file-config-store.js';
|
|
8
8
|
import { HttpMemoryStorageService } from '../infra/memory/http-memory-storage-service.js';
|
|
@@ -32,7 +32,7 @@ export default class Push extends Command {
|
|
|
32
32
|
async checkProjectInit(projectConfigStore) {
|
|
33
33
|
const projectConfig = await projectConfigStore.read();
|
|
34
34
|
if (projectConfig === undefined) {
|
|
35
|
-
this.error('Project not initialized. Run "
|
|
35
|
+
this.error('Project not initialized. Run "brv init" first.');
|
|
36
36
|
}
|
|
37
37
|
return projectConfig;
|
|
38
38
|
}
|
|
@@ -44,7 +44,7 @@ export default class Push extends Command {
|
|
|
44
44
|
ux.action.stop('✓');
|
|
45
45
|
// Clean executor outputs
|
|
46
46
|
const baseDir = process.cwd();
|
|
47
|
-
const aceDir = join(baseDir,
|
|
47
|
+
const aceDir = join(baseDir, BRV_DIR, ACE_DIR);
|
|
48
48
|
const executorOutputsDir = join(aceDir, EXECUTOR_OUTPUTS_DIR);
|
|
49
49
|
const reflectionsDir = join(aceDir, REFLECTIONS_DIR);
|
|
50
50
|
const deltasDir = join(aceDir, DELTAS_DIR);
|
|
@@ -67,10 +67,10 @@ export default class Push extends Command {
|
|
|
67
67
|
this.log(` Files to upload: ${fileCount}`);
|
|
68
68
|
this.log('\nAfter successful push, these local files will be cleaned up:');
|
|
69
69
|
this.log(' - Playbook content');
|
|
70
|
-
this.log(
|
|
71
|
-
this.log(
|
|
72
|
-
this.log(
|
|
73
|
-
this.log(
|
|
70
|
+
this.log(` - Bullet files (${BRV_DIR}/${ACE_DIR}/${BULLETS_DIR}/)`);
|
|
71
|
+
this.log(` - Executor outputs (${BRV_DIR}/${ACE_DIR}/${EXECUTOR_OUTPUTS_DIR}/)`);
|
|
72
|
+
this.log(` - Reflections (${BRV_DIR}/${ACE_DIR}/${REFLECTIONS_DIR}/)`);
|
|
73
|
+
this.log(` - Deltas (${BRV_DIR}/${ACE_DIR}/${DELTAS_DIR}/)`);
|
|
74
74
|
return confirm({
|
|
75
75
|
default: false,
|
|
76
76
|
message: 'Push to ByteRover and clean up local files?',
|
|
@@ -107,7 +107,7 @@ export default class Push extends Command {
|
|
|
107
107
|
const response = await memoryService.getPresignedUrls({
|
|
108
108
|
accessToken: token.accessToken,
|
|
109
109
|
branch: flags.branch,
|
|
110
|
-
fileNames: [
|
|
110
|
+
fileNames: [`${PLAYBOOK_FILE}`],
|
|
111
111
|
sessionKey: token.sessionKey,
|
|
112
112
|
spaceId: projectConfig.spaceId,
|
|
113
113
|
teamId: projectConfig.teamId,
|
|
@@ -164,17 +164,17 @@ export default class Push extends Command {
|
|
|
164
164
|
async validateAuth(tokenStore) {
|
|
165
165
|
const token = await tokenStore.load();
|
|
166
166
|
if (token === undefined) {
|
|
167
|
-
this.error('Not authenticated. Run "
|
|
167
|
+
this.error('Not authenticated. Run "brv login" first.');
|
|
168
168
|
}
|
|
169
169
|
if (!token.isValid()) {
|
|
170
|
-
this.error('Authentication token expired. Run "
|
|
170
|
+
this.error('Authentication token expired. Run "brv login" again.');
|
|
171
171
|
}
|
|
172
172
|
return token;
|
|
173
173
|
}
|
|
174
174
|
async verifyPlaybookExists(playbookStore) {
|
|
175
175
|
const playbookExists = await playbookStore.exists();
|
|
176
176
|
if (!playbookExists) {
|
|
177
|
-
this.error('Playbook not found. Run "
|
|
177
|
+
this.error('Playbook not found. Run "brv init" to create one.');
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import type { AuthToken } from '../core/domain/entities/auth-token.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { BrvConfig } from '../core/domain/entities/brv-config.js';
|
|
4
4
|
import type { IMemoryRetrievalService } from '../core/interfaces/i-memory-retrieval-service.js';
|
|
5
5
|
import type { IProjectConfigStore } from '../core/interfaces/i-project-config-store.js';
|
|
6
6
|
import type { ITokenStore } from '../core/interfaces/i-token-store.js';
|
|
@@ -13,7 +13,7 @@ export default class Retrieve extends Command {
|
|
|
13
13
|
'node-keys': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
query: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
};
|
|
16
|
-
protected checkProjectInt(projectConfigStore: IProjectConfigStore): Promise<
|
|
16
|
+
protected checkProjectInt(projectConfigStore: IProjectConfigStore): Promise<BrvConfig>;
|
|
17
17
|
protected createServices(): {
|
|
18
18
|
memoryService: IMemoryRetrievalService;
|
|
19
19
|
projectConfigStore: IProjectConfigStore;
|
|
@@ -31,7 +31,7 @@ export default class Retrieve extends Command {
|
|
|
31
31
|
async checkProjectInt(projectConfigStore) {
|
|
32
32
|
const isInitialized = await projectConfigStore.exists();
|
|
33
33
|
if (!isInitialized) {
|
|
34
|
-
this.error('Project is not initialized. Please run "
|
|
34
|
+
this.error('Project is not initialized. Please run "brv init" first.');
|
|
35
35
|
}
|
|
36
36
|
const config = await projectConfigStore.read();
|
|
37
37
|
if (!config) {
|
|
@@ -82,10 +82,10 @@ export default class Retrieve extends Command {
|
|
|
82
82
|
async validateAuth(tokenStore) {
|
|
83
83
|
const token = await tokenStore.load();
|
|
84
84
|
if (token === undefined) {
|
|
85
|
-
this.error('Not authenticated. Please run "
|
|
85
|
+
this.error('Not authenticated. Please run "brv login" first.');
|
|
86
86
|
}
|
|
87
87
|
if (!token.isValid()) {
|
|
88
|
-
this.error('Authentication token expired. Please run "
|
|
88
|
+
this.error('Authentication token expired. Please run "brv login" again.');
|
|
89
89
|
}
|
|
90
90
|
return token;
|
|
91
91
|
}
|