berget 2.2.6 → 2.2.8

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 (145) hide show
  1. package/.github/workflows/publish.yml +2 -2
  2. package/.github/workflows/test.yml +10 -4
  3. package/.husky/pre-commit +1 -0
  4. package/.prettierignore +15 -0
  5. package/.prettierrc +7 -3
  6. package/CONTRIBUTING.md +38 -0
  7. package/README.md +2 -148
  8. package/dist/index.js +10 -11
  9. package/dist/package.json +30 -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 +97 -117
  20. package/dist/src/commands/api-keys.js +75 -90
  21. package/dist/src/commands/auth.js +7 -16
  22. package/dist/src/commands/autocomplete.js +1 -1
  23. package/dist/src/commands/billing.js +6 -17
  24. package/dist/src/commands/chat.js +68 -101
  25. package/dist/src/commands/clusters.js +9 -18
  26. package/dist/src/commands/code/__tests__/auth-sync.test.js +351 -0
  27. package/dist/src/commands/code/__tests__/fake-api-key-service.js +13 -0
  28. package/dist/src/commands/code/__tests__/fake-auth-service.js +47 -0
  29. package/dist/src/commands/code/__tests__/fake-command-runner.js +21 -34
  30. package/dist/src/commands/code/__tests__/fake-file-store.js +20 -33
  31. package/dist/src/commands/code/__tests__/fake-prompter.js +83 -57
  32. package/dist/src/commands/code/__tests__/setup-flow.test.js +359 -92
  33. package/dist/src/commands/code/adapters/clack-prompter.js +15 -22
  34. package/dist/src/commands/code/adapters/fs-file-store.js +26 -40
  35. package/dist/src/commands/code/adapters/spawn-command-runner.js +27 -37
  36. package/dist/src/commands/code/auth-sync.js +270 -0
  37. package/dist/src/commands/code/errors.js +12 -9
  38. package/dist/src/commands/code/ports/auth-services.js +2 -0
  39. package/dist/src/commands/code/setup.js +387 -281
  40. package/dist/src/commands/code.js +205 -332
  41. package/dist/src/commands/index.js +5 -5
  42. package/dist/src/commands/models.js +6 -17
  43. package/dist/src/commands/users.js +5 -16
  44. package/dist/src/constants/command-structure.js +104 -104
  45. package/dist/src/services/api-key-service.js +132 -157
  46. package/dist/src/services/auth-service.js +89 -342
  47. package/dist/src/services/browser-auth.js +268 -0
  48. package/dist/src/services/chat-service.js +371 -401
  49. package/dist/src/services/cluster-service.js +47 -62
  50. package/dist/src/services/collaborator-service.js +10 -25
  51. package/dist/src/services/flux-service.js +14 -29
  52. package/dist/src/services/helm-service.js +10 -25
  53. package/dist/src/services/kubectl-service.js +16 -33
  54. package/dist/src/utils/config-checker.js +3 -3
  55. package/dist/src/utils/config-loader.js +95 -95
  56. package/dist/src/utils/default-api-key.js +124 -134
  57. package/dist/src/utils/env-manager.js +55 -66
  58. package/dist/src/utils/error-handler.js +20 -21
  59. package/dist/src/utils/logger.js +72 -65
  60. package/dist/src/utils/markdown-renderer.js +27 -27
  61. package/dist/src/utils/opencode-validator.js +63 -68
  62. package/dist/src/utils/token-manager.js +74 -45
  63. package/dist/tests/commands/chat.test.js +16 -25
  64. package/dist/tests/commands/code.test.js +95 -104
  65. package/dist/tests/utils/config-loader.test.js +48 -48
  66. package/dist/tests/utils/env-manager.test.js +43 -52
  67. package/dist/tests/utils/opencode-validator.test.js +22 -21
  68. package/dist/vitest.config.js +1 -1
  69. package/eslint.config.mjs +67 -0
  70. package/index.ts +35 -42
  71. package/package.json +30 -2
  72. package/src/agents/app.ts +27 -0
  73. package/src/agents/backend.ts +24 -0
  74. package/src/agents/devops.ts +33 -0
  75. package/src/agents/frontend.ts +24 -0
  76. package/src/agents/fullstack.ts +24 -0
  77. package/src/agents/index.ts +73 -0
  78. package/src/agents/quality.ts +69 -0
  79. package/src/agents/security.ts +26 -0
  80. package/src/agents/types.ts +17 -0
  81. package/src/client.ts +118 -152
  82. package/src/commands/api-keys.ts +241 -333
  83. package/src/commands/auth.ts +22 -27
  84. package/src/commands/autocomplete.ts +9 -9
  85. package/src/commands/billing.ts +20 -24
  86. package/src/commands/chat.ts +248 -338
  87. package/src/commands/clusters.ts +27 -26
  88. package/src/commands/code/__tests__/auth-sync.test.ts +482 -0
  89. package/src/commands/code/__tests__/fake-api-key-service.ts +13 -0
  90. package/src/commands/code/__tests__/fake-auth-service.ts +50 -0
  91. package/src/commands/code/__tests__/fake-command-runner.ts +45 -42
  92. package/src/commands/code/__tests__/fake-file-store.ts +32 -23
  93. package/src/commands/code/__tests__/fake-prompter.ts +116 -77
  94. package/src/commands/code/__tests__/setup-flow.test.ts +624 -268
  95. package/src/commands/code/adapters/clack-prompter.ts +53 -39
  96. package/src/commands/code/adapters/fs-file-store.ts +32 -27
  97. package/src/commands/code/adapters/spawn-command-runner.ts +38 -29
  98. package/src/commands/code/auth-sync.ts +329 -0
  99. package/src/commands/code/errors.ts +18 -18
  100. package/src/commands/code/ports/auth-services.ts +14 -0
  101. package/src/commands/code/ports/command-runner.ts +8 -4
  102. package/src/commands/code/ports/file-store.ts +5 -4
  103. package/src/commands/code/ports/prompter.ts +24 -18
  104. package/src/commands/code/setup.ts +570 -340
  105. package/src/commands/code.ts +338 -539
  106. package/src/commands/index.ts +20 -19
  107. package/src/commands/models.ts +28 -32
  108. package/src/commands/users.ts +15 -21
  109. package/src/constants/command-structure.ts +134 -157
  110. package/src/services/api-key-service.ts +105 -122
  111. package/src/services/auth-service.ts +99 -345
  112. package/src/services/browser-auth.ts +296 -0
  113. package/src/services/chat-service.ts +265 -299
  114. package/src/services/cluster-service.ts +42 -45
  115. package/src/services/collaborator-service.ts +14 -19
  116. package/src/services/flux-service.ts +23 -25
  117. package/src/services/helm-service.ts +19 -21
  118. package/src/services/kubectl-service.ts +17 -19
  119. package/src/types/api.d.ts +1905 -1907
  120. package/src/types/json.d.ts +2 -2
  121. package/src/utils/config-checker.ts +10 -10
  122. package/src/utils/config-loader.ts +162 -178
  123. package/src/utils/default-api-key.ts +114 -125
  124. package/src/utils/env-manager.ts +53 -57
  125. package/src/utils/error-handler.ts +61 -56
  126. package/src/utils/logger.ts +79 -73
  127. package/src/utils/markdown-renderer.ts +31 -31
  128. package/src/utils/opencode-validator.ts +85 -89
  129. package/src/utils/token-manager.ts +108 -87
  130. package/templates/agents/app.md +1 -0
  131. package/templates/agents/backend.md +1 -0
  132. package/templates/agents/devops.md +2 -0
  133. package/templates/agents/frontend.md +1 -0
  134. package/templates/agents/fullstack.md +1 -0
  135. package/templates/agents/quality.md +45 -40
  136. package/templates/agents/security.md +1 -0
  137. package/tests/commands/chat.test.ts +53 -62
  138. package/tests/commands/code.test.ts +265 -310
  139. package/tests/utils/config-loader.test.ts +189 -188
  140. package/tests/utils/env-manager.test.ts +110 -113
  141. package/tests/utils/opencode-validator.test.ts +52 -56
  142. package/tsconfig.json +4 -3
  143. package/vitest.config.ts +3 -3
  144. package/AGENTS.md +0 -374
  145. package/TODO.md +0 -19
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agent = void 0;
4
+ exports.agent = {
5
+ config: {
6
+ description: 'Quality assurance specialist for testing, building, and complete PR management.',
7
+ mode: 'subagent',
8
+ name: 'quality',
9
+ permission: {
10
+ bash: 'allow',
11
+ edit: 'allow',
12
+ webfetch: 'allow',
13
+ },
14
+ temperature: 0.1,
15
+ top_p: 0.9,
16
+ },
17
+ systemPrompt: `Voice: Scandinavian calm—precise, concise, confident. You are Berget Code Quality agent. Specialist in code quality assurance, testing, building, and pull request lifecycle management.
18
+
19
+ Core responsibilities:
20
+ - Run comprehensive test suites (npm test, npm run test, jest, vitest)
21
+ - Execute build processes (npm run build, webpack, vite, tsc)
22
+ - Create and manage pull requests with proper descriptions
23
+ - Handle merge conflicts and keep main updated
24
+ - Monitor GitHub for reviewer comments and address them
25
+ - Ensure code quality standards are met
26
+ - Validate linting and formatting (npm run lint, prettier)
27
+ - Check test coverage and performance benchmarks
28
+ - Handle CI/CD pipeline validation
29
+
30
+ Complete PR Workflow:
31
+ 1. Ensure all tests pass: npm test
32
+ 2. Build successfully: npm run build
33
+ 3. Commit all changes with proper message
34
+ 4. Push to feature branch
35
+ 5. Update main branch and handle merge conflicts
36
+ 6. Create or update PR with comprehensive description
37
+ 7. Monitor for reviewer comments
38
+ 8. Address feedback and push updates
39
+ 9. Always provide PR URL for user review
40
+
41
+ Essential CLI commands:
42
+ - npm test or npm run test (run test suite)
43
+ - npm run build (build project)
44
+ - npm run lint (run linting)
45
+ - npm run format (format code)
46
+ - npm run test:coverage (check coverage)
47
+ - git add <specific-files> && git commit -m "message" && git push (commit and push)
48
+ - git checkout main && git pull origin main (update main)
49
+ - git checkout feature-branch && git merge main (handle conflicts)
50
+ - gh pr create --title "title" --body "body" (create PR)
51
+ - gh pr view --comments (check PR comments)
52
+ - gh pr edit --title "title" --body "body" (update PR)
53
+
54
+ PR Creation Process:
55
+ - Always include clear summary of changes
56
+ - List technical details and improvements
57
+ - Include testing and validation results
58
+ - Add any breaking changes or migration notes
59
+ - Provide PR URL immediately after creation
60
+
61
+ GIT WORKFLOW RULES (CRITICAL - ENFORCE STRICTLY):
62
+ - NEVER push directly to main branch - ALWAYS use pull requests
63
+ - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'
64
+ - ALWAYS clean up test files, documentation files, and temporary artifacts before committing
65
+ - ALWAYS ensure git history maintains production quality - no test commits, no debugging code
66
+ - ALWAYS create descriptive commit messages following project conventions
67
+ - ALWAYS run tests and build before creating PR
68
+
69
+ Always provide specific command examples and wait for processes to complete before proceeding.`,
70
+ };
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agent = void 0;
4
+ exports.agent = {
5
+ config: {
6
+ description: 'Security specialist for pentesting, OWASP compliance, and vulnerability assessments.',
7
+ mode: 'subagent',
8
+ name: 'security',
9
+ permission: {
10
+ bash: 'allow',
11
+ edit: 'deny',
12
+ webfetch: 'allow',
13
+ },
14
+ temperature: 0.2,
15
+ top_p: 0.8,
16
+ },
17
+ systemPrompt: `Voice: Scandinavian calm—precise, concise, confident. You are Berget Code Security agent. Expert in application security, penetration testing, and OWASP standards. Core responsibilities: Conduct security assessments and penetration tests, Validate OWASP Top 10 compliance, Review code for security vulnerabilities, Implement security headers and Content Security Policy (CSP), Audit API security, Check for sensitive data exposure, Validate input sanitization and output encoding, Assess dependency security and supply chain risks. Tools and techniques: OWASP ZAP, Burp Suite, security linters, dependency scanners, manual code review. Always provide specific, actionable security recommendations with priority levels.
18
+
19
+ GIT WORKFLOW RULES (CRITICAL):
20
+ - NEVER push directly to main branch - ALWAYS use pull requests
21
+ - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'
22
+ - ALWAYS clean up test files, documentation files, and temporary artifacts before committing
23
+ - ALWAYS ensure git history maintains production quality - no test commits, no debugging code
24
+ - ALWAYS create descriptive commit messages following project conventions
25
+ - ALWAYS run tests and build before creating PR`,
26
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,31 +1,24 @@
1
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
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
14
5
  Object.defineProperty(exports, "__esModule", { value: true });
15
6
  exports.createAuthenticatedClient = exports.clearAuthToken = exports.saveAuthToken = exports.getAuthToken = exports.apiClient = exports.API_BASE_URL = void 0;
16
- const openapi_fetch_1 = __importDefault(require("openapi-fetch"));
17
7
  const chalk_1 = __importDefault(require("chalk"));
18
- const token_manager_1 = require("./utils/token-manager");
8
+ const openapi_fetch_1 = __importDefault(require("openapi-fetch"));
19
9
  const logger_1 = require("./utils/logger");
10
+ const token_manager_1 = require("./utils/token-manager");
20
11
  // API Base URL
21
12
  // Use --local flag to test against local API
22
13
  // Use --stage flag to test against stage API
23
14
  const isLocalMode = process.argv.includes('--local');
24
15
  const isStageMode = process.argv.includes('--stage');
25
16
  exports.API_BASE_URL = process.env.BERGET_API_URL ||
26
- (isLocalMode ? 'http://localhost:3000' :
27
- isStageMode ? 'https://api.stage.berget.ai' :
28
- 'https://api.berget.ai'); // production default
17
+ (isLocalMode
18
+ ? 'http://localhost:3000'
19
+ : isStageMode
20
+ ? 'https://api.stage.berget.ai'
21
+ : 'https://api.berget.ai'); // production default
29
22
  if (isLocalMode && !process.env.BERGET_API_URL) {
30
23
  logger_1.logger.debug('Using local API endpoint: http://localhost:3000');
31
24
  }
@@ -36,8 +29,8 @@ else if (isStageMode && !process.env.BERGET_API_URL) {
36
29
  exports.apiClient = (0, openapi_fetch_1.default)({
37
30
  baseUrl: exports.API_BASE_URL,
38
31
  headers: {
39
- 'Content-Type': 'application/json',
40
32
  Accept: 'application/json',
33
+ 'Content-Type': 'application/json',
41
34
  },
42
35
  });
43
36
  // Authentication functions
@@ -67,50 +60,44 @@ const createAuthenticatedClient = () => {
67
60
  baseUrl: exports.API_BASE_URL,
68
61
  headers: tokenManager.getAccessToken()
69
62
  ? {
63
+ Accept: 'application/json',
70
64
  Authorization: `Bearer ${tokenManager.getAccessToken()}`,
71
65
  'Content-Type': 'application/json',
72
- Accept: 'application/json',
73
66
  }
74
67
  : {
75
- 'Content-Type': 'application/json',
76
68
  Accept: 'application/json',
69
+ 'Content-Type': 'application/json',
77
70
  },
78
71
  });
79
72
  // Wrap the client to handle token refresh
80
73
  return new Proxy(client, {
81
- get(target, prop) {
74
+ get(target, property) {
82
75
  // For HTTP methods (GET, POST, etc.), add token refresh logic
83
- if (typeof target[prop] === 'function' &&
84
- ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'].includes(String(prop))) {
85
- return (...args) => __awaiter(this, void 0, void 0, function* () {
86
- var _a, _b, _c, _d;
76
+ if (typeof target[property] === 'function' &&
77
+ ['DELETE', 'GET', 'PATCH', 'POST', 'PUT'].includes(String(property))) {
78
+ return async (...arguments_) => {
87
79
  // Check if token is expired before making the request
88
80
  if (tokenManager.isTokenExpired() && tokenManager.getRefreshToken()) {
89
- yield refreshAccessToken(tokenManager);
81
+ await refreshAccessToken(tokenManager);
90
82
  }
91
83
  // Update the Authorization header with the current token
92
- if (!((_b = (_a = args[1]) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b.Authorization) &&
93
- tokenManager.getAccessToken()) {
94
- if (!args[1])
95
- args[1] = {};
96
- if (!args[1].headers)
97
- args[1].headers = {};
98
- args[1].headers.Authorization = `Bearer ${tokenManager.getAccessToken()}`;
84
+ if (!arguments_[1]?.headers?.Authorization && tokenManager.getAccessToken()) {
85
+ if (!arguments_[1])
86
+ arguments_[1] = {};
87
+ if (!arguments_[1].headers)
88
+ arguments_[1].headers = {};
89
+ arguments_[1].headers.Authorization = `Bearer ${tokenManager.getAccessToken()}`;
99
90
  }
100
91
  // Make the original request
101
92
  let result;
102
93
  try {
103
- result = yield target[prop](...args);
94
+ result = await target[property](...arguments_);
104
95
  }
105
96
  catch (requestError) {
106
- logger_1.logger.debug(`Request error: ${requestError instanceof Error
107
- ? requestError.message
108
- : String(requestError)}`);
97
+ logger_1.logger.debug(`Request error: ${requestError instanceof Error ? requestError.message : String(requestError)}`);
109
98
  return {
110
99
  error: {
111
- message: `Request failed: ${requestError instanceof Error
112
- ? requestError.message
113
- : String(requestError)}`,
100
+ message: `Request failed: ${requestError instanceof Error ? requestError.message : String(requestError)}`,
114
101
  },
115
102
  };
116
103
  }
@@ -120,8 +107,7 @@ const createAuthenticatedClient = () => {
120
107
  let isAuthError = false;
121
108
  try {
122
109
  // Standard 401 Unauthorized
123
- if (typeof result.error === 'object' &&
124
- result.error.status === 401) {
110
+ if (typeof result.error === 'object' && result.error.status === 401) {
125
111
  isAuthError = true;
126
112
  }
127
113
  // OAuth specific errors
@@ -129,8 +115,8 @@ const createAuthenticatedClient = () => {
129
115
  (result.error.error.code === 'invalid_token' ||
130
116
  result.error.error.code === 'token_expired' ||
131
117
  result.error.error.message === 'Invalid API key' ||
132
- ((_c = result.error.error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes('token')) ||
133
- ((_d = result.error.error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('unauthorized')))) {
118
+ result.error.error.message?.toLowerCase().includes('token') ||
119
+ result.error.error.message?.toLowerCase().includes('unauthorized'))) {
134
120
  isAuthError = true;
135
121
  }
136
122
  // Message-based detection as fallback
@@ -141,29 +127,29 @@ const createAuthenticatedClient = () => {
141
127
  isAuthError = true;
142
128
  }
143
129
  }
144
- catch (parseError) {
130
+ catch {
145
131
  // If we can't parse the error structure, do a simple string check
146
- const errorStr = String(result.error);
147
- if (errorStr.toLowerCase().includes('unauthorized') ||
148
- errorStr.toLowerCase().includes('token') ||
149
- errorStr.toLowerCase().includes('auth')) {
132
+ const errorString = String(result.error);
133
+ if (errorString.toLowerCase().includes('unauthorized') ||
134
+ errorString.toLowerCase().includes('token') ||
135
+ errorString.toLowerCase().includes('auth')) {
150
136
  isAuthError = true;
151
137
  }
152
138
  }
153
139
  if (isAuthError && tokenManager.getRefreshToken()) {
154
140
  logger_1.logger.debug('Auth error detected, attempting token refresh');
155
141
  logger_1.logger.debug(`Error details: ${JSON.stringify(result.error, null, 2)}`);
156
- const refreshed = yield refreshAccessToken(tokenManager);
142
+ const refreshed = await refreshAccessToken(tokenManager);
157
143
  if (refreshed) {
158
144
  logger_1.logger.debug('Token refreshed successfully, retrying request');
159
145
  // Update the Authorization header with the new token
160
- if (!args[1])
161
- args[1] = {};
162
- if (!args[1].headers)
163
- args[1].headers = {};
164
- args[1].headers.Authorization = `Bearer ${tokenManager.getAccessToken()}`;
146
+ if (!arguments_[1])
147
+ arguments_[1] = {};
148
+ if (!arguments_[1].headers)
149
+ arguments_[1].headers = {};
150
+ arguments_[1].headers.Authorization = `Bearer ${tokenManager.getAccessToken()}`;
165
151
  // Retry the request
166
- return yield target[prop](...args);
152
+ return await target[property](...arguments_);
167
153
  }
168
154
  else {
169
155
  logger_1.logger.debug('Token refresh failed');
@@ -176,87 +162,81 @@ const createAuthenticatedClient = () => {
176
162
  }
177
163
  }
178
164
  return result;
179
- });
165
+ };
180
166
  }
181
167
  // For other properties, just return the original
182
- return target[prop];
168
+ return target[property];
183
169
  },
184
170
  });
185
171
  };
186
172
  exports.createAuthenticatedClient = createAuthenticatedClient;
187
173
  // Keycloak configuration for token refresh (must match auth-service.ts)
188
- const KEYCLOAK_URL = (isStageMode || isLocalMode)
189
- ? 'https://keycloak.stage.berget.ai'
190
- : 'https://keycloak.berget.ai';
174
+ const KEYCLOAK_URL = isStageMode || isLocalMode ? 'https://keycloak.stage.berget.ai' : 'https://keycloak.berget.ai';
191
175
  const KEYCLOAK_REALM = 'berget';
192
176
  const KEYCLOAK_CLIENT_ID = 'berget-code';
193
177
  // Helper function to refresh the access token
194
- function refreshAccessToken(tokenManager) {
195
- return __awaiter(this, void 0, void 0, function* () {
178
+ async function refreshAccessToken(tokenManager) {
179
+ try {
180
+ const refreshToken = tokenManager.getRefreshToken();
181
+ if (!refreshToken)
182
+ return false;
183
+ logger_1.logger.debug('Attempting to refresh access token');
184
+ // Refresh directly against Keycloak (berget-code is a public PKCE client)
196
185
  try {
197
- const refreshToken = tokenManager.getRefreshToken();
198
- if (!refreshToken)
199
- return false;
200
- logger_1.logger.debug('Attempting to refresh access token');
201
- // Refresh directly against Keycloak (berget-code is a public PKCE client)
202
- try {
203
- const response = yield fetch(`${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token`, {
204
- method: 'POST',
205
- headers: {
206
- 'Content-Type': 'application/x-www-form-urlencoded',
207
- },
208
- body: new URLSearchParams({
209
- grant_type: 'refresh_token',
210
- client_id: KEYCLOAK_CLIENT_ID,
211
- refresh_token: refreshToken,
212
- }),
213
- });
214
- // Handle HTTP errors
215
- if (!response.ok) {
216
- logger_1.logger.debug(`Token refresh error: HTTP ${response.status} ${response.statusText}`);
217
- // Check if the refresh token itself is expired or invalid
218
- if (response.status === 401 || response.status === 403) {
219
- console.warn(chalk_1.default.yellow('Your refresh token has expired. Please run `berget auth login` again.'));
220
- // Clear tokens if unauthorized - they're invalid
221
- tokenManager.clearTokens();
222
- }
223
- else {
224
- console.warn(chalk_1.default.yellow(`Failed to refresh token: ${response.status} ${response.statusText}`));
225
- }
226
- return false;
186
+ const response = await fetch(`${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token`, {
187
+ body: new URLSearchParams({
188
+ client_id: KEYCLOAK_CLIENT_ID,
189
+ grant_type: 'refresh_token',
190
+ refresh_token: refreshToken,
191
+ }),
192
+ headers: {
193
+ 'Content-Type': 'application/x-www-form-urlencoded',
194
+ },
195
+ method: 'POST',
196
+ });
197
+ // Handle HTTP errors
198
+ if (!response.ok) {
199
+ logger_1.logger.debug(`Token refresh error: HTTP ${response.status} ${response.statusText}`);
200
+ // Check if the refresh token itself is expired or invalid
201
+ if (response.status === 401 || response.status === 403) {
202
+ console.warn(chalk_1.default.yellow('Your refresh token has expired. Please run `berget auth login` again.'));
203
+ // Clear tokens if unauthorized - they're invalid
204
+ tokenManager.clearTokens();
227
205
  }
228
- // Parse the response
229
- const contentType = response.headers.get('content-type');
230
- if (!contentType || !contentType.includes('application/json')) {
231
- console.warn(chalk_1.default.yellow(`Unexpected content type in response: ${contentType}`));
232
- return false;
233
- }
234
- const data = yield response.json();
235
- // Validate the response data
236
- if (!data || !data.token) {
237
- console.warn(chalk_1.default.yellow('Invalid token response. Please run `berget auth login` again.'));
238
- return false;
239
- }
240
- logger_1.logger.debug('Token refreshed successfully');
241
- // Update the token
242
- tokenManager.updateAccessToken(data.token, data.expires_in || 3600);
243
- // If a new refresh token was provided, update that too
244
- if (data.refresh_token) {
245
- tokenManager.setTokens(data.token, data.refresh_token, data.expires_in || 3600);
246
- logger_1.logger.debug('Refresh token also updated');
206
+ else {
207
+ console.warn(chalk_1.default.yellow(`Failed to refresh token: ${response.status} ${response.statusText}`));
247
208
  }
209
+ return false;
248
210
  }
249
- catch (fetchError) {
250
- console.warn(chalk_1.default.yellow(`Failed to refresh token: ${fetchError instanceof Error
251
- ? fetchError.message
252
- : String(fetchError)}`));
211
+ // Parse the response
212
+ const contentType = response.headers.get('content-type');
213
+ if (!contentType || !contentType.includes('application/json')) {
214
+ console.warn(chalk_1.default.yellow(`Unexpected content type in response: ${contentType}`));
253
215
  return false;
254
216
  }
255
- return true;
217
+ const data = (await response.json());
218
+ // Validate the response data
219
+ if (!data || !data.token) {
220
+ console.warn(chalk_1.default.yellow('Invalid token response. Please run `berget auth login` again.'));
221
+ return false;
222
+ }
223
+ logger_1.logger.debug('Token refreshed successfully');
224
+ // Update the token
225
+ tokenManager.updateAccessToken(data.token, data.expires_in || 3600);
226
+ // If a new refresh token was provided, update that too
227
+ if (data.refresh_token) {
228
+ tokenManager.setTokens(data.token, data.refresh_token, data.expires_in || 3600);
229
+ logger_1.logger.debug('Refresh token also updated');
230
+ }
256
231
  }
257
- catch (error) {
258
- console.warn(chalk_1.default.yellow(`Failed to refresh authentication token: ${error instanceof Error ? error.message : String(error)}`));
232
+ catch (fetchError) {
233
+ console.warn(chalk_1.default.yellow(`Failed to refresh token: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`));
259
234
  return false;
260
235
  }
261
- });
236
+ return true;
237
+ }
238
+ catch (error) {
239
+ console.warn(chalk_1.default.yellow(`Failed to refresh authentication token: ${error instanceof Error ? error.message : String(error)}`));
240
+ return false;
241
+ }
262
242
  }