berget 2.2.6 → 2.2.7

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 (144) hide show
  1. package/.github/workflows/publish.yml +6 -6
  2. package/.github/workflows/test.yml +11 -5
  3. package/.husky/pre-commit +1 -0
  4. package/.prettierignore +15 -0
  5. package/.prettierrc +5 -3
  6. package/CONTRIBUTING.md +38 -0
  7. package/README.md +2 -148
  8. package/dist/index.js +21 -21
  9. package/dist/package.json +28 -2
  10. package/dist/src/agents/app.js +28 -0
  11. package/dist/src/agents/backend.js +25 -0
  12. package/dist/src/agents/devops.js +34 -0
  13. package/dist/src/agents/frontend.js +25 -0
  14. package/dist/src/agents/fullstack.js +25 -0
  15. package/dist/src/agents/index.js +61 -0
  16. package/dist/src/agents/quality.js +70 -0
  17. package/dist/src/agents/security.js +26 -0
  18. package/dist/src/agents/types.js +2 -0
  19. package/dist/src/client.js +54 -62
  20. package/dist/src/commands/api-keys.js +132 -140
  21. package/dist/src/commands/auth.js +9 -9
  22. package/dist/src/commands/autocomplete.js +9 -9
  23. package/dist/src/commands/billing.js +7 -9
  24. package/dist/src/commands/chat.js +90 -92
  25. package/dist/src/commands/clusters.js +12 -12
  26. package/dist/src/commands/code/__tests__/auth-sync.test.js +348 -0
  27. package/dist/src/commands/code/__tests__/fake-api-key-service.js +23 -0
  28. package/dist/src/commands/code/__tests__/fake-auth-service.js +55 -0
  29. package/dist/src/commands/code/__tests__/fake-command-runner.js +5 -7
  30. package/dist/src/commands/code/__tests__/fake-file-store.js +9 -0
  31. package/dist/src/commands/code/__tests__/fake-prompter.js +60 -18
  32. package/dist/src/commands/code/__tests__/setup-flow.test.js +374 -107
  33. package/dist/src/commands/code/adapters/clack-prompter.js +10 -0
  34. package/dist/src/commands/code/adapters/fs-file-store.js +8 -3
  35. package/dist/src/commands/code/adapters/spawn-command-runner.js +15 -11
  36. package/dist/src/commands/code/auth-sync.js +283 -0
  37. package/dist/src/commands/code/errors.js +4 -4
  38. package/dist/src/commands/code/ports/auth-services.js +2 -0
  39. package/dist/src/commands/code/setup.js +234 -93
  40. package/dist/src/commands/code.js +139 -251
  41. package/dist/src/commands/models.js +13 -15
  42. package/dist/src/commands/users.js +6 -8
  43. package/dist/src/constants/command-structure.js +116 -116
  44. package/dist/src/services/api-key-service.js +43 -48
  45. package/dist/src/services/auth-service.js +60 -299
  46. package/dist/src/services/browser-auth.js +278 -0
  47. package/dist/src/services/chat-service.js +78 -91
  48. package/dist/src/services/cluster-service.js +6 -6
  49. package/dist/src/services/collaborator-service.js +5 -8
  50. package/dist/src/services/flux-service.js +5 -8
  51. package/dist/src/services/helm-service.js +5 -8
  52. package/dist/src/services/kubectl-service.js +7 -10
  53. package/dist/src/utils/config-checker.js +5 -5
  54. package/dist/src/utils/config-loader.js +25 -25
  55. package/dist/src/utils/default-api-key.js +23 -23
  56. package/dist/src/utils/env-manager.js +7 -7
  57. package/dist/src/utils/error-handler.js +60 -61
  58. package/dist/src/utils/logger.js +7 -7
  59. package/dist/src/utils/markdown-renderer.js +2 -2
  60. package/dist/src/utils/opencode-validator.js +17 -20
  61. package/dist/src/utils/token-manager.js +38 -11
  62. package/dist/tests/commands/chat.test.js +24 -24
  63. package/dist/tests/commands/code.test.js +147 -147
  64. package/dist/tests/utils/config-loader.test.js +114 -114
  65. package/dist/tests/utils/env-manager.test.js +57 -57
  66. package/dist/tests/utils/opencode-validator.test.js +33 -33
  67. package/dist/vitest.config.js +1 -1
  68. package/eslint.config.mjs +47 -0
  69. package/index.ts +42 -48
  70. package/package.json +28 -2
  71. package/src/agents/app.ts +27 -0
  72. package/src/agents/backend.ts +24 -0
  73. package/src/agents/devops.ts +33 -0
  74. package/src/agents/frontend.ts +24 -0
  75. package/src/agents/fullstack.ts +24 -0
  76. package/src/agents/index.ts +71 -0
  77. package/src/agents/quality.ts +69 -0
  78. package/src/agents/security.ts +26 -0
  79. package/src/agents/types.ts +17 -0
  80. package/src/client.ts +125 -167
  81. package/src/commands/api-keys.ts +261 -358
  82. package/src/commands/auth.ts +24 -30
  83. package/src/commands/autocomplete.ts +12 -12
  84. package/src/commands/billing.ts +22 -27
  85. package/src/commands/chat.ts +230 -323
  86. package/src/commands/clusters.ts +33 -33
  87. package/src/commands/code/__tests__/auth-sync.test.ts +481 -0
  88. package/src/commands/code/__tests__/fake-api-key-service.ts +13 -0
  89. package/src/commands/code/__tests__/fake-auth-service.ts +50 -0
  90. package/src/commands/code/__tests__/fake-command-runner.ts +39 -42
  91. package/src/commands/code/__tests__/fake-file-store.ts +32 -23
  92. package/src/commands/code/__tests__/fake-prompter.ts +107 -69
  93. package/src/commands/code/__tests__/setup-flow.test.ts +624 -270
  94. package/src/commands/code/adapters/clack-prompter.ts +50 -38
  95. package/src/commands/code/adapters/fs-file-store.ts +31 -27
  96. package/src/commands/code/adapters/spawn-command-runner.ts +33 -29
  97. package/src/commands/code/auth-sync.ts +329 -0
  98. package/src/commands/code/errors.ts +15 -15
  99. package/src/commands/code/ports/auth-services.ts +14 -0
  100. package/src/commands/code/ports/command-runner.ts +8 -4
  101. package/src/commands/code/ports/file-store.ts +5 -4
  102. package/src/commands/code/ports/prompter.ts +24 -18
  103. package/src/commands/code/setup.ts +545 -317
  104. package/src/commands/code.ts +271 -473
  105. package/src/commands/index.ts +19 -19
  106. package/src/commands/models.ts +32 -37
  107. package/src/commands/users.ts +15 -22
  108. package/src/constants/command-structure.ts +119 -142
  109. package/src/services/api-key-service.ts +96 -113
  110. package/src/services/auth-service.ts +92 -339
  111. package/src/services/browser-auth.ts +296 -0
  112. package/src/services/chat-service.ts +246 -279
  113. package/src/services/cluster-service.ts +29 -32
  114. package/src/services/collaborator-service.ts +13 -18
  115. package/src/services/flux-service.ts +16 -18
  116. package/src/services/helm-service.ts +16 -18
  117. package/src/services/kubectl-service.ts +12 -14
  118. package/src/types/api.d.ts +924 -926
  119. package/src/types/json.d.ts +3 -3
  120. package/src/utils/config-checker.ts +10 -10
  121. package/src/utils/config-loader.ts +110 -127
  122. package/src/utils/default-api-key.ts +81 -93
  123. package/src/utils/env-manager.ts +36 -40
  124. package/src/utils/error-handler.ts +83 -78
  125. package/src/utils/logger.ts +41 -41
  126. package/src/utils/markdown-renderer.ts +11 -11
  127. package/src/utils/opencode-validator.ts +51 -56
  128. package/src/utils/token-manager.ts +84 -64
  129. package/templates/agents/app.md +1 -0
  130. package/templates/agents/backend.md +1 -0
  131. package/templates/agents/devops.md +2 -0
  132. package/templates/agents/frontend.md +1 -0
  133. package/templates/agents/fullstack.md +1 -0
  134. package/templates/agents/quality.md +45 -40
  135. package/templates/agents/security.md +1 -0
  136. package/tests/commands/chat.test.ts +60 -70
  137. package/tests/commands/code.test.ts +330 -376
  138. package/tests/utils/config-loader.test.ts +260 -260
  139. package/tests/utils/env-manager.test.ts +127 -134
  140. package/tests/utils/opencode-validator.test.ts +58 -63
  141. package/tsconfig.json +2 -2
  142. package/vitest.config.ts +3 -3
  143. package/AGENTS.md +0 -374
  144. package/TODO.md +0 -19
