berget 2.2.10 → 2.2.12

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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "berget",
3
- "version": "2.2.10",
3
+ "version": "2.2.12",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "berget": "dist/index.js"
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const vitest_1 = require("vitest");
4
4
  const errors_1 = require("../errors");
5
- const setup_1 = require("../setup");
5
+ const init_1 = require("../init");
6
6
  const fake_api_key_service_1 = require("./fake-api-key-service");
7
7
  const fake_auth_service_1 = require("./fake-auth-service");
8
8
  const fake_command_runner_1 = require("./fake-command-runner");
@@ -35,7 +35,7 @@ function makeJwt(payload) {
35
35
  const body = base64urlEncode(JSON.stringify(payload));
36
36
  return `${header}.${body}.signature`;
37
37
  }
38
- (0, vitest_1.describe)('runSetup', () => {
38
+ (0, vitest_1.describe)('runInit', () => {
39
39
  (0, vitest_1.describe)('happy path', () => {
40
40
  (0, vitest_1.it)('sets up opencode project without existing config', async () => {
41
41
  const deps = makeDeps({
@@ -46,12 +46,12 @@ function makeJwt(payload) {
46
46
  (0, fake_prompter_1.multiselect)([]), // No agents selected
47
47
  ]),
48
48
  });
49
- await (0, setup_1.runSetup)(deps);
49
+ await (0, init_1.runInit)(deps);
50
50
  const files = deps.files;
51
51
  const written = files.getWrittenFiles();
52
52
  (0, vitest_1.expect)(written.has('/home/user/project/opencode.json')).toBe(true);
53
53
  const config = JSON.parse(written.get('/home/user/project/opencode.json'));
54
- (0, vitest_1.expect)(config.plugin).toContain('@bergetai/opencode-auth');
54
+ (0, vitest_1.expect)(config.plugin).toContain('@bergetai/opencode-auth@1.0.21');
55
55
  });
56
56
  (0, vitest_1.it)('sets up opencode globally without existing config', async () => {
57
57
  const deps = makeDeps({
@@ -62,7 +62,7 @@ function makeJwt(payload) {
62
62
  (0, fake_prompter_1.multiselect)([]), // No agents selected
63
63
  ]),
64
64
  });
65
- await (0, setup_1.runSetup)(deps);
65
+ await (0, init_1.runInit)(deps);
66
66
  const files = deps.files;
67
67
  const written = files.getWrittenFiles();
68
68
  (0, vitest_1.expect)(written.has('/home/user/.config/opencode/opencode.json')).toBe(true);
@@ -75,11 +75,12 @@ function makeJwt(payload) {
75
75
  prompter: new fake_prompter_1.FakePrompter([
76
76
  (0, fake_prompter_1.select)('pi'),
77
77
  (0, fake_prompter_1.select)('project'),
78
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
78
79
  (0, fake_prompter_1.select)('fullstack'), // Agent selection
79
80
  (0, fake_prompter_1.confirm)(true, 'Create'),
80
81
  ]),
81
82
  });
82
- await (0, setup_1.runSetup)(deps);
83
+ await (0, init_1.runInit)(deps);
83
84
  const commands = deps.commands;
84
85
  (0, vitest_1.expect)(commands.calls.length).toBeGreaterThan(0);
85
86
  const installCall = commands.calls.find((c) => c.command === 'pi');
@@ -93,10 +94,10 @@ function makeJwt(payload) {
93
94
  prompter: new fake_prompter_1.FakePrompter([
94
95
  (0, fake_prompter_1.select)('pi'),
95
96
  (0, fake_prompter_1.select)('project'),
96
- (0, fake_prompter_1.select)('__skip__'), // Skip agent selection
97
+ (0, fake_prompter_1.confirm)(false, 'Set up an agent for Pi?'),
97
98
  ]),
98
99
  });
99
- await (0, setup_1.runSetup)(deps);
100
+ await (0, init_1.runInit)(deps);
100
101
  const files = deps.files;
101
102
  const written = files.getWrittenFiles();
102
103
  // Should not create any agent files
@@ -112,7 +113,7 @@ function makeJwt(payload) {
112
113
  prompter: new fake_prompter_1.FakePrompter([(0, fake_prompter_1.select)('opencode'), (0, fake_prompter_1.select)('project')]),
113
114
  });
114
115
  // Simulate opencode not being installed
115
- await (0, vitest_1.expect)((0, setup_1.runSetup)(deps)).rejects.toBeInstanceOf(errors_1.PrerequisiteError);
116
+ await (0, vitest_1.expect)((0, init_1.runInit)(deps)).rejects.toBeInstanceOf(errors_1.PrerequisiteError);
116
117
  });
117
118
  });
