berget 2.2.5 → 2.2.6

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.
Files changed (44) hide show
  1. package/.github/workflows/publish.yml +2 -2
  2. package/.github/workflows/test.yml +1 -1
  3. package/dist/package.json +3 -1
  4. package/dist/src/commands/code/__tests__/fake-command-runner.js +52 -0
  5. package/dist/src/commands/code/__tests__/fake-file-store.js +46 -0
  6. package/dist/src/commands/code/__tests__/fake-prompter.js +91 -0
  7. package/dist/src/commands/code/__tests__/setup-flow.test.js +238 -0
  8. package/dist/src/commands/code/adapters/clack-prompter.js +71 -0
  9. package/dist/src/commands/code/adapters/fs-file-store.js +75 -0
  10. package/dist/src/commands/code/adapters/spawn-command-runner.js +49 -0
  11. package/dist/src/commands/code/errors.js +27 -0
  12. package/dist/src/commands/code/ports/command-runner.js +2 -0
  13. package/dist/src/commands/code/ports/file-store.js +2 -0
  14. package/dist/src/commands/code/ports/prompter.js +2 -0
  15. package/dist/src/commands/code/setup.js +392 -0
  16. package/dist/src/commands/code.js +187 -631
  17. package/dist/src/constants/command-structure.js +2 -0
  18. package/dist/tests/commands/code.test.js +31 -0
  19. package/dist/tests/utils/opencode-validator.test.js +15 -14
  20. package/package.json +3 -1
  21. package/src/commands/code/__tests__/fake-command-runner.ts +47 -0
  22. package/src/commands/code/__tests__/fake-file-store.ts +35 -0
  23. package/src/commands/code/__tests__/fake-prompter.ts +83 -0
  24. package/src/commands/code/__tests__/setup-flow.test.ts +274 -0
  25. package/src/commands/code/adapters/clack-prompter.ts +43 -0
  26. package/src/commands/code/adapters/fs-file-store.ts +33 -0
  27. package/src/commands/code/adapters/spawn-command-runner.ts +36 -0
  28. package/src/commands/code/errors.ts +23 -0
  29. package/src/commands/code/ports/command-runner.ts +6 -0
  30. package/src/commands/code/ports/file-store.ts +6 -0
  31. package/src/commands/code/ports/prompter.ts +23 -0
  32. package/src/commands/code/setup.ts +402 -0
  33. package/src/commands/code.ts +209 -746
  34. package/src/constants/command-structure.ts +3 -0
  35. package/templates/agents/app.md +22 -0
  36. package/templates/agents/backend.md +22 -0
  37. package/templates/agents/devops.md +28 -0
  38. package/templates/agents/frontend.md +24 -0
  39. package/templates/agents/fullstack.md +22 -0
  40. package/templates/agents/quality.md +64 -0
  41. package/templates/agents/security.md +20 -0
  42. package/tests/commands/code.test.ts +47 -0
  43. package/tests/utils/opencode-validator.test.ts +16 -15
  44. package/opencode.json +0 -146
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SpawnCommandRunner = void 0;
13
+ const node_child_process_1 = require("node:child_process");
14
+ class SpawnCommandRunner {
15
+ checkInstalled(binary) {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ return new Promise((resolve) => {
18
+ const child = (0, node_child_process_1.spawn)('which', [binary], { stdio: 'pipe' });
19
+ child.on('close', (code) => resolve(code === 0));
20
+ child.on('error', () => resolve(false));
21
+ });
22
+ });
23
+ }
24
+ run(command, args, options) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ return new Promise((resolve, reject) => {
27
+ var _a, _b;
28
+ const child = (0, node_child_process_1.spawn)(command, args, {
29
+ stdio: 'pipe',
30
+ cwd: (options === null || options === void 0 ? void 0 : options.cwd) || process.cwd(),
31
+ });
32
+ let stdout = '';
33
+ let stderr = '';
34
+ (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (d) => { stdout += d.toString(); });
35
+ (_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (d) => { stderr += d.toString(); });
36
+ child.on('close', (code) => {
37
+ if (code === 0) {
38
+ resolve(stdout);
39
+ }
40
+ else {
41
+ reject(new Error(stderr.trim() || `Command failed with exit code ${code}`));
42
+ }
43
+ });
44
+ child.on('error', (err) => reject(err));
45
+ });
46
+ });
47
+ }
48
+ }
49
+ exports.SpawnCommandRunner = SpawnCommandRunner;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommandFailedError = exports.CancelledError = exports.PrerequisiteError = void 0;
4
+ class PrerequisiteError extends Error {
5
+ constructor(binary) {
6
+ super(`Required binary not found: ${binary}`);
7
+ this.binary = binary;
8
+ this.name = 'PrerequisiteError';
9
+ }
10
+ }
11
+ exports.PrerequisiteError = PrerequisiteError;
12
+ class CancelledError extends Error {
13
+ constructor() {
14
+ super('Wizard cancelled');
15
+ this.name = 'CancelledError';
16
+ }
17
+ }
18
+ exports.CancelledError = CancelledError;
19
+ class CommandFailedError extends Error {
20
+ constructor(command, exitCode) {
21
+ super(`Command "${command}" failed with exit code ${exitCode}`);
22
+ this.command = command;
23
+ this.exitCode = exitCode;
24
+ this.name = 'CommandFailedError';
25
+ }
26
+ }
27
+ exports.CommandFailedError = CommandFailedError;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.runSetupCommand = exports.runSetup = void 0;
36
+ const errors_1 = require("./errors");
37
+ const jsonc_parser_1 = require("jsonc-parser");
38
+ const OPENCODE_PLUGIN = '@bergetai/opencode-auth@1.0.16';
39
+ const PI_PROVIDER = 'npm:@bergetai/pi-provider';
40
+ const OPENCODE_PLUGIN_NAME = '@bergetai/opencode-auth';
41
+ const PI_PROVIDER_NAME = '@bergetai/pi-provider';
42
+ function runSetup(deps) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const { prompter, files, commands, homeDir, cwd } = deps;
45
+ prompter.intro('\uD83D\uDD27 Berget Code Setup');
46
+ const ocState = yield getOpencodeState(files, homeDir, cwd);
47
+ const piState = yield getPiState(files, homeDir, cwd);
48
+ const tool = yield prompter.select({
49
+ message: 'How do you want to use Berget AI?',
50
+ options: [
51
+ {
52
+ value: 'opencode',
53
+ label: `OpenCode${getOpencodeLabel(ocState)}`,
54
+ hint: 'Open source AI coding agent',
55
+ },
56
+ {
57
+ value: 'pi',
58
+ label: `Pi${getPiLabel(piState)}`,
59
+ hint: 'Minimal terminal coding harness',
60
+ },
61
+ ],
62
+ });
63
+ const scope = yield prompter.select({
64
+ message: 'Where should the configuration apply?',
65
+ options: [
66
+ {
67
+ value: 'project',
68
+ label: 'This project only',
69
+ hint: tool === 'opencode'
70
+ ? (ocState.project ? 'Already configured' : 'opencode.json in current directory')
71
+ : (piState.project ? 'Already configured' : '.pi/settings.json in current directory'),
72
+ },
73
+ {
74
+ value: 'global',
75
+ label: 'Globally for all projects',
76
+ hint: tool === 'opencode'
77
+ ? (ocState.global ? 'Already configured' : '~/.config/opencode/opencode.json')
78
+ : (piState.global ? 'Already configured' : '~/.pi/agent/settings.json'),
79
+ },
80
+ ],
81
+ });
82
+ if (tool === 'opencode') {
83
+ yield setupOpenCode({ prompter, files, commands, homeDir, cwd, scope });
84
+ prompter.note(`Next steps:\n\n1. Run: opencode\n2. Type: /connect\n3. Choose your auth method:\n \u2022 "Login with Berget" \u2014 Berget Code plan\n \u2022 "Enter Berget API Key manually"\n \u2022 (or set BERGET_API_KEY env var)\n4. Select model: /models\n\nFor more information, see official docs:\n\nhttps://github.com/berget-ai/opencode-berget-auth`, 'Successfully configured Berget AI for OpenCode');
85
+ }
86
+ else {
87
+ yield setupPi({ prompter, files, commands, homeDir, cwd, scope });
88
+ prompter.note(`Next steps:\n\n1. Restart Pi or run /reload\n2. Type: /login\n3. Choose your auth method:\n \u2022 "Use a subscription" \u2192 Berget AI\n \u2022 (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');
89
+ }
90
+ prompter.outro('Setup complete!');
91
+ });
92
+ }
93
+ exports.runSetup = runSetup;
94
+ // ─── OpenCode ────────────────────────────────────────────────────────────────
95
+ function setupOpenCode(deps) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ const { prompter, files, commands, homeDir, cwd, scope } = deps;
98
+ const installed = yield commands.checkInstalled('opencode');
99
+ if (!installed) {
100
+ throw new errors_1.PrerequisiteError('opencode');
101
+ }
102
+ const configPath = yield resolveOpencodeConfigPath(files, homeDir, cwd, scope);
103
+ const existingContent = yield files.readFile(configPath);
104
+ const newContent = generateModifiedContent(existingContent, configPath);
105
+ if (existingContent && existingContent === newContent) {
106
+ return;
107
+ }
108
+ if (existingContent) {
109
+ prompter.note(generateDiff(existingContent, newContent, configPath), 'Changes to be written');
110
+ }
111
+ else {
112
+ prompter.note(`New config at ${configPath}:\n\n${newContent}`, 'Config preview');
113
+ }
114
+ const shouldWrite = yield prompter.confirm({
115
+ message: existingContent
116
+ ? `Write these changes to ${configPath}?`
117
+ : `Create ${configPath}?`,
118
+ initialValue: true,
119
+ });
120
+ if (!shouldWrite)
121
+ throw new errors_1.CancelledError();
122
+ const s = prompter.spinner();
123
+ s.start('Writing OpenCode configuration...');
124
+ yield files.writeFile(configPath, newContent);
125
+ s.stop(`Wrote configuration to ${configPath}.`);
126
+ });
127
+ }
128
+ // ─── Pi ────────────────────────────────────────────────────────────────────────
129
+ function setupPi(deps) {
130
+ return __awaiter(this, void 0, void 0, function* () {
131
+ const { prompter, files, commands, homeDir, cwd, scope } = deps;
132
+ const s = prompter.spinner();
133
+ const installed = yield commands.checkInstalled('pi');
134
+ if (!installed) {
135
+ throw new errors_1.PrerequisiteError('pi');
136
+ }
137
+ const installArgs = scope === 'project'
138
+ ? ['install', '-l', PI_PROVIDER]
139
+ : ['install', PI_PROVIDER];
140
+ s.start(`Installing Berget AI provider for Pi...`);
141
+ try {
142
+ yield commands.run('pi', installArgs);
143
+ s.stop('Installed Pi provider.');
144
+ }
145
+ catch (err) {
146
+ s.stop('Pi provider installation failed. Please try again or install manually.');
147
+ throw new errors_1.CommandFailedError(`pi ${installArgs.join(' ')}`, 1);
148
+ }
149
+ const settingsPath = scope === 'project'
150
+ ? pathJoin(cwd, '.pi', 'settings.json')
151
+ : pathJoin(homeDir, '.pi', 'agent', 'settings.json');
152
+ let settings = (yield readJsonMaybe(files, settingsPath)) || {};
153
+ if (settings.defaultProvider === 'berget') {
154
+ prompter.note('Berget AI is already set as your default provider.', 'Default provider already set');
155
+ }
156
+ else {
157
+ if (settings.defaultProvider) {
158
+ const makeDefault = yield prompter.confirm({
159
+ message: `Your default provider is ${settings.defaultProvider}. Switch to Berget AI instead?`,
160
+ initialValue: false,
161
+ });
162
+ if (makeDefault) {
163
+ settings.defaultProvider = 'berget';
164
+ yield writeJsonFile(files, settingsPath, settings);
165
+ prompter.note('Berget AI is now your default provider.', 'Updated default provider');
166
+ }
167
+ }
168
+ else {
169
+ settings.defaultProvider = 'berget';
170
+ yield writeJsonFile(files, settingsPath, settings);
171
+ prompter.note('Berget AI is now your default provider.', 'Updated default provider');
172
+ }
173
+ }
174
+ });
175
+ }
176
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
177
+ function pathJoin(...parts) {
178
+ // Simple path join that avoids importing 'path' module
179
+ // This is good enough for cross-platform testing since tests control the path format
180
+ return parts.join('/');
181
+ }
182
+ function stripJsoncComments(content) {
183
+ content = content.replace(/\/\/.*$/gm, '');
184
+ content = content.replace(/\/\*[\s\S]*?\*\//g, '');
185
+ return content;
186
+ }
187
+ function generateDiff(oldText, newText, filePath) {
188
+ const oldLines = oldText.split('\n');
189
+ const newLines = newText.split('\n');
190
+ let result = `--- ${filePath}\n+++ ${filePath}\n`;
191
+ const maxLen = Math.max(oldLines.length, newLines.length);
192
+ for (let i = 0; i < maxLen; i++) {
193
+ const oldLine = oldLines[i];
194
+ const newLine = newLines[i];
195
+ if (oldLine !== newLine) {
196
+ if (oldLine !== undefined)
197
+ result += `- ${oldLine}\n`;
198
+ if (newLine !== undefined)
199
+ result += `+ ${newLine}\n`;
200
+ }
201
+ }
202
+ return result.trimEnd();
203
+ }
204
+ function readJsonMaybe(files, filePath) {
205
+ return __awaiter(this, void 0, void 0, function* () {
206
+ const content = yield files.readFile(filePath);
207
+ if (!content)
208
+ return null;
209
+ try {
210
+ return JSON.parse(content);
211
+ }
212
+ catch (_a) {
213
+ try {
214
+ return JSON.parse(stripJsoncComments(content));
215
+ }
216
+ catch (_b) {
217
+ return null;
218
+ }
219
+ }
220
+ });
221
+ }
222
+ function writeJsonFile(files, filePath, data) {
223
+ return __awaiter(this, void 0, void 0, function* () {
224
+ yield files.writeFile(filePath, JSON.stringify(data, null, 2) + '\n');
225
+ });
226
+ }
227
+ function hasPluginInConfig(config) {
228
+ return __awaiter(this, void 0, void 0, function* () {
229
+ if (!config)
230
+ return false;
231
+ const plugins = config.plugin || config.plugins || [];
232
+ return plugins.some((p) => p.includes(OPENCODE_PLUGIN_NAME));
233
+ });
234
+ }
235
+ function hasPiProviderInSettings(settings) {
236
+ return __awaiter(this, void 0, void 0, function* () {
237
+ if (!settings)
238
+ return false;
239
+ const packages = settings.packages || [];
240
+ return packages.some((p) => {
241
+ if (typeof p === 'string')
242
+ return p.includes(PI_PROVIDER_NAME);
243
+ if (typeof p === 'object' && p.source)
244
+ return p.source.includes(PI_PROVIDER_NAME);
245
+ return false;
246
+ });
247
+ });
248
+ }
249
+ function getOpencodeState(files, homeDir, cwd) {
250
+ return __awaiter(this, void 0, void 0, function* () {
251
+ const projectJsonc = yield readJsonMaybe(files, pathJoin(cwd, 'opencode.jsonc'));
252
+ const projectJson = yield readJsonMaybe(files, pathJoin(cwd, 'opencode.json'));
253
+ const globalJsonc = yield readJsonMaybe(files, pathJoin(homeDir, '.config', 'opencode', 'opencode.jsonc'));
254
+ const globalJson = yield readJsonMaybe(files, pathJoin(homeDir, '.config', 'opencode', 'opencode.json'));
255
+ return {
256
+ project: (yield hasPluginInConfig(projectJsonc)) || (yield hasPluginInConfig(projectJson)),
257
+ global: (yield hasPluginInConfig(globalJsonc)) || (yield hasPluginInConfig(globalJson)),
258
+ };
259
+ });
260
+ }
261
+ function getPiState(files, homeDir, cwd) {
262
+ return __awaiter(this, void 0, void 0, function* () {
263
+ const projectSettings = yield readJsonMaybe(files, pathJoin(cwd, '.pi', 'settings.json'));
264
+ const globalSettings = yield readJsonMaybe(files, pathJoin(homeDir, '.pi', 'agent', 'settings.json'));
265
+ return {
266
+ project: yield hasPiProviderInSettings(projectSettings),
267
+ global: yield hasPiProviderInSettings(globalSettings),
268
+ };
269
+ });
270
+ }
271
+ function getOpencodeLabel(state) {
272
+ if (state.project || state.global)
273
+ return ' (already configured)';
274
+ return '';
275
+ }
276
+ function getPiLabel(state) {
277
+ if (state.project || state.global)
278
+ return ' (already configured)';
279
+ return '';
280
+ }
281
+ function resolveOpencodeConfigPath(files, homeDir, cwd, scope) {
282
+ return __awaiter(this, void 0, void 0, function* () {
283
+ if (scope === 'project') {
284
+ const jsoncPath = pathJoin(cwd, 'opencode.jsonc');
285
+ const jsonPath = pathJoin(cwd, 'opencode.json');
286
+ if (yield files.exists(jsoncPath))
287
+ return jsoncPath;
288
+ if (yield files.exists(jsonPath))
289
+ return jsonPath;
290
+ return jsonPath;
291
+ }
292
+ else {
293
+ const globalDir = pathJoin(homeDir, '.config', 'opencode');
294
+ const jsoncPath = pathJoin(globalDir, 'opencode.jsonc');
295
+ const jsonPath = pathJoin(globalDir, 'opencode.json');
296
+ if (yield files.exists(jsoncPath))
297
+ return jsoncPath;
298
+ if (yield files.exists(jsonPath))
299
+ return jsonPath;
300
+ return jsonPath;
301
+ }
302
+ });
303
+ }
304
+ function generateModifiedContent(existingContent, configPath) {
305
+ if (configPath.endsWith('.jsonc')) {
306
+ const content = existingContent || '{}';
307
+ const parseErrors = [];
308
+ const parsed = (0, jsonc_parser_1.parse)(content, parseErrors, { allowTrailingComma: true, disallowComments: false });
309
+ let jsConfig = {};
310
+ const canModifyText = parsed !== undefined &&
311
+ typeof parsed === 'object' &&
312
+ parsed !== null &&
313
+ !Array.isArray(parsed);
314
+ if (canModifyText) {
315
+ jsConfig = parsed;
316
+ }
317
+ const pluginsKey = jsConfig.plugins !== undefined ? 'plugins' : 'plugin';
318
+ const existing = jsConfig[pluginsKey] || [];
319
+ const filtered = existing.filter((p) => !p.includes(OPENCODE_PLUGIN_NAME));
320
+ filtered.push(OPENCODE_PLUGIN);
321
+ if (canModifyText) {
322
+ let modifiedContent = content;
323
+ const pluginEdits = (0, jsonc_parser_1.modify)(modifiedContent, [pluginsKey], filtered, {
324
+ formattingOptions: { insertSpaces: true, tabSize: 2 },
325
+ });
326
+ modifiedContent = (0, jsonc_parser_1.applyEdits)(modifiedContent, pluginEdits);
327
+ if (!jsConfig.$schema) {
328
+ const schemaEdits = (0, jsonc_parser_1.modify)(modifiedContent, ['$schema'], 'https://opencode.ai/config.json', {
329
+ formattingOptions: { insertSpaces: true, tabSize: 2 },
330
+ });
331
+ modifiedContent = (0, jsonc_parser_1.applyEdits)(modifiedContent, schemaEdits);
332
+ }
333
+ return modifiedContent;
334
+ }
335
+ // Malformed, empty, or non-object JSONC — write a clean config
336
+ const config = {
337
+ [pluginsKey]: filtered,
338
+ $schema: 'https://opencode.ai/config.json',
339
+ };
340
+ return JSON.stringify(config, null, 2) + '\n';
341
+ }
342
+ // Plain JSON
343
+ let config = {};
344
+ if (existingContent) {
345
+ try {
346
+ config = JSON.parse(existingContent);
347
+ }
348
+ catch (_a) {
349
+ // ignore malformed, overwrite
350
+ }
351
+ }
352
+ const pluginsKey = config.plugins !== undefined ? 'plugins' : 'plugin';
353
+ const existing = config[pluginsKey] || [];
354
+ const filtered = existing.filter((p) => !p.includes(OPENCODE_PLUGIN_NAME));
355
+ filtered.push(OPENCODE_PLUGIN);
356
+ config[pluginsKey] = filtered;
357
+ config.$schema = config.$schema || 'https://opencode.ai/config.json';
358
+ return JSON.stringify(config, null, 2) + '\n';
359
+ }
360
+ // ─── Production CLI entry point ──────────────────────────────────────────────
361
+ const clack_prompter_js_1 = require("./adapters/clack-prompter.js");
362
+ const fs_file_store_js_1 = require("./adapters/fs-file-store.js");
363
+ const spawn_command_runner_js_1 = require("./adapters/spawn-command-runner.js");
364
+ const os = __importStar(require("os"));
365
+ function runSetupCommand() {
366
+ return __awaiter(this, void 0, void 0, function* () {
367
+ try {
368
+ yield runSetup({
369
+ prompter: new clack_prompter_js_1.ClackPrompter(),
370
+ files: new fs_file_store_js_1.FsFileStore(),
371
+ commands: new spawn_command_runner_js_1.SpawnCommandRunner(),
372
+ homeDir: os.homedir(),
373
+ cwd: process.cwd(),
374
+ });
375
+ }
376
+ catch (err) {
377
+ if (err instanceof errors_1.CancelledError) {
378
+ process.exit(130);
379
+ }
380
+ if (err instanceof errors_1.PrerequisiteError) {
381
+ console.error(`Missing required binary: ${err.binary}`);
382
+ process.exit(2);
383
+ }
384
+ if (err instanceof errors_1.CommandFailedError) {
385
+ console.error(err.message);
386
+ process.exit(5);
387
+ }
388
+ throw err;
389
+ }
390
+ });
391
+ }
392
+ exports.runSetupCommand = runSetupCommand;