@@ -50,10 +50,10 @@ class FsFileStore {
50
50
  readFile(filePath) {
51
51
  return __awaiter(this, void 0, void 0, function* () {
52
52
  try {
53
- return yield node_fs_1.promises.readFile(filePath, 'utf8');
53
+ return yield node_fs_1.promises.readFile(filePath, "utf8");
54
54
  }
55
55
  catch (err) {
56
- if (err.code === 'ENOENT')
56
+ if (err.code === "ENOENT")
57
57
  return null;
58
58
  throw err;
59
59
  }
@@ -63,7 +63,7 @@ class FsFileStore {
63
63
  return __awaiter(this, void 0, void 0, function* () {
64
64
  const dir = path.dirname(filePath);
65
65
  yield node_fs_1.promises.mkdir(dir, { recursive: true });
66
- yield node_fs_1.promises.writeFile(filePath, content, 'utf8');
66
+ yield node_fs_1.promises.writeFile(filePath, content, "utf8");
67
67
  });
68
68
  }
69
69
  mkdir(dir) {
@@ -71,5 +71,10 @@ class FsFileStore {
71
71
  yield node_fs_1.promises.mkdir(dir, { recursive: true });
72
72
  });
73
73
  }
74
+ chmod(filePath, mode) {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ yield node_fs_1.promises.chmod(filePath, mode);
77
+ });
78
+ }
74
79
  }