118
119
  (0, vitest_1.describe)('cancellation', () => {
@@ -120,7 +121,7 @@ function makeJwt(payload) {
120
121
  const deps = makeDeps({
121
122
  prompter: new fake_prompter_1.FakePrompter([(0, fake_prompter_1.select)(fake_prompter_1.CANCEL)]),
122
123
  });
123
- await (0, vitest_1.expect)((0, setup_1.runSetup)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
124
+ await (0, vitest_1.expect)((0, init_1.runInit)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
124
125
  });
125
126
  (0, vitest_1.it)('throws CancelledError when user cancels at write confirmation', async () => {
126
127
  const deps = makeDeps({
@@ -130,7 +131,7 @@ function makeJwt(payload) {
130
131
  (0, fake_prompter_1.confirm)(false, 'Create'),
131
132
  ]),
132
133
  });
133
- await (0, vitest_1.expect)((0, setup_1.runSetup)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
134
+ await (0, vitest_1.expect)((0, init_1.runInit)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
134
135
  });
135
136
  (0, vitest_1.it)('throws CancelledError when user cancels at agent write confirmation (opencode)', async () => {
136
137
  const deps = makeDeps({
@@ -142,7 +143,7 @@ function makeJwt(payload) {
142
143
  (0, fake_prompter_1.confirm)(false, 'agent'),
143
144
  ]),
144
145
  });
145
- await (0, vitest_1.expect)((0, setup_1.runSetup)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
146
+ await (0, vitest_1.expect)((0, init_1.runInit)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
146
147
  });
147
148
  (0, vitest_1.it)('throws CancelledError when user cancels at agent write confirmation (pi)', async () => {
148
149
  const deps = makeDeps({
@@ -150,11 +151,12 @@ function makeJwt(payload) {
150
151
  prompter: new fake_prompter_1.FakePrompter([
151
152
  (0, fake_prompter_1.select)('pi'),
152
153
  (0, fake_prompter_1.select)('project'),
154
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
153
155
  (0, fake_prompter_1.select)('fullstack'),
154
156
  (0, fake_prompter_1.confirm)(false, /Create|Overwrite/),
155
157
  ]),
156
158
  });
157
- await (0, vitest_1.expect)((0, setup_1.runSetup)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
159
+ await (0, vitest_1.expect)((0, init_1.runInit)(deps)).rejects.toBeInstanceOf(errors_1.CancelledError);
158
160
  });
159
161
  });
160
162
  (0, vitest_1.describe)('file operations', () => {
@@ -172,12 +174,12 @@ function makeJwt(payload) {
172
174
  customField: 'should-preserve',
173
175
  plugin: ['other-plugin'],
174
176
  }));
175
- await (0, setup_1.runSetup)(deps);
177
+ await (0, init_1.runInit)(deps);
176
178
  const written = files.getWrittenFiles();
177
179
  const config = JSON.parse(written.get('/home/user/project/opencode.json'));
178
180
  (0, vitest_1.expect)(config.customField).toBe('should-preserve');
179
181
  (0, vitest_1.expect)(config.plugin).toContain('other-plugin');
180
- (0, vitest_1.expect)(config.plugin).toContain('@bergetai/opencode-auth');
182
+ (0, vitest_1.expect)(config.plugin).toContain('@bergetai/opencode-auth@1.0.21');
181
183
  });
182
184
  (0, vitest_1.it)('preserves jsonc comments when updating', async () => {
183
185
  const deps = makeDeps({
@@ -195,7 +197,7 @@ function makeJwt(payload) {
195
197
  /* block comment explaining plugin */
196
198
  "plugin": ["other-plugin"]
197
199
  }`);
198
- await (0, setup_1.runSetup)(deps);
200
+ await (0, init_1.runInit)(deps);
199
201
  const written = files.getWrittenFiles();
200
202
  const content = written.get('/home/user/project/opencode.jsonc');
201
203
  (0, vitest_1.expect)(content).toContain('// This is my custom config');
@@ -211,14 +213,14 @@ function makeJwt(payload) {
211
213
  // Already has the exact same plugin version
212
214
  files.seed('/home/user/project/opencode.json', JSON.stringify({
213
215
  $schema: 'https://opencode.ai/config.json',
214
- plugin: ['@bergetai/opencode-auth'],
216
+ plugin: ['@bergetai/opencode-auth@1.0.21'],
215
217
  }, null, 2) + '\n');
216
- await (0, setup_1.runSetup)(deps);
218
+ await (0, init_1.runInit)(deps);
217
219
  // Check that no write happened — content should be unchanged
218
220
  const written = files.getWrittenFiles();
219
221
  const content = written.get('/home/user/project/opencode.json');
220
222
  const config = JSON.parse(content);
221
- (0, vitest_1.expect)(config.plugin).toEqual(['@bergetai/opencode-auth']);
223
+ (0, vitest_1.expect)(config.plugin).toEqual(['@bergetai/opencode-auth@1.0.21']);
222
224
  (0, vitest_1.expect)(content).toContain('$schema');
223
225
  });
224
226
  (0, vitest_1.it)('preserves existing Pi settings when setting defaultProvider', async () => {
@@ -227,6 +229,7 @@ function makeJwt(payload) {
227
229
  prompter: new fake_prompter_1.FakePrompter([
228
230
  (0, fake_prompter_1.select)('pi'),
229
231
  (0, fake_prompter_1.select)('project'),
232
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
230
233
  (0, fake_prompter_1.select)('fullstack'),
231
234
  (0, fake_prompter_1.confirm)(true, 'Create'),
232
235
  ]),
@@ -236,7 +239,7 @@ function makeJwt(payload) {
236
239
  anotherSetting: true,
237
240
  existingKey: 'should-preserve',
238
241
  }));
239
- await (0, setup_1.runSetup)(deps);
242
+ await (0, init_1.runInit)(deps);
240
243
  const written = files.getWrittenFiles();
241
244
  const settings = JSON.parse(written.get('/home/user/project/.pi/settings.json'));
242
245
  (0, vitest_1.expect)(settings.existingKey).toBe('should-preserve');
@@ -252,7 +255,7 @@ function makeJwt(payload) {
252
255
  (0, fake_prompter_1.multiselect)([]),
253
256
  ]),
254
257
  });
255
- await (0, setup_1.runSetup)(deps);
258
+ await (0, init_1.runInit)(deps);
256
259
  const files = deps.files;
257
260
  const written = files.getWrittenFiles();
258
261
  (0, vitest_1.expect)(written.has('/home/user/.config/opencode/opencode.json')).toBe(true);
@@ -265,11 +268,12 @@ function makeJwt(payload) {
265
268
  prompter: new fake_prompter_1.FakePrompter([
266
269
  (0, fake_prompter_1.select)('pi'),
267
270
  (0, fake_prompter_1.select)('project'),
271
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
268
272
  (0, fake_prompter_1.select)('fullstack'),
269
273
  (0, fake_prompter_1.confirm)(true, 'Create'),
270
274
  ]),
271
275
  });
272
- await (0, setup_1.runSetup)(deps);
276
+ await (0, init_1.runInit)(deps);
273
277
  const commands = deps.commands;
274
278
  const installCall = commands.calls.find((c) => c.command === 'pi');
275
279
  (0, vitest_1.expect)(installCall?.args).toContain('npm:@bergetai/pi-provider');
@@ -284,7 +288,7 @@ function makeJwt(payload) {
284
288
  .handle('pi install', new Error('npm error')),
285
289
  prompter: new fake_prompter_1.FakePrompter([(0, fake_prompter_1.select)('pi'), (0, fake_prompter_1.select)('project')]),
286
290
  });
287
- await (0, vitest_1.expect)((0, setup_1.runSetup)(deps)).rejects.toBeInstanceOf(errors_1.CommandFailedError);
291
+ await (0, vitest_1.expect)((0, init_1.runInit)(deps)).rejects.toBeInstanceOf(errors_1.CommandFailedError);
288
292
  });
289
293
  });
290
294
  (0, vitest_1.describe)('auth integration', () => {
@@ -301,7 +305,7 @@ function makeJwt(payload) {
301
305
  (0, fake_prompter_1.multiselect)([]),
302
306
  ]),
303
307
  });
304
- await (0, setup_1.runSetup)(deps);
308
+ await (0, init_1.runInit)(deps);
305
309
  const prompter = deps.prompter;
306
310
  const notes = prompter.calls.filter((c) => c.method === 'note');
307
311
  const lastNote = notes.at(-1);
@@ -316,11 +320,12 @@ function makeJwt(payload) {
316
320
  prompter: new fake_prompter_1.FakePrompter([
317
321
  (0, fake_prompter_1.select)('pi'),
318
322
  (0, fake_prompter_1.select)('project'),
323
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
319
324
  (0, fake_prompter_1.select)('fullstack'),
320
325
  (0, fake_prompter_1.confirm)(true, 'Create'),
321
326
  ]),
322
327
  });
323
- await (0, setup_1.runSetup)(deps);
328
+ await (0, init_1.runInit)(deps);
324
329
  const prompter = deps.prompter;
325
330
  const notes = prompter.calls.filter((c) => c.method === 'note');
326
331
  const lastNote = notes.at(-1);
@@ -336,11 +341,12 @@ function makeJwt(payload) {
336
341
  (0, fake_prompter_1.select)('pi'),
337
342
  (0, fake_prompter_1.select)('project'),
338
343
  (0, fake_prompter_1.confirm)(true), // API key creation prompt
344
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
339
345
  (0, fake_prompter_1.select)('fullstack'),
340
346
  (0, fake_prompter_1.confirm)(true, 'Create'),
341
347
  ]),
342
348
  });
343
- await (0, setup_1.runSetup)(deps);
349
+ await (0, init_1.runInit)(deps);
344
350
  const written = files.getWrittenFiles();
345
351
  (0, vitest_1.expect)(written.has('/home/user/.pi/agent/auth.json')).toBe(true);
346
352
  const parsed = JSON.parse(written.get('/home/user/.pi/agent/auth.json'));
@@ -364,7 +370,7 @@ function makeJwt(payload) {
364
370
  (0, fake_prompter_1.multiselect)([]),
365
371
  ]),
366
372
  });
367
- await (0, setup_1.runSetup)(deps);
373
+ await (0, init_1.runInit)(deps);
368
374
  const written = files.getWrittenFiles();
369
375
  const parsed = JSON.parse(written.get('/home/user/.local/share/opencode/auth.json'));
370
376
  (0, vitest_1.expect)(parsed.berget.type).toBe('oauth');
@@ -381,7 +387,7 @@ function makeJwt(payload) {
381
387
  (0, fake_prompter_1.confirm)(true, 'agent'),
382
388
  ]),
383
389
  });
384
- await (0, setup_1.runSetup)(deps);
390
+ await (0, init_1.runInit)(deps);
385
391
  const files = deps.files;
386
392
  const written = files.getWrittenFiles();
387
393
  (0, vitest_1.expect)(written.has('/home/user/project/.opencode/agents/backend.md')).toBe(true);
@@ -396,7 +402,7 @@ function makeJwt(payload) {
396
402
  (0, fake_prompter_1.multiselect)([]),
397
403
  ]),
398
404
  });
399
- await (0, setup_1.runSetup)(deps);
405
+ await (0, init_1.runInit)(deps);
400
406
  const files = deps.files;
401
407
  const written = files.getWrittenFiles();
402
408
  for (const path of written.keys()) {
@@ -413,7 +419,7 @@ function makeJwt(payload) {
413
419
  (0, fake_prompter_1.confirm)(true, 'agent'),
414
420
  ]),
415
421
  });
416
- await (0, setup_1.runSetup)(deps);
422
+ await (0, init_1.runInit)(deps);
417
423
  const files = deps.files;
418
424
  const written = files.getWrittenFiles();
419
425
  (0, vitest_1.expect)(written.has('/home/user/.config/opencode/agents/fullstack.md')).toBe(true);
@@ -424,11 +430,12 @@ function makeJwt(payload) {
424
430
  prompter: new fake_prompter_1.FakePrompter([
425
431
  (0, fake_prompter_1.select)('pi'),
426
432
  (0, fake_prompter_1.select)('project'),
433
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
427
434
  (0, fake_prompter_1.select)('fullstack'),
428
435
  (0, fake_prompter_1.confirm)(true, 'Create'),
429
436
  ]),
430
437
  });
431
- await (0, setup_1.runSetup)(deps);
438
+ await (0, init_1.runInit)(deps);
432
439
  const files = deps.files;
433
440
  const written = files.getWrittenFiles();
434
441
  (0, vitest_1.expect)(written.has('/home/user/project/.pi/SYSTEM.md')).toBe(true);
@@ -439,11 +446,12 @@ function makeJwt(payload) {
439
446
  prompter: new fake_prompter_1.FakePrompter([
440
447
  (0, fake_prompter_1.select)('pi'),
441
448
  (0, fake_prompter_1.select)('global'),
449
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
442
450
  (0, fake_prompter_1.select)('backend'),
443
451
  (0, fake_prompter_1.confirm)(true, 'Create'),
444
452
  ]),
445
453
  });
446
- await (0, setup_1.runSetup)(deps);
454
+ await (0, init_1.runInit)(deps);
447
455
  const files = deps.files;
448
456
  const written = files.getWrittenFiles();
449
457
  (0, vitest_1.expect)(written.has('/home/user/.pi/agent/SYSTEM.md')).toBe(true);
@@ -459,7 +467,7 @@ function makeJwt(payload) {
459
467
  ]),
460
468
  });
461
469
  // First run writes the files
462
- await (0, setup_1.runSetup)(deps);
470
+ await (0, init_1.runInit)(deps);
463
471
  const files = deps.files;
464
472
  const firstBackend = files
465
473
  .getWrittenFiles()
@@ -467,16 +475,17 @@ function makeJwt(payload) {
467
475
  const firstFrontend = files
468
476
  .getWrittenFiles()
469
477
  .get('/home/user/project/.opencode/agents/frontend.md');
470
- // Second run with exact same content should not prompt for overwrite
478
+ // Second run with exact same content should prompt for confirmation
471
479
  const deps2 = makeDeps({
472
480
  files,
473
481
  prompter: new fake_prompter_1.FakePrompter([
474
482
  (0, fake_prompter_1.select)('opencode'),
475
483
  (0, fake_prompter_1.select)('project'),
476
484
  (0, fake_prompter_1.multiselect)(['backend', 'frontend']),
485
+ (0, fake_prompter_1.confirm)(true, 'Write'),
477
486
  ]),
478
487
  });
479
- await (0, setup_1.runSetup)(deps2);
488
+ await (0, init_1.runInit)(deps2);
480
489
  // Content should be unchanged
481
490
  (0, vitest_1.expect)(files.getWrittenFiles().get('/home/user/project/.opencode/agents/backend.md')).toBe(firstBackend);
482
491
  (0, vitest_1.expect)(files.getWrittenFiles().get('/home/user/project/.opencode/agents/frontend.md')).toBe(firstFrontend);
@@ -490,11 +499,12 @@ function makeJwt(payload) {
490
499
  prompter: new fake_prompter_1.FakePrompter([
491
500
  (0, fake_prompter_1.select)('pi'),
492
501
  (0, fake_prompter_1.select)('project'),
502
+ (0, fake_prompter_1.confirm)(true, 'Set up an agent for Pi?'),
493
503
  (0, fake_prompter_1.select)('fullstack'),
494
- (0, fake_prompter_1.confirm)(true, 'Overwrite'),
504
+ (0, fake_prompter_1.confirm)(true, 'SYSTEM.md already exists'),
495
505
  ]),
496
506
  });
497
- await (0, setup_1.runSetup)(deps);
507
+ await (0, init_1.runInit)(deps);
498
508
  const written = files.getWrittenFiles();
499
509
  const content = written.get('/home/user/project/.pi/SYSTEM.md');
500
510
  (0, vitest_1.expect)(content).not.toBe('old agent content');
@@ -38,7 +38,7 @@ async function configureAuth(deps, tool) {
38
38
  const loginResult = await authService.loginInteractive();
39
39
  if (!loginResult.success) {
40
40
  s.stop('Login failed.');
41
- prompter.note(`${loginResult.error || 'Login timed out or was cancelled.'}\n\nPlease run \`berget auth login\` manually, then run \`berget code setup\` again.`, 'Authentication Failed');
41
+ prompter.note(`${loginResult.error || 'Login timed out or was cancelled.'}\n\nPlease run \`berget auth login\` manually, then run \`berget code init\` again.`, 'Authentication Failed');
42
42
  return { authenticated: false };
43
43
  }
44
44
  s.stop('Successfully logged in to Berget.');
@@ -88,7 +88,7 @@ async function configureAuth(deps, tool) {
88
88
  s.start('Creating API key...');
89
89
  try {
90
90
  const { key } = await apiKeyService.create({
91
- description: 'Created by berget code setup',
91
+ description: 'Created by berget code init',
92
92
  name: `${tool === 'opencode' ? 'OpenCode' : 'Pi'} (created by berget CLI)`,
93
93
  });
94
94
  await syncApiKeyToTool(files, homeDir, tool, key);
@@ -111,7 +111,7 @@ async function configureAuth(deps, tool) {
111
111
  s.start('Creating API key...');
112
112
  try {
113
113
  const { key } = await apiKeyService.create({
114
- description: 'Created by berget code setup',
114
+ description: 'Created by berget code init',
115
115
  name: `${tool === 'opencode' ? 'OpenCode' : 'Pi'} (created by berget CLI)`,
116
116
  });
117
117
  await syncApiKeyToTool(files, homeDir, tool, key);
@@ -22,8 +22,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.runSetupCommand = exports.runSetup = void 0;
29
+ exports.runInitCommand = exports.runInit = void 0;
30
+ const chalk_1 = __importDefault(require("chalk"));
27
31
  const jsonc_parser_1 = require("jsonc-parser");
28
32
  const os = __importStar(require("node:os"));
29
33
  const index_js_1 = require("../../agents/index.js");
@@ -34,13 +38,14 @@ const fs_file_store_js_1 = require("./adapters/fs-file-store.js");
34
38
  const spawn_command_runner_js_1 = require("./adapters/spawn-command-runner.js");
35
39
  const auth_sync_js_1 = require("./auth-sync.js");
36
40
  const errors_1 = require("./errors");
37
- const OPENCODE_PLUGIN = '@bergetai/opencode-auth';
41
+ const OPENCODE_PLUGIN = '@bergetai/opencode-auth@1.0.21';
38
42
  const PI_PROVIDER = 'npm:@bergetai/pi-provider';
39
43
  const OPENCODE_PLUGIN_NAME = '@bergetai/opencode-auth';
40
44
  const PI_PROVIDER_NAME = '@bergetai/pi-provider';
41
- async function runSetup(deps) {
45
+ async function runInit(deps) {
42
46
  const { apiKeyService, authService, commands, cwd, files, homeDir, prompter } = deps;
43
- prompter.intro('\uD83D\uDD27 Berget Code Setup');
47
+ prompter.intro(`${chalk_1.default.bgGreen.black(' berget code ')}`);
48
+ prompter.note(`Ask questions and report bugs on our GitHub repository:\n\n${chalk_1.default.cyan.underline('https://github.com/berget-ai/cli')}`, 'Need help?');
44
49
  const ocState = await getOpencodeState(files, homeDir, cwd);
45
50
  const piState = await getPiState(files, homeDir, cwd);
46
51
  const tool = await prompter.select({
@@ -106,13 +111,13 @@ async function runSetup(deps) {
106
111
  prompter.note(`Next steps:\n\n1. Restart Pi or run /reload\n2. Type: /login\n3. Choose your auth method:\n • "Use a subscription" → Berget AI\n • (or set BERGET_API_KEY env var)\n4. Select model: /model\n\nFor more information, see official docs:\n\nhttps://github.com/berget-ai/pi-provider`, 'Successfully configured Berget AI for Pi');
107
112
  }
108
113
  }
109
- prompter.outro('Setup complete!');
114
+ prompter.outro('Initialization complete!');
110
115
  }
111
- exports.runSetup = runSetup;
116
+ exports.runInit = runInit;
112
117
  // ─── OpenCode ────────────────────────────────────────────────────────────────
113
- async function runSetupCommand() {
118
+ async function runInitCommand() {
114
119
  try {
115
- await runSetup({
120
+ await runInit({
116
121
  apiKeyService: api_key_service_js_1.ApiKeyService.getInstance(),
117
122
  authService: auth_service_js_1.AuthService.getInstance(),
118
123
  commands: new spawn_command_runner_js_1.SpawnCommandRunner(),
@@ -138,25 +143,8 @@ async function runSetupCommand() {
138
143
  throw error;
139
144
  }
140
145
  }
141
- exports.runSetupCommand = runSetupCommand;
142
- // ─── Pi ────────────────────────────────────────────────────────────────────────
143
- function generateDiff(oldText, newText, filePath) {
144
- const oldLines = oldText.split('\n');
145
- const newLines = newText.split('\n');
146
- let result = `--- ${filePath}\n+++ ${filePath}\n`;
147
- const maxLength = Math.max(oldLines.length, newLines.length);
148
- for (let index = 0; index < maxLength; index++) {
149
- const oldLine = oldLines[index];
150
- const newLine = newLines[index];
151
- if (oldLine !== newLine) {
152
- if (oldLine !== undefined)
153
- result += `- ${oldLine}\n`;
154
- if (newLine !== undefined)
155
- result += `+ ${newLine}\n`;
156
- }
157
- }
158
- return result.trimEnd();
159
- }
146
+ exports.runInitCommand = runInitCommand;
147
+ // ─── OpenCode Config Helpers ──────────────────────────────────────────────────
160
148
  function generateModifiedContent(existingContent, configPath) {
161
149
  if (configPath.endsWith('.jsonc')) {
162
150
  const content = existingContent || '{}';
@@ -318,10 +306,10 @@ async function setupOpenCode(deps) {
318
306
  return;
319
307
  }
320
308
  if (existingContent) {
321
- prompter.note(generateDiff(existingContent, newContent, configPath), 'Changes to be written');
309
+ prompter.note(`OpenCode config will be updated at:\n ${configPath}`, 'Config update');
322
310
  }
323
311
  else {
324
- prompter.note(`New config at ${configPath}:\n\n${newContent}`, 'Config preview');
312
+ prompter.note(`OpenCode config will be created at:\n ${configPath}`, 'Config update');
325
313
  }
326
314
  const shouldWrite = await prompter.confirm({
327
315
  initialValue: true,
@@ -338,41 +326,43 @@ async function setupOpenCodeAgents(deps) {
338
326
  const { cwd, files, homeDir, prompter, scope } = deps;
339
327
  const agents = (0, index_js_1.getAllAgents)().filter((a) => a.config.mode === 'primary');
340
328
  if (agents.length === 0) {
341
- return;
329
+ return false;
342
330
  }
343
- const selectedAgents = await prompter.multiselect({
344
- message: 'Select agents to set up (optional - press enter to skip):',
345
- options: agents.map((agent) => ({
346
- hint: agent.config.description,
331
+ const agentsDir = scope === 'project'
332
+ ? pathJoin(cwd, '.opencode', 'agents')
333
+ : pathJoin(homeDir, '.config', 'opencode', 'agents');
334
+ prompter.note('Space to toggle, Enter to confirm.', 'Agent Setup');
335
+ const agentOptions = await Promise.all(agents.map(async (agent) => {
336
+ const agentPath = pathJoin(agentsDir, `${agent.config.name}.md`);
337
+ const exists = await files.exists(agentPath);
338
+ return {
339
+ hint: exists ? 'already configured' : agent.config.description,
347
340
  label: agent.config.name,
348
341
  value: agent.config.name,
349
- })),
342
+ };
343
+ }));
344
+ const selectedAgents = await prompter.multiselect({
345
+ message: 'Select agents to set up:',
346
+ options: agentOptions,
347
+ required: false,
350
348
  });
351
349
  if (selectedAgents.length === 0) {
352
- return;
350
+ return false;
353
351
  }
354
- const agentsDir = scope === 'project'
355
- ? pathJoin(cwd, '.opencode', 'agents')
356
- : pathJoin(homeDir, '.config', 'opencode', 'agents');
357
- await files.mkdir(agentsDir);
358
- const hasChanges = await Promise.all(selectedAgents.map(async (agentName) => {
359
- const agent = agents.find((a) => a.config.name === agentName);
360
- if (!agent)
361
- return false;
352
+ const newAgents = [];
353
+ const existingAgents = [];
354
+ await Promise.all(selectedAgents.map(async (agentName) => {
362
355
  const agentPath = pathJoin(agentsDir, `${agentName}.md`);
363
- const existing = await files.readFile(agentPath);
364
- const newContent = (0, index_js_1.toMarkdown)(agent);
365
- if (existing === newContent) {
366
- return false;
367
- }
368
- if (existing) {
369
- prompter.note(generateDiff(existing, newContent, agentPath), `Changes to ${agentName} agent`);
370
- }
371
- return true;
356
+ const exists = await files.exists(agentPath);
357
+ (exists ? existingAgents : newAgents).push(agentName);
372
358
  }));
373
- if (!hasChanges.some(Boolean)) {
374
- prompter.note('Agent files are already up to date.', 'No changes needed');
375
- return;
359
+ const summaryParts = [];
360
+ if (newAgents.length > 0)
361
+ summaryParts.push(`New: ${newAgents.join(', ')}`);
362
+ if (existingAgents.length > 0)
363
+ summaryParts.push(`Replaced: ${existingAgents.join(', ')}`);
364
+ if (summaryParts.length > 0) {
365
+ prompter.note(` Agent Setup Summary:\n${summaryParts.map((part) => ` ${part}`).join('\n')}`, 'Agent Setup');
376
366
  }
377
367
  const shouldWrite = await prompter.confirm({
378
368
  initialValue: true,
@@ -381,6 +371,7 @@ async function setupOpenCodeAgents(deps) {
381
371
  if (!shouldWrite) {
382
372
  throw new errors_1.CancelledError();
383
373
  }
374
+ await files.mkdir(agentsDir);
384
375
  const s = prompter.spinner();
385
376
  s.start('Writing agent configurations...');
386
377
  for (const agentName of selectedAgents) {
@@ -392,6 +383,7 @@ async function setupOpenCodeAgents(deps) {
392
383
  await files.writeFile(agentPath, content);
393
384
  }
394
385
  s.stop(`Wrote ${selectedAgents.length} agent(s) to ${agentsDir}`);
386
+ return true;
395
387
  }
396
388
  async function setupPi(deps) {
397
389
  const { commands, cwd, files, homeDir, prompter, scope } = deps;
@@ -440,43 +432,36 @@ async function setupPiAgent(deps) {
440
432
  const { cwd, files, homeDir, prompter, scope } = deps;
441
433
  const agents = (0, index_js_1.getAllAgents)().filter((a) => a.config.mode === 'primary');
442
434
  if (agents.length === 0) {
443
- return;
435
+ return false;
444
436
  }
437
+ const systemPath = scope === 'project'
438
+ ? pathJoin(cwd, '.pi', 'SYSTEM.md')
439
+ : pathJoin(homeDir, '.pi', 'agent', 'SYSTEM.md');
440
+ prompter.note('Pi uses a single system prompt.', 'Agent Setup');
441
+ const setupAgent = await prompter.confirm({
442
+ initialValue: false,
443
+ message: 'Set up an agent for Pi?',
444
+ });
445
+ if (!setupAgent)
446
+ return false;
445
447
  const selectedAgentName = await prompter.select({
446
- message: 'Select an agent (optional - press enter to skip):',
447
- options: [
448
- { label: 'Skip agent setup', value: '__skip__' },
449
- ...agents.map((agent) => ({
450
- hint: agent.config.description,
451
- label: agent.config.name,
452
- value: agent.config.name,
453
- })),
454
- ],
448
+ message: 'Choose an agent:',
449
+ options: agents.map((agent) => ({
450
+ hint: agent.config.description,
451
+ label: agent.config.name,
452
+ value: agent.config.name,
453
+ })),
455
454
  });
456
- if (selectedAgentName === '__skip__') {
457
- return;
458
- }
459
455
  const agent = agents.find((a) => a.config.name === selectedAgentName);
460
456
  if (!agent)
461
- return;
462
- const systemPath = scope === 'project'
463
- ? pathJoin(cwd, '.pi', 'SYSTEM.md')
464
- : pathJoin(homeDir, '.pi', 'agent', 'SYSTEM.md');
465
- const existing = await files.readFile(systemPath);
466
- const newContent = (0, index_js_1.toPiPrompt)(agent);
467
- if (existing === newContent) {
468
- prompter.note('Agent configuration is already up to date.', 'No changes needed');
469
- return;
470
- }
471
- if (existing) {
472
- prompter.note(generateDiff(existing, newContent, systemPath), 'Changes to agent configuration');
473
- }
474
- else {
475
- prompter.note(newContent, 'New agent configuration');
476
- }
457
+ return false;
458
+ const systemExists = await files.exists(systemPath);
459
+ const confirmMsg = systemExists
460
+ ? `SYSTEM.md already exists. Replace with ${agent.config.name}?`
461
+ : 'Create agent configuration?';
477
462
  const shouldWrite = await prompter.confirm({
478
463
  initialValue: true,
479
- message: existing ? 'Overwrite existing agent configuration?' : 'Create agent configuration?',
464
+ message: confirmMsg,
480
465
  });
481
466
  if (!shouldWrite) {
482
467
  throw new errors_1.CancelledError();
@@ -485,8 +470,9 @@ async function setupPiAgent(deps) {
485
470
  s.start('Writing agent configuration...');
486
471
  const systemDir = scope === 'project' ? pathJoin(cwd, '.pi') : pathJoin(homeDir, '.pi', 'agent');
487
472
  await files.mkdir(systemDir);
488
- await files.writeFile(systemPath, newContent);
473
+ await files.writeFile(systemPath, (0, index_js_1.toPiPrompt)(agent));
489
474
  s.stop(`Wrote agent configuration to ${systemPath}`);
475
+ return true;
490
476
  }
491
477
  function stripJsoncComments(content) {
492
478
  content = content.replaceAll(/\/\/.*$/gm, '');