byterover-cli 0.3.0 → 0.3.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.
@@ -2,8 +2,10 @@ import { Command } from '@oclif/core';
2
2
  import type { AuthToken } from '../core/domain/entities/auth-token.js';
3
3
  import type { Space } from '../core/domain/entities/space.js';
4
4
  import type { Team } from '../core/domain/entities/team.js';
5
+ import type { ICogitPullService } from '../core/interfaces/i-cogit-pull-service.js';
5
6
  import type { IContextTreeService } from '../core/interfaces/i-context-tree-service.js';
6
7
  import type { IContextTreeSnapshotService } from '../core/interfaces/i-context-tree-snapshot-service.js';
8
+ import type { IContextTreeWriterService } from '../core/interfaces/i-context-tree-writer-service.js';
7
9
  import type { IProjectConfigStore } from '../core/interfaces/i-project-config-store.js';
8
10
  import type { IRuleWriterService } from '../core/interfaces/i-rule-writer-service.js';
9
11
  import type { ISpaceService } from '../core/interfaces/i-space-service.js';
@@ -35,8 +37,10 @@ export default class Init extends Command {
35
37
  protected cleanupBeforeReInitialization(): Promise<void>;
36
38
  protected confirmReInitialization(config: BrvConfig | LegacyProjectConfigInfo): Promise<boolean>;
37
39
  protected createServices(): {
40
+ cogitPullService: ICogitPullService;
38
41
  contextTreeService: IContextTreeService;
39
42
  contextTreeSnapshotService: IContextTreeSnapshotService;
43
+ contextTreeWriterService: IContextTreeWriterService;
40
44
  projectConfigStore: IProjectConfigStore;
41
45
  ruleWriterService: IRuleWriterService;
42
46
  spaceService: ISpaceService;
@@ -71,5 +75,16 @@ export default class Init extends Command {
71
75
  protected promptForTeamSelection(teams: Team[]): Promise<Team>;
72
76
  protected removeAceDirectory(baseDir?: string): Promise<void>;
73
77
  run(): Promise<void>;
78
+ protected syncFromRemoteOrInitialize(params: {
79
+ cogitPullService: ICogitPullService;
80
+ contextTreeService: IContextTreeService;
81
+ contextTreeSnapshotService: IContextTreeSnapshotService;
82
+ contextTreeWriterService: IContextTreeWriterService;
83
+ projectConfig: {
84
+ spaceId: string;
85
+ teamId: string;
86
+ };
87
+ token: AuthToken;
88
+ }): Promise<void>;
74
89
  private logSuccess;
75
90
  }
@@ -3,14 +3,16 @@ import { Command, Flags, ux } from '@oclif/core';
3
3
  import { access, readFile, rm } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
5
  import { getCurrentConfig } from '../config/environment.js';
6
- import { ACE_DIR, BRV_CONFIG_VERSION, BRV_DIR, PROJECT_CONFIG_FILE } from '../constants.js';
6
+ import { ACE_DIR, BRV_CONFIG_VERSION, BRV_DIR, DEFAULT_BRANCH, PROJECT_CONFIG_FILE } from '../constants.js';
7
7
  import { AGENT_VALUES } from '../core/domain/entities/agent.js';
8
8
  import { BrvConfig } from '../core/domain/entities/brv-config.js';
9
9
  import { BrvConfigVersionError } from '../core/domain/errors/brv-config-version-error.js';
10
10
  import { RuleExistsError } from '../core/domain/errors/rule-error.js';
11
+ import { HttpCogitPullService } from '../infra/cogit/http-cogit-pull-service.js';
11
12
  import { ProjectConfigStore } from '../infra/config/file-config-store.js';
12
13
  import { FileContextTreeService } from '../infra/context-tree/file-context-tree-service.js';
13
14
  import { FileContextTreeSnapshotService } from '../infra/context-tree/file-context-tree-snapshot-service.js';
15
+ import { FileContextTreeWriterService } from '../infra/context-tree/file-context-tree-writer-service.js';
14
16
  import { FsFileService } from '../infra/file/fs-file-service.js';
15
17
  import { RuleTemplateService } from '../infra/rule/rule-template-service.js';
16
18
  import { RuleWriterService } from '../infra/rule/rule-writer-service.js';
@@ -86,9 +88,14 @@ export default class Init extends Command {
86
88
  const fileService = new FsFileService();
87
89
  const templateLoader = new FsTemplateLoader(fileService);
88
90
  const ruleTemplateService = new RuleTemplateService(templateLoader);
91
+ const contextTreeSnapshotService = new FileContextTreeSnapshotService();
89
92
  return {
93
+ cogitPullService: new HttpCogitPullService({
94
+ apiBaseUrl: envConfig.cogitApiBaseUrl,
95
+ }),
90
96
  contextTreeService: new FileContextTreeService(),
91
- contextTreeSnapshotService: new FileContextTreeSnapshotService(),
97
+ contextTreeSnapshotService,
98
+ contextTreeWriterService: new FileContextTreeWriterService({ snapshotService: contextTreeSnapshotService }),
92
99
  projectConfigStore: new ProjectConfigStore(),
93
100
  ruleWriterService: new RuleWriterService(fileService, ruleTemplateService),
94
101
  spaceService: new HttpSpaceService({
@@ -286,7 +293,7 @@ export default class Init extends Command {
286
293
  async run() {
287
294
  try {
288
295
  const { flags } = await this.parse(Init);
289
- const { contextTreeService, contextTreeSnapshotService, projectConfigStore, ruleWriterService, spaceService, teamService, tokenStore, trackingService, } = this.createServices();
296
+ const { cogitPullService, contextTreeService, contextTreeSnapshotService, contextTreeWriterService, projectConfigStore, ruleWriterService, spaceService, teamService, tokenStore, trackingService, } = this.createServices();
290
297
  const authToken = await this.ensureAuthenticated(tokenStore);
291
298
  const existingConfig = await this.getExistingConfig(projectConfigStore);
292
299
  if (existingConfig) {
@@ -316,11 +323,15 @@ export default class Init extends Command {
316
323
  this.log('✓ ACE folder removed');
317
324
  }
318
325
  }
319
- // ACE is deprecated - only initialize context tree
320
- await this.initializeMemoryContextDir('context tree', () => contextTreeService.initialize());
321
- // Create initial snapshot for change tracking (includes the template files just created)
322
- await contextTreeSnapshotService.saveSnapshot();
323
- this.log('✓ Context tree snapshot created');
326
+ // Sync from remote or initialize context tree with templates
327
+ await this.syncFromRemoteOrInitialize({
328
+ cogitPullService,
329
+ contextTreeService,
330
+ contextTreeSnapshotService,
331
+ contextTreeWriterService,
332
+ projectConfig: { spaceId: selectedSpace.id, teamId: selectedTeam.id },
333
+ token: authToken,
334
+ });
324
335
  this.log();
325
336
  const selectedAgent = await this.promptForAgentSelection();
326
337
  this.log('Detecting workspaces...');
@@ -344,6 +355,38 @@ export default class Init extends Command {
344
355
  this.error(`Initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
345
356
  }
346
357
  }
358
+ async syncFromRemoteOrInitialize(params) {
359
+ // Pull from remote - fail if network/API error
360
+ this.log('\nSyncing from ByteRover...');
361
+ try {
362
+ const coGitSnapshot = await params.cogitPullService.pull({
363
+ accessToken: params.token.accessToken,
364
+ branch: DEFAULT_BRANCH,
365
+ sessionKey: params.token.sessionKey,
366
+ spaceId: params.projectConfig.spaceId,
367
+ teamId: params.projectConfig.teamId,
368
+ });
369
+ // Check if space is "empty" (no files, or only README.md placeholder)
370
+ // CoGit follows Git semantics - empty repos have a README.md placeholder
371
+ const isEmptySpace = coGitSnapshot.files.length === 0 ||
372
+ (coGitSnapshot.files.length === 1 && coGitSnapshot.files[0].path === '/README.md');
373
+ if (isEmptySpace) {
374
+ // Remote is empty - ignore placeholder, create templates with empty snapshot
375
+ await this.initializeMemoryContextDir('context tree', () => params.contextTreeService.initialize());
376
+ await params.contextTreeSnapshotService.initEmptySnapshot();
377
+ this.log('✓ Context tree initialized');
378
+ }
379
+ else {
380
+ // Remote has real data - sync it to local
381
+ await params.contextTreeWriterService.sync({ files: [...coGitSnapshot.files] });
382
+ await params.contextTreeSnapshotService.saveSnapshot();
383
+ this.log(`✓ Synced ${coGitSnapshot.files.length} context files from remote`);
384
+ }
385
+ }
386
+ catch (error) {
387
+ throw new Error(`Failed to sync from ByteRover: ${error instanceof Error ? error.message : 'Unknown error'}. Please try again.`);
388
+ }
389
+ }
347
390
  logSuccess(space) {
348
391
  this.log(`\n✓ Project initialized successfully!`);
349
392
  this.log(`✓ Connected to space: ${space.getDisplayName()}`);
@@ -759,5 +759,5 @@
759
759
  ]
760
760
  }
761
761
  },
762
- "version": "0.3.0"
762
+ "version": "0.3.1"
763
763
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "byterover-cli",
3
3
  "description": "ByteRover's CLI",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "author": "ByteRover",
6
6
  "bin": {
7
7
  "brv": "./bin/run.js"