75
80
  exports.FsFileStore = FsFileStore;
@@ -14,10 +14,10 @@ const node_child_process_1 = require("node:child_process");
14
14
  class SpawnCommandRunner {
15
15
  checkInstalled(binary) {
16
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));
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
21
  });
22
22
  });
23
23
  }
@@ -26,14 +26,18 @@ class SpawnCommandRunner {
26
26
  return new Promise((resolve, reject) => {
27
27
  var _a, _b;
28
28
  const child = (0, node_child_process_1.spawn)(command, args, {
29
- stdio: 'pipe',
29
+ stdio: "pipe",
30
30
  cwd: (options === null || options === void 0 ? void 0 : options.cwd) || process.cwd(),
31
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) => {
32
+ let stdout = "";
33
+ let stderr = "";
34
+ (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", d => {
35
+ stdout += d.toString();
36
+ });
37
+ (_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", d => {
38
+ stderr += d.toString();
39
+ });
40
+ child.on("close", code => {
37
41
  if (code === 0) {
38
42
  resolve(stdout);
39
43
  }
@@ -41,7 +45,7 @@ class SpawnCommandRunner {
41
45
  reject(new Error(stderr.trim() || `Command failed with exit code ${code}`));
42
46
  }
43
47
  });
44
- child.on('error', (err) => reject(err));
48
+ child.on("error", err => reject(err));
45
49
  });
46
50
  });
47
51
  }
