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
@@ -50,7 +50,7 @@ const child_process_1 = require("child_process");
50
50
  */
51
51
  function hasGit() {
52
52
  try {
53
- return fs.existsSync(path_1.default.join(process.cwd(), '.git'));
53
+ return fs.existsSync(path_1.default.join(process.cwd(), ".git"));
54
54
  }
55
55
  catch (_a) {
56
56
  return false;
@@ -64,36 +64,14 @@ function confirm(question, autoYes = false) {
64
64
  if (autoYes) {
65
65
  return true;
66
66
  }
67
- return new Promise((resolve) => {
67
+ return new Promise(resolve => {
68
68
  const rl = readline_1.default.createInterface({
69
69
  input: process.stdin,
70
70
  output: process.stdout,
71
71
  });
72
- rl.question(question, (answer) => {
72
+ rl.question(question, answer => {
73
73
  rl.close();
74
- resolve(answer.toLowerCase() === 'y' ||
75
- answer.toLowerCase() === 'yes' ||
76
- answer === '');
77
- });
78
- });
79
- });
80
- }
81
- /**
82
- * Helper function to get user input
83
- */
84
- function getInput(question, defaultValue, autoYes = false) {
85
- return __awaiter(this, void 0, void 0, function* () {
86
- if (autoYes) {
87
- return defaultValue;
88
- }
89
- const rl = readline_1.default.createInterface({
90
- input: process.stdin,
91
- output: process.stdout,
92
- });
93
- return new Promise((resolve) => {
94
- rl.question(question, (answer) => {
95
- rl.close();
96
- resolve(answer.trim() || defaultValue);
74
+ resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes" || answer === "");
97
75
  });
98
76
  });
99
77
  });
@@ -103,14 +81,14 @@ function getInput(question, defaultValue, autoYes = false) {
103
81
  */
104
82
  function getProjectName() {
105
83
  try {
106
- const packageJsonPath = path_1.default.join(process.cwd(), 'package.json');
84
+ const packageJsonPath = path_1.default.join(process.cwd(), "package.json");
107
85
  if (fs.existsSync(packageJsonPath)) {
108
- const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
86
+ const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
109
87
  const packageJson = JSON.parse(packageJsonContent);
110
88
  return packageJson.name || path_1.default.basename(process.cwd());
111
89
  }
112
90
  }
113
- catch (error) {
91
+ catch (_a) {
114
92
  // Ignore error and fallback to directory name
115
93
  }
116
94
  return path_1.default.basename(process.cwd());
@@ -119,99 +97,20 @@ function getProjectName() {
119
97
  * Get the path to the bundled agent templates directory
120
98
  */
121
99
  function getAgentTemplatesDir() {
122
- return path_1.default.resolve(__dirname, '../../templates/agents');
123
- }
124
- /**
125
- * Parse a markdown agent file with YAML frontmatter into an agent config object
126
- */
127
- function parseAgentMarkdown(content) {
128
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
129
- if (!frontmatterMatch) {
130
- throw new Error('Invalid agent markdown: missing frontmatter');
131
- }
132
- const yamlStr = frontmatterMatch[1];
133
- const promptBody = frontmatterMatch[2].trim();
134
- const config = { prompt: promptBody };
135
- for (const line of yamlStr.split('\n')) {
136
- const trimmed = line.trim();
137
- if (!trimmed || trimmed.startsWith('#'))
138
- continue;
139
- const colonIdx = trimmed.indexOf(':');
140
- if (colonIdx === -1)
141
- continue;
142
- const key = trimmed.substring(0, colonIdx).trim();
143
- const value = trimmed.substring(colonIdx + 1).trim();
144
- if (key === 'permission')
145
- continue;
146
- if (value === 'true') {
147
- config[key] = true;
148
- }
149
- else if (value === 'false') {
150
- config[key] = false;
151
- }
152
- else if (!isNaN(Number(value)) && value !== '') {
153
- config[key] = Number(value);
154
- }
155
- else {
156
- config[key] = value;
157
- }
158
- }
159
- const permission = {};
160
- const permMatch = yamlStr.match(/permission:\s*\n((?:\s+\w+:.*\n?)*)/);
161
- if (permMatch) {
162
- for (const permLine of permMatch[1].split('\n')) {
163
- const permTrimmed = permLine.trim();
164
- if (!permTrimmed)
165
- continue;
166
- const permColonIdx = permTrimmed.indexOf(':');
167
- if (permColonIdx === -1)
168
- continue;
169
- const permKey = permTrimmed.substring(0, permColonIdx).trim();
170
- const permValue = permTrimmed.substring(permColonIdx + 1).trim();
171
- if (permKey && permValue) {
172
- permission[permKey] = permValue;
173
- }
174
- }
175
- }
176
- if (Object.keys(permission).length > 0) {
177
- config.permission = permission;
178
- }
179
- return config;
180
- }
181
- /**
182
- * Load the latest agent configuration from bundled markdown templates
183
- */
184
- function loadLatestAgentConfig() {
185
- return __awaiter(this, void 0, void 0, function* () {
186
- const templatesDir = getAgentTemplatesDir();
187
- const agents = {};
188
- const files = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
189
- for (const file of files) {
190
- const agentName = path_1.default.basename(file, '.md');
191
- const filePath = path_1.default.join(templatesDir, file);
192
- const content = fs.readFileSync(filePath, 'utf8');
193
- try {
194
- agents[agentName] = parseAgentMarkdown(content);
195
- }
196
- catch (error) {
197
- console.warn(chalk_1.default.yellow(`Warning: Failed to parse agent template ${file}: ${error}`));
198
- }
199
- }
200
- return agents;
201
- });
100
+ return path_1.default.resolve(__dirname, "../../templates/agents");
202
101
  }
203
102
  /**
204
103
  * Check if opencode is installed
205
104
  */
206
105
  function checkOpencodeInstalled() {
207
- return new Promise((resolve) => {
208
- const child = (0, child_process_1.spawn)('which', ['opencode'], {
209
- stdio: 'pipe',
106
+ return new Promise(resolve => {
107
+ const child = (0, child_process_1.spawn)("which", ["opencode"], {
108
+ stdio: "pipe",
210
109
  });
211
- child.on('close', (code) => {
110
+ child.on("close", code => {
212
111
  resolve(code === 0);
213
112
  });
214
- child.on('error', () => {
113
+ child.on("error", () => {
215
114
  resolve(false);
216
115
  });
217
116
  });
@@ -221,38 +120,38 @@ function checkOpencodeInstalled() {
221
120
  */
222
121
  function installOpencode() {
223
122
  return __awaiter(this, void 0, void 0, function* () {
224
- console.log(chalk_1.default.cyan('Installing OpenCode via npm...'));
123
+ console.log(chalk_1.default.cyan("Installing OpenCode via npm..."));
225
124
  try {
226
125
  yield new Promise((resolve, reject) => {
227
- const install = (0, child_process_1.spawn)('npm', ['install', '-g', 'opencode-ai@1.3'], {
228
- stdio: 'inherit',
126
+ const install = (0, child_process_1.spawn)("npm", ["install", "-g", "opencode-ai@1.3"], {
127
+ stdio: "inherit",
229
128
  });
230
- install.on('close', (code) => {
129
+ install.on("close", code => {
231
130
  if (code === 0) {
232
- console.log(chalk_1.default.green('✓ OpenCode installed successfully!'));
131
+ console.log(chalk_1.default.green("✓ OpenCode installed successfully!"));
233
132
  resolve();
234
133
  }
235
134
  else {
236
135
  reject(new Error(`Installation failed with code ${code}`));
237
136
  }
238
137
  });
239
- install.on('error', reject);
138
+ install.on("error", reject);
240
139
  });
241
140
  // Verify installation
242
141
  const opencodeInstalled = yield checkOpencodeInstalled();
243
142
  if (!opencodeInstalled) {
244
- console.log(chalk_1.default.yellow('Installation completed but opencode command not found.'));
245
- console.log(chalk_1.default.yellow('You may need to restart your terminal or check your PATH.'));
143
+ console.log(chalk_1.default.yellow("Installation completed but opencode command not found."));
144
+ console.log(chalk_1.default.yellow("You may need to restart your terminal or check your PATH."));
246
145
  return false;
247
146
  }
248
147
  return true;
249
148
  }
250
149
  catch (error) {
251
- console.error(chalk_1.default.red('Failed to install OpenCode:'));
150
+ console.error(chalk_1.default.red("Failed to install OpenCode:"));
252
151
  console.error(error instanceof Error ? error.message : String(error));
253
- console.log(chalk_1.default.blue('\nAlternative installation methods:'));
254
- console.log(chalk_1.default.blue(' curl -fsSL https://opencode.ai/install | sh'));
255
- console.log(chalk_1.default.blue(' Or visit: https://opencode.ai/docs'));
152
+ console.log(chalk_1.default.blue("\nAlternative installation methods:"));
153
+ console.log(chalk_1.default.blue(" curl -fsSL https://opencode.ai/install | sh"));
154
+ console.log(chalk_1.default.blue(" Or visit: https://opencode.ai/docs"));
256
155
  return false;
257
156
  }
258
157
  });
@@ -265,17 +164,17 @@ function ensureOpencodeInstalled(autoYes = false) {
265
164
  let opencodeInstalled = yield checkOpencodeInstalled();
266
165
  if (!opencodeInstalled) {
267
166
  if (!autoYes) {
268
- console.log(chalk_1.default.red('OpenCode is not installed.'));
269
- console.log(chalk_1.default.blue('OpenCode is required for the AI coding assistant.'));
167
+ console.log(chalk_1.default.red("OpenCode is not installed."));
168
+ console.log(chalk_1.default.blue("OpenCode is required for the AI coding assistant."));
270
169
  }
271
- if (yield confirm('Would you like to install OpenCode automatically? (Y/n): ', autoYes)) {
170
+ if (yield confirm("Would you like to install OpenCode automatically? (Y/n): ", autoYes)) {
272
171
  opencodeInstalled = yield installOpencode();
273
172
  }
274
173
  else {
275
174
  if (!autoYes) {
276
- console.log(chalk_1.default.blue('\nInstallation cancelled.'));
277
- console.log(chalk_1.default.blue('To install manually: curl -fsSL https://opencode.ai/install | bash'));
278
- console.log(chalk_1.default.blue('Or visit: https://opencode.ai/docs'));
175
+ console.log(chalk_1.default.blue("\nInstallation cancelled."));
176
+ console.log(chalk_1.default.blue("To install manually: curl -fsSL https://opencode.ai/install | bash"));
177
+ console.log(chalk_1.default.blue("Or visit: https://opencode.ai/docs"));
279
178
  }
280
179
  }
281
180
  }
@@ -288,37 +187,37 @@ function ensureOpencodeInstalled(autoYes = false) {
288
187
  function registerCodeCommands(program) {
289
188
  const code = program
290
189
  .command(command_structure_1.COMMAND_GROUPS.CODE)
291
- .description('AI-powered coding assistant with OpenCode');
190
+ .description("AI-powered coding assistant with OpenCode");
292
191
  if (process.env.BERGET_EXPERIMENTAL) {
293
192
  code
294
- .command('setup')
295
- .description('Interactive setup for Berget AI coding tools')
193
+ .command("setup")
194
+ .description("Interactive setup for Berget AI coding tools")
296
195
  .action(() => __awaiter(this, void 0, void 0, function* () {
297
196
  try {
298
197
  yield (0, setup_1.runSetupCommand)();
299
198
  }
300
199
  catch (error) {
301
- (0, error_handler_1.handleError)('Setup failed', error);
200
+ (0, error_handler_1.handleError)("Setup failed", error);
302
201
  }
303
202
  }));
304
203
  }
305
204
  code
306
205
  .command(command_structure_1.SUBCOMMANDS.CODE.INIT)
307
- .description('Initialize project for AI coding assistant')
308
- .option('-n, --name <name>', 'Project name (defaults to directory name)')
309
- .option('-f, --force', 'Overwrite existing configuration')
310
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
206
+ .description("Initialize project for AI coding assistant")
207
+ .option("-n, --name <name>", "Project name (defaults to directory name)")
208
+ .option("-f, --force", "Overwrite existing configuration")
209
+ .option("-y, --yes", "Automatically answer yes to all prompts (for automation)")
311
210
  .action((options) => __awaiter(this, void 0, void 0, function* () {
312
211
  try {
313
212
  const projectName = options.name || getProjectName();
314
- const configPath = path_1.default.join(process.cwd(), 'opencode.json');
213
+ const configPath = path_1.default.join(process.cwd(), "opencode.json");
315
214
  // Check if already initialized
316
215
  if (fs.existsSync(configPath) && !options.force) {
317
216
  if (!options.yes) {
318
- console.log(chalk_1.default.yellow('Project already initialized for OpenCode.'));
217
+ console.log(chalk_1.default.yellow("Project already initialized for OpenCode."));
319
218
  console.log(chalk_1.default.dim(`Config file: ${configPath}`));
320
219
  }
321
- if (yield confirm('Do you want to reinitialize? (Y/n): ', options.yes)) {
220
+ if (yield confirm("Do you want to reinitialize? (Y/n): ", options.yes)) {
322
221
  // Continue with reinitialization
323
222
  }
324
223
  else {
@@ -331,26 +230,24 @@ function registerCodeCommands(program) {
331
230
  }
332
231
  console.log(chalk_1.default.cyan(`Initializing OpenCode for project: ${projectName}`));
333
232
  const config = {
334
- $schema: 'https://opencode.ai/config.json',
335
- plugin: ['@bergetai/opencode-auth@1.0.16'],
233
+ $schema: "https://opencode.ai/config.json",
234
+ plugin: ["@bergetai/opencode-auth@1.0.16"],
336
235
  };
337
- const agentsDir = path_1.default.join(process.cwd(), '.opencode', 'agents');
236
+ const agentsDir = path_1.default.join(process.cwd(), ".opencode", "agents");
338
237
  const templatesDir = getAgentTemplatesDir();
339
238
  if (!options.yes) {
340
- console.log(chalk_1.default.blue('\nAbout to create configuration files:'));
239
+ console.log(chalk_1.default.blue("\nAbout to create configuration files:"));
341
240
  console.log(chalk_1.default.dim(`Config: ${configPath}`));
342
241
  console.log(chalk_1.default.dim(`Agents: ${agentsDir}/`));
343
- console.log(chalk_1.default.dim('This will configure OpenCode with the Berget auth plugin.'));
242
+ console.log(chalk_1.default.dim("This will configure OpenCode with the Berget auth plugin."));
344
243
  }
345
- if (yield confirm('\nCreate configuration files? (Y/n): ', options.yes)) {
244
+ if (yield confirm("\nCreate configuration files? (Y/n): ", options.yes)) {
346
245
  try {
347
246
  yield (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2));
348
- console.log(chalk_1.default.green('✓ Created opencode.json'));
349
- console.log(chalk_1.default.dim(' Plugin: @bergetai/opencode-auth'));
247
+ console.log(chalk_1.default.green("✓ Created opencode.json"));
248
+ console.log(chalk_1.default.dim(" Plugin: @bergetai/opencode-auth"));
350
249
  fs.mkdirSync(agentsDir, { recursive: true });
351
- const templateFiles = fs
352
- .readdirSync(templatesDir)
353
- .filter((f) => f.endsWith('.md'));
250
+ const templateFiles = fs.readdirSync(templatesDir).filter(f => f.endsWith(".md"));
354
251
  for (const file of templateFiles) {
355
252
  const src = path_1.default.join(templatesDir, file);
356
253
  const dest = path_1.default.join(agentsDir, file);
@@ -359,38 +256,38 @@ function registerCodeCommands(program) {
359
256
  console.log(chalk_1.default.green(`✓ Created ${templateFiles.length} agent definitions in .opencode/agents/`));
360
257
  }
361
258
  catch (error) {
362
- console.error(chalk_1.default.red('Failed to create config files:'));
363
- (0, error_handler_1.handleError)('Config file creation failed', error);
259
+ console.error(chalk_1.default.red("Failed to create config files:"));
260
+ (0, error_handler_1.handleError)("Config file creation failed", error);
364
261
  return;
365
262
  }
366
263
  }
367
264
  else {
368
- console.log(chalk_1.default.yellow('Configuration file creation cancelled.'));
265
+ console.log(chalk_1.default.yellow("Configuration file creation cancelled."));
369
266
  return;
370
267
  }
371
- console.log(chalk_1.default.green('\n✅ Project initialized successfully!'));
372
- console.log(chalk_1.default.blue('\nNext steps:'));
373
- console.log(chalk_1.default.cyan(' 1. Run: opencode'));
374
- console.log(chalk_1.default.cyan(' 2. Type: /connect'));
375
- console.log(chalk_1.default.cyan(' 3. Choose your auth method:'));
268
+ console.log(chalk_1.default.green("\n✅ Project initialized successfully!"));
269
+ console.log(chalk_1.default.blue("\nNext steps:"));
270
+ console.log(chalk_1.default.cyan(" 1. Run: opencode"));
271
+ console.log(chalk_1.default.cyan(" 2. Type: /connect"));
272
+ console.log(chalk_1.default.cyan(" 3. Choose your auth method:"));
376
273
  console.log(chalk_1.default.dim(' • "Login with Berget" — Berget Code team members (SSO)'));
377
274
  console.log(chalk_1.default.dim(' • "Enter API Key" — API key users (console.berget.ai)'));
378
275
  }
379
276
  catch (error) {
380
- (0, error_handler_1.handleError)('Failed to initialize project', error);
277
+ (0, error_handler_1.handleError)("Failed to initialize project", error);
381
278
  }
382
279
  }));
383
280
  code
384
281
  .command(command_structure_1.SUBCOMMANDS.CODE.RUN)
385
- .description('Run AI coding assistant')
386
- .argument('[prompt]', 'Prompt to send directly to OpenCode')
387
- .option('-m, --model <model>', 'Model to use (overrides config)')
388
- .option('-a, --analysis', 'Use fast analysis model for context building')
389
- .option('--no-config', 'Run without loading project config')
390
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
282
+ .description("Run AI coding assistant")
283
+ .argument("[prompt]", "Prompt to send directly to OpenCode")
284
+ .option("-m, --model <model>", "Model to use (overrides config)")
285
+ .option("-a, --analysis", "Use fast analysis model for context building")
286
+ .option("--no-config", "Run without loading project config")
287
+ .option("-y, --yes", "Automatically answer yes to all prompts (for automation)")
391
288
  .action((prompt, options) => __awaiter(this, void 0, void 0, function* () {
392
289
  try {
393
- const configPath = path_1.default.join(process.cwd(), 'opencode.json');
290
+ const configPath = path_1.default.join(process.cwd(), "opencode.json");
394
291
  // Ensure opencode is installed
395
292
  if (!(yield ensureOpencodeInstalled(options.yes))) {
396
293
  return;
@@ -398,17 +295,17 @@ function registerCodeCommands(program) {
398
295
  let config = null;
399
296
  if (!options.noConfig && fs.existsSync(configPath)) {
400
297
  try {
401
- const configContent = yield (0, promises_1.readFile)(configPath, 'utf8');
298
+ const configContent = yield (0, promises_1.readFile)(configPath, "utf8");
402
299
  config = JSON.parse(configContent);
403
300
  console.log(chalk_1.default.dim(`Loaded config for project: ${config.projectName}`));
404
301
  console.log(chalk_1.default.dim(`Models: Analysis=${config.analysisModel}, Build=${config.buildModel}`));
405
302
  }
406
- catch (error) {
407
- console.log(chalk_1.default.yellow('Warning: Failed to load opencode.json'));
303
+ catch (_a) {
304
+ console.log(chalk_1.default.yellow("Warning: Failed to load opencode.json"));
408
305
  }
409
306
  }
410
307
  if (!config) {
411
- console.log(chalk_1.default.yellow('No project configuration found.'));
308
+ console.log(chalk_1.default.yellow("No project configuration found."));
412
309
  console.log(chalk_1.default.blue(`Run ${chalk_1.default.bold(`berget ${command_structure_1.COMMAND_GROUPS.CODE} ${command_structure_1.SUBCOMMANDS.CODE.INIT}`)} first.`));
413
310
  return;
414
311
  }
@@ -417,20 +314,20 @@ function registerCodeCommands(program) {
417
314
  const opencodeArgs = [];
418
315
  // Read --stage and --local from root program options
419
316
  // (these flags are registered at program level, not subcommand level)
420
- const isStage = process.argv.includes('--stage');
421
- const isLocal = process.argv.includes('--local');
317
+ const isStage = process.argv.includes("--stage");
318
+ const isLocal = process.argv.includes("--local");
422
319
  if (isStage) {
423
- console.log(chalk_1.default.cyan('Using Berget stage environment'));
424
- env.BERGET_API_URL = 'https://api.stage.berget.ai';
425
- env.BERGET_INFERENCE_URL = 'https://api.stage.berget.ai/v1';
320
+ console.log(chalk_1.default.cyan("Using Berget stage environment"));
321
+ env.BERGET_API_URL = "https://api.stage.berget.ai";
322
+ env.BERGET_INFERENCE_URL = "https://api.stage.berget.ai/v1";
426
323
  }
427
324
  else if (isLocal) {
428
- console.log(chalk_1.default.cyan('Using local development environment'));
429
- env.BERGET_API_URL = 'http://localhost:3000';
430
- env.BERGET_INFERENCE_URL = 'http://localhost:3000/v1';
325
+ console.log(chalk_1.default.cyan("Using local development environment"));
326
+ env.BERGET_API_URL = "http://localhost:3000";
327
+ env.BERGET_INFERENCE_URL = "http://localhost:3000/v1";
431
328
  }
432
329
  if (prompt) {
433
- opencodeArgs.push('run', prompt);
330
+ opencodeArgs.push("run", prompt);
434
331
  }
435
332
  // Choose model based on analysis flag or override
436
333
  let selectedModel = options.model || config.buildModel;
@@ -438,115 +335,106 @@ function registerCodeCommands(program) {
438
335
  selectedModel = config.analysisModel;
439
336
  }
440
337
  if (selectedModel) {
441
- opencodeArgs.push('--model', selectedModel);
338
+ opencodeArgs.push("--model", selectedModel);
442
339
  }
443
- console.log(chalk_1.default.cyan('Starting OpenCode...'));
340
+ console.log(chalk_1.default.cyan("Starting OpenCode..."));
444
341
  // Spawn opencode process
445
- const opencode = (0, child_process_1.spawn)('opencode', opencodeArgs, {
446
- stdio: 'inherit',
342
+ const opencode = (0, child_process_1.spawn)("opencode", opencodeArgs, {
343
+ stdio: "inherit",
447
344
  env: env,
448
345
  });
449
- opencode.on('close', (code) => {
346
+ opencode.on("close", code => {
450
347
  if (code !== 0) {
451
348
  console.log(chalk_1.default.red(`OpenCode exited with code ${code}`));
452
349
  }
453
350
  });
454
- opencode.on('error', (error) => {
455
- console.error(chalk_1.default.red('Failed to start OpenCode:'));
351
+ opencode.on("error", error => {
352
+ console.error(chalk_1.default.red("Failed to start OpenCode:"));
456
353
  console.error(error.message);
457
354
  });
458
355
  }
459
356
  catch (error) {
460
- (0, error_handler_1.handleError)('Failed to run OpenCode', error);
357
+ (0, error_handler_1.handleError)("Failed to run OpenCode", error);
461
358
  }
462
359
  }));
463
360
  code
464
361
  .command(command_structure_1.SUBCOMMANDS.CODE.SERVE)
465
- .description('Start OpenCode web server')
466
- .option('-p, --port <port>', 'Port to run the server on (default: 3000)')
467
- .option('-h, --host <host>', 'Host to bind the server to (default: localhost)')
468
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
362
+ .description("Start OpenCode web server")
363
+ .option("-p, --port <port>", "Port to run the server on (default: 3000)")
364
+ .option("-h, --host <host>", "Host to bind the server to (default: localhost)")
365
+ .option("-y, --yes", "Automatically answer yes to all prompts (for automation)")
469
366
  .action((options) => __awaiter(this, void 0, void 0, function* () {
470
367
  try {
471
368
  // Ensure opencode is installed
472
369
  if (!(yield ensureOpencodeInstalled(options.yes))) {
473
370
  return;
474
371
  }
475
- console.log(chalk_1.default.cyan('🚀 Starting OpenCode web server...'));
372
+ console.log(chalk_1.default.cyan("🚀 Starting OpenCode web server..."));
476
373
  // Prepare opencode serve command
477
- const serveArgs = ['serve'];
374
+ const serveArgs = ["serve"];
478
375
  if (options.port) {
479
- serveArgs.push('--port', options.port);
376
+ serveArgs.push("--port", options.port);
480
377
  }
481
378
  if (options.host) {
482
- serveArgs.push('--host', options.host);
379
+ serveArgs.push("--host", options.host);
483
380
  }
484
381
  // Spawn opencode serve process
485
- const opencode = (0, child_process_1.spawn)('opencode', serveArgs, {
486
- stdio: 'inherit',
382
+ const opencode = (0, child_process_1.spawn)("opencode", serveArgs, {
383
+ stdio: "inherit",
487
384
  });
488
- opencode.on('close', (code) => {
385
+ opencode.on("close", code => {
489
386
  if (code !== 0) {
490
387
  console.log(chalk_1.default.red(`OpenCode server exited with code ${code}`));
491
388
  }
492
389
  });
493
- opencode.on('error', (error) => {
494
- console.error(chalk_1.default.red('Failed to start OpenCode server:'));
390
+ opencode.on("error", error => {
391
+ console.error(chalk_1.default.red("Failed to start OpenCode server:"));
495
392
  console.error(error.message);
496
393
  });
497
394
  }
498
395
  catch (error) {
499
- (0, error_handler_1.handleError)('Failed to start OpenCode server', error);
396
+ (0, error_handler_1.handleError)("Failed to start OpenCode server", error);
500
397
  }
501
398
  }));
502
399
  code
503
400
  .command(command_structure_1.SUBCOMMANDS.CODE.UPDATE)
504
- .description('Update OpenCode and agents to latest versions')
505
- .option('-f, --force', 'Force update even if already latest')
506
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
401
+ .description("Update OpenCode and agents to latest versions")
402
+ .option("-f, --force", "Force update even if already latest")
403
+ .option("-y, --yes", "Automatically answer yes to all prompts (for automation)")
507
404
  .action((options) => __awaiter(this, void 0, void 0, function* () {
508
405
  try {
509
- console.log(chalk_1.default.cyan('🔄 Updating OpenCode configuration...'));
406
+ console.log(chalk_1.default.cyan("🔄 Updating OpenCode configuration..."));
510
407
  // Ensure opencode is installed first
511
408
  if (!(yield ensureOpencodeInstalled(options.yes))) {
512
409
  return;
513
410
  }
514
- const configPath = path_1.default.join(process.cwd(), 'opencode.json');
411
+ const configPath = path_1.default.join(process.cwd(), "opencode.json");
515
412
  // Check if project is initialized
516
413
  if (!fs.existsSync(configPath)) {
517
- console.log(chalk_1.default.red('❌ No OpenCode configuration found.'));
414
+ console.log(chalk_1.default.red("❌ No OpenCode configuration found."));
518
415
  console.log(chalk_1.default.blue(`Run ${chalk_1.default.bold(`berget ${command_structure_1.COMMAND_GROUPS.CODE} ${command_structure_1.SUBCOMMANDS.CODE.INIT}`)} first.`));
519
416
  return;
520
417
  }
521
418
  // Read current configuration
522
419
  let currentConfig;
523
420
  try {
524
- const configContent = yield (0, promises_1.readFile)(configPath, 'utf8');
421
+ const configContent = yield (0, promises_1.readFile)(configPath, "utf8");
525
422
  currentConfig = JSON.parse(configContent);
526
423
  }
527
424
  catch (error) {
528
- console.error(chalk_1.default.red('Failed to read current opencode.json:'));
529
- (0, error_handler_1.handleError)('Config read failed', error);
425
+ console.error(chalk_1.default.red("Failed to read current opencode.json:"));
426
+ (0, error_handler_1.handleError)("Config read failed", error);
530
427
  return;
531
428
  }
532
- console.log(chalk_1.default.blue('📋 Current configuration:'));
429
+ console.log(chalk_1.default.blue("📋 Current configuration:"));
533
430
  if (currentConfig.model) {
534
431
  console.log(chalk_1.default.dim(` Model: ${currentConfig.model}`));
535
432
  }
536
- const agentsDir = path_1.default.join(process.cwd(), '.opencode', 'agents');
433
+ const agentsDir = path_1.default.join(process.cwd(), ".opencode", "agents");
537
434
  const templatesDir = getAgentTemplatesDir();
538
- const templateFiles = fs
539
- .readdirSync(templatesDir)
540
- .filter((f) => f.endsWith('.md'));
541
- const latestConfig = {
542
- $schema: 'https://opencode.ai/config.json',
543
- plugin: ['@bergetai/opencode-auth@1.0.16'],
544
- };
435
+ const templateFiles = fs.readdirSync(templatesDir).filter(f => f.endsWith(".md"));
545
436
  // Check if agent definitions need updating
546
437
  let agentsNeedUpdate = false;
547
- const existingAgentFiles = fs.existsSync(agentsDir)
548
- ? fs.readdirSync(agentsDir).filter((f) => f.endsWith('.md'))
549
- : [];
550
438
  for (const file of templateFiles) {
551
439
  const src = path_1.default.join(templatesDir, file);
552
440
  const dest = path_1.default.join(agentsDir, file);
@@ -554,8 +442,8 @@ function registerCodeCommands(program) {
554
442
  agentsNeedUpdate = true;
555
443
  break;
556
444
  }
557
- const srcContent = fs.readFileSync(src, 'utf8');
558
- const destContent = fs.readFileSync(dest, 'utf8');
445
+ const srcContent = fs.readFileSync(src, "utf8");
446
+ const destContent = fs.readFileSync(dest, "utf8");
559
447
  if (srcContent !== destContent) {
560
448
  agentsNeedUpdate = true;
561
449
  break;
@@ -564,32 +452,32 @@ function registerCodeCommands(program) {
564
452
  // Check if opencode.json still has inline agent config (needs migration)
565
453
  const needsMigration = !!currentConfig.agent;
566
454
  if (!agentsNeedUpdate && !needsMigration && !options.force) {
567
- console.log(chalk_1.default.green('✅ Already using the latest configuration!'));
455
+ console.log(chalk_1.default.green("✅ Already using the latest configuration!"));
568
456
  return;
569
457
  }
570
458
  if (agentsNeedUpdate || needsMigration) {
571
- console.log(chalk_1.default.blue('\n🔄 Updates available:'));
459
+ console.log(chalk_1.default.blue("\n🔄 Updates available:"));
572
460
  if (needsMigration) {
573
- console.log(chalk_1.default.cyan(' • Migrate agents from opencode.json to .opencode/agents/'));
461
+ console.log(chalk_1.default.cyan(" • Migrate agents from opencode.json to .opencode/agents/"));
574
462
  }
575
463
  if (agentsNeedUpdate) {
576
- console.log(chalk_1.default.cyan(' • Latest agent prompts and improvements'));
464
+ console.log(chalk_1.default.cyan(" • Latest agent prompts and improvements"));
577
465
  }
578
466
  }
579
467
  if (options.force) {
580
- console.log(chalk_1.default.yellow('🔧 Force update requested'));
468
+ console.log(chalk_1.default.yellow("🔧 Force update requested"));
581
469
  }
582
470
  if (!options.yes) {
583
- console.log(chalk_1.default.blue('\nThis will update your agent definitions and OpenCode configuration.'));
471
+ console.log(chalk_1.default.blue("\nThis will update your agent definitions and OpenCode configuration."));
584
472
  const hasGitRepo = hasGit();
585
473
  if (!hasGitRepo) {
586
- console.log(chalk_1.default.yellow('⚠️ No .git repository detected - backup will be created'));
474
+ console.log(chalk_1.default.yellow("⚠️ No .git repository detected - backup will be created"));
587
475
  }
588
476
  else {
589
- console.log(chalk_1.default.green('✓ Git repository detected - changes are tracked'));
477
+ console.log(chalk_1.default.green("✓ Git repository detected - changes are tracked"));
590
478
  }
591
479
  }
592
- if (yield confirm('\nProceed with update? (Y/n): ', options.yes)) {
480
+ if (yield confirm("\nProceed with update? (Y/n): ", options.yes)) {
593
481
  try {
594
482
  let backupPath = null;
595
483
  if (!hasGit()) {
@@ -601,7 +489,7 @@ function registerCodeCommands(program) {
601
489
  if (currentConfig.agent) {
602
490
  delete currentConfig.agent;
603
491
  yield (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
604
- console.log(chalk_1.default.green('✓ Removed inline agent config from opencode.json'));
492
+ console.log(chalk_1.default.green("✓ Removed inline agent config from opencode.json"));
605
493
  }
606
494
  // Sync agent markdown files from templates
607
495
  fs.mkdirSync(agentsDir, { recursive: true });
@@ -609,9 +497,9 @@ function registerCodeCommands(program) {
609
497
  for (const file of templateFiles) {
610
498
  const src = path_1.default.join(templatesDir, file);
611
499
  const dest = path_1.default.join(agentsDir, file);
612
- const agentName = path_1.default.basename(file, '.md');
500
+ const agentName = path_1.default.basename(file, ".md");
613
501
  if (!fs.existsSync(dest) ||
614
- fs.readFileSync(src, 'utf8') !== fs.readFileSync(dest, 'utf8')) {
502
+ fs.readFileSync(src, "utf8") !== fs.readFileSync(dest, "utf8")) {
615
503
  fs.copyFileSync(src, dest);
616
504
  updatedCount++;
617
505
  console.log(chalk_1.default.cyan(` • Updated agent: ${agentName}`));
@@ -621,7 +509,7 @@ function registerCodeCommands(program) {
621
509
  console.log(chalk_1.default.green(`✓ Updated ${updatedCount} agent definition(s)`));
622
510
  }
623
511
  // Update AGENTS.md if it doesn't exist
624
- const agentsMdPath = path_1.default.join(process.cwd(), 'AGENTS.md');
512
+ const agentsMdPath = path_1.default.join(process.cwd(), "AGENTS.md");
625
513
  if (!fs.existsSync(agentsMdPath)) {
626
514
  const agentsMdContent = `# Berget Code Agents
627
515
 
@@ -673,28 +561,28 @@ See https://opencode.ai/docs/agents/ for available options.
673
561
  *Updated by berget code update*
674
562
  `;
675
563
  yield (0, promises_1.writeFile)(agentsMdPath, agentsMdContent);
676
- console.log(chalk_1.default.green('✓ Created AGENTS.md documentation'));
564
+ console.log(chalk_1.default.green("✓ Created AGENTS.md documentation"));
677
565
  }
678
- console.log(chalk_1.default.green('\n✅ Update completed successfully!'));
566
+ console.log(chalk_1.default.green("\n✅ Update completed successfully!"));
679
567
  }
680
568
  catch (error) {
681
- console.error(chalk_1.default.red('Failed to update configuration:'));
682
- (0, error_handler_1.handleError)('Update failed', error);
569
+ console.error(chalk_1.default.red("Failed to update configuration:"));
570
+ (0, error_handler_1.handleError)("Update failed", error);
683
571
  try {
684
572
  yield (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
685
- console.log(chalk_1.default.yellow('📁 Restored original configuration from backup'));
573
+ console.log(chalk_1.default.yellow("📁 Restored original configuration from backup"));
686
574
  }
687
- catch (restoreError) {
688
- console.error(chalk_1.default.red('Failed to restore backup:'));
575
+ catch (_b) {
576
+ console.error(chalk_1.default.red("Failed to restore backup:"));
689
577
  }
690
578
  }
691
579
  }
692
580
  else {
693
- console.log(chalk_1.default.yellow('Update cancelled.'));
581
+ console.log(chalk_1.default.yellow("Update cancelled."));
694
582
  }
695
583
  }
696
- catch (error) {
697
- (0, error_handler_1.handleError)('Failed to update OpenCode configuration', error);
584
+ catch (_c) {
585
+ console.error(chalk_1.default.red("Failed to update OpenCode configuration"));
698
586
  }
699
587
  }));
700
588
  }