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.
- package/.github/workflows/publish.yml +6 -6
- package/.github/workflows/test.yml +11 -5
- package/.husky/pre-commit +1 -0
- package/.prettierignore +15 -0
- package/.prettierrc +5 -3
- package/CONTRIBUTING.md +38 -0
- package/README.md +2 -148
- package/dist/index.js +21 -21
- package/dist/package.json +28 -2
- package/dist/src/agents/app.js +28 -0
- package/dist/src/agents/backend.js +25 -0
- package/dist/src/agents/devops.js +34 -0
- package/dist/src/agents/frontend.js +25 -0
- package/dist/src/agents/fullstack.js +25 -0
- package/dist/src/agents/index.js +61 -0
- package/dist/src/agents/quality.js +70 -0
- package/dist/src/agents/security.js +26 -0
- package/dist/src/agents/types.js +2 -0
- package/dist/src/client.js +54 -62
- package/dist/src/commands/api-keys.js +132 -140
- package/dist/src/commands/auth.js +9 -9
- package/dist/src/commands/autocomplete.js +9 -9
- package/dist/src/commands/billing.js +7 -9
- package/dist/src/commands/chat.js +90 -92
- package/dist/src/commands/clusters.js +12 -12
- package/dist/src/commands/code/__tests__/auth-sync.test.js +348 -0
- package/dist/src/commands/code/__tests__/fake-api-key-service.js +23 -0
- package/dist/src/commands/code/__tests__/fake-auth-service.js +55 -0
- package/dist/src/commands/code/__tests__/fake-command-runner.js +5 -7
- package/dist/src/commands/code/__tests__/fake-file-store.js +9 -0
- package/dist/src/commands/code/__tests__/fake-prompter.js +60 -18
- package/dist/src/commands/code/__tests__/setup-flow.test.js +374 -107
- package/dist/src/commands/code/adapters/clack-prompter.js +10 -0
- package/dist/src/commands/code/adapters/fs-file-store.js +8 -3
- package/dist/src/commands/code/adapters/spawn-command-runner.js +15 -11
- package/dist/src/commands/code/auth-sync.js +283 -0
- package/dist/src/commands/code/errors.js +4 -4
- package/dist/src/commands/code/ports/auth-services.js +2 -0
- package/dist/src/commands/code/setup.js +234 -93
- package/dist/src/commands/code.js +139 -251
- package/dist/src/commands/models.js +13 -15
- package/dist/src/commands/users.js +6 -8
- package/dist/src/constants/command-structure.js +116 -116
- package/dist/src/services/api-key-service.js +43 -48
- package/dist/src/services/auth-service.js +60 -299
- package/dist/src/services/browser-auth.js +278 -0
- package/dist/src/services/chat-service.js +78 -91
- package/dist/src/services/cluster-service.js +6 -6
- package/dist/src/services/collaborator-service.js +5 -8
- package/dist/src/services/flux-service.js +5 -8
- package/dist/src/services/helm-service.js +5 -8
- package/dist/src/services/kubectl-service.js +7 -10
- package/dist/src/utils/config-checker.js +5 -5
- package/dist/src/utils/config-loader.js +25 -25
- package/dist/src/utils/default-api-key.js +23 -23
- package/dist/src/utils/env-manager.js +7 -7
- package/dist/src/utils/error-handler.js +60 -61
- package/dist/src/utils/logger.js +7 -7
- package/dist/src/utils/markdown-renderer.js +2 -2
- package/dist/src/utils/opencode-validator.js +17 -20
- package/dist/src/utils/token-manager.js +38 -11
- package/dist/tests/commands/chat.test.js +24 -24
- package/dist/tests/commands/code.test.js +147 -147
- package/dist/tests/utils/config-loader.test.js +114 -114
- package/dist/tests/utils/env-manager.test.js +57 -57
- package/dist/tests/utils/opencode-validator.test.js +33 -33
- package/dist/vitest.config.js +1 -1
- package/eslint.config.mjs +47 -0
- package/index.ts +42 -48
- package/package.json +28 -2
- package/src/agents/app.ts +27 -0
- package/src/agents/backend.ts +24 -0
- package/src/agents/devops.ts +33 -0
- package/src/agents/frontend.ts +24 -0
- package/src/agents/fullstack.ts +24 -0
- package/src/agents/index.ts +71 -0
- package/src/agents/quality.ts +69 -0
- package/src/agents/security.ts +26 -0
- package/src/agents/types.ts +17 -0
- package/src/client.ts +125 -167
- package/src/commands/api-keys.ts +261 -358
- package/src/commands/auth.ts +24 -30
- package/src/commands/autocomplete.ts +12 -12
- package/src/commands/billing.ts +22 -27
- package/src/commands/chat.ts +230 -323
- package/src/commands/clusters.ts +33 -33
- package/src/commands/code/__tests__/auth-sync.test.ts +481 -0
- package/src/commands/code/__tests__/fake-api-key-service.ts +13 -0
- package/src/commands/code/__tests__/fake-auth-service.ts +50 -0
- package/src/commands/code/__tests__/fake-command-runner.ts +39 -42
- package/src/commands/code/__tests__/fake-file-store.ts +32 -23
- package/src/commands/code/__tests__/fake-prompter.ts +107 -69
- package/src/commands/code/__tests__/setup-flow.test.ts +624 -270
- package/src/commands/code/adapters/clack-prompter.ts +50 -38
- package/src/commands/code/adapters/fs-file-store.ts +31 -27
- package/src/commands/code/adapters/spawn-command-runner.ts +33 -29
- package/src/commands/code/auth-sync.ts +329 -0
- package/src/commands/code/errors.ts +15 -15
- package/src/commands/code/ports/auth-services.ts +14 -0
- package/src/commands/code/ports/command-runner.ts +8 -4
- package/src/commands/code/ports/file-store.ts +5 -4
- package/src/commands/code/ports/prompter.ts +24 -18
- package/src/commands/code/setup.ts +545 -317
- package/src/commands/code.ts +271 -473
- package/src/commands/index.ts +19 -19
- package/src/commands/models.ts +32 -37
- package/src/commands/users.ts +15 -22
- package/src/constants/command-structure.ts +119 -142
- package/src/services/api-key-service.ts +96 -113
- package/src/services/auth-service.ts +92 -339
- package/src/services/browser-auth.ts +296 -0
- package/src/services/chat-service.ts +246 -279
- package/src/services/cluster-service.ts +29 -32
- package/src/services/collaborator-service.ts +13 -18
- package/src/services/flux-service.ts +16 -18
- package/src/services/helm-service.ts +16 -18
- package/src/services/kubectl-service.ts +12 -14
- package/src/types/api.d.ts +924 -926
- package/src/types/json.d.ts +3 -3
- package/src/utils/config-checker.ts +10 -10
- package/src/utils/config-loader.ts +110 -127
- package/src/utils/default-api-key.ts +81 -93
- package/src/utils/env-manager.ts +36 -40
- package/src/utils/error-handler.ts +83 -78
- package/src/utils/logger.ts +41 -41
- package/src/utils/markdown-renderer.ts +11 -11
- package/src/utils/opencode-validator.ts +51 -56
- package/src/utils/token-manager.ts +84 -64
- package/templates/agents/app.md +1 -0
- package/templates/agents/backend.md +1 -0
- package/templates/agents/devops.md +2 -0
- package/templates/agents/frontend.md +1 -0
- package/templates/agents/fullstack.md +1 -0
- package/templates/agents/quality.md +45 -40
- package/templates/agents/security.md +1 -0
- package/tests/commands/chat.test.ts +60 -70
- package/tests/commands/code.test.ts +330 -376
- package/tests/utils/config-loader.test.ts +260 -260
- package/tests/utils/env-manager.test.ts +127 -134
- package/tests/utils/opencode-validator.test.ts +58 -63
- package/tsconfig.json +2 -2
- package/vitest.config.ts +3 -3
- package/AGENTS.md +0 -374
- 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
|
+
name: "quality",
|
|
7
|
+
description: "Quality assurance specialist for testing, building, and complete PR management.",
|
|
8
|
+
mode: "subagent",
|
|
9
|
+
temperature: 0.1,
|
|
10
|
+
top_p: 0.9,
|
|
11
|
+
permission: {
|
|
12
|
+
edit: "allow",
|
|
13
|
+
bash: "allow",
|
|
14
|
+
webfetch: "allow",
|
|
15
|
+
},
|
|
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
|
+
name: "security",
|
|
7
|
+
description: "Security specialist for pentesting, OWASP compliance, and vulnerability assessments.",
|
|
8
|
+
mode: "subagent",
|
|
9
|
+
temperature: 0.2,
|
|
10
|
+
top_p: 0.8,
|
|
11
|
+
permission: {
|
|
12
|
+
edit: "deny",
|
|
13
|
+
bash: "allow",
|
|
14
|
+
webfetch: "allow",
|
|
15
|
+
},
|
|
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
|
+
};
|
package/dist/src/client.js
CHANGED
|
@@ -20,24 +20,26 @@ const logger_1 = require("./utils/logger");
|
|
|
20
20
|
// API Base URL
|
|
21
21
|
// Use --local flag to test against local API
|
|
22
22
|
// Use --stage flag to test against stage API
|
|
23
|
-
const isLocalMode = process.argv.includes(
|
|
24
|
-
const isStageMode = process.argv.includes(
|
|
23
|
+
const isLocalMode = process.argv.includes("--local");
|
|
24
|
+
const isStageMode = process.argv.includes("--stage");
|
|
25
25
|
exports.API_BASE_URL = process.env.BERGET_API_URL ||
|
|
26
|
-
(isLocalMode
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
(isLocalMode
|
|
27
|
+
? "http://localhost:3000"
|
|
28
|
+
: isStageMode
|
|
29
|
+
? "https://api.stage.berget.ai"
|
|
30
|
+
: "https://api.berget.ai"); // production default
|
|
29
31
|
if (isLocalMode && !process.env.BERGET_API_URL) {
|
|
30
|
-
logger_1.logger.debug(
|
|
32
|
+
logger_1.logger.debug("Using local API endpoint: http://localhost:3000");
|
|
31
33
|
}
|
|
32
34
|
else if (isStageMode && !process.env.BERGET_API_URL) {
|
|
33
|
-
logger_1.logger.debug(
|
|
35
|
+
logger_1.logger.debug("Using stage API endpoint: https://api.stage.berget.ai");
|
|
34
36
|
}
|
|
35
37
|
// Create a typed client for the Berget API
|
|
36
38
|
exports.apiClient = (0, openapi_fetch_1.default)({
|
|
37
39
|
baseUrl: exports.API_BASE_URL,
|
|
38
40
|
headers: {
|
|
39
|
-
|
|
40
|
-
Accept:
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
Accept: "application/json",
|
|
41
43
|
},
|
|
42
44
|
});
|
|
43
45
|
// Authentication functions
|
|
@@ -60,7 +62,7 @@ exports.clearAuthToken = clearAuthToken;
|
|
|
60
62
|
const createAuthenticatedClient = () => {
|
|
61
63
|
const tokenManager = token_manager_1.TokenManager.getInstance();
|
|
62
64
|
if (!tokenManager.getAccessToken()) {
|
|
63
|
-
logger_1.logger.debug(
|
|
65
|
+
logger_1.logger.debug("No authentication token found. Please run `berget auth login` first.");
|
|
64
66
|
}
|
|
65
67
|
// Create the base client
|
|
66
68
|
const client = (0, openapi_fetch_1.default)({
|
|
@@ -68,20 +70,20 @@ const createAuthenticatedClient = () => {
|
|
|
68
70
|
headers: tokenManager.getAccessToken()
|
|
69
71
|
? {
|
|
70
72
|
Authorization: `Bearer ${tokenManager.getAccessToken()}`,
|
|
71
|
-
|
|
72
|
-
Accept:
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Accept: "application/json",
|
|
73
75
|
}
|
|
74
76
|
: {
|
|
75
|
-
|
|
76
|
-
Accept:
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
Accept: "application/json",
|
|
77
79
|
},
|
|
78
80
|
});
|
|
79
81
|
// Wrap the client to handle token refresh
|
|
80
82
|
return new Proxy(client, {
|
|
81
83
|
get(target, prop) {
|
|
82
84
|
// For HTTP methods (GET, POST, etc.), add token refresh logic
|
|
83
|
-
if (typeof target[prop] ===
|
|
84
|
-
[
|
|
85
|
+
if (typeof target[prop] === "function" &&
|
|
86
|
+
["GET", "POST", "PUT", "DELETE", "PATCH"].includes(String(prop))) {
|
|
85
87
|
return (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
86
88
|
var _a, _b, _c, _d;
|
|
87
89
|
// Check if token is expired before making the request
|
|
@@ -89,8 +91,7 @@ const createAuthenticatedClient = () => {
|
|
|
89
91
|
yield refreshAccessToken(tokenManager);
|
|
90
92
|
}
|
|
91
93
|
// 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 (!((_b = (_a = args[1]) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b.Authorization) && tokenManager.getAccessToken()) {
|
|
94
95
|
if (!args[1])
|
|
95
96
|
args[1] = {};
|
|
96
97
|
if (!args[1].headers)
|
|
@@ -103,14 +104,10 @@ const createAuthenticatedClient = () => {
|
|
|
103
104
|
result = yield target[prop](...args);
|
|
104
105
|
}
|
|
105
106
|
catch (requestError) {
|
|
106
|
-
logger_1.logger.debug(`Request error: ${requestError instanceof Error
|
|
107
|
-
? requestError.message
|
|
108
|
-
: String(requestError)}`);
|
|
107
|
+
logger_1.logger.debug(`Request error: ${requestError instanceof Error ? requestError.message : String(requestError)}`);
|
|
109
108
|
return {
|
|
110
109
|
error: {
|
|
111
|
-
message: `Request failed: ${requestError instanceof Error
|
|
112
|
-
? requestError.message
|
|
113
|
-
: String(requestError)}`,
|
|
110
|
+
message: `Request failed: ${requestError instanceof Error ? requestError.message : String(requestError)}`,
|
|
114
111
|
},
|
|
115
112
|
};
|
|
116
113
|
}
|
|
@@ -120,42 +117,41 @@ const createAuthenticatedClient = () => {
|
|
|
120
117
|
let isAuthError = false;
|
|
121
118
|
try {
|
|
122
119
|
// Standard 401 Unauthorized
|
|
123
|
-
if (typeof result.error ===
|
|
124
|
-
result.error.status === 401) {
|
|
120
|
+
if (typeof result.error === "object" && result.error.status === 401) {
|
|
125
121
|
isAuthError = true;
|
|
126
122
|
}
|
|
127
123
|
// OAuth specific errors
|
|
128
124
|
else if (result.error.error &&
|
|
129
|
-
(result.error.error.code ===
|
|
130
|
-
result.error.error.code ===
|
|
131
|
-
result.error.error.message ===
|
|
132
|
-
((_c = result.error.error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes(
|
|
133
|
-
((_d = result.error.error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes(
|
|
125
|
+
(result.error.error.code === "invalid_token" ||
|
|
126
|
+
result.error.error.code === "token_expired" ||
|
|
127
|
+
result.error.error.message === "Invalid API key" ||
|
|
128
|
+
((_c = result.error.error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes("token")) ||
|
|
129
|
+
((_d = result.error.error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes("unauthorized")))) {
|
|
134
130
|
isAuthError = true;
|
|
135
131
|
}
|
|
136
132
|
// Message-based detection as fallback
|
|
137
|
-
else if (typeof result.error ===
|
|
138
|
-
(result.error.toLowerCase().includes(
|
|
139
|
-
result.error.toLowerCase().includes(
|
|
140
|
-
result.error.toLowerCase().includes(
|
|
133
|
+
else if (typeof result.error === "string" &&
|
|
134
|
+
(result.error.toLowerCase().includes("unauthorized") ||
|
|
135
|
+
result.error.toLowerCase().includes("token") ||
|
|
136
|
+
result.error.toLowerCase().includes("auth"))) {
|
|
141
137
|
isAuthError = true;
|
|
142
138
|
}
|
|
143
139
|
}
|
|
144
|
-
catch (
|
|
140
|
+
catch (_e) {
|
|
145
141
|
// If we can't parse the error structure, do a simple string check
|
|
146
142
|
const errorStr = String(result.error);
|
|
147
|
-
if (errorStr.toLowerCase().includes(
|
|
148
|
-
errorStr.toLowerCase().includes(
|
|
149
|
-
errorStr.toLowerCase().includes(
|
|
143
|
+
if (errorStr.toLowerCase().includes("unauthorized") ||
|
|
144
|
+
errorStr.toLowerCase().includes("token") ||
|
|
145
|
+
errorStr.toLowerCase().includes("auth")) {
|
|
150
146
|
isAuthError = true;
|
|
151
147
|
}
|
|
152
148
|
}
|
|
153
149
|
if (isAuthError && tokenManager.getRefreshToken()) {
|
|
154
|
-
logger_1.logger.debug(
|
|
150
|
+
logger_1.logger.debug("Auth error detected, attempting token refresh");
|
|
155
151
|
logger_1.logger.debug(`Error details: ${JSON.stringify(result.error, null, 2)}`);
|
|
156
152
|
const refreshed = yield refreshAccessToken(tokenManager);
|
|
157
153
|
if (refreshed) {
|
|
158
|
-
logger_1.logger.debug(
|
|
154
|
+
logger_1.logger.debug("Token refreshed successfully, retrying request");
|
|
159
155
|
// Update the Authorization header with the new token
|
|
160
156
|
if (!args[1])
|
|
161
157
|
args[1] = {};
|
|
@@ -166,11 +162,11 @@ const createAuthenticatedClient = () => {
|
|
|
166
162
|
return yield target[prop](...args);
|
|
167
163
|
}
|
|
168
164
|
else {
|
|
169
|
-
logger_1.logger.debug(
|
|
165
|
+
logger_1.logger.debug("Token refresh failed");
|
|
170
166
|
// Add a more helpful error message for users
|
|
171
|
-
if (typeof result.error ===
|
|
167
|
+
if (typeof result.error === "object") {
|
|
172
168
|
result.error.userMessage =
|
|
173
|
-
|
|
169
|
+
"Your session has expired. Please run `berget auth login` to log in again.";
|
|
174
170
|
}
|
|
175
171
|
}
|
|
176
172
|
}
|
|
@@ -185,11 +181,9 @@ const createAuthenticatedClient = () => {
|
|
|
185
181
|
};
|
|
186
182
|
exports.createAuthenticatedClient = createAuthenticatedClient;
|
|
187
183
|
// Keycloak configuration for token refresh (must match auth-service.ts)
|
|
188
|
-
const KEYCLOAK_URL =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const KEYCLOAK_REALM = 'berget';
|
|
192
|
-
const KEYCLOAK_CLIENT_ID = 'berget-code';
|
|
184
|
+
const KEYCLOAK_URL = isStageMode || isLocalMode ? "https://keycloak.stage.berget.ai" : "https://keycloak.berget.ai";
|
|
185
|
+
const KEYCLOAK_REALM = "berget";
|
|
186
|
+
const KEYCLOAK_CLIENT_ID = "berget-code";
|
|
193
187
|
// Helper function to refresh the access token
|
|
194
188
|
function refreshAccessToken(tokenManager) {
|
|
195
189
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -197,16 +191,16 @@ function refreshAccessToken(tokenManager) {
|
|
|
197
191
|
const refreshToken = tokenManager.getRefreshToken();
|
|
198
192
|
if (!refreshToken)
|
|
199
193
|
return false;
|
|
200
|
-
logger_1.logger.debug(
|
|
194
|
+
logger_1.logger.debug("Attempting to refresh access token");
|
|
201
195
|
// Refresh directly against Keycloak (berget-code is a public PKCE client)
|
|
202
196
|
try {
|
|
203
197
|
const response = yield fetch(`${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token`, {
|
|
204
|
-
method:
|
|
198
|
+
method: "POST",
|
|
205
199
|
headers: {
|
|
206
|
-
|
|
200
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
207
201
|
},
|
|
208
202
|
body: new URLSearchParams({
|
|
209
|
-
grant_type:
|
|
203
|
+
grant_type: "refresh_token",
|
|
210
204
|
client_id: KEYCLOAK_CLIENT_ID,
|
|
211
205
|
refresh_token: refreshToken,
|
|
212
206
|
}),
|
|
@@ -216,7 +210,7 @@ function refreshAccessToken(tokenManager) {
|
|
|
216
210
|
logger_1.logger.debug(`Token refresh error: HTTP ${response.status} ${response.statusText}`);
|
|
217
211
|
// Check if the refresh token itself is expired or invalid
|
|
218
212
|
if (response.status === 401 || response.status === 403) {
|
|
219
|
-
console.warn(chalk_1.default.yellow(
|
|
213
|
+
console.warn(chalk_1.default.yellow("Your refresh token has expired. Please run `berget auth login` again."));
|
|
220
214
|
// Clear tokens if unauthorized - they're invalid
|
|
221
215
|
tokenManager.clearTokens();
|
|
222
216
|
}
|
|
@@ -226,30 +220,28 @@ function refreshAccessToken(tokenManager) {
|
|
|
226
220
|
return false;
|
|
227
221
|
}
|
|
228
222
|
// Parse the response
|
|
229
|
-
const contentType = response.headers.get(
|
|
230
|
-
if (!contentType || !contentType.includes(
|
|
223
|
+
const contentType = response.headers.get("content-type");
|
|
224
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
231
225
|
console.warn(chalk_1.default.yellow(`Unexpected content type in response: ${contentType}`));
|
|
232
226
|
return false;
|
|
233
227
|
}
|
|
234
228
|
const data = yield response.json();
|
|
235
229
|
// Validate the response data
|
|
236
230
|
if (!data || !data.token) {
|
|
237
|
-
console.warn(chalk_1.default.yellow(
|
|
231
|
+
console.warn(chalk_1.default.yellow("Invalid token response. Please run `berget auth login` again."));
|
|
238
232
|
return false;
|
|
239
233
|
}
|
|
240
|
-
logger_1.logger.debug(
|
|
234
|
+
logger_1.logger.debug("Token refreshed successfully");
|
|
241
235
|
// Update the token
|
|
242
236
|
tokenManager.updateAccessToken(data.token, data.expires_in || 3600);
|
|
243
237
|
// If a new refresh token was provided, update that too
|
|
244
238
|
if (data.refresh_token) {
|
|
245
239
|
tokenManager.setTokens(data.token, data.refresh_token, data.expires_in || 3600);
|
|
246
|
-
logger_1.logger.debug(
|
|
240
|
+
logger_1.logger.debug("Refresh token also updated");
|
|
247
241
|
}
|
|
248
242
|
}
|
|
249
243
|
catch (fetchError) {
|
|
250
|
-
console.warn(chalk_1.default.yellow(`Failed to refresh token: ${fetchError instanceof Error
|
|
251
|
-
? fetchError.message
|
|
252
|
-
: String(fetchError)}`));
|
|
244
|
+
console.warn(chalk_1.default.yellow(`Failed to refresh token: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`));
|
|
253
245
|
return false;
|
|
254
246
|
}
|
|
255
247
|
return true;
|