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
@@ -11,12 +11,12 @@ const path_1 = require("path");
11
11
  const path_2 = require("path");
12
12
  // Load the official OpenCode JSON Schema
13
13
  const __dirname = (0, path_2.dirname)(__filename);
14
- const schemaPath = (0, path_1.join)(__dirname, '..', 'schemas', 'opencode-schema.json');
14
+ const schemaPath = (0, path_1.join)(__dirname, "..", "schemas", "opencode-schema.json");
15
15
  let ajv;
16
16
  let openCodeSchema;
17
17
  let validateFunction;
18
18
  try {
19
- const schemaContent = (0, fs_1.readFileSync)(schemaPath, 'utf-8');
19
+ const schemaContent = (0, fs_1.readFileSync)(schemaPath, "utf-8");
20
20
  openCodeSchema = JSON.parse(schemaContent);
21
21
  // Initialize AJV with formats and options
22
22
  ajv = new ajv_1.default({
@@ -32,8 +32,8 @@ try {
32
32
  validateFunction = ajv.compile(openCodeSchema);
33
33
  }
34
34
  catch (error) {
35
- console.error('Failed to load OpenCode schema:', error);
36
- throw new Error('Could not initialize OpenCode validator');
35
+ console.error("Failed to load OpenCode schema:", error);
36
+ throw new Error("Could not initialize OpenCode validator");
37
37
  }
38
38
  /**
39
39
  * Validate OpenCode configuration against the official JSON Schema
@@ -42,7 +42,7 @@ function validateOpenCodeConfig(config) {
42
42
  var _a;
43
43
  try {
44
44
  if (!validateFunction) {
45
- return { valid: false, errors: ['Schema validator not initialized'] };
45
+ return { valid: false, errors: ["Schema validator not initialized"] };
46
46
  }
47
47
  const isValid = validateFunction(config);
48
48
  if (isValid) {
@@ -50,16 +50,16 @@ function validateOpenCodeConfig(config) {
50
50
  }
51
51
  else {
52
52
  const errors = ((_a = validateFunction.errors) === null || _a === void 0 ? void 0 : _a.map((err) => {
53
- const path = err.instancePath || err.schemaPath || 'root';
54
- const message = err.message || 'Unknown error';
53
+ const path = err.instancePath || err.schemaPath || "root";
54
+ const message = err.message || "Unknown error";
55
55
  return `${path}: ${message}`;
56
- })) || ['Unknown validation error'];
56
+ })) || ["Unknown validation error"];
57
57
  return { valid: false, errors };
58
58
  }
59
59
  }
60
60
  catch (error) {
61
- console.error('Validation error:', error);
62
- return { valid: false, errors: ['Validation process failed'] };
61
+ console.error("Validation error:", error);
62
+ return { valid: false, errors: ["Validation process failed"] };
63
63
  }
64
64
  }
65
65
  exports.validateOpenCodeConfig = validateOpenCodeConfig;
@@ -69,14 +69,14 @@ exports.validateOpenCodeConfig = validateOpenCodeConfig;
69
69
  function fixOpenCodeConfig(config) {
70
70
  const fixed = Object.assign({}, config);
71
71
  // Fix tools.compact - should be boolean, not object
72
- if (fixed.tools && typeof fixed.tools.compact === 'object') {
73
- console.warn('⚠️ Converting tools.compact from object to boolean');
72
+ if (fixed.tools && typeof fixed.tools.compact === "object") {
73
+ console.warn("⚠️ Converting tools.compact from object to boolean");
74
74
  // If it has properties, assume it should be enabled
75
75
  fixed.tools.compact = true;
76
76
  }
77
77
  // Remove invalid properties
78
- const invalidProps = ['maxTokens', 'contextWindow'];
79
- invalidProps.forEach((prop) => {
78
+ const invalidProps = ["maxTokens", "contextWindow"];
79
+ invalidProps.forEach(prop => {
80
80
  if (fixed[prop] !== undefined) {
81
81
  console.warn(`⚠️ Removing invalid property: ${prop}`);
82
82
  delete fixed[prop];
@@ -87,16 +87,13 @@ function fixOpenCodeConfig(config) {
87
87
  Object.values(fixed.provider).forEach((provider) => {
88
88
  if (provider === null || provider === void 0 ? void 0 : provider.models) {
89
89
  Object.values(provider.models).forEach((model) => {
90
- if (model && typeof model === 'object') {
90
+ if (model && typeof model === "object") {
91
91
  // Move maxTokens/contextWindow to proper structure if needed
92
92
  if (model.maxTokens || model.contextWindow) {
93
93
  if (!model.limit)
94
94
  model.limit = {};
95
95
  // Use the larger of maxTokens/contextWindow for context
96
- const contextValues = [
97
- model.maxTokens,
98
- model.contextWindow,
99
- ].filter(Boolean);
96
+ const contextValues = [model.maxTokens, model.contextWindow].filter(Boolean);
100
97
  if (contextValues.length > 0) {
101
98
  const newContext = Math.max(...contextValues);
102
99
  if (!model.limit.context || newContext > model.limit.context) {
@@ -110,7 +107,7 @@ function fixOpenCodeConfig(config) {
110
107
  }
111
108
  delete model.maxTokens;
112
109
  delete model.contextWindow;
113
- console.warn('⚠️ Moved maxTokens/contextWindow to limit.context/output');
110
+ console.warn("⚠️ Moved maxTokens/contextWindow to limit.context/output");
114
111
  }
115
112
  }
116
113
  });
@@ -28,6 +28,27 @@ const fs = __importStar(require("fs"));
28
28
  const path = __importStar(require("path"));
29
29
  const os = __importStar(require("os"));
30
30
  const logger_1 = require("./logger");
31
+ /**
32
+ * Extract the expiration time from a JWT token
33
+ * @param accessToken The JWT access token
34
+ * @returns The expiration timestamp in milliseconds, or 0 if invalid
35
+ */
36
+ function extractJwtExpiresAt(accessToken) {
37
+ try {
38
+ const parts = accessToken.split(".");
39
+ if (parts.length !== 3)
40
+ return 0;
41
+ const payload = Buffer.from(parts[1], "base64url").toString("utf8");
42
+ const decoded = JSON.parse(payload);
43
+ if (typeof decoded.exp === "number") {
44
+ return decoded.exp * 1000; // JWT exp is in seconds, convert to milliseconds
45
+ }
46
+ }
47
+ catch (_a) {
48
+ // If decoding fails, return 0 (treated as expired)
49
+ }
50
+ return 0;
51
+ }
31
52
  /**
32
53
  * Manages authentication tokens including refresh functionality
33
54
  */
@@ -35,11 +56,11 @@ class TokenManager {
35
56
  constructor() {
36
57
  this.tokenData = null;
37
58
  // Set up token file path in user's home directory
38
- const bergetDir = path.join(os.homedir(), '.berget');
59
+ const bergetDir = path.join(os.homedir(), ".berget");
39
60
  if (!fs.existsSync(bergetDir)) {
40
61
  fs.mkdirSync(bergetDir, { recursive: true });
41
62
  }
42
- this.tokenFilePath = path.join(bergetDir, 'auth.json');
63
+ this.tokenFilePath = path.join(bergetDir, "auth.json");
43
64
  this.loadToken();
44
65
  }
45
66
  static getInstance() {
@@ -54,12 +75,12 @@ class TokenManager {
54
75
  loadToken() {
55
76
  try {
56
77
  if (fs.existsSync(this.tokenFilePath)) {
57
- const data = fs.readFileSync(this.tokenFilePath, 'utf8');
78
+ const data = fs.readFileSync(this.tokenFilePath, "utf8");
58
79
  this.tokenData = JSON.parse(data);
59
80
  }
60
81
  }
61
- catch (error) {
62
- logger_1.logger.error('Failed to load authentication token');
82
+ catch (_a) {
83
+ logger_1.logger.error("Failed to load authentication token");
63
84
  this.tokenData = null;
64
85
  }
65
86
  }
@@ -80,8 +101,8 @@ class TokenManager {
80
101
  }
81
102
  }
82
103
  }
83
- catch (error) {
84
- logger_1.logger.error('Failed to save authentication token');
104
+ catch (_a) {
105
+ logger_1.logger.error("Failed to save authentication token");
85
106
  }
86
107
  }
87
108
  /**
@@ -134,26 +155,32 @@ class TokenManager {
134
155
  * Set new token data
135
156
  * @param accessToken The new access token
136
157
  * @param refreshToken The new refresh token
137
- * @param expiresIn Expiration time in seconds
158
+ * @param expiresIn Expiration time in seconds (fallback if JWT parsing fails)
138
159
  */
139
160
  setTokens(accessToken, refreshToken, expiresIn) {
161
+ // Extract the actual expiry time from the JWT token
162
+ const jwtExpiresAt = extractJwtExpiresAt(accessToken);
163
+ const expiresAt = jwtExpiresAt > 0 ? jwtExpiresAt : Date.now() + expiresIn * 1000;
140
164
  this.tokenData = {
141
165
  access_token: accessToken,
142
166
  refresh_token: refreshToken,
143
- expires_at: Date.now() + expiresIn * 1000,
167
+ expires_at: expiresAt,
144
168
  };
145
169
  this.saveToken();
146
170
  }
147
171
  /**
148
172
  * Update just the access token and its expiration
149
173
  * @param accessToken The new access token
150
- * @param expiresIn Expiration time in seconds
174
+ * @param expiresIn Expiration time in seconds (fallback if JWT parsing fails)
151
175
  */
152
176
  updateAccessToken(accessToken, expiresIn) {
153
177
  if (!this.tokenData)
154
178
  return;
179
+ // Extract the actual expiry time from the JWT token
180
+ const jwtExpiresAt = extractJwtExpiresAt(accessToken);
181
+ const expiresAt = jwtExpiresAt > 0 ? jwtExpiresAt : Date.now() + expiresIn * 1000;
155
182
  this.tokenData.access_token = accessToken;
156
- this.tokenData.expires_at = Date.now() + expiresIn * 1000;
183
+ this.tokenData.expires_at = expiresAt;
157
184
  this.saveToken();
158
185
  }
159
186
  /**
@@ -15,15 +15,15 @@ const chat_1 = require("../../src/commands/chat");
15
15
  const chat_service_1 = require("../../src/services/chat-service");
16
16
  const default_api_key_1 = require("../../src/utils/default-api-key");
17
17
  // Mock dependencies
18
- vitest_1.vi.mock('../../src/services/chat-service');
19
- vitest_1.vi.mock('../../src/utils/default-api-key');
20
- vitest_1.vi.mock('readline', () => ({
18
+ vitest_1.vi.mock("../../src/services/chat-service");
19
+ vitest_1.vi.mock("../../src/utils/default-api-key");
20
+ vitest_1.vi.mock("readline", () => ({
21
21
  createInterface: vitest_1.vi.fn(() => ({
22
22
  question: vitest_1.vi.fn(),
23
23
  close: vitest_1.vi.fn(),
24
24
  })),
25
25
  }));
26
- (0, vitest_1.describe)('Chat Commands', () => {
26
+ (0, vitest_1.describe)("Chat Commands", () => {
27
27
  let program;
28
28
  let mockChatService;
29
29
  let mockDefaultApiKeyManager;
@@ -46,32 +46,32 @@ vitest_1.vi.mock('readline', () => ({
46
46
  (0, vitest_1.afterEach)(() => {
47
47
  vitest_1.vi.clearAllMocks();
48
48
  });
49
- (0, vitest_1.describe)('chat run command', () => {
50
- (0, vitest_1.it)('should use berget/glm-4.7 as default model', () => {
51
- const chatCommand = program.commands.find((cmd) => cmd.name() === 'chat');
52
- const runCommand = chatCommand === null || chatCommand === void 0 ? void 0 : chatCommand.commands.find((cmd) => cmd.name() === 'run');
49
+ (0, vitest_1.describe)("chat run command", () => {
50
+ (0, vitest_1.it)("should use berget/glm-4.7 as default model", () => {
51
+ const chatCommand = program.commands.find(cmd => cmd.name() === "chat");
52
+ const runCommand = chatCommand === null || chatCommand === void 0 ? void 0 : chatCommand.commands.find(cmd => cmd.name() === "run");
53
53
  (0, vitest_1.expect)(runCommand).toBeDefined();
54
54
  // Check the help text which contains the default model
55
55
  const helpText = runCommand === null || runCommand === void 0 ? void 0 : runCommand.helpInformation();
56
- (0, vitest_1.expect)(helpText).toContain('glm-4.7');
56
+ (0, vitest_1.expect)(helpText).toContain("glm-4.7");
57
57
  });
58
- (0, vitest_1.it)('should have streaming enabled by default', () => {
59
- const chatCommand = program.commands.find((cmd) => cmd.name() === 'chat');
60
- const runCommand = chatCommand === null || chatCommand === void 0 ? void 0 : chatCommand.commands.find((cmd) => cmd.name() === 'run');
58
+ (0, vitest_1.it)("should have streaming enabled by default", () => {
59
+ const chatCommand = program.commands.find(cmd => cmd.name() === "chat");
60
+ const runCommand = chatCommand === null || chatCommand === void 0 ? void 0 : chatCommand.commands.find(cmd => cmd.name() === "run");
61
61
  (0, vitest_1.expect)(runCommand).toBeDefined();
62
62
  // Check that the option is --no-stream (meaning streaming is default)
63
- const streamOption = runCommand === null || runCommand === void 0 ? void 0 : runCommand.options.find((opt) => opt.long === '--no-stream');
63
+ const streamOption = runCommand === null || runCommand === void 0 ? void 0 : runCommand.options.find(opt => opt.long === "--no-stream");
64
64
  (0, vitest_1.expect)(streamOption).toBeDefined();
65
- (0, vitest_1.expect)(streamOption === null || streamOption === void 0 ? void 0 : streamOption.description).toContain('Disable streaming');
65
+ (0, vitest_1.expect)(streamOption === null || streamOption === void 0 ? void 0 : streamOption.description).toContain("Disable streaming");
66
66
  });
67
- (0, vitest_1.it)('should create completion with correct default options', () => __awaiter(void 0, void 0, void 0, function* () {
67
+ (0, vitest_1.it)("should create completion with correct default options", () => __awaiter(void 0, void 0, void 0, function* () {
68
68
  // Mock API key
69
- process.env.BERGET_API_KEY = 'test-key';
69
+ process.env.BERGET_API_KEY = "test-key";
70
70
  // Mock successful completion
71
71
  mockChatService.createCompletion.mockResolvedValue({
72
72
  choices: [
73
73
  {
74
- message: { content: 'Test response' },
74
+ message: { content: "Test response" },
75
75
  },
76
76
  ],
77
77
  });
@@ -83,13 +83,13 @@ vitest_1.vi.mock('readline', () => ({
83
83
  delete process.env.BERGET_API_KEY;
84
84
  }));
85
85
  });
86
- (0, vitest_1.describe)('chat list command', () => {
87
- (0, vitest_1.it)('should list available models', () => __awaiter(void 0, void 0, void 0, function* () {
86
+ (0, vitest_1.describe)("chat list command", () => {
87
+ (0, vitest_1.it)("should list available models", () => __awaiter(void 0, void 0, void 0, function* () {
88
88
  const mockModels = {
89
89
  data: [
90
90
  {
91
- id: 'gpt-oss',
92
- owned_by: 'openai',
91
+ id: "gpt-oss",
92
+ owned_by: "openai",
93
93
  active: true,
94
94
  capabilities: {
95
95
  vision: false,
@@ -100,10 +100,10 @@ vitest_1.vi.mock('readline', () => ({
100
100
  ],
101
101
  };
102
102
  mockChatService.listModels.mockResolvedValue(mockModels);
103
- const chatCommand = program.commands.find((cmd) => cmd.name() === 'chat');
104
- const listCommand = chatCommand === null || chatCommand === void 0 ? void 0 : chatCommand.commands.find((cmd) => cmd.name() === 'list');
103
+ const chatCommand = program.commands.find(cmd => cmd.name() === "chat");
104
+ const listCommand = chatCommand === null || chatCommand === void 0 ? void 0 : chatCommand.commands.find(cmd => cmd.name() === "list");
105
105
  (0, vitest_1.expect)(listCommand).toBeDefined();
106
- (0, vitest_1.expect)(listCommand === null || listCommand === void 0 ? void 0 : listCommand.description()).toBe('List available chat models');
106
+ (0, vitest_1.expect)(listCommand === null || listCommand === void 0 ? void 0 : listCommand.description()).toBe("List available chat models");
107
107
  }));
108
108
  });
109
109
  });