byterover-cli 0.1.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 +781 -0
- package/bin/dev.cmd +4 -0
- package/bin/dev.js +7 -0
- package/bin/run.cmd +4 -0
- package/bin/run.js +7 -0
- package/dist/commands/add.d.ts +60 -0
- package/dist/commands/add.js +230 -0
- package/dist/commands/clear.d.ts +13 -0
- package/dist/commands/clear.js +57 -0
- package/dist/commands/complete.d.ts +108 -0
- package/dist/commands/complete.js +340 -0
- package/dist/commands/gen-rules.d.ts +26 -0
- package/dist/commands/gen-rules.js +89 -0
- package/dist/commands/init.d.ts +24 -0
- package/dist/commands/init.js +135 -0
- package/dist/commands/login.d.ts +22 -0
- package/dist/commands/login.js +103 -0
- package/dist/commands/push.d.ts +33 -0
- package/dist/commands/push.js +150 -0
- package/dist/commands/retrieve.d.ts +26 -0
- package/dist/commands/retrieve.js +101 -0
- package/dist/commands/space/list.d.ts +22 -0
- package/dist/commands/space/list.js +105 -0
- package/dist/commands/space/switch.d.ts +20 -0
- package/dist/commands/space/switch.js +110 -0
- package/dist/commands/status.d.ts +22 -0
- package/dist/commands/status.js +116 -0
- package/dist/config/auth.config.d.ts +32 -0
- package/dist/config/auth.config.js +35 -0
- package/dist/config/environment.d.ts +35 -0
- package/dist/config/environment.js +39 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.js +12 -0
- package/dist/core/domain/entities/agent.d.ts +5 -0
- package/dist/core/domain/entities/agent.js +23 -0
- package/dist/core/domain/entities/auth-token.d.ts +43 -0
- package/dist/core/domain/entities/auth-token.js +70 -0
- package/dist/core/domain/entities/br-config.d.ts +25 -0
- package/dist/core/domain/entities/br-config.js +58 -0
- package/dist/core/domain/entities/bullet.d.ts +51 -0
- package/dist/core/domain/entities/bullet.js +94 -0
- package/dist/core/domain/entities/curator-output.d.ts +14 -0
- package/dist/core/domain/entities/curator-output.js +23 -0
- package/dist/core/domain/entities/delta-batch.d.ts +30 -0
- package/dist/core/domain/entities/delta-batch.js +52 -0
- package/dist/core/domain/entities/delta-operation.d.ts +31 -0
- package/dist/core/domain/entities/delta-operation.js +50 -0
- package/dist/core/domain/entities/event.d.ts +8 -0
- package/dist/core/domain/entities/event.js +15 -0
- package/dist/core/domain/entities/executor-output.d.ts +27 -0
- package/dist/core/domain/entities/executor-output.js +33 -0
- package/dist/core/domain/entities/memory.d.ts +55 -0
- package/dist/core/domain/entities/memory.js +90 -0
- package/dist/core/domain/entities/oauth-token-data.d.ts +13 -0
- package/dist/core/domain/entities/oauth-token-data.js +20 -0
- package/dist/core/domain/entities/playbook.d.ts +97 -0
- package/dist/core/domain/entities/playbook.js +275 -0
- package/dist/core/domain/entities/presigned-url.d.ts +9 -0
- package/dist/core/domain/entities/presigned-url.js +18 -0
- package/dist/core/domain/entities/presigned-urls-response.d.ts +10 -0
- package/dist/core/domain/entities/presigned-urls-response.js +18 -0
- package/dist/core/domain/entities/reflector-output.d.ts +38 -0
- package/dist/core/domain/entities/reflector-output.js +44 -0
- package/dist/core/domain/entities/retrieve-result.d.ts +35 -0
- package/dist/core/domain/entities/retrieve-result.js +35 -0
- package/dist/core/domain/entities/space.d.ts +24 -0
- package/dist/core/domain/entities/space.js +52 -0
- package/dist/core/domain/entities/team.d.ts +42 -0
- package/dist/core/domain/entities/team.js +89 -0
- package/dist/core/domain/entities/user.d.ts +20 -0
- package/dist/core/domain/entities/user.js +32 -0
- package/dist/core/domain/errors/ace-error.d.ts +34 -0
- package/dist/core/domain/errors/ace-error.js +53 -0
- package/dist/core/domain/errors/auth-error.d.ts +10 -0
- package/dist/core/domain/errors/auth-error.js +20 -0
- package/dist/core/domain/errors/discovery-error.d.ts +21 -0
- package/dist/core/domain/errors/discovery-error.js +33 -0
- package/dist/core/domain/errors/rule-error.d.ts +6 -0
- package/dist/core/domain/errors/rule-error.js +12 -0
- package/dist/core/interfaces/i-ace-prompt-builder.d.ts +48 -0
- package/dist/core/interfaces/i-ace-prompt-builder.js +1 -0
- package/dist/core/interfaces/i-auth-service.d.ts +35 -0
- package/dist/core/interfaces/i-auth-service.js +1 -0
- package/dist/core/interfaces/i-browser-launcher.d.ts +11 -0
- package/dist/core/interfaces/i-browser-launcher.js +1 -0
- package/dist/core/interfaces/i-bullet-content-store.d.ts +36 -0
- package/dist/core/interfaces/i-bullet-content-store.js +1 -0
- package/dist/core/interfaces/i-callback-handler.d.ts +35 -0
- package/dist/core/interfaces/i-callback-handler.js +1 -0
- package/dist/core/interfaces/i-delta-store.d.ts +15 -0
- package/dist/core/interfaces/i-delta-store.js +1 -0
- package/dist/core/interfaces/i-executor-output-store.d.ts +14 -0
- package/dist/core/interfaces/i-executor-output-store.js +1 -0
- package/dist/core/interfaces/i-file-service.d.ts +34 -0
- package/dist/core/interfaces/i-file-service.js +1 -0
- package/dist/core/interfaces/i-http-client.d.ts +33 -0
- package/dist/core/interfaces/i-http-client.js +1 -0
- package/dist/core/interfaces/i-memory-retrieval-service.d.ts +40 -0
- package/dist/core/interfaces/i-memory-retrieval-service.js +1 -0
- package/dist/core/interfaces/i-memory-storage-service.d.ts +55 -0
- package/dist/core/interfaces/i-memory-storage-service.js +1 -0
- package/dist/core/interfaces/i-oidc-discovery-service.d.ts +20 -0
- package/dist/core/interfaces/i-oidc-discovery-service.js +1 -0
- package/dist/core/interfaces/i-playbook-service.d.ts +69 -0
- package/dist/core/interfaces/i-playbook-service.js +1 -0
- package/dist/core/interfaces/i-playbook-store.d.ts +38 -0
- package/dist/core/interfaces/i-playbook-store.js +1 -0
- package/dist/core/interfaces/i-project-config-store.d.ts +26 -0
- package/dist/core/interfaces/i-project-config-store.js +1 -0
- package/dist/core/interfaces/i-reflection-store.d.ts +21 -0
- package/dist/core/interfaces/i-reflection-store.js +1 -0
- package/dist/core/interfaces/i-rule-template-service.d.ts +17 -0
- package/dist/core/interfaces/i-rule-template-service.js +4 -0
- package/dist/core/interfaces/i-rule-writer-service.d.ts +13 -0
- package/dist/core/interfaces/i-rule-writer-service.js +1 -0
- package/dist/core/interfaces/i-space-service.d.ts +28 -0
- package/dist/core/interfaces/i-space-service.js +1 -0
- package/dist/core/interfaces/i-team-service.d.ts +29 -0
- package/dist/core/interfaces/i-team-service.js +1 -0
- package/dist/core/interfaces/i-template-loader.d.ts +29 -0
- package/dist/core/interfaces/i-template-loader.js +1 -0
- package/dist/core/interfaces/i-token-store.d.ts +22 -0
- package/dist/core/interfaces/i-token-store.js +1 -0
- package/dist/core/interfaces/i-tracking-service.d.ts +21 -0
- package/dist/core/interfaces/i-tracking-service.js +1 -0
- package/dist/core/interfaces/i-user-service.d.ts +14 -0
- package/dist/core/interfaces/i-user-service.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/infra/ace/ace-file-utils.d.ts +46 -0
- package/dist/infra/ace/ace-file-utils.js +83 -0
- package/dist/infra/ace/ace-prompt-templates.d.ts +13 -0
- package/dist/infra/ace/ace-prompt-templates.js +177 -0
- package/dist/infra/ace/file-bullet-content-store.d.ts +27 -0
- package/dist/infra/ace/file-bullet-content-store.js +89 -0
- package/dist/infra/ace/file-delta-store.d.ts +9 -0
- package/dist/infra/ace/file-delta-store.js +26 -0
- package/dist/infra/ace/file-executor-output-store.d.ts +9 -0
- package/dist/infra/ace/file-executor-output-store.js +26 -0
- package/dist/infra/ace/file-playbook-store.d.ts +29 -0
- package/dist/infra/ace/file-playbook-store.js +107 -0
- package/dist/infra/ace/file-reflection-store.d.ts +10 -0
- package/dist/infra/ace/file-reflection-store.js +55 -0
- package/dist/infra/auth/oauth-service.d.ts +49 -0
- package/dist/infra/auth/oauth-service.js +126 -0
- package/dist/infra/auth/oidc-discovery-service.d.ts +51 -0
- package/dist/infra/auth/oidc-discovery-service.js +145 -0
- package/dist/infra/browser/system-browser-launcher.d.ts +10 -0
- package/dist/infra/browser/system-browser-launcher.js +18 -0
- package/dist/infra/config/file-config-store.d.ts +21 -0
- package/dist/infra/config/file-config-store.js +57 -0
- package/dist/infra/file/fs-file-service.d.ts +28 -0
- package/dist/infra/file/fs-file-service.js +57 -0
- package/dist/infra/http/authenticated-http-client.d.ts +46 -0
- package/dist/infra/http/authenticated-http-client.js +99 -0
- package/dist/infra/http/callback-handler.d.ts +13 -0
- package/dist/infra/http/callback-handler.js +24 -0
- package/dist/infra/http/callback-server.d.ts +18 -0
- package/dist/infra/http/callback-server.js +93 -0
- package/dist/infra/memory/http-memory-retrieval-service.d.ts +18 -0
- package/dist/infra/memory/http-memory-retrieval-service.js +63 -0
- package/dist/infra/memory/http-memory-storage-service.d.ts +18 -0
- package/dist/infra/memory/http-memory-storage-service.js +67 -0
- package/dist/infra/memory/memory-to-playbook-mapper.d.ts +33 -0
- package/dist/infra/memory/memory-to-playbook-mapper.js +51 -0
- package/dist/infra/playbook/file-playbook-service.d.ts +43 -0
- package/dist/infra/playbook/file-playbook-service.js +133 -0
- package/dist/infra/rule/agent-rule-config.d.ts +19 -0
- package/dist/infra/rule/agent-rule-config.js +77 -0
- package/dist/infra/rule/rule-template-service.d.ts +18 -0
- package/dist/infra/rule/rule-template-service.js +80 -0
- package/dist/infra/rule/rule-writer-service.d.ts +19 -0
- package/dist/infra/rule/rule-writer-service.js +43 -0
- package/dist/infra/space/http-space-service.d.ts +20 -0
- package/dist/infra/space/http-space-service.js +67 -0
- package/dist/infra/storage/keychain-token-store.d.ts +10 -0
- package/dist/infra/storage/keychain-token-store.js +40 -0
- package/dist/infra/team/http-team-service.d.ts +21 -0
- package/dist/infra/team/http-team-service.js +71 -0
- package/dist/infra/template/fs-template-loader.d.ts +33 -0
- package/dist/infra/template/fs-template-loader.js +62 -0
- package/dist/infra/tracking/mixpanel-tracking-service.d.ts +14 -0
- package/dist/infra/tracking/mixpanel-tracking-service.js +44 -0
- package/dist/infra/user/http-user-service.d.ts +12 -0
- package/dist/infra/user/http-user-service.js +26 -0
- package/dist/templates/README.md +103 -0
- package/dist/templates/base.md +3 -0
- package/dist/templates/sections/command-reference.md +141 -0
- package/dist/templates/sections/workflow.md +46 -0
- package/dist/utils/file-helpers.d.ts +15 -0
- package/dist/utils/file-helpers.js +45 -0
- package/oclif.manifest.json +476 -0
- package/package.json +82 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { select } from '@inquirer/prompts';
|
|
2
|
+
import { Command, ux } from '@oclif/core';
|
|
3
|
+
import { getCurrentConfig } from '../../config/environment.js';
|
|
4
|
+
import { BrConfig } from '../../core/domain/entities/br-config.js';
|
|
5
|
+
import { ProjectConfigStore } from '../../infra/config/file-config-store.js';
|
|
6
|
+
import { HttpSpaceService } from '../../infra/space/http-space-service.js';
|
|
7
|
+
import { KeychainTokenStore } from '../../infra/storage/keychain-token-store.js';
|
|
8
|
+
import { HttpTeamService } from '../../infra/team/http-team-service.js';
|
|
9
|
+
export default class SpaceSwitch extends Command {
|
|
10
|
+
static description = 'Switch to a different team or space (updates .br/config.json)';
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> <%= command.id %>',
|
|
13
|
+
'# Shows current configuration, then prompts for new team/space selection',
|
|
14
|
+
];
|
|
15
|
+
createServices() {
|
|
16
|
+
const envConfig = getCurrentConfig();
|
|
17
|
+
return {
|
|
18
|
+
projectConfigStore: new ProjectConfigStore(),
|
|
19
|
+
spaceService: new HttpSpaceService({
|
|
20
|
+
apiBaseUrl: envConfig.apiBaseUrl,
|
|
21
|
+
}),
|
|
22
|
+
teamService: new HttpTeamService({
|
|
23
|
+
apiBaseUrl: envConfig.apiBaseUrl,
|
|
24
|
+
}),
|
|
25
|
+
tokenStore: new KeychainTokenStore(),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async promptForSpaceSelection(spaces) {
|
|
29
|
+
const selectedSpaceId = await select({
|
|
30
|
+
choices: spaces.map((space) => ({
|
|
31
|
+
name: space.getDisplayName(),
|
|
32
|
+
value: space.id,
|
|
33
|
+
})),
|
|
34
|
+
message: 'Select a space',
|
|
35
|
+
});
|
|
36
|
+
const selectedSpace = spaces.find((space) => space.id === selectedSpaceId);
|
|
37
|
+
if (!selectedSpace) {
|
|
38
|
+
this.error('Space selection failed');
|
|
39
|
+
}
|
|
40
|
+
return selectedSpace;
|
|
41
|
+
}
|
|
42
|
+
async promptForTeamSelection(teams) {
|
|
43
|
+
const selectedTeamId = await select({
|
|
44
|
+
choices: teams.map((team) => ({
|
|
45
|
+
name: team.name,
|
|
46
|
+
value: team.id,
|
|
47
|
+
})),
|
|
48
|
+
message: 'Select a team',
|
|
49
|
+
});
|
|
50
|
+
const selectedTeam = teams.find((team) => team.id === selectedTeamId);
|
|
51
|
+
if (!selectedTeam) {
|
|
52
|
+
this.error('Team selection failed');
|
|
53
|
+
}
|
|
54
|
+
return selectedTeam;
|
|
55
|
+
}
|
|
56
|
+
async run() {
|
|
57
|
+
try {
|
|
58
|
+
const { projectConfigStore, spaceService, teamService, tokenStore } = this.createServices();
|
|
59
|
+
// Check project initialization (MUST exist for switch)
|
|
60
|
+
const currentConfig = await projectConfigStore.read();
|
|
61
|
+
if (currentConfig === undefined) {
|
|
62
|
+
this.error('Project not initialized. Run "br init" first.');
|
|
63
|
+
}
|
|
64
|
+
// Show current configuration
|
|
65
|
+
this.log('Current configuration:');
|
|
66
|
+
this.log(` Team: ${currentConfig.teamName}`);
|
|
67
|
+
this.log(` Space: ${currentConfig.spaceName}`);
|
|
68
|
+
this.log();
|
|
69
|
+
// Validate authentication
|
|
70
|
+
const token = await tokenStore.load();
|
|
71
|
+
if (token === undefined) {
|
|
72
|
+
this.error('Not authenticated. Please run "br login" first.');
|
|
73
|
+
}
|
|
74
|
+
if (!token.isValid()) {
|
|
75
|
+
this.error('Authentication token expired. Please run "br login" again.');
|
|
76
|
+
}
|
|
77
|
+
// Fetch all teams
|
|
78
|
+
ux.action.start('Fetching all teams');
|
|
79
|
+
const teamResult = await teamService.getTeams(token.accessToken, token.sessionKey, { fetchAll: true });
|
|
80
|
+
ux.action.stop();
|
|
81
|
+
if (teamResult.teams.length === 0) {
|
|
82
|
+
this.error('No teams found. Please create a team in the ByteRover dashboard first.');
|
|
83
|
+
}
|
|
84
|
+
// Prompt for team selection
|
|
85
|
+
this.log();
|
|
86
|
+
const selectedTeam = await this.promptForTeamSelection(teamResult.teams);
|
|
87
|
+
// Fetch spaces for selected team
|
|
88
|
+
ux.action.start('Fetching all spaces');
|
|
89
|
+
const spaceResult = await spaceService.getSpaces(token.accessToken, token.sessionKey, selectedTeam.id, {
|
|
90
|
+
fetchAll: true,
|
|
91
|
+
});
|
|
92
|
+
ux.action.stop();
|
|
93
|
+
if (spaceResult.spaces.length === 0) {
|
|
94
|
+
this.error(`No spaces found in team "${selectedTeam.getDisplayName()}". Please create a space in the ByteRover dashboard first.`);
|
|
95
|
+
}
|
|
96
|
+
// Prompt for space selection
|
|
97
|
+
this.log();
|
|
98
|
+
const selectedSpace = await this.promptForSpaceSelection(spaceResult.spaces);
|
|
99
|
+
// Update configuration
|
|
100
|
+
const newConfig = BrConfig.fromSpace(selectedSpace);
|
|
101
|
+
await projectConfigStore.write(newConfig);
|
|
102
|
+
// Display success
|
|
103
|
+
this.log(`\n✓ Successfully switched to space: ${selectedSpace.getDisplayName()}`);
|
|
104
|
+
this.log(`✓ Configuration updated in: .br/config.json`);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
this.error(error instanceof Error ? error.message : 'Switch failed');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import type { IPlaybookStore } from '../core/interfaces/i-playbook-store.js';
|
|
3
|
+
import type { IProjectConfigStore } from '../core/interfaces/i-project-config-store.js';
|
|
4
|
+
import type { ITokenStore } from '../core/interfaces/i-token-store.js';
|
|
5
|
+
import { ITrackingService } from '../core/interfaces/i-tracking-service.js';
|
|
6
|
+
export default class Status extends Command {
|
|
7
|
+
static args: {
|
|
8
|
+
directory: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
9
|
+
};
|
|
10
|
+
static description: string;
|
|
11
|
+
static examples: string[];
|
|
12
|
+
static flags: {
|
|
13
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
protected createServices(): {
|
|
16
|
+
playbookStore: IPlaybookStore;
|
|
17
|
+
projectConfigStore: IProjectConfigStore;
|
|
18
|
+
tokenStore: ITokenStore;
|
|
19
|
+
trackingService: ITrackingService;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { ACE_DIR, BR_DIR, BULLETS_DIR } from '../constants.js';
|
|
4
|
+
import { FilePlaybookStore } from '../infra/ace/file-playbook-store.js';
|
|
5
|
+
import { ProjectConfigStore } from '../infra/config/file-config-store.js';
|
|
6
|
+
import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
|
|
7
|
+
import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
|
|
8
|
+
export default class Status extends Command {
|
|
9
|
+
static args = {
|
|
10
|
+
directory: Args.string({ description: 'Project directory (defaults to current directory)', required: false }),
|
|
11
|
+
};
|
|
12
|
+
static description = 'Show CLI status and project information. Display local ACE context (ACE playbook) managed by ByteRover CLI';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %>',
|
|
15
|
+
'# Check status after login:\n<%= config.bin %> login\n<%= config.bin %> <%= command.id %>',
|
|
16
|
+
'# Verify project initialization:\n<%= config.bin %> init\n<%= config.bin %> <%= command.id %>',
|
|
17
|
+
'<%= config.bin %> <%= command.id %>',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> /path/to/project',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> --format json',
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
format: Flags.string({
|
|
23
|
+
char: 'f',
|
|
24
|
+
default: 'table',
|
|
25
|
+
description: 'Output format',
|
|
26
|
+
options: ['table', 'json'],
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
createServices() {
|
|
30
|
+
const tokenStore = new KeychainTokenStore();
|
|
31
|
+
const trackingService = new MixpanelTrackingService(tokenStore);
|
|
32
|
+
return {
|
|
33
|
+
playbookStore: new FilePlaybookStore(),
|
|
34
|
+
projectConfigStore: new ProjectConfigStore(),
|
|
35
|
+
tokenStore,
|
|
36
|
+
trackingService,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async run() {
|
|
40
|
+
const { playbookStore, projectConfigStore, tokenStore } = this.createServices();
|
|
41
|
+
const { args, flags } = await this.parse(Status);
|
|
42
|
+
this.log(`CLI Version: ${this.config.version}`);
|
|
43
|
+
try {
|
|
44
|
+
const token = await tokenStore.load();
|
|
45
|
+
if (token !== undefined && token.isValid()) {
|
|
46
|
+
this.log(`Status: Logged in as ${token.userEmail}`);
|
|
47
|
+
}
|
|
48
|
+
else if (token === undefined) {
|
|
49
|
+
this.log('Status: Not logged in');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.log('Status: Session expired (login required)');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
this.log('Status: Unable to check authentication status');
|
|
57
|
+
this.warn(`Warning: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
const cwd = process.cwd();
|
|
60
|
+
this.log(`Current Directory: ${cwd}`);
|
|
61
|
+
try {
|
|
62
|
+
const isInitialized = await projectConfigStore.exists();
|
|
63
|
+
if (isInitialized) {
|
|
64
|
+
const config = await projectConfigStore.read();
|
|
65
|
+
if (config) {
|
|
66
|
+
this.log(`Project Status: Connected to ${config.teamName}/${config.spaceName}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.log('Project Status: Configuration file exists but is invalid');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.log('Project Status: Not initialized');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.log('Project Status: Unable to read project configuration');
|
|
78
|
+
this.warn(`Warning: ${error.message}`);
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const playbook = await playbookStore.load(args.directory);
|
|
82
|
+
if (!playbook) {
|
|
83
|
+
this.error('Playbook not found. Run `br init` to initialize.');
|
|
84
|
+
}
|
|
85
|
+
// Display based on format
|
|
86
|
+
if (flags.format === 'json') {
|
|
87
|
+
return this.log(JSON.stringify(playbook.toJson(), null, 2));
|
|
88
|
+
}
|
|
89
|
+
// Display file URLs like git status
|
|
90
|
+
const bullets = playbook.getBullets();
|
|
91
|
+
const sections = playbook.getSections();
|
|
92
|
+
if (bullets.length === 0) {
|
|
93
|
+
this.log('Playbook is empty. Use "br add" commands to add knowledge.');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this.log(`\nMemory not pushed to cloud:`);
|
|
97
|
+
for (const section of sections) {
|
|
98
|
+
// Space between sections
|
|
99
|
+
this.log(' ');
|
|
100
|
+
// Section title
|
|
101
|
+
this.log(`# ${section}`);
|
|
102
|
+
const sectionBullets = playbook.getBulletsInSection(section);
|
|
103
|
+
for (const bullet of sectionBullets) {
|
|
104
|
+
const relativePath = `${BR_DIR}/${ACE_DIR}/${BULLETS_DIR}/${bullet.id}.md`;
|
|
105
|
+
// Display like git status: red path
|
|
106
|
+
this.log(` ${chalk.red(relativePath)}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Guide user to push memory to cloud
|
|
110
|
+
this.log(`Use "br push" to push memory to cloud.`);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
this.error(error instanceof Error ? error.message : 'Failed to load playbook statistics');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { IOidcDiscoveryService } from '../core/interfaces/i-oidc-discovery-service.js';
|
|
2
|
+
/**
|
|
3
|
+
* OAuth/OIDC configuration for the application.
|
|
4
|
+
* This CLI uses PKCE flow (public client), so clientSecret is optional and typically undefined.
|
|
5
|
+
*/
|
|
6
|
+
export type OAuthConfig = {
|
|
7
|
+
authorizationUrl: string;
|
|
8
|
+
clientId: string;
|
|
9
|
+
clientSecret?: string;
|
|
10
|
+
/**
|
|
11
|
+
* OAuth redirect URI for receiving authorization codes.
|
|
12
|
+
*
|
|
13
|
+
* For CLI flows with local callback servers, this is typically built dynamically
|
|
14
|
+
* after the server starts on a random port (e.g., `http://localhost:3456/callback`).
|
|
15
|
+
*
|
|
16
|
+
* For other flows (web apps, etc.), this can be provided as a static value in config.
|
|
17
|
+
*
|
|
18
|
+
* Optional - can be omitted if redirectUri is determined at runtime.
|
|
19
|
+
*/
|
|
20
|
+
redirectUri?: string;
|
|
21
|
+
scopes: string[];
|
|
22
|
+
tokenUrl: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Get OAuth configuration using OIDC discovery.
|
|
26
|
+
* Configuration is built from environment-specific defaults with fallback
|
|
27
|
+
* to hardcoded URLs if discovery fails.
|
|
28
|
+
*
|
|
29
|
+
* @param discoveryService OIDC discovery service for fetching endpoints
|
|
30
|
+
* @returns OAuth configuration
|
|
31
|
+
*/
|
|
32
|
+
export declare const getAuthConfig: (discoveryService: IOidcDiscoveryService) => Promise<OAuthConfig>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ENVIRONMENT, getCurrentConfig } from './environment.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get OAuth configuration using OIDC discovery.
|
|
4
|
+
* Configuration is built from environment-specific defaults with fallback
|
|
5
|
+
* to hardcoded URLs if discovery fails.
|
|
6
|
+
*
|
|
7
|
+
* @param discoveryService OIDC discovery service for fetching endpoints
|
|
8
|
+
* @returns OAuth configuration
|
|
9
|
+
*/
|
|
10
|
+
export const getAuthConfig = async (discoveryService) => {
|
|
11
|
+
// Get environment config
|
|
12
|
+
const envConfig = getCurrentConfig();
|
|
13
|
+
// Discover OIDC endpoints
|
|
14
|
+
let authorizationUrl;
|
|
15
|
+
let tokenUrl;
|
|
16
|
+
try {
|
|
17
|
+
const metadata = await discoveryService.discover(envConfig.issuerUrl);
|
|
18
|
+
// Use discovered endpoints
|
|
19
|
+
authorizationUrl = metadata.authorizationEndpoint;
|
|
20
|
+
tokenUrl = metadata.tokenEndpoint;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
// Fallback to hardcoded environment-specific URLs
|
|
24
|
+
authorizationUrl = envConfig.authorizationUrl;
|
|
25
|
+
tokenUrl = envConfig.tokenUrl;
|
|
26
|
+
// Warn user about fallback
|
|
27
|
+
console.warn(`Warning: OIDC discovery failed, using fallback URLs for ${ENVIRONMENT} environment.`, error instanceof Error ? error.message : 'Unknown error');
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
authorizationUrl,
|
|
31
|
+
clientId: envConfig.clientId,
|
|
32
|
+
scopes: envConfig.scopes,
|
|
33
|
+
tokenUrl,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment types supported by the CLI.
|
|
3
|
+
*/
|
|
4
|
+
type Environment = 'development' | 'production';
|
|
5
|
+
/**
|
|
6
|
+
* Current environment - set at runtime by the launcher scripts.
|
|
7
|
+
* - `./bin/dev.js` sets BR_ENV=development
|
|
8
|
+
* - `./bin/run.js` sets BR_ENV=production
|
|
9
|
+
*/
|
|
10
|
+
export declare const ENVIRONMENT: Environment;
|
|
11
|
+
/**
|
|
12
|
+
* Environment-specific configuration.
|
|
13
|
+
*/
|
|
14
|
+
type EnvironmentConfig = {
|
|
15
|
+
apiBaseUrl: string;
|
|
16
|
+
authorizationUrl: string;
|
|
17
|
+
clientId: string;
|
|
18
|
+
cogitApiBaseUrl: string;
|
|
19
|
+
issuerUrl: string;
|
|
20
|
+
memoraApiBaseUrl: string;
|
|
21
|
+
mixpanelToken: string;
|
|
22
|
+
scopes: string[];
|
|
23
|
+
tokenUrl: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for each environment.
|
|
27
|
+
* These values are bundled at build time.
|
|
28
|
+
*/
|
|
29
|
+
export declare const ENV_CONFIG: Record<Environment, EnvironmentConfig>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the configuration for the current environment.
|
|
32
|
+
* @returns The environment configuration.
|
|
33
|
+
*/
|
|
34
|
+
export declare const getCurrentConfig: () => EnvironmentConfig;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Current environment - set at runtime by the launcher scripts.
|
|
3
|
+
* - `./bin/dev.js` sets BR_ENV=development
|
|
4
|
+
* - `./bin/run.js` sets BR_ENV=production
|
|
5
|
+
*/
|
|
6
|
+
export const ENVIRONMENT = process.env.BR_ENV ?? 'development';
|
|
7
|
+
/**
|
|
8
|
+
* Configuration for each environment.
|
|
9
|
+
* These values are bundled at build time.
|
|
10
|
+
*/
|
|
11
|
+
export const ENV_CONFIG = {
|
|
12
|
+
development: {
|
|
13
|
+
apiBaseUrl: 'https://dev-beta-iam.byterover.dev/api/v1',
|
|
14
|
+
authorizationUrl: 'https://dev-beta-iam.byterover.dev/api/v1/oidc/authorize',
|
|
15
|
+
clientId: 'byterover-cli-client',
|
|
16
|
+
cogitApiBaseUrl: 'https://dev-beta-cogit.byterover.dev/api/v1',
|
|
17
|
+
issuerUrl: 'https://dev-beta-iam.byterover.dev/api/v1/oidc',
|
|
18
|
+
memoraApiBaseUrl: 'https://dev-beta-memora-retrieve.byterover.dev/api/v3',
|
|
19
|
+
mixpanelToken: '258e1a2b3d44cc634ef28964771b1da0',
|
|
20
|
+
scopes: ['read', 'write', 'debug'],
|
|
21
|
+
tokenUrl: 'https://dev-beta-iam.byterover.dev/api/v1/oidc/token',
|
|
22
|
+
},
|
|
23
|
+
production: {
|
|
24
|
+
apiBaseUrl: 'https://prod-beta-iam.byterover.dev/api/v1',
|
|
25
|
+
authorizationUrl: 'https://prod-beta-iam.byterover.dev/api/v1/oidc/authorize',
|
|
26
|
+
clientId: 'byterover-cli-prod',
|
|
27
|
+
cogitApiBaseUrl: 'https://prod-beta-cogit.byterover.dev/api/v1',
|
|
28
|
+
issuerUrl: 'https://prod-beta-iam.byterover.dev/api/v1/oidc',
|
|
29
|
+
memoraApiBaseUrl: 'https://prod-beta-memora-retrieve.byterover.dev/api/v3',
|
|
30
|
+
mixpanelToken: 'fac9051df8242c885a9e0eaf60f78b10',
|
|
31
|
+
scopes: ['read', 'write'],
|
|
32
|
+
tokenUrl: 'https://prod-beta-iam.byterover.dev/api/v1/oidc/token',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Get the configuration for the current environment.
|
|
37
|
+
* @returns The environment configuration.
|
|
38
|
+
*/
|
|
39
|
+
export const getCurrentConfig = () => ENV_CONFIG[ENVIRONMENT];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const BR_DIR = ".br";
|
|
2
|
+
export declare const ACE_DIR = "ace";
|
|
3
|
+
export declare const EXECUTOR_OUTPUTS_DIR = "executor-outputs";
|
|
4
|
+
export declare const REFLECTIONS_DIR = "reflections";
|
|
5
|
+
export declare const DELTAS_DIR = "deltas";
|
|
6
|
+
export declare const BULLETS_DIR = "bullets";
|
|
7
|
+
/**
|
|
8
|
+
* Default ByteRover branch name for memory storage.
|
|
9
|
+
* This is ByteRover's internal branching mechanism, not Git branches.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_BRANCH = "main";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// ACE directory structure constants
|
|
2
|
+
export const BR_DIR = '.br';
|
|
3
|
+
export const ACE_DIR = 'ace';
|
|
4
|
+
export const EXECUTOR_OUTPUTS_DIR = 'executor-outputs';
|
|
5
|
+
export const REFLECTIONS_DIR = 'reflections';
|
|
6
|
+
export const DELTAS_DIR = 'deltas';
|
|
7
|
+
export const BULLETS_DIR = 'bullets';
|
|
8
|
+
/**
|
|
9
|
+
* Default ByteRover branch name for memory storage.
|
|
10
|
+
* This is ByteRover's internal branching mechanism, not Git branches.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_BRANCH = 'main';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array of all supported Agents.
|
|
3
|
+
*/
|
|
4
|
+
export declare const AGENT_VALUES: readonly ["Amp", "Augment Code", "Claude Code", "Cline", "Codex", "Cursor", "Gemini CLI", "Github Copilot", "Junie", "Kilo Code", "Kiro", "Qoder", "Qwen Code", "Roo Code", "Trae.ai", "Warp", "Windsurf", "Zed"];
|
|
5
|
+
export type Agent = (typeof AGENT_VALUES)[number];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array of all supported Agents.
|
|
3
|
+
*/
|
|
4
|
+
export const AGENT_VALUES = [
|
|
5
|
+
'Amp',
|
|
6
|
+
'Augment Code',
|
|
7
|
+
'Claude Code',
|
|
8
|
+
'Cline',
|
|
9
|
+
'Codex',
|
|
10
|
+
'Cursor',
|
|
11
|
+
'Gemini CLI',
|
|
12
|
+
'Github Copilot',
|
|
13
|
+
'Junie',
|
|
14
|
+
'Kilo Code',
|
|
15
|
+
'Kiro',
|
|
16
|
+
'Qoder',
|
|
17
|
+
'Qwen Code',
|
|
18
|
+
'Roo Code',
|
|
19
|
+
'Trae.ai',
|
|
20
|
+
'Warp',
|
|
21
|
+
'Windsurf',
|
|
22
|
+
'Zed',
|
|
23
|
+
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type AuthTokenParams = {
|
|
2
|
+
accessToken: string;
|
|
3
|
+
expiresAt: Date;
|
|
4
|
+
refreshToken: string;
|
|
5
|
+
sessionKey: string;
|
|
6
|
+
tokenType?: string;
|
|
7
|
+
userEmail: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Represents an authentication token with access and refresh tokens, expiration, and type.
|
|
12
|
+
*/
|
|
13
|
+
export declare class AuthToken {
|
|
14
|
+
readonly accessToken: string;
|
|
15
|
+
readonly expiresAt: Date;
|
|
16
|
+
readonly refreshToken: string;
|
|
17
|
+
readonly sessionKey: string;
|
|
18
|
+
readonly tokenType: string;
|
|
19
|
+
readonly userEmail: string;
|
|
20
|
+
readonly userId: string;
|
|
21
|
+
constructor(params: AuthTokenParams);
|
|
22
|
+
/**
|
|
23
|
+
* Create an AuthToken instance from a JSON object.
|
|
24
|
+
* @param json JSON object representing the AuthToken
|
|
25
|
+
* @returns An instance of AuthToken, or undefined if required fields are missing
|
|
26
|
+
*/
|
|
27
|
+
static fromJson(json: Record<string, string>): AuthToken | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Check if the token is expired.
|
|
30
|
+
* @returns True if the token is expired, false otherwise.
|
|
31
|
+
*/
|
|
32
|
+
isExpired(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Check if the token is valid.
|
|
35
|
+
* @returns True if the token is valid, false otherwise.
|
|
36
|
+
*/
|
|
37
|
+
isValid(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Convert the AuthToken instance to a JSON object.
|
|
40
|
+
* @returns A JSON object representing the AuthToken
|
|
41
|
+
*/
|
|
42
|
+
toJson(): Record<string, string>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents an authentication token with access and refresh tokens, expiration, and type.
|
|
3
|
+
*/
|
|
4
|
+
export class AuthToken {
|
|
5
|
+
accessToken;
|
|
6
|
+
expiresAt;
|
|
7
|
+
refreshToken;
|
|
8
|
+
sessionKey;
|
|
9
|
+
tokenType;
|
|
10
|
+
userEmail;
|
|
11
|
+
userId;
|
|
12
|
+
constructor(params) {
|
|
13
|
+
this.accessToken = params.accessToken;
|
|
14
|
+
this.expiresAt = params.expiresAt;
|
|
15
|
+
this.refreshToken = params.refreshToken;
|
|
16
|
+
this.sessionKey = params.sessionKey;
|
|
17
|
+
this.tokenType = params.tokenType ?? 'Bearer';
|
|
18
|
+
this.userId = params.userId;
|
|
19
|
+
this.userEmail = params.userEmail;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create an AuthToken instance from a JSON object.
|
|
23
|
+
* @param json JSON object representing the AuthToken
|
|
24
|
+
* @returns An instance of AuthToken, or undefined if required fields are missing
|
|
25
|
+
*/
|
|
26
|
+
static fromJson(json) {
|
|
27
|
+
// Validate that new required fields exist (for backward compatibility with old tokens)
|
|
28
|
+
if (!json.userId || !json.userEmail) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return new AuthToken({
|
|
32
|
+
accessToken: json.accessToken,
|
|
33
|
+
expiresAt: new Date(json.expiresAt),
|
|
34
|
+
refreshToken: json.refreshToken,
|
|
35
|
+
sessionKey: json.sessionKey,
|
|
36
|
+
tokenType: json.tokenType,
|
|
37
|
+
userEmail: json.userEmail,
|
|
38
|
+
userId: json.userId,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if the token is expired.
|
|
43
|
+
* @returns True if the token is expired, false otherwise.
|
|
44
|
+
*/
|
|
45
|
+
isExpired() {
|
|
46
|
+
return this.expiresAt <= new Date();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if the token is valid.
|
|
50
|
+
* @returns True if the token is valid, false otherwise.
|
|
51
|
+
*/
|
|
52
|
+
isValid() {
|
|
53
|
+
return Boolean(this.accessToken) && !this.isExpired();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Convert the AuthToken instance to a JSON object.
|
|
57
|
+
* @returns A JSON object representing the AuthToken
|
|
58
|
+
*/
|
|
59
|
+
toJson() {
|
|
60
|
+
return {
|
|
61
|
+
accessToken: this.accessToken,
|
|
62
|
+
expiresAt: this.expiresAt.toISOString(),
|
|
63
|
+
refreshToken: this.refreshToken,
|
|
64
|
+
sessionKey: this.sessionKey,
|
|
65
|
+
tokenType: this.tokenType,
|
|
66
|
+
userEmail: this.userEmail,
|
|
67
|
+
userId: this.userId,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Space } from './space.js';
|
|
2
|
+
/**
|
|
3
|
+
* Represents the configuration stored in .br/config.json
|
|
4
|
+
* This config links a project directory to a ByteRover space.
|
|
5
|
+
*/
|
|
6
|
+
export declare class BrConfig {
|
|
7
|
+
readonly createdAt: string;
|
|
8
|
+
readonly spaceId: string;
|
|
9
|
+
readonly spaceName: string;
|
|
10
|
+
readonly teamId: string;
|
|
11
|
+
readonly teamName: string;
|
|
12
|
+
constructor(createdAt: string, spaceId: string, spaceName: string, teamId: string, teamName: string);
|
|
13
|
+
/**
|
|
14
|
+
* Deserializes config from JSON format
|
|
15
|
+
*/
|
|
16
|
+
static fromJson(json: Record<string, string>): BrConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a BrConfig from a Space entity
|
|
19
|
+
*/
|
|
20
|
+
static fromSpace(space: Space): BrConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Serializes the config to JSON format
|
|
23
|
+
*/
|
|
24
|
+
toJson(): Record<string, string>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the configuration stored in .br/config.json
|
|
3
|
+
* This config links a project directory to a ByteRover space.
|
|
4
|
+
*/
|
|
5
|
+
export class BrConfig {
|
|
6
|
+
createdAt;
|
|
7
|
+
spaceId;
|
|
8
|
+
spaceName;
|
|
9
|
+
teamId;
|
|
10
|
+
teamName;
|
|
11
|
+
// eslint-disable-next-line max-params
|
|
12
|
+
constructor(createdAt, spaceId, spaceName, teamId, teamName) {
|
|
13
|
+
if (createdAt.trim().length === 0) {
|
|
14
|
+
throw new Error('Created at cannot be empty');
|
|
15
|
+
}
|
|
16
|
+
if (spaceId.trim().length === 0) {
|
|
17
|
+
throw new Error('Space ID cannot be empty');
|
|
18
|
+
}
|
|
19
|
+
if (spaceName.trim().length === 0) {
|
|
20
|
+
throw new Error('Space name cannot be empty');
|
|
21
|
+
}
|
|
22
|
+
if (teamId.trim().length === 0) {
|
|
23
|
+
throw new Error('Team ID cannot be empty');
|
|
24
|
+
}
|
|
25
|
+
if (teamName.trim().length === 0) {
|
|
26
|
+
throw new Error('Team name cannot be empty');
|
|
27
|
+
}
|
|
28
|
+
this.createdAt = createdAt;
|
|
29
|
+
this.spaceId = spaceId;
|
|
30
|
+
this.spaceName = spaceName;
|
|
31
|
+
this.teamId = teamId;
|
|
32
|
+
this.teamName = teamName;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Deserializes config from JSON format
|
|
36
|
+
*/
|
|
37
|
+
static fromJson(json) {
|
|
38
|
+
return new BrConfig(json.createdAt, json.spaceId, json.spaceName, json.teamId, json.teamName);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a BrConfig from a Space entity
|
|
42
|
+
*/
|
|
43
|
+
static fromSpace(space) {
|
|
44
|
+
return new BrConfig(new Date().toISOString(), space.id, space.name, space.teamId, space.teamName);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Serializes the config to JSON format
|
|
48
|
+
*/
|
|
49
|
+
toJson() {
|
|
50
|
+
return {
|
|
51
|
+
createdAt: this.createdAt,
|
|
52
|
+
spaceId: this.spaceId,
|
|
53
|
+
spaceName: this.spaceName,
|
|
54
|
+
teamId: this.teamId,
|
|
55
|
+
teamName: this.teamName,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|