berget 2.2.7 → 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 (130) hide show
  1. package/.github/workflows/publish.yml +6 -6
  2. package/.github/workflows/test.yml +1 -1
  3. package/.prettierrc +5 -3
  4. package/dist/index.js +24 -25
  5. package/dist/package.json +5 -3
  6. package/dist/src/agents/app.js +8 -8
  7. package/dist/src/agents/backend.js +3 -3
  8. package/dist/src/agents/devops.js +8 -8
  9. package/dist/src/agents/frontend.js +3 -3
  10. package/dist/src/agents/fullstack.js +3 -3
  11. package/dist/src/agents/index.js +18 -18
  12. package/dist/src/agents/quality.js +8 -8
  13. package/dist/src/agents/security.js +8 -8
  14. package/dist/src/client.js +115 -127
  15. package/dist/src/commands/api-keys.js +195 -202
  16. package/dist/src/commands/auth.js +16 -25
  17. package/dist/src/commands/autocomplete.js +8 -8
  18. package/dist/src/commands/billing.js +10 -19
  19. package/dist/src/commands/chat.js +139 -170
  20. package/dist/src/commands/clusters.js +21 -30
  21. package/dist/src/commands/code/__tests__/auth-sync.test.js +189 -186
  22. package/dist/src/commands/code/__tests__/fake-api-key-service.js +3 -13
  23. package/dist/src/commands/code/__tests__/fake-auth-service.js +21 -29
  24. package/dist/src/commands/code/__tests__/fake-command-runner.js +22 -33
  25. package/dist/src/commands/code/__tests__/fake-file-store.js +19 -41
  26. package/dist/src/commands/code/__tests__/fake-prompter.js +81 -97
  27. package/dist/src/commands/code/__tests__/setup-flow.test.js +295 -295
  28. package/dist/src/commands/code/adapters/clack-prompter.js +15 -32
  29. package/dist/src/commands/code/adapters/fs-file-store.js +25 -44
  30. package/dist/src/commands/code/adapters/spawn-command-runner.js +27 -41
  31. package/dist/src/commands/code/auth-sync.js +215 -228
  32. package/dist/src/commands/code/errors.js +15 -12
  33. package/dist/src/commands/code/setup.js +390 -425
  34. package/dist/src/commands/code.js +279 -294
  35. package/dist/src/commands/index.js +5 -5
  36. package/dist/src/commands/models.js +16 -25
  37. package/dist/src/commands/users.js +9 -18
  38. package/dist/src/constants/command-structure.js +138 -138
  39. package/dist/src/services/api-key-service.js +132 -152
  40. package/dist/src/services/auth-service.js +81 -95
  41. package/dist/src/services/browser-auth.js +121 -131
  42. package/dist/src/services/chat-service.js +369 -386
  43. package/dist/src/services/cluster-service.js +47 -62
  44. package/dist/src/services/collaborator-service.js +9 -21
  45. package/dist/src/services/flux-service.js +13 -25
  46. package/dist/src/services/helm-service.js +9 -21
  47. package/dist/src/services/kubectl-service.js +15 -29
  48. package/dist/src/utils/config-checker.js +7 -7
  49. package/dist/src/utils/config-loader.js +109 -109
  50. package/dist/src/utils/default-api-key.js +129 -139
  51. package/dist/src/utils/env-manager.js +55 -66
  52. package/dist/src/utils/error-handler.js +62 -62
  53. package/dist/src/utils/logger.js +74 -67
  54. package/dist/src/utils/markdown-renderer.js +28 -28
  55. package/dist/src/utils/opencode-validator.js +67 -69
  56. package/dist/src/utils/token-manager.js +67 -65
  57. package/dist/tests/commands/chat.test.js +30 -39
  58. package/dist/tests/commands/code.test.js +186 -195
  59. package/dist/tests/utils/config-loader.test.js +107 -107
  60. package/dist/tests/utils/env-manager.test.js +81 -90
  61. package/dist/tests/utils/opencode-validator.test.js +42 -41
  62. package/dist/vitest.config.js +1 -1
  63. package/eslint.config.mjs +50 -30
  64. package/index.ts +30 -31
  65. package/package.json +5 -3
  66. package/src/agents/app.ts +9 -9
  67. package/src/agents/backend.ts +4 -4
  68. package/src/agents/devops.ts +9 -9
  69. package/src/agents/frontend.ts +4 -4
  70. package/src/agents/fullstack.ts +4 -4
  71. package/src/agents/index.ts +27 -25
  72. package/src/agents/quality.ts +9 -9
  73. package/src/agents/security.ts +9 -9
  74. package/src/agents/types.ts +10 -10
  75. package/src/client.ts +85 -77
  76. package/src/commands/api-keys.ts +190 -185
  77. package/src/commands/auth.ts +15 -14
  78. package/src/commands/autocomplete.ts +10 -10
  79. package/src/commands/billing.ts +13 -12
  80. package/src/commands/chat.ts +145 -142
  81. package/src/commands/clusters.ts +20 -19
  82. package/src/commands/code/__tests__/auth-sync.test.ts +176 -175
  83. package/src/commands/code/__tests__/fake-api-key-service.ts +2 -2
  84. package/src/commands/code/__tests__/fake-auth-service.ts +18 -18
  85. package/src/commands/code/__tests__/fake-command-runner.ts +28 -22
  86. package/src/commands/code/__tests__/fake-file-store.ts +15 -15
  87. package/src/commands/code/__tests__/fake-prompter.ts +86 -85
  88. package/src/commands/code/__tests__/setup-flow.test.ts +253 -251
  89. package/src/commands/code/adapters/clack-prompter.ts +32 -30
  90. package/src/commands/code/adapters/fs-file-store.ts +18 -17
  91. package/src/commands/code/adapters/spawn-command-runner.ts +20 -15
  92. package/src/commands/code/auth-sync.ts +210 -210
  93. package/src/commands/code/errors.ts +11 -11
  94. package/src/commands/code/ports/auth-services.ts +7 -7
  95. package/src/commands/code/ports/command-runner.ts +2 -2
  96. package/src/commands/code/ports/file-store.ts +3 -3
  97. package/src/commands/code/ports/prompter.ts +13 -13
  98. package/src/commands/code/setup.ts +408 -406
  99. package/src/commands/code.ts +288 -287
  100. package/src/commands/index.ts +11 -10
  101. package/src/commands/models.ts +19 -18
  102. package/src/commands/users.ts +11 -10
  103. package/src/constants/command-structure.ts +159 -159
  104. package/src/services/api-key-service.ts +85 -85
  105. package/src/services/auth-service.ts +55 -54
  106. package/src/services/browser-auth.ts +62 -62
  107. package/src/services/chat-service.ts +169 -170
  108. package/src/services/cluster-service.ts +28 -28
  109. package/src/services/collaborator-service.ts +6 -6
  110. package/src/services/flux-service.ts +17 -17
  111. package/src/services/helm-service.ts +11 -11
  112. package/src/services/kubectl-service.ts +12 -12
  113. package/src/types/api.d.ts +1933 -1933
  114. package/src/types/json.d.ts +1 -1
  115. package/src/utils/config-checker.ts +6 -6
  116. package/src/utils/config-loader.ts +130 -129
  117. package/src/utils/default-api-key.ts +81 -80
  118. package/src/utils/env-manager.ts +37 -37
  119. package/src/utils/error-handler.ts +64 -64
  120. package/src/utils/logger.ts +72 -66
  121. package/src/utils/markdown-renderer.ts +28 -28
  122. package/src/utils/opencode-validator.ts +72 -71
  123. package/src/utils/token-manager.ts +69 -68
  124. package/tests/commands/chat.test.ts +32 -31
  125. package/tests/commands/code.test.ts +182 -181
  126. package/tests/utils/config-loader.test.ts +111 -110
  127. package/tests/utils/env-manager.test.ts +83 -79
  128. package/tests/utils/opencode-validator.test.ts +43 -42
  129. package/tsconfig.json +2 -1
  130. package/vitest.config.ts +2 -2
