berget 2.2.7 → 2.2.9

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 +7 -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 +181 -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 +8 -8
  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 +65 -30
  64. package/index.ts +30 -31
  65. package/package.json +7 -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 +180 -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 +170 -171
  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 +7 -7
  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
@@ -22,46 +22,37 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  Object.defineProperty(exports, "__esModule", { value: true });
35
- const vitest_1 = require("vitest");
36
26
  const commander_1 = require("commander");
27
+ const fs = __importStar(require("node:fs"));
28
+ const promises_1 = require("node:fs/promises");
29
+ const vitest_1 = require("vitest");
37
30
  const code_1 = require("../../src/commands/code");
38
31
  const api_key_service_1 = require("../../src/services/api-key-service");
39
- const fs = __importStar(require("fs"));
40
- const promises_1 = require("fs/promises");
41
32
  const env_manager_1 = require("../../src/utils/env-manager");
42
33
  // Mock dependencies
43
- vitest_1.vi.mock("../../src/services/api-key-service");
44
- vitest_1.vi.mock("fs", () => ({
34
+ vitest_1.vi.mock('../../src/services/api-key-service');
35
+ vitest_1.vi.mock('fs', () => ({
45
36
  default: {
46
37
  existsSync: vitest_1.vi.fn(),
47
38
  readFileSync: vitest_1.vi.fn(),
48
39
  },
49
40
  }));
50
- vitest_1.vi.mock("fs/promises", () => ({
41
+ vitest_1.vi.mock('fs/promises', () => ({
51
42
  readFile: vitest_1.vi.fn(),
52
43
  writeFile: vitest_1.vi.fn(),
53
44
  }));
54
- vitest_1.vi.mock("../../src/utils/env-manager");
55
- vitest_1.vi.mock("child_process", () => ({
45
+ vitest_1.vi.mock('../../src/utils/env-manager');
46
+ vitest_1.vi.mock('child_process', () => ({
56
47
  spawn: vitest_1.vi.fn(),
57
48
  }));
58
- vitest_1.vi.mock("readline", () => ({
49
+ vitest_1.vi.mock('readline', () => ({
59
50
  createInterface: vitest_1.vi.fn(() => ({
60
- question: vitest_1.vi.fn(),
61
51
  close: vitest_1.vi.fn(),
52
+ question: vitest_1.vi.fn(),
62
53
  })),
63
54
  }));
64
- (0, vitest_1.describe)("Code Commands", () => {
55
+ (0, vitest_1.describe)('Code Commands', () => {
65
56
  let program;
66
57
  let mockApiKeyService;
67
58
  let mockFs;
@@ -86,47 +77,47 @@ vitest_1.vi.mock("readline", () => ({
86
77
  mockFsPromises.writeFile = vitest_1.vi.fn();
87
78
  // Mock spawn
88
79
  mockSpawn = vitest_1.vi.fn();
89
- vitest_1.vi.doMock("child_process", () => ({ spawn: mockSpawn }));
80
+ vitest_1.vi.doMock('child_process', () => ({ spawn: mockSpawn }));
90
81
  (0, code_1.registerCodeCommands)(program);
91
82
  });
92
83
  (0, vitest_1.afterEach)(() => {
93
84
  vitest_1.vi.clearAllMocks();
94
85
  });
95
- (0, vitest_1.describe)("code init command", () => {
96
- (0, vitest_1.it)("should register init command with correct description", () => {
97
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
98
- const initCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "init");
86
+ (0, vitest_1.describe)('code init command', () => {
87
+ (0, vitest_1.it)('should register init command with correct description', () => {
88
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
89
+ const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
99
90
  (0, vitest_1.expect)(initCommand).toBeDefined();
100
- (0, vitest_1.expect)(initCommand === null || initCommand === void 0 ? void 0 : initCommand.description()).toBe("Initialize project for AI coding assistant");
91
+ (0, vitest_1.expect)(initCommand?.description()).toBe('Initialize project for AI coding assistant');
101
92
  });
102
- (0, vitest_1.it)("should have name, force, and yes options", () => {
103
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
104
- const initCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "init");
93
+ (0, vitest_1.it)('should have name, force, and yes options', () => {
94
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
95
+ const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
105
96
  (0, vitest_1.expect)(initCommand).toBeDefined();
106
- const nameOption = initCommand === null || initCommand === void 0 ? void 0 : initCommand.options.find(opt => opt.long === "--name");
107
- const forceOption = initCommand === null || initCommand === void 0 ? void 0 : initCommand.options.find(opt => opt.long === "--force");
108
- const yesOption = initCommand === null || initCommand === void 0 ? void 0 : initCommand.options.find(opt => opt.long === "--yes");
97
+ const nameOption = initCommand?.options.find((opt) => opt.long === '--name');
98
+ const forceOption = initCommand?.options.find((opt) => opt.long === '--force');
99
+ const yesOption = initCommand?.options.find((opt) => opt.long === '--yes');
109
100
  (0, vitest_1.expect)(nameOption).toBeDefined();
110
- (0, vitest_1.expect)(nameOption === null || nameOption === void 0 ? void 0 : nameOption.description).toContain("Project name");
101
+ (0, vitest_1.expect)(nameOption?.description).toContain('Project name');
111
102
  (0, vitest_1.expect)(forceOption).toBeDefined();
112
- (0, vitest_1.expect)(forceOption === null || forceOption === void 0 ? void 0 : forceOption.description).toContain("Overwrite existing configuration");
103
+ (0, vitest_1.expect)(forceOption?.description).toContain('Overwrite existing configuration');
113
104
  (0, vitest_1.expect)(yesOption).toBeDefined();
114
- (0, vitest_1.expect)(yesOption === null || yesOption === void 0 ? void 0 : yesOption.description).toContain("Automatically answer yes");
105
+ (0, vitest_1.expect)(yesOption?.description).toContain('Automatically answer yes');
115
106
  });
116
- (0, vitest_1.it)("should check if opencode is installed", () => {
117
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
118
- const initCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "init");
107
+ (0, vitest_1.it)('should check if opencode is installed', () => {
108
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
109
+ const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
119
110
  (0, vitest_1.expect)(initCommand).toBeDefined();
120
111
  // The command should attempt to spawn opencode --version
121
112
  // This is tested implicitly through the spawn mock
122
113
  });
123
- (0, vitest_1.it)("should list existing API keys and allow selection", () => __awaiter(void 0, void 0, void 0, function* () {
114
+ (0, vitest_1.it)('should list existing API keys and allow selection', async () => {
124
115
  // Mock successful opencode installation check
125
- mockSpawn.mockImplementation((command, args) => {
126
- if (command === "opencode" && args[0] === "--version") {
116
+ mockSpawn.mockImplementation((command, arguments_) => {
117
+ if (command === 'opencode' && arguments_[0] === '--version') {
127
118
  return {
128
119
  on: vitest_1.vi.fn().mockImplementation((event, callback) => {
129
- if (event === "close")
120
+ if (event === 'close')
130
121
  callback(0);
131
122
  }),
132
123
  };
@@ -136,34 +127,34 @@ vitest_1.vi.mock("readline", () => ({
136
127
  // Mock existing API keys
137
128
  const mockExistingKeys = [
138
129
  {
130
+ created: '2023-01-01T00:00:00.000Z',
139
131
  id: 1,
140
- name: "existing-key-1",
141
- prefix: "sk_ber",
142
- created: "2023-01-01T00:00:00.000Z",
143
132
  lastUsed: null,
133
+ name: 'existing-key-1',
134
+ prefix: 'sk_ber',
144
135
  },
145
136
  {
137
+ created: '2023-01-02T00:00:00.000Z',
146
138
  id: 2,
147
- name: "existing-key-2",
148
- prefix: "sk_ber",
149
- created: "2023-01-02T00:00:00.000Z",
150
- lastUsed: "2023-01-03T00:00:00.000Z",
139
+ lastUsed: '2023-01-03T00:00:00.000Z',
140
+ name: 'existing-key-2',
141
+ prefix: 'sk_ber',
151
142
  },
152
143
  ];
153
144
  mockApiKeyService.list.mockResolvedValue(mockExistingKeys);
154
145
  // Mock file operations
155
146
  mockFs.existsSync.mockReturnValue(false);
156
- mockFsPromises.writeFile.mockResolvedValue(undefined);
147
+ mockFsPromises.writeFile.mockResolvedValue();
157
148
  // Verify that the list method is called
158
149
  (0, vitest_1.expect)(mockApiKeyService.list).toBeDefined();
159
- }));
160
- (0, vitest_1.it)("should create new API key with project-based naming", () => __awaiter(void 0, void 0, void 0, function* () {
150
+ });
151
+ (0, vitest_1.it)('should create new API key with project-based naming', async () => {
161
152
  // Mock successful opencode installation check
162
- mockSpawn.mockImplementation((command, args) => {
163
- if (command === "opencode" && args[0] === "--version") {
153
+ mockSpawn.mockImplementation((command, arguments_) => {
154
+ if (command === 'opencode' && arguments_[0] === '--version') {
164
155
  return {
165
156
  on: vitest_1.vi.fn().mockImplementation((event, callback) => {
166
- if (event === "close")
157
+ if (event === 'close')
167
158
  callback(0);
168
159
  }),
169
160
  };
@@ -175,77 +166,77 @@ vitest_1.vi.mock("readline", () => ({
175
166
  // Mock successful API key creation
176
167
  const mockApiKeyData = {
177
168
  id: 123,
178
- name: "opencode-testproject-1234567890",
179
- key: "test-api-key-12345",
169
+ key: 'test-api-key-12345',
170
+ name: 'opencode-testproject-1234567890',
180
171
  };
181
172
  mockApiKeyService.create.mockResolvedValue(mockApiKeyData);
182
173
  // Mock file operations
183
174
  mockFs.existsSync.mockReturnValue(false);
184
- mockFsPromises.writeFile.mockResolvedValue(undefined);
175
+ mockFsPromises.writeFile.mockResolvedValue();
185
176
  // Verify that the create method is available
186
177
  (0, vitest_1.expect)(mockApiKeyService.create).toBeDefined();
187
- }));
188
- (0, vitest_1.it)("should create opencode.json with correct structure", () => __awaiter(void 0, void 0, void 0, function* () {
178
+ });
179
+ (0, vitest_1.it)('should create opencode.json with correct structure', async () => {
189
180
  // This tests the expected config structure
190
181
  const expectedConfig = {
191
- model: "berget/glm-4-6",
192
- apiKey: "test-api-key",
193
- projectName: "testproject",
194
- provider: "berget",
182
+ apiKey: 'test-api-key',
195
183
  created: vitest_1.expect.any(String),
196
- version: "1.0.0",
184
+ model: 'berget/glm-4-6',
185
+ projectName: 'testproject',
186
+ provider: 'berget',
187
+ version: '1.0.0',
197
188
  };
198
- (0, vitest_1.expect)(expectedConfig.model).toBe("berget/glm-4-6");
199
- (0, vitest_1.expect)(expectedConfig.provider).toBe("berget");
200
- (0, vitest_1.expect)(expectedConfig.version).toBe("1.0.0");
201
- }));
202
- (0, vitest_1.it)("should handle existing config file", () => {
203
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
204
- const initCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "init");
189
+ (0, vitest_1.expect)(expectedConfig.model).toBe('berget/glm-4-6');
190
+ (0, vitest_1.expect)(expectedConfig.provider).toBe('berget');
191
+ (0, vitest_1.expect)(expectedConfig.version).toBe('1.0.0');
192
+ });
193
+ (0, vitest_1.it)('should handle existing config file', () => {
194
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
195
+ const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
205
196
  (0, vitest_1.expect)(initCommand).toBeDefined();
206
197
  // Should check if opencode.json exists before proceeding
207
198
  (0, vitest_1.expect)(mockFs.existsSync).toBeDefined();
208
199
  });
209
200
  });
210
- (0, vitest_1.describe)("code run command", () => {
211
- (0, vitest_1.it)("should register run command with correct description", () => {
212
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
213
- const runCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "run");
201
+ (0, vitest_1.describe)('code run command', () => {
202
+ (0, vitest_1.it)('should register run command with correct description', () => {
203
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
204
+ const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
214
205
  (0, vitest_1.expect)(runCommand).toBeDefined();
215
- (0, vitest_1.expect)(runCommand === null || runCommand === void 0 ? void 0 : runCommand.description()).toBe("Run AI coding assistant");
206
+ (0, vitest_1.expect)(runCommand?.description()).toBe('Run AI coding assistant');
216
207
  });
217
- (0, vitest_1.it)("should accept prompt argument and model, no-config, and yes options", () => {
218
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
219
- const runCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "run");
208
+ (0, vitest_1.it)('should accept prompt argument and model, no-config, and yes options', () => {
209
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
210
+ const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
220
211
  (0, vitest_1.expect)(runCommand).toBeDefined();
221
- const modelOption = runCommand === null || runCommand === void 0 ? void 0 : runCommand.options.find(opt => opt.long === "--model");
222
- const noConfigOption = runCommand === null || runCommand === void 0 ? void 0 : runCommand.options.find(opt => opt.long === "--no-config");
223
- const yesOption = runCommand === null || runCommand === void 0 ? void 0 : runCommand.options.find(opt => opt.long === "--yes");
212
+ const modelOption = runCommand?.options.find((opt) => opt.long === '--model');
213
+ const noConfigOption = runCommand?.options.find((opt) => opt.long === '--no-config');
214
+ const yesOption = runCommand?.options.find((opt) => opt.long === '--yes');
224
215
  (0, vitest_1.expect)(modelOption).toBeDefined();
225
- (0, vitest_1.expect)(modelOption === null || modelOption === void 0 ? void 0 : modelOption.description).toContain("Model to use");
216
+ (0, vitest_1.expect)(modelOption?.description).toContain('Model to use');
226
217
  (0, vitest_1.expect)(noConfigOption).toBeDefined();
227
- (0, vitest_1.expect)(noConfigOption === null || noConfigOption === void 0 ? void 0 : noConfigOption.description).toContain("Run without loading project config");
218
+ (0, vitest_1.expect)(noConfigOption?.description).toContain('Run without loading project config');
228
219
  (0, vitest_1.expect)(yesOption).toBeDefined();
229
- (0, vitest_1.expect)(yesOption === null || yesOption === void 0 ? void 0 : yesOption.description).toContain("Automatically answer yes");
220
+ (0, vitest_1.expect)(yesOption?.description).toContain('Automatically answer yes');
230
221
  });
231
- (0, vitest_1.it)("should load configuration from opencode.json", () => __awaiter(void 0, void 0, void 0, function* () {
222
+ (0, vitest_1.it)('should load configuration from opencode.json', async () => {
232
223
  const mockConfig = {
233
- model: "berget/glm-4-6",
234
- apiKey: "test-api-key",
235
- projectName: "testproject",
236
- provider: "berget",
237
- created: "2023-01-01T00:00:00.000Z",
238
- version: "1.0.0",
224
+ apiKey: 'test-api-key',
225
+ created: '2023-01-01T00:00:00.000Z',
226
+ model: 'berget/glm-4-6',
227
+ projectName: 'testproject',
228
+ provider: 'berget',
229
+ version: '1.0.0',
239
230
  };
240
231
  // Mock file exists and contains config
241
232
  mockFs.existsSync.mockReturnValue(true);
242
233
  mockFsPromises.readFile.mockResolvedValue(JSON.stringify(mockConfig));
243
234
  // Mock successful opencode check
244
- mockSpawn.mockImplementation((command, args) => {
245
- if (command === "opencode" && args[0] === "--version") {
235
+ mockSpawn.mockImplementation((command, arguments_) => {
236
+ if (command === 'opencode' && arguments_[0] === '--version') {
246
237
  return {
247
238
  on: vitest_1.vi.fn().mockImplementation((event, callback) => {
248
- if (event === "close")
239
+ if (event === 'close')
249
240
  callback(0);
250
241
  }),
251
242
  };
@@ -253,37 +244,37 @@ vitest_1.vi.mock("readline", () => ({
253
244
  return { on: vitest_1.vi.fn() };
254
245
  });
255
246
  // Verify config structure expectations
256
- (0, vitest_1.expect)(mockConfig.model).toBe("berget/glm-4-6");
257
- (0, vitest_1.expect)(mockConfig.apiKey).toBe("test-api-key");
258
- (0, vitest_1.expect)(mockConfig.projectName).toBe("testproject");
259
- }));
260
- (0, vitest_1.it)("should spawn opencode with correct arguments", () => {
261
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
262
- const runCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "run");
247
+ (0, vitest_1.expect)(mockConfig.model).toBe('berget/glm-4-6');
248
+ (0, vitest_1.expect)(mockConfig.apiKey).toBe('test-api-key');
249
+ (0, vitest_1.expect)(mockConfig.projectName).toBe('testproject');
250
+ });
251
+ (0, vitest_1.it)('should spawn opencode with correct arguments', () => {
252
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
253
+ const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
263
254
  (0, vitest_1.expect)(runCommand).toBeDefined();
264
255
  // Should spawn opencode with appropriate arguments
265
256
  (0, vitest_1.expect)(mockSpawn).toBeDefined();
266
257
  });
267
- (0, vitest_1.it)("should handle missing configuration file", () => {
268
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
269
- const runCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "run");
258
+ (0, vitest_1.it)('should handle missing configuration file', () => {
259
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
260
+ const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
270
261
  (0, vitest_1.expect)(runCommand).toBeDefined();
271
262
  // Should check if opencode.json exists
272
263
  (0, vitest_1.expect)(mockFs.existsSync).toBeDefined();
273
264
  });
274
265
  });
275
- (0, vitest_1.describe)("opencode installation", () => {
276
- (0, vitest_1.it)("should check if opencode is installed", () => {
266
+ (0, vitest_1.describe)('opencode installation', () => {
267
+ (0, vitest_1.it)('should check if opencode is installed', () => {
277
268
  // The spawn function should be called with opencode --version
278
269
  (0, vitest_1.expect)(mockSpawn).toBeDefined();
279
270
  });
280
- (0, vitest_1.it)("should offer to install opencode if not found", () => {
271
+ (0, vitest_1.it)('should offer to install opencode if not found', () => {
281
272
  // Mock opencode not installed
282
- mockSpawn.mockImplementation((command, args) => {
283
- if (command === "opencode" && args[0] === "--version") {
273
+ mockSpawn.mockImplementation((command, arguments_) => {
274
+ if (command === 'opencode' && arguments_[0] === '--version') {
284
275
  return {
285
276
  on: vitest_1.vi.fn().mockImplementation((event, callback) => {
286
- if (event === "close")
277
+ if (event === 'close')
287
278
  callback(1); // Non-zero exit code
288
279
  }),
289
280
  };
@@ -293,153 +284,153 @@ vitest_1.vi.mock("readline", () => ({
293
284
  // Should handle the case where opencode is not installed
294
285
  (0, vitest_1.expect)(mockSpawn).toBeDefined();
295
286
  });
296
- (0, vitest_1.it)("should install opencode via npm if user agrees", () => {
287
+ (0, vitest_1.it)('should install opencode via npm if user agrees', () => {
297
288
  // Should spawn npm install -g opencode-ai
298
289
  (0, vitest_1.expect)(mockSpawn).toBeDefined();
299
290
  });
300
291
  });
301
- (0, vitest_1.describe)("automation support", () => {
302
- (0, vitest_1.it)("should support -y flag for automated initialization", () => {
303
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
304
- const initCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "init");
292
+ (0, vitest_1.describe)('automation support', () => {
293
+ (0, vitest_1.it)('should support -y flag for automated initialization', () => {
294
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
295
+ const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
305
296
  (0, vitest_1.expect)(initCommand).toBeDefined();
306
- const yesOption = initCommand === null || initCommand === void 0 ? void 0 : initCommand.options.find(opt => opt.long === "--yes");
297
+ const yesOption = initCommand?.options.find((opt) => opt.long === '--yes');
307
298
  (0, vitest_1.expect)(yesOption).toBeDefined();
308
- (0, vitest_1.expect)(yesOption === null || yesOption === void 0 ? void 0 : yesOption.description).toContain("automation");
299
+ (0, vitest_1.expect)(yesOption?.description).toContain('automation');
309
300
  });
310
- (0, vitest_1.it)("should support -y flag for automated run", () => {
311
- const codeCommand = program.commands.find(cmd => cmd.name() === "code");
312
- const runCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "run");
301
+ (0, vitest_1.it)('should support -y flag for automated run', () => {
302
+ const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
303
+ const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
313
304
  (0, vitest_1.expect)(runCommand).toBeDefined();
314
- const yesOption = runCommand === null || runCommand === void 0 ? void 0 : runCommand.options.find(opt => opt.long === "--yes");
305
+ const yesOption = runCommand?.options.find((opt) => opt.long === '--yes');
315
306
  (0, vitest_1.expect)(yesOption).toBeDefined();
316
- (0, vitest_1.expect)(yesOption === null || yesOption === void 0 ? void 0 : yesOption.description).toContain("automation");
307
+ (0, vitest_1.expect)(yesOption?.description).toContain('automation');
317
308
  });
318
- (0, vitest_1.it)("should use BERGET_API_KEY environment variable in automation mode", () => {
309
+ (0, vitest_1.it)('should use BERGET_API_KEY environment variable in automation mode', () => {
319
310
  // Test that environment variable is used when -y flag is set
320
- process.env.BERGET_API_KEY = "test-env-key";
321
- (0, vitest_1.expect)(process.env.BERGET_API_KEY).toBe("test-env-key");
311
+ process.env.BERGET_API_KEY = 'test-env-key';
312
+ (0, vitest_1.expect)(process.env.BERGET_API_KEY).toBe('test-env-key');
322
313
  // Clean up
323
314
  delete process.env.BERGET_API_KEY;
324
315
  });
325
316
  });
326
- (0, vitest_1.describe)(".env file handling", () => {
327
- let mockUpdateEnvFile;
317
+ (0, vitest_1.describe)('.env file handling', () => {
318
+ let mockUpdateEnvironmentFile;
328
319
  (0, vitest_1.beforeEach)(() => {
329
- mockUpdateEnvFile = vitest_1.vi.mocked(env_manager_1.updateEnvFile);
320
+ mockUpdateEnvironmentFile = vitest_1.vi.mocked(env_manager_1.updateEnvFile);
330
321
  });
331
- (0, vitest_1.it)("should call updateEnvFile when creating new project", () => __awaiter(void 0, void 0, void 0, function* () {
332
- mockUpdateEnvFile.mockResolvedValue(true);
322
+ (0, vitest_1.it)('should call updateEnvFile when creating new project', async () => {
323
+ mockUpdateEnvironmentFile.mockResolvedValue(true);
333
324
  mockFs.existsSync.mockReturnValue(false); // .env doesn't exist
334
- mockFsPromises.writeFile.mockResolvedValue(undefined);
325
+ mockFsPromises.writeFile.mockResolvedValue();
335
326
  // This would be tested by actually calling the init command
336
327
  // For now we verify the mock is properly set up
337
- (0, vitest_1.expect)(mockUpdateEnvFile).toBeDefined();
338
- }));
339
- (0, vitest_1.it)("should not overwrite existing BERGET_API_KEY in .env", () => __awaiter(void 0, void 0, void 0, function* () {
340
- const consoleSpy = vitest_1.vi.spyOn(console, "log").mockImplementation(() => { });
328
+ (0, vitest_1.expect)(mockUpdateEnvironmentFile).toBeDefined();
329
+ });
330
+ (0, vitest_1.it)('should not overwrite existing BERGET_API_KEY in .env', async () => {
331
+ const consoleSpy = vitest_1.vi.spyOn(console, 'log').mockImplementation(() => { });
341
332
  // Mock existing .env with BERGET_API_KEY
342
333
  mockFs.existsSync.mockReturnValue(true);
343
- mockFs.readFileSync.mockReturnValue("BERGET_API_KEY=existing_key\nOTHER_KEY=value\n");
334
+ mockFs.readFileSync.mockReturnValue('BERGET_API_KEY=existing_key\nOTHER_KEY=value\n');
344
335
  // Mock updateEnvFile to simulate the check
345
- mockUpdateEnvFile.mockImplementation((options) => __awaiter(void 0, void 0, void 0, function* () {
346
- if (options.key === "BERGET_API_KEY" && !options.force) {
336
+ mockUpdateEnvironmentFile.mockImplementation(async (options) => {
337
+ if (options.key === 'BERGET_API_KEY' && !options.force) {
347
338
  console.log(`⚠ ${options.key} already exists in .env - leaving unchanged`);
348
339
  return false;
349
340
  }
350
341
  return true;
351
- }));
352
- yield (0, env_manager_1.updateEnvFile)({
353
- key: "BERGET_API_KEY",
354
- value: "new_key",
355
342
  });
356
- (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("BERGET_API_KEY already exists in .env - leaving unchanged"));
343
+ await (0, env_manager_1.updateEnvFile)({
344
+ key: 'BERGET_API_KEY',
345
+ value: 'new_key',
346
+ });
347
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('BERGET_API_KEY already exists in .env - leaving unchanged'));
357
348
  consoleSpy.mockRestore();
358
- }));
359
- (0, vitest_1.it)("should add new key to existing .env file", () => __awaiter(void 0, void 0, void 0, function* () {
349
+ });
350
+ (0, vitest_1.it)('should add new key to existing .env file', async () => {
360
351
  mockFs.existsSync.mockReturnValue(true);
361
- mockFs.readFileSync.mockReturnValue("EXISTING_KEY=value\n");
362
- mockUpdateEnvFile.mockResolvedValue(true);
363
- yield (0, env_manager_1.updateEnvFile)({
364
- key: "BERGET_API_KEY",
365
- value: "new_api_key",
366
- comment: "Berget AI Configuration",
352
+ mockFs.readFileSync.mockReturnValue('EXISTING_KEY=value\n');
353
+ mockUpdateEnvironmentFile.mockResolvedValue(true);
354
+ await (0, env_manager_1.updateEnvFile)({
355
+ comment: 'Berget AI Configuration',
356
+ key: 'BERGET_API_KEY',
357
+ value: 'new_api_key',
367
358
  });
368
- (0, vitest_1.expect)(mockUpdateEnvFile).toHaveBeenCalledWith({
369
- key: "BERGET_API_KEY",
370
- value: "new_api_key",
371
- comment: "Berget AI Configuration",
359
+ (0, vitest_1.expect)(mockUpdateEnvironmentFile).toHaveBeenCalledWith({
360
+ comment: 'Berget AI Configuration',
361
+ key: 'BERGET_API_KEY',
362
+ value: 'new_api_key',
372
363
  });
373
- }));
374
- (0, vitest_1.it)("should create new .env file when none exists", () => __awaiter(void 0, void 0, void 0, function* () {
364
+ });
365
+ (0, vitest_1.it)('should create new .env file when none exists', async () => {
375
366
  mockFs.existsSync.mockReturnValue(false);
376
- mockUpdateEnvFile.mockResolvedValue(true);
377
- yield (0, env_manager_1.updateEnvFile)({
378
- key: "BERGET_API_KEY",
379
- value: "new_api_key",
367
+ mockUpdateEnvironmentFile.mockResolvedValue(true);
368
+ await (0, env_manager_1.updateEnvFile)({
369
+ key: 'BERGET_API_KEY',
370
+ value: 'new_api_key',
380
371
  });
381
- (0, vitest_1.expect)(mockUpdateEnvFile).toHaveBeenCalledWith({
382
- key: "BERGET_API_KEY",
383
- value: "new_api_key",
372
+ (0, vitest_1.expect)(mockUpdateEnvironmentFile).toHaveBeenCalledWith({
373
+ key: 'BERGET_API_KEY',
374
+ value: 'new_api_key',
384
375
  });
385
- }));
376
+ });
386
377
  });
387
- (0, vitest_1.describe)("error handling", () => {
388
- (0, vitest_1.it)("should handle API key creation failures", () => {
378
+ (0, vitest_1.describe)('error handling', () => {
379
+ (0, vitest_1.it)('should handle API key creation failures', () => {
389
380
  // Mock API key service to throw error
390
- mockApiKeyService.create.mockRejectedValue(new Error("API Error"));
381
+ mockApiKeyService.create.mockRejectedValue(new Error('API Error'));
391
382
  (0, vitest_1.expect)(mockApiKeyService.create).toBeDefined();
392
383
  });
393
- (0, vitest_1.it)("should handle file system errors", () => {
384
+ (0, vitest_1.it)('should handle file system errors', () => {
394
385
  // Mock file operations to throw errors
395
- mockFsPromises.writeFile.mockRejectedValue(new Error("File write error"));
386
+ mockFsPromises.writeFile.mockRejectedValue(new Error('File write error'));
396
387
  (0, vitest_1.expect)(mockFsPromises.writeFile).toBeDefined();
397
388
  });
398
- (0, vitest_1.it)("should handle spawn errors", () => {
389
+ (0, vitest_1.it)('should handle spawn errors', () => {
399
390
  // Mock spawn to throw error
400
391
  mockSpawn.mockImplementation(() => {
401
- throw new Error("Command not found");
392
+ throw new Error('Command not found');
402
393
  });
403
394
  (0, vitest_1.expect)(mockSpawn).toBeDefined();
404
395
  });
405
- (0, vitest_1.it)("should handle .env update failures", () => __awaiter(void 0, void 0, void 0, function* () {
406
- const mockUpdateEnvFile = vitest_1.vi.mocked(env_manager_1.updateEnvFile);
407
- mockUpdateEnvFile.mockRejectedValue(new Error("Env update failed"));
408
- yield (0, vitest_1.expect)((0, env_manager_1.updateEnvFile)({
409
- key: "TEST_KEY",
410
- value: "test_value",
411
- })).rejects.toThrow("Env update failed");
412
- }));
396
+ (0, vitest_1.it)('should handle .env update failures', async () => {
397
+ const mockUpdateEnvironmentFile = vitest_1.vi.mocked(env_manager_1.updateEnvFile);
398
+ mockUpdateEnvironmentFile.mockRejectedValue(new Error('Env update failed'));
399
+ await (0, vitest_1.expect)((0, env_manager_1.updateEnvFile)({
400
+ key: 'TEST_KEY',
401
+ value: 'test_value',
402
+ })).rejects.toThrow('Env update failed');
403
+ });
413
404
  });
414
- (0, vitest_1.describe)("experimental features", () => {
415
- let originalEnv;
405
+ (0, vitest_1.describe)('experimental features', () => {
406
+ let originalEnvironment;
416
407
  (0, vitest_1.beforeEach)(() => {
417
- originalEnv = process.env.BERGET_EXPERIMENTAL;
408
+ originalEnvironment = process.env.BERGET_EXPERIMENTAL;
418
409
  });
419
410
  (0, vitest_1.afterEach)(() => {
420
- if (originalEnv === undefined) {
411
+ if (originalEnvironment === undefined) {
421
412
  delete process.env.BERGET_EXPERIMENTAL;
422
413
  }
423
414
  else {
424
- process.env.BERGET_EXPERIMENTAL = originalEnv;
415
+ process.env.BERGET_EXPERIMENTAL = originalEnvironment;
425
416
  }
426
417
  });
427
- (0, vitest_1.it)("should NOT show setup command when BERGET_EXPERIMENTAL is not set", () => {
418
+ (0, vitest_1.it)('should NOT show setup command when BERGET_EXPERIMENTAL is not set', () => {
428
419
  delete process.env.BERGET_EXPERIMENTAL;
429
420
  const freshProgram = new commander_1.Command();
430
421
  (0, code_1.registerCodeCommands)(freshProgram);
431
- const codeCommand = freshProgram.commands.find(cmd => cmd.name() === "code");
432
- const setupCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "setup");
422
+ const codeCommand = freshProgram.commands.find((cmd) => cmd.name() === 'code');
423
+ const setupCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'setup');
433
424
  (0, vitest_1.expect)(setupCommand).toBeUndefined();
434
425
  });
435
- (0, vitest_1.it)("should show setup command when BERGET_EXPERIMENTAL is set", () => {
436
- process.env.BERGET_EXPERIMENTAL = "1";
426
+ (0, vitest_1.it)('should show setup command when BERGET_EXPERIMENTAL is set', () => {
427
+ process.env.BERGET_EXPERIMENTAL = '1';
437
428
  const freshProgram = new commander_1.Command();
438
429
  (0, code_1.registerCodeCommands)(freshProgram);
439
- const codeCommand = freshProgram.commands.find(cmd => cmd.name() === "code");
440
- const setupCommand = codeCommand === null || codeCommand === void 0 ? void 0 : codeCommand.commands.find(cmd => cmd.name() === "setup");
430
+ const codeCommand = freshProgram.commands.find((cmd) => cmd.name() === 'code');
431
+ const setupCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'setup');
441
432
  (0, vitest_1.expect)(setupCommand).toBeDefined();
442
- (0, vitest_1.expect)(setupCommand === null || setupCommand === void 0 ? void 0 : setupCommand.description()).toBe("Interactive setup for Berget AI coding tools");
433
+ (0, vitest_1.expect)(setupCommand?.description()).toBe('Interactive setup for Berget AI coding tools');
443
434
  });
444
435
  });
445
436
  });