byterover-cli 0.3.0 → 0.3.2

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()}`);
@@ -142,7 +142,8 @@ Bad:
142
142
  });
143
143
  this.log('\nQuery Results:');
144
144
  this.log(response);
145
- await trackingService.track('ace:query');
145
+ // Track query
146
+ await trackingService.track('mem:query');
146
147
  }
147
148
  finally {
148
149
  // console.log('Logic for agent stopping and resource cleanup may go here!')
@@ -47,7 +47,7 @@ export default class Status extends Command {
47
47
  };
48
48
  }
49
49
  async run() {
50
- const { contextTreeService, contextTreeSnapshotService, projectConfigStore, tokenStore } = this.createServices();
50
+ const { contextTreeService, contextTreeSnapshotService, projectConfigStore, tokenStore, trackingService } = this.createServices();
51
51
  this.log(`CLI Version: ${this.config.version}`);
52
52
  try {
53
53
  const token = await tokenStore.load();
@@ -116,6 +116,8 @@ export default class Status extends Command {
116
116
  for (const change of allChanges) {
117
117
  this.log(`\t${change.color(`${change.status.padEnd(10)} ${formatPath(change.path)}`)}`);
118
118
  }
119
+ // Track status
120
+ await trackingService.track('mem:status');
119
121
  }
120
122
  catch (error) {
121
123
  this.log('Context Tree: Unable to check status');
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Array of all supported Events.
3
3
  */
4
- export declare const EVENT_VALUES: readonly ["auth:signed_in", "auth:signed_out", "space:init", "space:changed", "rule:generate", "ace:update_bullet", "ace:remove_bullet", "ace:view_status", "ace:query", "mem:curate", "mem:pull", "mem:push", "mem:retrieve"];
4
+ export declare const EVENT_VALUES: readonly ["auth:signed_in", "auth:signed_out", "space:init", "space:changed", "rule:generate", "mem:status", "mem:curate", "mem:pull", "mem:push", "mem:query"];
5
5
  export type EventName = (typeof EVENT_VALUES)[number];
6
6
  export interface PropertyDict {
7
7
  [key: string]: any;
@@ -7,12 +7,9 @@ export const EVENT_VALUES = [
7
7
  'space:init',
8
8
  'space:changed',
9
9
  'rule:generate',
10
- 'ace:update_bullet',
11
- 'ace:remove_bullet',
12
- 'ace:view_status',
13
- 'ace:query',
10
+ 'mem:status',
14
11
  'mem:curate',
15
12
  'mem:pull',
16
13
  'mem:push',
17
- 'mem:retrieve',
14
+ 'mem:query',
18
15
  ];
@@ -759,5 +759,5 @@
759
759
  ]
760
760
  }
761
761
  },
762
- "version": "0.3.0"
762
+ "version": "0.3.2"
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.2",
5
5
  "author": "ByteRover",
6
6
  "bin": {
7
7
  "brv": "./bin/run.js"