@@ -5,13 +5,13 @@ const config_loader_1 = require("../../src/utils/config-loader");
5
5
  // Mock fs module
6
6
  const mockFs = vitest_1.vi.hoisted(() => ({
7
7
  existsSync: vitest_1.vi.fn(),
8
+ mkdirSync: vitest_1.vi.fn(),
8
9
  readFileSync: vitest_1.vi.fn(),
9
10
  writeFileSync: vitest_1.vi.fn(),
10
- mkdirSync: vitest_1.vi.fn(),
11
11
  }));
12
- vitest_1.vi.mock("fs", () => mockFs);
13
- (0, vitest_1.describe)("ConfigLoader", () => {
14
- const testConfigPath = "/tmp/test-opencode.json";
12
+ vitest_1.vi.mock('fs', () => mockFs);
13
+ (0, vitest_1.describe)('ConfigLoader', () => {
14
+ const testConfigPath = '/tmp/test-opencode.json';
15
15
  let configLoader;
16
16
  (0, vitest_1.beforeEach)(() => {
17
17
  // Reset mocks and clear singleton
@@ -24,242 +24,242 @@ vitest_1.vi.mock("fs", () => mockFs);
24
24
  vitest_1.vi.clearAllMocks();
25
25
  config_loader_1.ConfigLoader.clearInstance();
26
26
  });
27
- (0, vitest_1.describe)("when config file does not exist", () => {
27
+ (0, vitest_1.describe)('when config file does not exist', () => {
28
28
  (0, vitest_1.beforeEach)(() => {
29
29
  mockFs.existsSync.mockReturnValue(false);
30
30
  });
31
- (0, vitest_1.describe)("getModelConfig", () => {
32
- (0, vitest_1.it)("should return default values when config file does not exist", () => {
31
+ (0, vitest_1.describe)('getModelConfig', () => {
32
+ (0, vitest_1.it)('should return default values when config file does not exist', () => {
33
33
  const modelConfig = configLoader.getModelConfig();
34
34
  (0, vitest_1.expect)(modelConfig).toEqual({
35
- primary: "berget/glm-4.7",
36
- small: "berget/gpt-oss",
35
+ primary: 'berget/glm-4.7',
36
+ small: 'berget/gpt-oss',
37
37
  });
38
38
  });
39
- (0, vitest_1.it)("should return default values when using convenience function", () => {
39
+ (0, vitest_1.it)('should return default values when using convenience function', () => {
40
40
  const modelConfig = (0, config_loader_1.getModelConfig)(testConfigPath);
41
41
  (0, vitest_1.expect)(modelConfig).toEqual({
42
- primary: "berget/glm-4.7",
43
- small: "berget/gpt-oss",
42
+ primary: 'berget/glm-4.7',
43
+ small: 'berget/gpt-oss',
44
44
  });
45
45
  });
46
46
  });
47
- (0, vitest_1.describe)("getProviderModels", () => {
48
- (0, vitest_1.it)("should return default provider models when config file does not exist", () => {
47
+ (0, vitest_1.describe)('getProviderModels', () => {
48
+ (0, vitest_1.it)('should return default provider models when config file does not exist', () => {
49
49
  const models = configLoader.getProviderModels();
50
50
  (0, vitest_1.expect)(models).toEqual({
51
- "glm-4.7": {
52
- name: "GLM-4.7",
53
- limit: { output: 4000, context: 90000 },
51
+ 'glm-4.7': {
52
+ limit: { context: 90000, output: 4000 },
53
+ name: 'GLM-4.7',
54
54
  },
55
- "gpt-oss": {
56
- name: "GPT-OSS",
57
- limit: { output: 4000, context: 128000 },
55
+ 'gpt-oss': {
56
+ limit: { context: 128000, output: 4000 },
58
57
  modalities: {
59
- input: ["text", "image"],
60
- output: ["text"],
58
+ input: ['text', 'image'],
59
+ output: ['text'],
61
60
  },
61
+ name: 'GPT-OSS',
62
62
  },
63
- "llama-8b": {
64
- name: "llama-3.1-8b",
65
- limit: { output: 4000, context: 128000 },
63
+ 'llama-8b': {
64
+ limit: { context: 128000, output: 4000 },
65
+ name: 'llama-3.1-8b',
66
66
  },
67
67
  });
68
68
  });
69
- (0, vitest_1.it)("should return default provider models when using convenience function", () => {
69
+ (0, vitest_1.it)('should return default provider models when using convenience function', () => {
70
70
  const models = (0, config_loader_1.getProviderModels)(testConfigPath);
71
71
  (0, vitest_1.expect)(models).toEqual({
72
- "glm-4.7": {
73
- name: "GLM-4.7",
74
- limit: { output: 4000, context: 90000 },
72
+ 'glm-4.7': {
73
+ limit: { context: 90000, output: 4000 },
74
+ name: 'GLM-4.7',
75
75
  },
76
- "gpt-oss": {
77
- name: "GPT-OSS",
78
- limit: { output: 4000, context: 128000 },
76
+ 'gpt-oss': {
77
+ limit: { context: 128000, output: 4000 },
79
78
  modalities: {
80
- input: ["text", "image"],
81
- output: ["text"],
79
+ input: ['text', 'image'],
80
+ output: ['text'],
82
81
  },
82
+ name: 'GPT-OSS',
83
83
  },
84
- "llama-8b": {
85
- name: "llama-3.1-8b",
86
- limit: { output: 4000, context: 128000 },
84
+ 'llama-8b': {
85
+ limit: { context: 128000, output: 4000 },
86
+ name: 'llama-3.1-8b',
87
87
  },
88
88
  });
89
89
  });
90
90
  });
91
- (0, vitest_1.describe)("getAllAgentConfigs", () => {
92
- (0, vitest_1.it)("should return empty object when config file does not exist", () => {
91
+ (0, vitest_1.describe)('getAllAgentConfigs', () => {
92
+ (0, vitest_1.it)('should return empty object when config file does not exist', () => {
93
93
  const agents = configLoader.getAllAgentConfigs();
94
94
  (0, vitest_1.expect)(agents).toEqual({});
95
95
  });
96
- (0, vitest_1.it)("should return empty object when using convenience function", () => {
96
+ (0, vitest_1.it)('should return empty object when using convenience function', () => {
97
97
  const agents = (0, config_loader_1.getAllAgentConfigs)(testConfigPath);
98
98
  (0, vitest_1.expect)(agents).toEqual({});
99
99
  });
100
100
  });
101
- (0, vitest_1.describe)("getAgentConfig", () => {
102
- (0, vitest_1.it)("should return null when config file does not exist", () => {
103
- const agent = configLoader.getAgentConfig("fullstack");
101
+ (0, vitest_1.describe)('getAgentConfig', () => {
102
+ (0, vitest_1.it)('should return null when config file does not exist', () => {
103
+ const agent = configLoader.getAgentConfig('fullstack');
104
104
  (0, vitest_1.expect)(agent).toBeNull();
105
105
  });
106
106
  });
107
107
  });
108
- (0, vitest_1.describe)("when config file exists", () => {
108
+ (0, vitest_1.describe)('when config file exists', () => {
109
109
  const mockConfig = {
110
- model: "custom-model",
111
- small_model: "custom-small-model",
112
110
  agent: {
113
111
  fullstack: {
114
- model: "custom-agent-model",
115
- temperature: 0.5,
116
- mode: "primary",
112
+ mode: 'primary',
113
+ model: 'custom-agent-model',
117
114
  permission: {
118
- edit: "allow",
119
- bash: "allow",
120
- webfetch: "allow",
115
+ bash: 'allow',
116
+ edit: 'allow',
117
+ webfetch: 'allow',
121
118
  },
119
+ temperature: 0.5,
122
120
  },
123
121
  },
124
122
  command: {
125
123
  test: {
126
- description: "Test command",
124
+ description: 'Test command',
127
125
  },
128
126
  },
129
- watcher: {
130
- ignore: ["custom-ignore"],
131
- },
127
+ model: 'custom-model',
132
128
  provider: {
133
129
  berget: {
134
130
  models: {
135
- "custom-model": {
136
- name: "Custom Model",
137
- limit: { output: 8000, context: 160000 },
131
+ 'custom-model': {
132
+ limit: { context: 160000, output: 8000 },
133
+ name: 'Custom Model',
138
134
  },
139
135
  },
140
136
  },
141
137
  },
138
+ small_model: 'custom-small-model',
139
+ watcher: {
140
+ ignore: ['custom-ignore'],
141
+ },
142
142
  };
143
143
  (0, vitest_1.beforeEach)(() => {
144
144
  mockFs.existsSync.mockReturnValue(true);
145
145
  mockFs.readFileSync.mockReturnValue(JSON.stringify(mockConfig));
146
146
  });
147
- (0, vitest_1.describe)("getModelConfig", () => {
148
- (0, vitest_1.it)("should return values from config file", () => {
147
+ (0, vitest_1.describe)('getModelConfig', () => {
148
+ (0, vitest_1.it)('should return values from config file', () => {
149
149
  const modelConfig = configLoader.getModelConfig();
150
150
  (0, vitest_1.expect)(modelConfig).toEqual({
151
- primary: "custom-model",
152
- small: "custom-small-model",
151
+ primary: 'custom-model',
152
+ small: 'custom-small-model',
153
153
  });
154
154
  });
155
155
  });
156
- (0, vitest_1.describe)("getProviderModels", () => {
157
- (0, vitest_1.it)("should return models from config file", () => {
156
+ (0, vitest_1.describe)('getProviderModels', () => {
157
+ (0, vitest_1.it)('should return models from config file', () => {
158
158
  const models = configLoader.getProviderModels();
159
159
  (0, vitest_1.expect)(models).toEqual({
160
- "custom-model": {
161
- name: "Custom Model",
162
- limit: { output: 8000, context: 160000 },
160
+ 'custom-model': {
161
+ limit: { context: 160000, output: 8000 },
162
+ name: 'Custom Model',
163
163
  },
164
164
  });
165
165
  });
166
166
  });
167
- (0, vitest_1.describe)("getAllAgentConfigs", () => {
168
- (0, vitest_1.it)("should return agents from config file", () => {
167
+ (0, vitest_1.describe)('getAllAgentConfigs', () => {
168
+ (0, vitest_1.it)('should return agents from config file', () => {
169
169
  const agents = configLoader.getAllAgentConfigs();
170
170
  (0, vitest_1.expect)(agents).toEqual(mockConfig.agent);
171
171
  });
172
172
  });
173
- (0, vitest_1.describe)("getAgentConfig", () => {
174
- (0, vitest_1.it)("should return specific agent from config file", () => {
175
- const agent = configLoader.getAgentConfig("fullstack");
173
+ (0, vitest_1.describe)('getAgentConfig', () => {
174
+ (0, vitest_1.it)('should return specific agent from config file', () => {
175
+ const agent = configLoader.getAgentConfig('fullstack');
176
176
  (0, vitest_1.expect)(agent).toEqual(mockConfig.agent.fullstack);
177
177
  });
178
- (0, vitest_1.it)("should return null for non-existent agent", () => {
179
- const agent = configLoader.getAgentConfig("nonexistent");
178
+ (0, vitest_1.it)('should return null for non-existent agent', () => {
179
+ const agent = configLoader.getAgentConfig('nonexistent');
180
180
  (0, vitest_1.expect)(agent).toBeNull();
181
181
  });
182
182
  });
183
183
  });
184
- (0, vitest_1.describe)("when config file is invalid JSON", () => {
184
+ (0, vitest_1.describe)('when config file is invalid JSON', () => {
185
185
  (0, vitest_1.beforeEach)(() => {
186
186
  mockFs.existsSync.mockReturnValue(true);
187
- mockFs.readFileSync.mockReturnValue("invalid json {");
187
+ mockFs.readFileSync.mockReturnValue('invalid json {');
188
188
  });
189
- (0, vitest_1.it)("should fall back to defaults for getModelConfig", () => {
189
+ (0, vitest_1.it)('should fall back to defaults for getModelConfig', () => {
190
190
  const modelConfig = configLoader.getModelConfig();
191
191
  (0, vitest_1.expect)(modelConfig).toEqual({
192
- primary: "berget/glm-4.7",
193
- small: "berget/gpt-oss",
192
+ primary: 'berget/glm-4.7',
193
+ small: 'berget/gpt-oss',
194
194
  });
195
195
  });
196
- (0, vitest_1.it)("should fall back to defaults for getProviderModels", () => {
196
+ (0, vitest_1.it)('should fall back to defaults for getProviderModels', () => {
197
197
  const models = configLoader.getProviderModels();
198
198
  (0, vitest_1.expect)(models).toEqual({
199
- "glm-4.7": {
200
- name: "GLM-4.7",
201
- limit: { output: 4000, context: 90000 },
199
+ 'glm-4.7': {
200
+ limit: { context: 90000, output: 4000 },
201
+ name: 'GLM-4.7',
202
202
  },
203
- "gpt-oss": {
204
- name: "GPT-OSS",
205
- limit: { output: 4000, context: 128000 },
203
+ 'gpt-oss': {
204
+ limit: { context: 128000, output: 4000 },
206
205
  modalities: {
207
- input: ["text", "image"],
208
- output: ["text"],
206
+ input: ['text', 'image'],
207
+ output: ['text'],
209
208
  },
209
+ name: 'GPT-OSS',
210
210
  },
211
- "llama-8b": {
212
- name: "llama-3.1-8b",
213
- limit: { output: 4000, context: 128000 },
211
+ 'llama-8b': {
212
+ limit: { context: 128000, output: 4000 },
213
+ name: 'llama-3.1-8b',
214
214
  },
215
215
  });
216
216
  });
217
- (0, vitest_1.it)("should fall back to defaults for getAllAgentConfigs", () => {
217
+ (0, vitest_1.it)('should fall back to defaults for getAllAgentConfigs', () => {
218
218
  const agents = configLoader.getAllAgentConfigs();
219
219
  (0, vitest_1.expect)(agents).toEqual({});
220
220
  });
221
221
  });
222
- (0, vitest_1.describe)("singleton pattern", () => {
223
- (0, vitest_1.it)("should return the same instance for same path", () => {
222
+ (0, vitest_1.describe)('singleton pattern', () => {
223
+ (0, vitest_1.it)('should return the same instance for same path', () => {
224
224
  config_loader_1.ConfigLoader.clearInstance();
225
225
  const loader1 = config_loader_1.ConfigLoader.getInstance(testConfigPath);
226
226
  const loader2 = config_loader_1.ConfigLoader.getInstance(testConfigPath);
227
227
  (0, vitest_1.expect)(loader1).toBe(loader2);
228
228
  });
229
- (0, vitest_1.it)("should return the same instance even for different paths (true singleton)", () => {
229
+ (0, vitest_1.it)('should return the same instance even for different paths (true singleton)', () => {
230
230
  config_loader_1.ConfigLoader.clearInstance();
231
- const loader1 = config_loader_1.ConfigLoader.getInstance("/path1/config.json");
232
- const loader2 = config_loader_1.ConfigLoader.getInstance("/path2/config.json");
231
+ const loader1 = config_loader_1.ConfigLoader.getInstance('/path1/config.json');
232
+ const loader2 = config_loader_1.ConfigLoader.getInstance('/path2/config.json');
233
233
  // ConfigLoader is a true singleton - it returns the same instance regardless of path
234
234
  (0, vitest_1.expect)(loader1).toBe(loader2);
235
235
  });
236
236
  });
237
- (0, vitest_1.describe)("init scenario regression tests", () => {
238
- (0, vitest_1.it)("should handle missing config file during init scenario", () => {
237
+ (0, vitest_1.describe)('init scenario regression tests', () => {
238
+ (0, vitest_1.it)('should handle missing config file during init scenario', () => {
239
239
  // This test specifically verifies the fix for the init issue
240
240
  mockFs.existsSync.mockReturnValue(false);
241
241
  // All these methods should work without throwing errors
242
242
  (0, vitest_1.expect)(() => configLoader.getModelConfig()).not.toThrow();
243
243
  (0, vitest_1.expect)(() => configLoader.getProviderModels()).not.toThrow();
244
244
  (0, vitest_1.expect)(() => configLoader.getAllAgentConfigs()).not.toThrow();
245
- (0, vitest_1.expect)(() => configLoader.getAgentConfig("fullstack")).not.toThrow();
245
+ (0, vitest_1.expect)(() => configLoader.getAgentConfig('fullstack')).not.toThrow();
246
246
  // And return sensible defaults
247
247
  (0, vitest_1.expect)(configLoader.getModelConfig()).toEqual({
248
- primary: "berget/glm-4.7",
249
- small: "berget/gpt-oss",
248
+ primary: 'berget/glm-4.7',
249
+ small: 'berget/gpt-oss',
250
250
  });
251
251
  (0, vitest_1.expect)(configLoader.getAllAgentConfigs()).toEqual({});
252
- (0, vitest_1.expect)(configLoader.getAgentConfig("fullstack")).toBeNull();
252
+ (0, vitest_1.expect)(configLoader.getAgentConfig('fullstack')).toBeNull();
253
253
  });
254
- (0, vitest_1.it)("should work with convenience functions during init scenario", () => {
254
+ (0, vitest_1.it)('should work with convenience functions during init scenario', () => {
255
255
  // This test verifies that convenience functions also work during init
256
256
  mockFs.existsSync.mockReturnValue(false);
257
257
  (0, vitest_1.expect)(() => (0, config_loader_1.getModelConfig)(testConfigPath)).not.toThrow();
258
258
  (0, vitest_1.expect)(() => (0, config_loader_1.getProviderModels)(testConfigPath)).not.toThrow();
259
259
  (0, vitest_1.expect)(() => (0, config_loader_1.getAllAgentConfigs)(testConfigPath)).not.toThrow();
260
260
  (0, vitest_1.expect)((0, config_loader_1.getModelConfig)(testConfigPath)).toEqual({
261
- primary: "berget/glm-4.7",
262
- small: "berget/gpt-oss",
261
+ primary: 'berget/glm-4.7',
262
+ small: 'berget/gpt-oss',
263
263
  });
264
264
  (0, vitest_1.expect)((0, config_loader_1.getAllAgentConfigs)(testConfigPath)).toEqual({});
265
265
  });
@@ -1,148 +1,139 @@
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 });
6
+ const node_fs_1 = __importDefault(require("node:fs"));
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_path_1 = __importDefault(require("node:path"));
15
9
  const vitest_1 = require("vitest");
16
- const fs_1 = __importDefault(require("fs"));
17
- const promises_1 = require("fs/promises");
18
- const path_1 = __importDefault(require("path"));
19
10
  const env_manager_1 = require("../../src/utils/env-manager");
20
- vitest_1.vi.mock("fs");
21
- vitest_1.vi.mock("fs/promises");
22
- vitest_1.vi.mock("path");
23
- const mockFs = vitest_1.vi.mocked(fs_1.default);
11
+ vitest_1.vi.mock('fs');
12
+ vitest_1.vi.mock('fs/promises');
13
+ vitest_1.vi.mock('path');
14
+ const mockFs = vitest_1.vi.mocked(node_fs_1.default);
24
15
  const mockWriteFile = vitest_1.vi.mocked(promises_1.writeFile);
25
- const mockPath = vitest_1.vi.mocked(path_1.default);
26
- (0, vitest_1.describe)("env-manager", () => {
27
- const testEnvPath = "/test/.env";
28
- const testCwd = "/test";
16
+ const mockPath = vitest_1.vi.mocked(node_path_1.default);
17
+ (0, vitest_1.describe)('env-manager', () => {
18
+ const testEnvironmentPath = '/test/.env';
19
+ const testCwd = '/test';
29
20
  (0, vitest_1.beforeEach)(() => {
30
21
  vitest_1.vi.clearAllMocks();
31
- mockPath.join.mockReturnValue(testEnvPath);
32
- vitest_1.vi.spyOn(process, "cwd").mockReturnValue(testCwd);
22
+ mockPath.join.mockReturnValue(testEnvironmentPath);
23
+ vitest_1.vi.spyOn(process, 'cwd').mockReturnValue(testCwd);
33
24
  });
34
25
  (0, vitest_1.afterEach)(() => {
35
26
  vitest_1.vi.restoreAllMocks();
36
27
  });
37
- (0, vitest_1.describe)("updateEnvFile", () => {
38
- (0, vitest_1.it)("should create a new .env file with the key when file does not exist", () => __awaiter(void 0, void 0, void 0, function* () {
28
+ (0, vitest_1.describe)('updateEnvFile', () => {
29
+ (0, vitest_1.it)('should create a new .env file with the key when file does not exist', async () => {
39
30
  mockFs.existsSync.mockReturnValue(false);
40
- yield (0, env_manager_1.updateEnvFile)({
41
- key: "TEST_KEY",
42
- value: "test_value",
43
- comment: "Test comment",
31
+ await (0, env_manager_1.updateEnvFile)({
32
+ comment: 'Test comment',
33
+ key: 'TEST_KEY',
34
+ value: 'test_value',
44
35
  });
45
- (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(testEnvPath);
46
- (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvPath, "# Test comment\nTEST_KEY=test_value\n");
47
- }));
48
- (0, vitest_1.it)("should append to existing .env file when key does not exist", () => __awaiter(void 0, void 0, void 0, function* () {
49
- const existingContent = "EXISTING_KEY=existing_value\n";
36
+ (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(testEnvironmentPath);
37
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvironmentPath, '# Test comment\nTEST_KEY=test_value\n');
38
+ });
39
+ (0, vitest_1.it)('should append to existing .env file when key does not exist', async () => {
40
+ const existingContent = 'EXISTING_KEY=existing_value\n';
50
41
  mockFs.existsSync.mockReturnValue(true);
51
42
  mockFs.readFileSync.mockReturnValue(existingContent);
52
- yield (0, env_manager_1.updateEnvFile)({
53
- key: "NEW_KEY",
54
- value: "new_value",
55
- comment: "Test comment",
43
+ await (0, env_manager_1.updateEnvFile)({
44
+ comment: 'Test comment',
45
+ key: 'NEW_KEY',
46
+ value: 'new_value',
56
47
  });
57
- (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvPath, "EXISTING_KEY=existing_value\nNEW_KEY=new_value\n");
58
- }));
59
- (0, vitest_1.it)("should not update when key already exists and force is false", () => __awaiter(void 0, void 0, void 0, function* () {
60
- const existingContent = "EXISTING_KEY=existing_value\nTEST_KEY=old_value\n";
48
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvironmentPath, 'EXISTING_KEY=existing_value\nNEW_KEY=new_value\n');
49
+ });
50
+ (0, vitest_1.it)('should not update when key already exists and force is false', async () => {
51
+ const existingContent = 'EXISTING_KEY=existing_value\nTEST_KEY=old_value\n';
61
52
  mockFs.existsSync.mockReturnValue(true);
62
53
  mockFs.readFileSync.mockReturnValue(existingContent);
63
- const consoleSpy = vitest_1.vi.spyOn(console, "log").mockImplementation(() => { });
64
- yield (0, env_manager_1.updateEnvFile)({
65
- key: "TEST_KEY",
66
- value: "new_value",
54
+ const consoleSpy = vitest_1.vi.spyOn(console, 'log').mockImplementation(() => { });
55
+ await (0, env_manager_1.updateEnvFile)({
56
+ key: 'TEST_KEY',
57
+ value: 'new_value',
67
58
  });
68
- (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("TEST_KEY already exists in .env - leaving unchanged"));
59
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('TEST_KEY already exists in .env - leaving unchanged'));
69
60
  (0, vitest_1.expect)(mockWriteFile).not.toHaveBeenCalled();
70
61
  consoleSpy.mockRestore();
71
- }));
72
- (0, vitest_1.it)("should update existing key when force is true", () => __awaiter(void 0, void 0, void 0, function* () {
73
- const existingContent = "EXISTING_KEY=existing_value\nTEST_KEY=old_value\n";
62
+ });
63
+ (0, vitest_1.it)('should update existing key when force is true', async () => {
64
+ const existingContent = 'EXISTING_KEY=existing_value\nTEST_KEY=old_value\n';
74
65
  mockFs.existsSync.mockReturnValue(true);
75
66
  mockFs.readFileSync.mockReturnValue(existingContent);
76
- yield (0, env_manager_1.updateEnvFile)({
77
- key: "TEST_KEY",
78
- value: "new_value",
67
+ await (0, env_manager_1.updateEnvFile)({
79
68
  force: true,
69
+ key: 'TEST_KEY',
70
+ value: 'new_value',
80
71
  });
81
- (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvPath, "EXISTING_KEY=existing_value\nTEST_KEY=new_value\n");
82
- }));
83
- (0, vitest_1.it)("should handle complex values with quotes and special characters", () => __awaiter(void 0, void 0, void 0, function* () {
72
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvironmentPath, 'EXISTING_KEY=existing_value\nTEST_KEY=new_value\n');
73
+ });
74
+ (0, vitest_1.it)('should handle complex values with quotes and special characters', async () => {
84
75
  mockFs.existsSync.mockReturnValue(false);
85
- yield (0, env_manager_1.updateEnvFile)({
86
- key: "COMPLEX_KEY",
76
+ await (0, env_manager_1.updateEnvFile)({
77
+ comment: 'Complex test',
78
+ key: 'COMPLEX_KEY',
87
79
  value: 'value with "quotes" and $special',
88
- comment: "Complex test",
89
80
  });
90
- (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvPath, '# Complex test\nCOMPLEX_KEY=value with "quotes" and $special\n');
91
- }));
92
- (0, vitest_1.it)("should use custom env path when provided", () => __awaiter(void 0, void 0, void 0, function* () {
93
- const customPath = "/custom/.env";
81
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(testEnvironmentPath, '# Complex test\nCOMPLEX_KEY=value with "quotes" and $special\n');
82
+ });
83
+ (0, vitest_1.it)('should use custom env path when provided', async () => {
84
+ const customPath = '/custom/.env';
94
85
  mockFs.existsSync.mockReturnValue(false);
95
- yield (0, env_manager_1.updateEnvFile)({
86
+ await (0, env_manager_1.updateEnvFile)({
96
87
  envPath: customPath,
97
- key: "TEST_KEY",
98
- value: "test_value",
88
+ key: 'TEST_KEY',
89
+ value: 'test_value',
99
90
  });
100
91
  (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(customPath);
101
- (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(customPath, "TEST_KEY=test_value\n");
102
- }));
103
- (0, vitest_1.it)("should throw error when write fails", () => __awaiter(void 0, void 0, void 0, function* () {
92
+ (0, vitest_1.expect)(mockWriteFile).toHaveBeenCalledWith(customPath, 'TEST_KEY=test_value\n');
93
+ });
94
+ (0, vitest_1.it)('should throw error when write fails', async () => {
104
95
  mockFs.existsSync.mockReturnValue(false);
105
- mockWriteFile.mockRejectedValue(new Error("Write error"));
106
- yield (0, vitest_1.expect)((0, env_manager_1.updateEnvFile)({
107
- key: "TEST_KEY",
108
- value: "test_value",
109
- })).rejects.toThrow("Write error");
110
- }));
96
+ mockWriteFile.mockRejectedValue(new Error('Write error'));
97
+ await (0, vitest_1.expect)((0, env_manager_1.updateEnvFile)({
98
+ key: 'TEST_KEY',
99
+ value: 'test_value',
100
+ })).rejects.toThrow('Write error');
101
+ });
111
102
  });
112
- (0, vitest_1.describe)("hasEnvKey", () => {
113
- (0, vitest_1.it)("should return false when .env file does not exist", () => {
103
+ (0, vitest_1.describe)('hasEnvKey', () => {
104
+ (0, vitest_1.it)('should return false when .env file does not exist', () => {
114
105
  mockFs.existsSync.mockReturnValue(false);
115
- const result = (0, env_manager_1.hasEnvKey)(testEnvPath, "TEST_KEY");
106
+ const result = (0, env_manager_1.hasEnvKey)(testEnvironmentPath, 'TEST_KEY');
116
107
  (0, vitest_1.expect)(result).toBe(false);
117
- (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(testEnvPath);
108
+ (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(testEnvironmentPath);
118
109
  (0, vitest_1.expect)(mockFs.readFileSync).not.toHaveBeenCalled();
119
110
  });
120
- (0, vitest_1.it)("should return true when key exists in .env file", () => {
121
- const existingContent = "KEY1=value1\nTEST_KEY=test_value\nKEY2=value2\n";
111
+ (0, vitest_1.it)('should return true when key exists in .env file', () => {
112
+ const existingContent = 'KEY1=value1\nTEST_KEY=test_value\nKEY2=value2\n';
122
113
  mockFs.existsSync.mockReturnValue(true);
123
114
  mockFs.readFileSync.mockReturnValue(existingContent);
124
- const result = (0, env_manager_1.hasEnvKey)(testEnvPath, "TEST_KEY");
115
+ const result = (0, env_manager_1.hasEnvKey)(testEnvironmentPath, 'TEST_KEY');
125
116
  (0, vitest_1.expect)(result).toBe(true);
126
117
  });
127
- (0, vitest_1.it)("should return false when key does not exist in .env file", () => {
128
- const existingContent = "KEY1=value1\nKEY2=value2\n";
118
+ (0, vitest_1.it)('should return false when key does not exist in .env file', () => {
119
+ const existingContent = 'KEY1=value1\nKEY2=value2\n';
129
120
  mockFs.existsSync.mockReturnValue(true);
130
121
  mockFs.readFileSync.mockReturnValue(existingContent);
131
- const result = (0, env_manager_1.hasEnvKey)(testEnvPath, "TEST_KEY");
122
+ const result = (0, env_manager_1.hasEnvKey)(testEnvironmentPath, 'TEST_KEY');
132
123
  (0, vitest_1.expect)(result).toBe(false);
133
124
  });
134
- (0, vitest_1.it)("should return false when .env file is malformed", () => {
125
+ (0, vitest_1.it)('should return false when .env file is malformed', () => {
135
126
  mockFs.existsSync.mockReturnValue(true);
136
127
  mockFs.readFileSync.mockImplementation(() => {
137
- throw new Error("Read error");
128
+ throw new Error('Read error');
138
129
  });
139
- const result = (0, env_manager_1.hasEnvKey)(testEnvPath, "TEST_KEY");
130
+ const result = (0, env_manager_1.hasEnvKey)(testEnvironmentPath, 'TEST_KEY');
140
131
  (0, vitest_1.expect)(result).toBe(false);
141
132
  });
142
- (0, vitest_1.it)("should use default path when not provided", () => {
133
+ (0, vitest_1.it)('should use default path when not provided', () => {
143
134
  mockFs.existsSync.mockReturnValue(false);
144
- (0, env_manager_1.hasEnvKey)(undefined, "TEST_KEY");
145
- (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(testEnvPath);
135
+ (0, env_manager_1.hasEnvKey)(undefined, 'TEST_KEY');
136
+ (0, vitest_1.expect)(mockFs.existsSync).toHaveBeenCalledWith(testEnvironmentPath);
146
137
  });
147
138
  });
148
139
  });