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
|
@@ -1,146 +1,151 @@
|
|
|
1
|
-
import chalk from
|
|
1
|
+
import chalk from "chalk";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Formats and prints error messages in a consistent way
|
|
5
5
|
*/
|
|
6
6
|
export function handleError(message: string, error: any): void {
|
|
7
|
-
console.error(chalk.red(`❌ Error: ${message}`))
|
|
7
|
+
console.error(chalk.red(`❌ Error: ${message}`));
|
|
8
8
|
|
|
9
|
-
let errorDetails =
|
|
10
|
-
let errorCode =
|
|
11
|
-
let errorType =
|
|
9
|
+
let errorDetails = "";
|
|
10
|
+
let errorCode = "";
|
|
11
|
+
let errorType = "";
|
|
12
12
|
|
|
13
13
|
// If the error is a string (like JSON.stringify(error))
|
|
14
|
-
if (typeof error ===
|
|
14
|
+
if (typeof error === "string") {
|
|
15
15
|
try {
|
|
16
16
|
// Try to parse it as JSON
|
|
17
|
-
const parsedError = JSON.parse(error)
|
|
17
|
+
const parsedError = JSON.parse(error);
|
|
18
18
|
if (parsedError.error) {
|
|
19
|
-
errorDetails = parsedError.error.message || parsedError.error
|
|
20
|
-
errorCode = parsedError.error.code || parsedError.code
|
|
21
|
-
errorType = parsedError.error.type ||
|
|
19
|
+
errorDetails = parsedError.error.message || parsedError.error;
|
|
20
|
+
errorCode = parsedError.error.code || parsedError.code;
|
|
21
|
+
errorType = parsedError.error.type || "";
|
|
22
22
|
} else {
|
|
23
|
-
errorDetails = error
|
|
23
|
+
errorDetails = error;
|
|
24
24
|
}
|
|
25
25
|
} catch {
|
|
26
26
|
// If it's not valid JSON, just print the string
|
|
27
|
-
errorDetails = error
|
|
27
|
+
errorDetails = error;
|
|
28
28
|
}
|
|
29
29
|
} else if (error && error.message) {
|
|
30
30
|
// If it's an Error object
|
|
31
|
-
errorDetails = error.message
|
|
32
|
-
errorCode = error.code
|
|
33
|
-
errorType = error.type
|
|
31
|
+
errorDetails = error.message;
|
|
32
|
+
errorCode = error.code;
|
|
33
|
+
errorType = error.type;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// Print error details
|
|
37
37
|
if (errorDetails) {
|
|
38
|
-
console.error(chalk.dim(`📝 Details: ${errorDetails}`))
|
|
38
|
+
console.error(chalk.dim(`📝 Details: ${errorDetails}`));
|
|
39
39
|
}
|
|
40
40
|
if (errorCode) {
|
|
41
|
-
console.error(chalk.dim(`🔢 Code: ${errorCode}`))
|
|
41
|
+
console.error(chalk.dim(`🔢 Code: ${errorCode}`));
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// Provide helpful troubleshooting based on error type
|
|
45
|
-
provideTroubleshootingTips(errorType, errorCode, errorDetails)
|
|
45
|
+
provideTroubleshootingTips(errorType, errorCode, errorDetails);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Provides helpful troubleshooting tips based on error type
|
|
50
50
|
*/
|
|
51
|
-
function provideTroubleshootingTips(
|
|
52
|
-
|
|
51
|
+
function provideTroubleshootingTips(
|
|
52
|
+
errorType: string,
|
|
53
|
+
errorCode: string,
|
|
54
|
+
errorDetails: string
|
|
55
|
+
): void {
|
|
56
|
+
console.error(chalk.blue("\n💡 Troubleshooting tips:"));
|
|
53
57
|
|
|
54
58
|
// Authentication errors
|
|
55
59
|
if (
|
|
56
|
-
errorType ===
|
|
57
|
-
errorCode ===
|
|
58
|
-
errorDetails?.includes(
|
|
59
|
-
errorDetails?.includes(
|
|
60
|
+
errorType === "authentication_error" ||
|
|
61
|
+
errorCode === "AUTH_FAILED" ||
|
|
62
|
+
errorDetails?.includes("Unauthorized") ||
|
|
63
|
+
errorDetails?.includes("Authentication failed")
|
|
60
64
|
) {
|
|
61
|
-
console.error(chalk.yellow(
|
|
62
|
-
console.error(chalk.white(
|
|
63
|
-
console.error(chalk.white(
|
|
64
|
-
console.error(chalk.white(
|
|
65
|
+
console.error(chalk.yellow(" 🔐 Authentication issue detected:"));
|
|
66
|
+
console.error(chalk.white(" • Run `berget auth login` to log in"));
|
|
67
|
+
console.error(chalk.white(" • Check if your session has expired"));
|
|
68
|
+
console.error(chalk.white(" • Verify you have the correct permissions"));
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
// Network/connection errors
|
|
68
72
|
if (
|
|
69
|
-
errorDetails?.includes(
|
|
70
|
-
errorDetails?.includes(
|
|
71
|
-
errorDetails?.includes(
|
|
72
|
-
errorDetails?.includes(
|
|
73
|
+
errorDetails?.includes("fetch failed") ||
|
|
74
|
+
errorDetails?.includes("ECONNREFUSED") ||
|
|
75
|
+
errorDetails?.includes("ENOTFOUND") ||
|
|
76
|
+
errorDetails?.includes("network")
|
|
73
77
|
) {
|
|
74
|
-
console.error(chalk.yellow(
|
|
75
|
-
console.error(chalk.white(
|
|
76
|
-
console.error(chalk.white(
|
|
77
|
-
console.error(chalk.white(
|
|
78
|
-
console.error(chalk.white(
|
|
78
|
+
console.error(chalk.yellow(" 🌐 Network issue detected:"));
|
|
79
|
+
console.error(chalk.white(" • Check your internet connection"));
|
|
80
|
+
console.error(chalk.white(" • Verify you can reach api.berget.ai"));
|
|
81
|
+
console.error(chalk.white(" • Try again in a few minutes"));
|
|
82
|
+
console.error(chalk.white(" • Check if any firewall is blocking the request"));
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
// API key errors
|
|
82
86
|
if (
|
|
83
|
-
errorCode?.includes(
|
|
84
|
-
errorDetails?.includes(
|
|
85
|
-
errorType ===
|
|
87
|
+
errorCode?.includes("API_KEY") ||
|
|
88
|
+
errorDetails?.includes("API key") ||
|
|
89
|
+
errorType === "invalid_request_error"
|
|
86
90
|
) {
|
|
87
|
-
console.error(chalk.yellow(
|
|
88
|
-
console.error(chalk.white(
|
|
89
|
-
console.error(
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
console.error(chalk.yellow(" 🔑 API key issue detected:"));
|
|
92
|
+
console.error(chalk.white(" • Run `berget api-keys list` to check your keys"));
|
|
93
|
+
console.error(
|
|
94
|
+
chalk.white(' • Create a new key with `berget api-keys create --name "My Key"`')
|
|
95
|
+
);
|
|
96
|
+
console.error(chalk.white(" • Set a default key with `berget api-keys set-default <id>`"));
|
|
97
|
+
console.error(chalk.white(" • Check if your API key has expired"));
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
// Rate limiting
|
|
95
101
|
if (
|
|
96
|
-
errorCode ===
|
|
97
|
-
errorDetails?.includes(
|
|
98
|
-
errorDetails?.includes(
|
|
102
|
+
errorCode === "RATE_LIMIT_EXCEEDED" ||
|
|
103
|
+
errorDetails?.includes("rate limit") ||
|
|
104
|
+
errorDetails?.includes("too many requests")
|
|
99
105
|
) {
|
|
100
|
-
console.error(chalk.yellow(
|
|
101
|
-
console.error(chalk.white(
|
|
102
|
-
console.error(chalk.white(
|
|
103
|
-
console.error(chalk.white(
|
|
106
|
+
console.error(chalk.yellow(" ⏱️ Rate limit exceeded:"));
|
|
107
|
+
console.error(chalk.white(" • Wait a few minutes before trying again"));
|
|
108
|
+
console.error(chalk.white(" • Consider upgrading your plan for higher limits"));
|
|
109
|
+
console.error(chalk.white(" • Use `berget billing get-usage` to check your usage"));
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
// Server errors
|
|
107
113
|
if (
|
|
108
|
-
errorCode?.includes(
|
|
109
|
-
errorType ===
|
|
114
|
+
errorCode?.includes("SERVER_ERROR") ||
|
|
115
|
+
errorType === "server_error" ||
|
|
110
116
|
(errorCode && parseInt(errorCode) >= 500)
|
|
111
117
|
) {
|
|
112
|
-
console.error(chalk.yellow(
|
|
113
|
-
console.error(chalk.white(
|
|
114
|
-
console.error(chalk.white(
|
|
115
|
-
console.error(chalk.white(
|
|
116
|
-
console.error(chalk.white(
|
|
118
|
+
console.error(chalk.yellow(" 🖥️ Server issue detected:"));
|
|
119
|
+
console.error(chalk.white(" • This is a temporary problem on our end"));
|
|
120
|
+
console.error(chalk.white(" • Try again in a few minutes"));
|
|
121
|
+
console.error(chalk.white(" • Check status.berget.ai for service status"));
|
|
122
|
+
console.error(chalk.white(" • Contact support if the problem persists"));
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
// Cluster errors
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
console.error(chalk.
|
|
125
|
-
console.error(chalk.white(' • Clusters may be temporarily unavailable'))
|
|
126
|
-
console.error(chalk.white(' • Try again later or contact support'))
|
|
127
|
-
console.error(chalk.white(' • Check your cluster permissions'))
|
|
126
|
+
if (errorCode?.includes("CLUSTERS") || errorDetails?.includes("cluster")) {
|
|
127
|
+
console.error(chalk.yellow(" 🏗️ Cluster issue detected:"));
|
|
128
|
+
console.error(chalk.white(" • Clusters may be temporarily unavailable"));
|
|
129
|
+
console.error(chalk.white(" • Try again later or contact support"));
|
|
130
|
+
console.error(chalk.white(" • Check your cluster permissions"));
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
// Generic fallback
|
|
131
134
|
if (
|
|
132
|
-
!errorType?.includes(
|
|
133
|
-
!errorDetails?.includes(
|
|
134
|
-
!errorCode?.includes(
|
|
135
|
-
!errorCode?.includes(
|
|
136
|
-
!errorCode?.includes(
|
|
137
|
-
!errorCode?.includes(
|
|
135
|
+
!errorType?.includes("authentication") &&
|
|
136
|
+
!errorDetails?.includes("fetch failed") &&
|
|
137
|
+
!errorCode?.includes("API_KEY") &&
|
|
138
|
+
!errorCode?.includes("RATE_LIMIT") &&
|
|
139
|
+
!errorCode?.includes("SERVER_ERROR") &&
|
|
140
|
+
!errorCode?.includes("CLUSTERS")
|
|
138
141
|
) {
|
|
139
|
-
console.error(chalk.yellow(
|
|
140
|
-
console.error(chalk.white(
|
|
141
|
-
console.error(chalk.white(
|
|
142
|
-
console.error(chalk.white(
|
|
142
|
+
console.error(chalk.yellow(" ❓ General issue:"));
|
|
143
|
+
console.error(chalk.white(" • Try running the command with --debug for more info"));
|
|
144
|
+
console.error(chalk.white(" • Check your configuration with `berget auth whoami`"));
|
|
145
|
+
console.error(chalk.white(" • Contact support if the problem persists"));
|
|
143
146
|
}
|
|
144
147
|
|
|
145
|
-
console.error(
|
|
148
|
+
console.error(
|
|
149
|
+
chalk.dim("\nNeed more help? Visit https://docs.berget.ai or contact support@berget.ai")
|
|
150
|
+
);
|
|
146
151
|
}
|
package/src/utils/logger.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import chalk from
|
|
1
|
+
import chalk from "chalk";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Log levels in order of increasing verbosity
|
|
@@ -15,25 +15,25 @@ export enum LogLevel {
|
|
|
15
15
|
* Logger class for centralized logging with configurable log levels
|
|
16
16
|
*/
|
|
17
17
|
export class Logger {
|
|
18
|
-
private static instance: Logger
|
|
19
|
-
private logLevel: LogLevel = LogLevel.INFO // Default log level
|
|
18
|
+
private static instance: Logger;
|
|
19
|
+
private logLevel: LogLevel = LogLevel.INFO; // Default log level
|
|
20
20
|
|
|
21
21
|
private constructor() {
|
|
22
22
|
// Set log level from environment variable or command line argument
|
|
23
23
|
if (process.env.LOG_LEVEL) {
|
|
24
|
-
this.setLogLevelFromString(process.env.LOG_LEVEL)
|
|
25
|
-
} else if (process.argv.includes(
|
|
26
|
-
this.logLevel = LogLevel.DEBUG
|
|
27
|
-
} else if (process.argv.includes(
|
|
28
|
-
this.logLevel = LogLevel.ERROR
|
|
24
|
+
this.setLogLevelFromString(process.env.LOG_LEVEL);
|
|
25
|
+
} else if (process.argv.includes("--debug")) {
|
|
26
|
+
this.logLevel = LogLevel.DEBUG;
|
|
27
|
+
} else if (process.argv.includes("--quiet")) {
|
|
28
|
+
this.logLevel = LogLevel.ERROR;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
public static getInstance(): Logger {
|
|
33
33
|
if (!Logger.instance) {
|
|
34
|
-
Logger.instance = new Logger()
|
|
34
|
+
Logger.instance = new Logger();
|
|
35
35
|
}
|
|
36
|
-
return Logger.instance
|
|
36
|
+
return Logger.instance;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -41,24 +41,24 @@ export class Logger {
|
|
|
41
41
|
*/
|
|
42
42
|
private setLogLevelFromString(level: string): void {
|
|
43
43
|
switch (level.toLowerCase()) {
|
|
44
|
-
case
|
|
45
|
-
this.logLevel = LogLevel.NONE
|
|
46
|
-
break
|
|
47
|
-
case
|
|
48
|
-
this.logLevel = LogLevel.ERROR
|
|
49
|
-
break
|
|
50
|
-
case
|
|
51
|
-
this.logLevel = LogLevel.WARN
|
|
52
|
-
break
|
|
53
|
-
case
|
|
54
|
-
this.logLevel = LogLevel.INFO
|
|
55
|
-
break
|
|
56
|
-
case
|
|
57
|
-
this.logLevel = LogLevel.DEBUG
|
|
58
|
-
break
|
|
44
|
+
case "none":
|
|
45
|
+
this.logLevel = LogLevel.NONE;
|
|
46
|
+
break;
|
|
47
|
+
case "error":
|
|
48
|
+
this.logLevel = LogLevel.ERROR;
|
|
49
|
+
break;
|
|
50
|
+
case "warn":
|
|
51
|
+
this.logLevel = LogLevel.WARN;
|
|
52
|
+
break;
|
|
53
|
+
case "info":
|
|
54
|
+
this.logLevel = LogLevel.INFO;
|
|
55
|
+
break;
|
|
56
|
+
case "debug":
|
|
57
|
+
this.logLevel = LogLevel.DEBUG;
|
|
58
|
+
break;
|
|
59
59
|
default:
|
|
60
60
|
// Invalid log level, keep default
|
|
61
|
-
console.warn(`Invalid log level: ${level}. Using default (INFO).`)
|
|
61
|
+
console.warn(`Invalid log level: ${level}. Using default (INFO).`);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -66,14 +66,14 @@ export class Logger {
|
|
|
66
66
|
* Set the log level
|
|
67
67
|
*/
|
|
68
68
|
public setLogLevel(level: LogLevel): void {
|
|
69
|
-
this.logLevel = level
|
|
69
|
+
this.logLevel = level;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Get the current log level
|
|
74
74
|
*/
|
|
75
75
|
public getLogLevel(): LogLevel {
|
|
76
|
-
return this.logLevel
|
|
76
|
+
return this.logLevel;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/**
|
|
@@ -82,9 +82,9 @@ export class Logger {
|
|
|
82
82
|
public debug(message: string, ...args: any[]): void {
|
|
83
83
|
if (this.logLevel >= LogLevel.DEBUG) {
|
|
84
84
|
if (args.length > 0) {
|
|
85
|
-
console.log(chalk.yellow(`DEBUG: ${message}`), ...args)
|
|
85
|
+
console.log(chalk.yellow(`DEBUG: ${message}`), ...args);
|
|
86
86
|
} else {
|
|
87
|
-
console.log(chalk.yellow(`DEBUG: ${message}`))
|
|
87
|
+
console.log(chalk.yellow(`DEBUG: ${message}`));
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
@@ -95,9 +95,9 @@ export class Logger {
|
|
|
95
95
|
public info(message: string, ...args: any[]): void {
|
|
96
96
|
if (this.logLevel >= LogLevel.INFO) {
|
|
97
97
|
if (args.length > 0) {
|
|
98
|
-
console.log(chalk.blue(message), ...args)
|
|
98
|
+
console.log(chalk.blue(message), ...args);
|
|
99
99
|
} else {
|
|
100
|
-
console.log(chalk.blue(message))
|
|
100
|
+
console.log(chalk.blue(message));
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -108,9 +108,9 @@ export class Logger {
|
|
|
108
108
|
public warn(message: string, ...args: any[]): void {
|
|
109
109
|
if (this.logLevel >= LogLevel.WARN) {
|
|
110
110
|
if (args.length > 0) {
|
|
111
|
-
console.log(chalk.yellow(message), ...args)
|
|
111
|
+
console.log(chalk.yellow(message), ...args);
|
|
112
112
|
} else {
|
|
113
|
-
console.log(chalk.yellow(message))
|
|
113
|
+
console.log(chalk.yellow(message));
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
}
|
|
@@ -121,9 +121,9 @@ export class Logger {
|
|
|
121
121
|
public error(message: string, ...args: any[]): void {
|
|
122
122
|
if (this.logLevel >= LogLevel.ERROR) {
|
|
123
123
|
if (args.length > 0) {
|
|
124
|
-
console.error(chalk.red(message), ...args)
|
|
124
|
+
console.error(chalk.red(message), ...args);
|
|
125
125
|
} else {
|
|
126
|
-
console.error(chalk.red(message))
|
|
126
|
+
console.error(chalk.red(message));
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
@@ -134,9 +134,9 @@ export class Logger {
|
|
|
134
134
|
public success(message: string, ...args: any[]): void {
|
|
135
135
|
if (this.logLevel >= LogLevel.INFO) {
|
|
136
136
|
if (args.length > 0) {
|
|
137
|
-
console.log(chalk.green(message), ...args)
|
|
137
|
+
console.log(chalk.green(message), ...args);
|
|
138
138
|
} else {
|
|
139
|
-
console.log(chalk.green(message))
|
|
139
|
+
console.log(chalk.green(message));
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -147,13 +147,13 @@ export class Logger {
|
|
|
147
147
|
public log(message: string, ...args: any[]): void {
|
|
148
148
|
if (this.logLevel >= LogLevel.INFO) {
|
|
149
149
|
if (args.length > 0) {
|
|
150
|
-
console.log(message, ...args)
|
|
150
|
+
console.log(message, ...args);
|
|
151
151
|
} else {
|
|
152
|
-
console.log(message)
|
|
152
|
+
console.log(message);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// Export a singleton instance for easy import
|
|
159
|
-
export const logger = Logger.getInstance()
|
|
159
|
+
export const logger = Logger.getInstance();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { marked } from
|
|
2
|
-
import TerminalRenderer from
|
|
3
|
-
import chalk from
|
|
1
|
+
import { marked } from "marked";
|
|
2
|
+
import TerminalRenderer from "marked-terminal";
|
|
3
|
+
import chalk from "chalk";
|
|
4
4
|
|
|
5
5
|
// Configure marked to use the terminal renderer
|
|
6
6
|
marked.setOptions({
|
|
@@ -20,7 +20,7 @@ marked.setOptions({
|
|
|
20
20
|
// Customize code block rendering
|
|
21
21
|
codespan: chalk.cyan,
|
|
22
22
|
}),
|
|
23
|
-
})
|
|
23
|
+
});
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Render markdown text to terminal-friendly formatted text
|
|
@@ -28,15 +28,15 @@ marked.setOptions({
|
|
|
28
28
|
* @returns Formatted text for terminal display
|
|
29
29
|
*/
|
|
30
30
|
export function renderMarkdown(markdown: string): string {
|
|
31
|
-
if (!markdown) return
|
|
31
|
+
if (!markdown) return "";
|
|
32
32
|
|
|
33
33
|
try {
|
|
34
34
|
// Convert markdown to terminal-friendly text
|
|
35
|
-
return marked(markdown)
|
|
35
|
+
return marked(markdown);
|
|
36
36
|
} catch (error) {
|
|
37
37
|
// If rendering fails, return the original text
|
|
38
|
-
console.error(`Error rendering markdown: ${error}`)
|
|
39
|
-
return markdown
|
|
38
|
+
console.error(`Error rendering markdown: ${error}`);
|
|
39
|
+
return markdown;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -46,7 +46,7 @@ export function renderMarkdown(markdown: string): string {
|
|
|
46
46
|
* @returns True if the text contains markdown formatting
|
|
47
47
|
*/
|
|
48
48
|
export function containsMarkdown(text: string): boolean {
|
|
49
|
-
if (!text) return false
|
|
49
|
+
if (!text) return false;
|
|
50
50
|
|
|
51
51
|
// Check for common markdown patterns
|
|
52
52
|
const markdownPatterns = [
|
|
@@ -62,7 +62,7 @@ export function containsMarkdown(text: string): boolean {
|
|
|
62
62
|
/\|.*\|.*\|/, // Tables
|
|
63
63
|
/^---+$/m, // Horizontal rules
|
|
64
64
|
/^===+$/m, // Alternative headers
|
|
65
|
-
]
|
|
65
|
+
];
|
|
66
66
|
|
|
67
|
-
return markdownPatterns.some(
|
|
67
|
+
return markdownPatterns.some(pattern => pattern.test(text));
|
|
68
68
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import Ajv from
|
|
2
|
-
import addFormats from
|
|
3
|
-
import { readFileSync } from
|
|
4
|
-
import { join } from
|
|
5
|
-
import { dirname } from
|
|
1
|
+
import Ajv from "ajv";
|
|
2
|
+
import addFormats from "ajv-formats";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { dirname } from "path";
|
|
6
6
|
|
|
7
7
|
// Load the official OpenCode JSON Schema
|
|
8
|
-
const __dirname = dirname(__filename)
|
|
9
|
-
const schemaPath = join(__dirname,
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const schemaPath = join(__dirname, "..", "schemas", "opencode-schema.json");
|
|
10
10
|
|
|
11
|
-
let ajv: Ajv
|
|
12
|
-
let openCodeSchema: any
|
|
13
|
-
let validateFunction: any
|
|
11
|
+
let ajv: Ajv;
|
|
12
|
+
let openCodeSchema: any;
|
|
13
|
+
let validateFunction: any;
|
|
14
14
|
|
|
15
15
|
try {
|
|
16
|
-
const schemaContent = readFileSync(schemaPath,
|
|
17
|
-
openCodeSchema = JSON.parse(schemaContent)
|
|
16
|
+
const schemaContent = readFileSync(schemaPath, "utf-8");
|
|
17
|
+
openCodeSchema = JSON.parse(schemaContent);
|
|
18
18
|
|
|
19
19
|
// Initialize AJV with formats and options
|
|
20
20
|
ajv = new Ajv({
|
|
@@ -23,48 +23,48 @@ try {
|
|
|
23
23
|
strict: false,
|
|
24
24
|
allowUnionTypes: true,
|
|
25
25
|
removeAdditional: false,
|
|
26
|
-
})
|
|
26
|
+
});
|
|
27
27
|
|
|
28
28
|
// Add JSON Schema formats
|
|
29
|
-
addFormats(ajv)
|
|
29
|
+
addFormats(ajv);
|
|
30
30
|
|
|
31
31
|
// Compile the schema
|
|
32
|
-
validateFunction = ajv.compile(openCodeSchema)
|
|
32
|
+
validateFunction = ajv.compile(openCodeSchema);
|
|
33
33
|
} catch (error) {
|
|
34
|
-
console.error(
|
|
35
|
-
throw new Error(
|
|
34
|
+
console.error("Failed to load OpenCode schema:", error);
|
|
35
|
+
throw new Error("Could not initialize OpenCode validator");
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export type OpenCodeConfig = any
|
|
38
|
+
export type OpenCodeConfig = any;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Validate OpenCode configuration against the official JSON Schema
|
|
42
42
|
*/
|
|
43
43
|
export function validateOpenCodeConfig(config: any): {
|
|
44
|
-
valid: boolean
|
|
45
|
-
errors?: string[]
|
|
44
|
+
valid: boolean;
|
|
45
|
+
errors?: string[];
|
|
46
46
|
} {
|
|
47
47
|
try {
|
|
48
48
|
if (!validateFunction) {
|
|
49
|
-
return { valid: false, errors: [
|
|
49
|
+
return { valid: false, errors: ["Schema validator not initialized"] };
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const isValid = validateFunction(config)
|
|
52
|
+
const isValid = validateFunction(config);
|
|
53
53
|
|
|
54
54
|
if (isValid) {
|
|
55
|
-
return { valid: true }
|
|
55
|
+
return { valid: true };
|
|
56
56
|
} else {
|
|
57
57
|
const errors = validateFunction.errors?.map((err: any) => {
|
|
58
|
-
const path = err.instancePath || err.schemaPath ||
|
|
59
|
-
const message = err.message ||
|
|
60
|
-
return `${path}: ${message}
|
|
61
|
-
}) || [
|
|
58
|
+
const path = err.instancePath || err.schemaPath || "root";
|
|
59
|
+
const message = err.message || "Unknown error";
|
|
60
|
+
return `${path}: ${message}`;
|
|
61
|
+
}) || ["Unknown validation error"];
|
|
62
62
|
|
|
63
|
-
return { valid: false, errors }
|
|
63
|
+
return { valid: false, errors };
|
|
64
64
|
}
|
|
65
65
|
} catch (error) {
|
|
66
|
-
console.error(
|
|
67
|
-
return { valid: false, errors: [
|
|
66
|
+
console.error("Validation error:", error);
|
|
67
|
+
return { valid: false, errors: ["Validation process failed"] };
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -72,63 +72,58 @@ export function validateOpenCodeConfig(config: any): {
|
|
|
72
72
|
* Fix common OpenCode configuration issues
|
|
73
73
|
*/
|
|
74
74
|
export function fixOpenCodeConfig(config: any): OpenCodeConfig {
|
|
75
|
-
const fixed = { ...config }
|
|
75
|
+
const fixed = { ...config };
|
|
76
76
|
|
|
77
77
|
// Fix tools.compact - should be boolean, not object
|
|
78
|
-
if (fixed.tools && typeof fixed.tools.compact ===
|
|
79
|
-
console.warn(
|
|
78
|
+
if (fixed.tools && typeof fixed.tools.compact === "object") {
|
|
79
|
+
console.warn("⚠️ Converting tools.compact from object to boolean");
|
|
80
80
|
// If it has properties, assume it should be enabled
|
|
81
|
-
fixed.tools.compact = true
|
|
81
|
+
fixed.tools.compact = true;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// Remove invalid properties
|
|
85
|
-
const invalidProps = [
|
|
86
|
-
invalidProps.forEach(
|
|
85
|
+
const invalidProps = ["maxTokens", "contextWindow"];
|
|
86
|
+
invalidProps.forEach(prop => {
|
|
87
87
|
if (fixed[prop] !== undefined) {
|
|
88
|
-
console.warn(`⚠️ Removing invalid property: ${prop}`)
|
|
89
|
-
delete fixed[prop]
|
|
88
|
+
console.warn(`⚠️ Removing invalid property: ${prop}`);
|
|
89
|
+
delete fixed[prop];
|
|
90
90
|
}
|
|
91
|
-
})
|
|
91
|
+
});
|
|
92
92
|
|
|
93
93
|
// Fix provider models with invalid properties
|
|
94
94
|
if (fixed.provider) {
|
|
95
95
|
Object.values(fixed.provider).forEach((provider: any) => {
|
|
96
96
|
if (provider?.models) {
|
|
97
97
|
Object.values(provider.models).forEach((model: any) => {
|
|
98
|
-
if (model && typeof model ===
|
|
98
|
+
if (model && typeof model === "object") {
|
|
99
99
|
// Move maxTokens/contextWindow to proper structure if needed
|
|
100
100
|
if (model.maxTokens || model.contextWindow) {
|
|
101
|
-
if (!model.limit) model.limit = {}
|
|
101
|
+
if (!model.limit) model.limit = {};
|
|
102
102
|
|
|
103
103
|
// Use the larger of maxTokens/contextWindow for context
|
|
104
|
-
const contextValues = [
|
|
105
|
-
model.maxTokens,
|
|
106
|
-
model.contextWindow,
|
|
107
|
-
].filter(Boolean)
|
|
104
|
+
const contextValues = [model.maxTokens, model.contextWindow].filter(Boolean);
|
|
108
105
|
if (contextValues.length > 0) {
|
|
109
|
-
const newContext = Math.max(...contextValues)
|
|
106
|
+
const newContext = Math.max(...contextValues);
|
|
110
107
|
if (!model.limit.context || newContext > model.limit.context) {
|
|
111
|
-
model.limit.context = newContext
|
|
108
|
+
model.limit.context = newContext;
|
|
112
109
|
}
|
|
113
110
|
}
|
|
114
111
|
|
|
115
112
|
// Set a reasonable default for output if not present
|
|
116
113
|
// (typically 1/4 to 1/8 of context window)
|
|
117
114
|
if (!model.limit.output && model.limit.context) {
|
|
118
|
-
model.limit.output = Math.floor(model.limit.context / 4)
|
|
115
|
+
model.limit.output = Math.floor(model.limit.context / 4);
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
delete model.maxTokens
|
|
122
|
-
delete model.contextWindow
|
|
123
|
-
console.warn(
|
|
124
|
-
'⚠️ Moved maxTokens/contextWindow to limit.context/output',
|
|
125
|
-
)
|
|
118
|
+
delete model.maxTokens;
|
|
119
|
+
delete model.contextWindow;
|
|
120
|
+
console.warn("⚠️ Moved maxTokens/contextWindow to limit.context/output");
|
|
126
121
|
}
|
|
127
122
|
}
|
|
128
|
-
})
|
|
123
|
+
});
|
|
129
124
|
}
|
|
130
|
-
})
|
|
125
|
+
});
|
|
131
126
|
}
|
|
132
127
|
|
|
133
|
-
return fixed
|
|
128
|
+
return fixed;
|
|
134
129
|
}
|