File size: 3,368 Bytes
a5d1c1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61b1da1
a5d1c1b
 
 
 
 
 
61b1da1
a5d1c1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61b1da1
a5d1c1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61b1da1
a5d1c1b
 
 
 
 
61b1da1
a5d1c1b
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import prompts from 'prompts';
import { projectConfigManager } from '../config/project-config.js';
import { syncService, parseRepoUrl } from '../services/sync-service.js';
import { metaSkillService } from '../services/meta-skill-service.js';
import { CliApiClient } from '../client/api-client.js';
import { logger } from '../utils/logger.js';
import { outputResult, outputError } from '../utils/output.js';

export interface InitCommandOptions {
  branch?: string;
  yes?: boolean;
  noAgentSkill?: boolean;
  apiUrl?: string;
  json?: boolean;
}

export async function handleInit(
  repoUrlArg?: string,
  options: InitCommandOptions = {}
): Promise<void> {
  const workspaceRoot = process.cwd();

  let repoUrl = repoUrlArg;
  if (!repoUrl) {
    if (!options.yes && process.stdout.isTTY) {
      const response = await prompts({
        type: 'text',
        name: 'repo',
        message: 'Enter Ever-Brain source GitHub repository (e.g. owner/repo or URL):',
        validate: (value) => (value && value.trim().length > 0 ? true : 'Repository URL is required'),
      });
      repoUrl = response.repo;
    }

    if (!repoUrl) {
      return outputError('Repository URL is required. Usage: evb init <owner/repo>', 'INVALID_ARGS', options);
    }
  }

  try {
    const { owner, repo } = parseRepoUrl(repoUrl);
    const apiUrl = options.apiUrl || projectConfigManager.getApiUrl();
    const client = new CliApiClient(apiUrl);

    let defaultBranch = options.branch;
    if (!defaultBranch) {
      try {
        const meta = await client.getRepoMetadata(owner, repo);
        defaultBranch = meta.defaultBranch;
      } catch {
        defaultBranch = 'main';
      }
    }

    // 1. Write .evb/config.yaml
    projectConfigManager.writeConfig(workspaceRoot, {
      version: 1,
      source: {
        repository: `https://github.com/${owner}/${repo}`,
        branch: defaultBranch,
        api_url: options.apiUrl || undefined,
      },
    });

    // 2. Ensure .gitignore entries
    projectConfigManager.ensureGitignore(workspaceRoot);

    // 3. Initial sync
    const syncRes = await syncService.sync(workspaceRoot, { client, force: true });

    // 4. Auto-bootstrap agent meta-skill
    let bootstrapped: string[] = [];
    if (!options.noAgentSkill) {
      const metaRes = metaSkillService.bootstrapMetaSkill(workspaceRoot);
      bootstrapped = metaRes.installedLocations;
    }

    outputResult(
      {
        status: 'initialized',
        repository: `${owner}/${repo}`,
        branch: defaultBranch,
        filesCached: syncRes.total,
        metaSkillsInstalled: bootstrapped,
      },
      options,
      () => {
        logger.success(`Resolved repository: ${owner}/${repo} (branch: ${defaultBranch})`);
        logger.success(`Created local configuration: .evb/config.yaml`);
        logger.success(`Updated .gitignore for cache and state files`);
        logger.success(`Synchronized ${syncRes.total} files into local cache`);
        if (bootstrapped.length > 0) {
          logger.success(`Bootstrapped agent meta-skill in: ${bootstrapped.join(', ')}`);
        }
        console.log(`\n✨ Ever-Brain connected successfully! Run 'evb status' to view details.`);
      }
    );
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : String(err);
    outputError(message, 'INIT_ERROR', options);
  }
}