@@ -0,0 +1,283 @@
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.configureAuth = exports.isTokenExpired = exports.syncApiKeyToTool = exports.syncOAuthToTool = exports.hasBergetCodeSeat = exports.decodeJwtPayload = exports.isToolAuthenticated = exports.readCliAuth = void 0;
13
+ const CLI_AUTH_PATH = (homeDir) => homeDir + "/.berget/auth.json";
14
+ const TOOL_AUTH_PATHS = {
15
+ opencode: (homeDir) => homeDir + "/.local/share/opencode/auth.json",
16
+ pi: (homeDir) => homeDir + "/.pi/agent/auth.json",
17
+ };
18
+ const TOOL_API_KEY_TYPES = {
19
+ opencode: "api",
20
+ pi: "api_key",
21
+ };
22
+ function extractJwtExpiresAt(accessToken) {
23
+ try {
24
+ const parts = accessToken.split(".");
25
+ if (parts.length !== 3)
26
+ return 0;
27
+ const payload = Buffer.from(parts[1], "base64url").toString("utf8");
28
+ const decoded = JSON.parse(payload);
29
+ if (typeof decoded.exp === "number") {
30
+ return decoded.exp * 1000; // JWT exp is in seconds, convert to milliseconds
31
+ }
32
+ }
33
+ catch (_a) {
34
+ // If decoding fails, return 0 (treated as expired)
35
+ }
36
+ return 0;
37
+ }
38
+ function readCliAuth(files, homeDir) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const content = yield files.readFile(CLI_AUTH_PATH(homeDir));
41
+ if (!content)
42
+ return null;
43
+ try {
44
+ const parsed = JSON.parse(content);
45
+ if (parsed.access_token && parsed.refresh_token) {
46
+ // Extract the actual expiry time from the JWT token instead of using the stored expires_at
47
+ const jwtExpiresAt = extractJwtExpiresAt(parsed.access_token);
48
+ if (jwtExpiresAt === 0) {
49
+ // Invalid token, return null
50
+ return null;
51
+ }
52
+ return {
53
+ access_token: parsed.access_token,
54
+ refresh_token: parsed.refresh_token,
55
+ expires_at: jwtExpiresAt,
56
+ };
57
+ }
58
+ return null;
59
+ }
60
+ catch (_a) {
61
+ return null;
62
+ }
63
+ });
64
+ }
65
+ exports.readCliAuth = readCliAuth;
66
+ function isToolAuthenticated(files, homeDir, tool) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ const content = yield files.readFile(TOOL_AUTH_PATHS[tool](homeDir));
69
+ if (!content)
70
+ return false;
71
+ try {
72
+ const parsed = JSON.parse(content);
73
+ return typeof parsed.berget === "object" && parsed.berget !== null;
74
+ }
75
+ catch (_a) {
76
+ return false;
77
+ }
78
+ });
79
+ }
80
+ exports.isToolAuthenticated = isToolAuthenticated;
81
+ function decodeJwtPayload(token) {
82
+ try {
83
+ const parts = token.split(".");
84
+ if (parts.length !== 3)
85
+ return null;
86
+ const payload = Buffer.from(parts[1], "base64url").toString("utf8");
87
+ return JSON.parse(payload);
88
+ }
89
+ catch (_a) {
90
+ return null;
91
+ }
92
+ }
93
+ exports.decodeJwtPayload = decodeJwtPayload;
94
+ function hasBergetCodeSeat(accessToken) {
95
+ const payload = decodeJwtPayload(accessToken);
96
+ if (!payload || typeof payload !== "object")
97
+ return false;
98
+ const p = payload;
99
+ const realmAccess = p.realm_access;
100
+ if (!realmAccess)
101
+ return false;
102
+ const roles = realmAccess.roles;
103
+ if (!Array.isArray(roles))
104
+ return false;
105
+ return roles.includes("berget_code_seat");
106
+ }
107
+ exports.hasBergetCodeSeat = hasBergetCodeSeat;
108
+ function syncOAuthToTool(files, homeDir, tool, cliAuth) {
109
+ return __awaiter(this, void 0, void 0, function* () {
110
+ const authPath = TOOL_AUTH_PATHS[tool](homeDir);
111
+ let existing = {};
112
+ const content = yield files.readFile(authPath);
113
+ if (content) {
114
+ try {
115
+ existing = JSON.parse(content);
116
+ }
117
+ catch (_a) {
118
+ existing = {};
119
+ }
120
+ }
121
+ // Use the JWT's actual expiry time for consistency
122
+ const jwtExpiresAt = extractJwtExpiresAt(cliAuth.access_token);
123
+ const updated = Object.assign(Object.assign({}, existing), { berget: {
124
+ type: "oauth",
125
+ access: cliAuth.access_token,
126
+ refresh: cliAuth.refresh_token,
127
+ expires: jwtExpiresAt,
128
+ } });
129
+ yield files.writeFile(authPath, JSON.stringify(updated, null, 2) + "\n");
130
+ yield files.chmod(authPath, 0o600);
131
+ });
132
+ }
133
+ exports.syncOAuthToTool = syncOAuthToTool;
134
+ function syncApiKeyToTool(files, homeDir, tool, apiKey) {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ const authPath = TOOL_AUTH_PATHS[tool](homeDir);
137
+ let existing = {};
138
+ const content = yield files.readFile(authPath);
139
+ if (content) {
140
+ try {
141
+ existing = JSON.parse(content);
142
+ }
143
+ catch (_a) {
144
+ existing = {};
145
+ }
146
+ }
147
+ const updated = Object.assign(Object.assign({}, existing), { berget: {
148
+ type: TOOL_API_KEY_TYPES[tool],
149
+ key: apiKey,
150
+ } });
151
+ yield files.writeFile(authPath, JSON.stringify(updated, null, 2) + "\n");
152
+ yield files.chmod(authPath, 0o600);
153
+ });
154
+ }
155
+ exports.syncApiKeyToTool = syncApiKeyToTool;
156
+ function isTokenExpired(expiresAt) {
157
+ const now = Date.now();
158
+ const timeUntilExpiry = expiresAt - now;
159
+ const buffer = Math.min(30 * 1000, timeUntilExpiry * 0.1);
160
+ return now + buffer >= expiresAt;
161
+ }
162
+ exports.isTokenExpired = isTokenExpired;
163
+ function configureAuth(deps, tool) {
164
+ return __awaiter(this, void 0, void 0, function* () {
165
+ const { prompter, files, authService, apiKeyService, homeDir } = deps;
166
+ const alreadyAuth = yield isToolAuthenticated(files, homeDir, tool);
167
+ if (alreadyAuth) {
168
+ const choice = yield prompter.select({
169
+ message: `Account is already connected to Berget AI (${tool === "opencode" ? "OpenCode" : "Pi"}). How do you want to proceed?`,
170
+ options: [
171
+ { value: "keep", label: "Keep existing authentication" },
172
+ { value: "reconfigure", label: "Reconfigure — choose a different method" },
173
+ ],
174
+ });
175
+ if (choice === "keep") {
176
+ return { authenticated: true };
177
+ }
178
+ // Fall through to reconfigure
179
+ }
180
+ else {
181
+ prompter.note("Authentication required to use Berget AI.", "Connect your account");
182
+ }
183
+ // Try to reuse existing CLI tokens (from ~/.berget/auth.json)
184
+ let cliAuth = yield readCliAuth(files, homeDir);
185
+ if (!cliAuth || isTokenExpired(cliAuth.expires_at)) {
186
+ // No valid tokens → full browser login
187
+ const s = prompter.spinner();
188
+ s.start("Waiting for browser login...");
189
+ const loginResult = yield authService.loginInteractive();
190
+ if (!loginResult.success) {
191
+ s.stop("Login failed.");
192
+ 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");
193
+ return { authenticated: false };
194
+ }
195
+ s.stop("Successfully logged in to Berget.");
196
+ const jwtExpiresAt = extractJwtExpiresAt(loginResult.accessToken);
197
+ if (jwtExpiresAt === 0) {
198
+ s.stop("Login succeeded but received invalid token.");
199
+ prompter.note("Please try logging in again or contact support.", "Authentication Error");
200
+ return { authenticated: false };
201
+ }
202
+ cliAuth = {
203
+ access_token: loginResult.accessToken,
204
+ refresh_token: loginResult.refreshToken,
205
+ expires_at: jwtExpiresAt,
206
+ };
207
+ }
208
+ // Check Berget Code seat
209
+ const jwtPayload = decodeJwtPayload(cliAuth.access_token);
210
+ const hasSeat = jwtPayload ? hasBergetCodeSeat(cliAuth.access_token) : true;
211
+ // If we can't decode the JWT, sync OAuth anyway — the tokens are valid even if
212
+ // we can't verify the subscription role. Let the tool handle authorization.
213
+ if (!jwtPayload) {
214
+ const s = prompter.spinner();
215
+ s.start("Authenticating with Berget AI...");
216
+ yield syncOAuthToTool(files, homeDir, tool, cliAuth);
217
+ s.stop("Authenticated.");
218
+ prompter.note("Warning: Could not verify Berget Code subscription status.\nIf you do not have a subscription, the tool may show an authorization error.", "Authentication");
219
+ return { authenticated: true };
220
+ }
221
+ if (hasSeat) {
222
+ // Case B: Has seat — ask how to authenticate
223
+ const method = yield prompter.select({
224
+ message: "You have a Berget Code subscription. How do you want to authenticate?",
225
+ options: [
226
+ { value: "subscription", label: "Use my Berget Code subscription" },
227
+ { value: "api_key", label: "Use an API key instead" },
228
+ ],
229
+ });
230
+ if (method === "subscription") {
231
+ const s = prompter.spinner();
232
+ s.start("Authenticating with Berget AI via subscription...");
233
+ yield syncOAuthToTool(files, homeDir, tool, cliAuth);
234
+ s.stop("Authenticated.");
235
+ return { authenticated: true };
236
+ }
237
+ // Create API key instead
238
+ const s = prompter.spinner();
239
+ s.start("Creating API key...");
240
+ try {
241
+ const { key } = yield apiKeyService.create({
242
+ name: `${tool === "opencode" ? "OpenCode" : "Pi"} (created by berget CLI)`,
243
+ description: "Created by berget code setup",
244
+ });
245
+ yield syncApiKeyToTool(files, homeDir, tool, key);
246
+ s.stop("API key created and saved.");
247
+ return { authenticated: true };
248
+ }
249
+ catch (_a) {
250
+ s.stop("API key creation failed.");
251
+ prompter.note("Could not create API key. Please create one manually with `berget api-keys create`.", "Error");
252
+ return { authenticated: false };
253
+ }
254
+ }
255
+ // No Berget Code seat — prompt for API key creation
256
+ const shouldCreate = yield prompter.confirm({
257
+ message: "You do not have a Berget Code subscription. Would you like to create a new API key?",
258
+ initialValue: true,
259
+ });
260
+ if (shouldCreate) {
261
+ const s = prompter.spinner();
262
+ s.start("Creating API key...");
263
+ try {
264
+ const { key } = yield apiKeyService.create({
265
+ name: `${tool === "opencode" ? "OpenCode" : "Pi"} (created by berget CLI)`,
266
+ description: "Created by berget code setup",
267
+ });
268
+ yield syncApiKeyToTool(files, homeDir, tool, key);
269
+ s.stop("API key created and saved.");
270
+ return { authenticated: true };
271
+ }
272
+ catch (_b) {
273
+ s.stop("API key creation failed.");
274
+ prompter.note("Could not create API key. Please create one manually with `berget api-keys create`.", "Error");
275
+ return { authenticated: false };
276
+ }
277
+ }
278
+ // Case D: Declined
279
+ prompter.note('Authentication skipped. You\'ll need to set up authentication manually:\n1. Run: berget api-keys create --name "My Key"\n2. Set BERGET_API_KEY environment variable, or\n3. Run `berget auth login` and try again', "Authentication");
280
+ return { authenticated: false };
281
+ });
282
+ }
283
+ exports.configureAuth = configureAuth;
@@ -5,14 +5,14 @@ class PrerequisiteError extends Error {
5
5
  constructor(binary) {
6
6
  super(`Required binary not found: ${binary}`);
7
7
  this.binary = binary;
8
- this.name = 'PrerequisiteError';
8
+ this.name = "PrerequisiteError";
9
9
  }
10
10
  }
11
11
  exports.PrerequisiteError = PrerequisiteError;
12
12
  class CancelledError extends Error {
13
13
  constructor() {
14
- super('Wizard cancelled');
15
- this.name = 'CancelledError';
14
+ super("Wizard cancelled");
15
+ this.name = "CancelledError";
16
16
  }
17
17
  }
18
18
  exports.CancelledError = CancelledError;
@@ -21,7 +21,7 @@ class CommandFailedError extends Error {
21
21
  super(`Command "${command}" failed with exit code ${exitCode}`);
22
22
  this.command = command;
23
23
  this.exitCode = exitCode;
24
- this.name = 'CommandFailedError';
24
+ this.name = "CommandFailedError";
25
25
  }
26
26
  }
27
27
  exports.CommandFailedError = CommandFailedError;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });