berget 2.2.11 → 2.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/commands/code/__tests__/setup-flow.test.js +34 -34
- package/dist/src/commands/code/auth-sync.js +3 -3
- package/dist/src/commands/code/{setup.js → init.js} +17 -29
- package/dist/src/commands/code.js +5 -553
- package/dist/src/constants/command-structure.js +1 -9
- package/dist/src/services/auth-service.js +1 -1
- package/dist/tests/commands/code.test.js +4 -415
- package/package.json +1 -1
- package/src/commands/code/__tests__/setup-flow.test.ts +36 -36
- package/src/commands/code/auth-sync.ts +3 -3
- package/src/commands/code/{setup.ts → init.ts} +14 -26
- package/src/commands/code.ts +5 -608
- package/src/constants/command-structure.ts +1 -11
- package/src/services/auth-service.ts +1 -1
- package/tests/commands/code.test.ts +5 -483
- package/templates/agents/app.md +0 -23
- package/templates/agents/backend.md +0 -23
- package/templates/agents/devops.md +0 -30
- package/templates/agents/frontend.md +0 -25
- package/templates/agents/fullstack.md +0 -23
- package/templates/agents/quality.md +0 -69
- package/templates/agents/security.md +0 -21
|
@@ -1,41 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
3
|
exports.registerCodeCommands = void 0;
|
|
30
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
31
|
-
const node_child_process_1 = require("node:child_process");
|
|
32
|
-
const fs = __importStar(require("node:fs"));
|
|
33
|
-
const promises_1 = require("node:fs/promises");
|
|
34
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
35
|
-
const node_readline_1 = __importDefault(require("node:readline"));
|
|
36
4
|
const command_structure_1 = require("../constants/command-structure");
|
|
37
5
|
const error_handler_1 = require("../utils/error-handler");
|
|
38
|
-
const
|
|
6
|
+
const init_1 = require("./code/init");
|
|
39
7
|
/**
|
|
40
8
|
* Register code commands
|
|
41
9
|
*/
|
|
@@ -43,532 +11,16 @@ function registerCodeCommands(program) {
|
|
|
43
11
|
const code = program
|
|
44
12
|
.command(command_structure_1.COMMAND_GROUPS.CODE)
|
|
45
13
|
.description('AI-powered coding assistant with OpenCode');
|
|
46
|
-
if (process.env.BERGET_EXPERIMENTAL) {
|
|
47
|
-
code
|
|
48
|
-
.command('setup')
|
|
49
|
-
.description('Interactive setup for Berget AI coding tools')
|
|
50
|
-
.action(async () => {
|
|
51
|
-
try {
|
|
52
|
-
await (0, setup_1.runSetupCommand)();
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
(0, error_handler_1.handleError)('Setup failed', error);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
14
|
code
|
|
60
15
|
.command(command_structure_1.SUBCOMMANDS.CODE.INIT)
|
|
61
|
-
.description('
|
|
62
|
-
.
|
|
63
|
-
.option('-f, --force', 'Overwrite existing configuration')
|
|
64
|
-
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
65
|
-
.action(async (options) => {
|
|
16
|
+
.description('Interactive setup for Berget AI coding tools')
|
|
17
|
+
.action(async () => {
|
|
66
18
|
try {
|
|
67
|
-
|
|
68
|
-
const configPath = node_path_1.default.join(process.cwd(), 'opencode.json');
|
|
69
|
-
// Check if already initialized
|
|
70
|
-
if (fs.existsSync(configPath) && !options.force) {
|
|
71
|
-
if (!options.yes) {
|
|
72
|
-
console.log(chalk_1.default.yellow('Project already initialized for OpenCode.'));
|
|
73
|
-
console.log(chalk_1.default.dim(`Config file: ${configPath}`));
|
|
74
|
-
}
|
|
75
|
-
if (await confirm('Do you want to reinitialize? (Y/n): ', options.yes)) {
|
|
76
|
-
// Continue with reinitialization
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Ensure opencode is installed
|
|
83
|
-
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
console.log(chalk_1.default.cyan(`Initializing OpenCode for project: ${projectName}`));
|
|
87
|
-
const config = {
|
|
88
|
-
$schema: 'https://opencode.ai/config.json',
|
|
89
|
-
plugin: ['@bergetai/opencode-auth@1.0.16'],
|
|
90
|
-
};
|
|
91
|
-
const agentsDir = node_path_1.default.join(process.cwd(), '.opencode', 'agents');
|
|
92
|
-
const templatesDir = getAgentTemplatesDir();
|
|
93
|
-
if (!options.yes) {
|
|
94
|
-
console.log(chalk_1.default.blue('\nAbout to create configuration files:'));
|
|
95
|
-
console.log(chalk_1.default.dim(`Config: ${configPath}`));
|
|
96
|
-
console.log(chalk_1.default.dim(`Agents: ${agentsDir}/`));
|
|
97
|
-
console.log(chalk_1.default.dim('This will configure OpenCode with the Berget auth plugin.'));
|
|
98
|
-
}
|
|
99
|
-
if (await confirm('\nCreate configuration files? (Y/n): ', options.yes)) {
|
|
100
|
-
try {
|
|
101
|
-
await (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2));
|
|
102
|
-
console.log(chalk_1.default.green('✓ Created opencode.json'));
|
|
103
|
-
console.log(chalk_1.default.dim(' Plugin: @bergetai/opencode-auth'));
|
|
104
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
105
|
-
const templateFiles = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
|
|
106
|
-
for (const file of templateFiles) {
|
|
107
|
-
const source = node_path_1.default.join(templatesDir, file);
|
|
108
|
-
const destination = node_path_1.default.join(agentsDir, file);
|
|
109
|
-
fs.copyFileSync(source, destination);
|
|
110
|
-
}
|
|
111
|
-
console.log(chalk_1.default.green(`✓ Created ${templateFiles.length} agent definitions in .opencode/agents/`));
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
console.error(chalk_1.default.red('Failed to create config files:'));
|
|
115
|
-
(0, error_handler_1.handleError)('Config file creation failed', error);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
console.log(chalk_1.default.yellow('Configuration file creation cancelled.'));
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
console.log(chalk_1.default.green('\n✅ Project initialized successfully!'));
|
|
124
|
-
console.log(chalk_1.default.blue('\nNext steps:'));
|
|
125
|
-
console.log(chalk_1.default.cyan(' 1. Run: opencode'));
|
|
126
|
-
console.log(chalk_1.default.cyan(' 2. Type: /connect'));
|
|
127
|
-
console.log(chalk_1.default.cyan(' 3. Choose your auth method:'));
|
|
128
|
-
console.log(chalk_1.default.dim(' • "Login with Berget" — Berget Code team members (SSO)'));
|
|
129
|
-
console.log(chalk_1.default.dim(' • "Enter API Key" — API key users (console.berget.ai)'));
|
|
19
|
+
await (0, init_1.runInitCommand)();
|
|
130
20
|
}
|
|
131
21
|
catch (error) {
|
|
132
|
-
(0, error_handler_1.handleError)('
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
code
|
|
136
|
-
.command(command_structure_1.SUBCOMMANDS.CODE.RUN)
|
|
137
|
-
.description('Run AI coding assistant')
|
|
138
|
-
.argument('[prompt]', 'Prompt to send directly to OpenCode')
|
|
139
|
-
.option('-m, --model <model>', 'Model to use (overrides config)')
|
|
140
|
-
.option('-a, --analysis', 'Use fast analysis model for context building')
|
|
141
|
-
.option('--no-config', 'Run without loading project config')
|
|
142
|
-
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
143
|
-
.action(async (prompt, options) => {
|
|
144
|
-
try {
|
|
145
|
-
const configPath = node_path_1.default.join(process.cwd(), 'opencode.json');
|
|
146
|
-
// Ensure opencode is installed
|
|
147
|
-
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
let config = null;
|
|
151
|
-
if (!options.noConfig && fs.existsSync(configPath)) {
|
|
152
|
-
try {
|
|
153
|
-
const configContent = await (0, promises_1.readFile)(configPath, 'utf8');
|
|
154
|
-
config = JSON.parse(configContent);
|
|
155
|
-
console.log(chalk_1.default.dim(`Loaded config for project: ${config.projectName}`));
|
|
156
|
-
console.log(chalk_1.default.dim(`Models: Analysis=${config.analysisModel}, Build=${config.buildModel}`));
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
console.log(chalk_1.default.yellow('Warning: Failed to load opencode.json'));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if (!config) {
|
|
163
|
-
console.log(chalk_1.default.yellow('No project configuration found.'));
|
|
164
|
-
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.`));
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
// Prepare opencode command
|
|
168
|
-
const environment = { ...process.env };
|
|
169
|
-
const opencodeArguments = [];
|
|
170
|
-
// Read --stage and --local from root program options
|
|
171
|
-
// (these flags are registered at program level, not subcommand level)
|
|
172
|
-
const isStage = process.argv.includes('--stage');
|
|
173
|
-
const isLocal = process.argv.includes('--local');
|
|
174
|
-
if (isStage) {
|
|
175
|
-
console.log(chalk_1.default.cyan('Using Berget stage environment'));
|
|
176
|
-
environment.BERGET_API_URL = 'https://api.stage.berget.ai';
|
|
177
|
-
environment.BERGET_INFERENCE_URL = 'https://api.stage.berget.ai/v1';
|
|
178
|
-
}
|
|
179
|
-
else if (isLocal) {
|
|
180
|
-
console.log(chalk_1.default.cyan('Using local development environment'));
|
|
181
|
-
environment.BERGET_API_URL = 'http://localhost:3000';
|
|
182
|
-
environment.BERGET_INFERENCE_URL = 'http://localhost:3000/v1';
|
|
183
|
-
}
|
|
184
|
-
if (prompt) {
|
|
185
|
-
opencodeArguments.push('run', prompt);
|
|
186
|
-
}
|
|
187
|
-
// Choose model based on analysis flag or override
|
|
188
|
-
let selectedModel = options.model || config.buildModel;
|
|
189
|
-
if (options.analysis && !options.model) {
|
|
190
|
-
selectedModel = config.analysisModel;
|
|
191
|
-
}
|
|
192
|
-
if (selectedModel) {
|
|
193
|
-
opencodeArguments.push('--model', selectedModel);
|
|
194
|
-
}
|
|
195
|
-
console.log(chalk_1.default.cyan('Starting OpenCode...'));
|
|
196
|
-
// Spawn opencode process
|
|
197
|
-
const opencode = (0, node_child_process_1.spawn)('opencode', opencodeArguments, {
|
|
198
|
-
env: environment,
|
|
199
|
-
stdio: 'inherit',
|
|
200
|
-
});
|
|
201
|
-
opencode.on('close', (code) => {
|
|
202
|
-
if (code !== 0) {
|
|
203
|
-
console.log(chalk_1.default.red(`OpenCode exited with code ${code}`));
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
opencode.on('error', (error) => {
|
|
207
|
-
console.error(chalk_1.default.red('Failed to start OpenCode:'));
|
|
208
|
-
console.error(error.message);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
catch (error) {
|
|
212
|
-
(0, error_handler_1.handleError)('Failed to run OpenCode', error);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
code
|
|
216
|
-
.command(command_structure_1.SUBCOMMANDS.CODE.SERVE)
|
|
217
|
-
.description('Start OpenCode web server')
|
|
218
|
-
.option('-p, --port <port>', 'Port to run the server on (default: 3000)')
|
|
219
|
-
.option('-h, --host <host>', 'Host to bind the server to (default: localhost)')
|
|
220
|
-
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
221
|
-
.action(async (options) => {
|
|
222
|
-
try {
|
|
223
|
-
// Ensure opencode is installed
|
|
224
|
-
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
console.log(chalk_1.default.cyan('🚀 Starting OpenCode web server...'));
|
|
228
|
-
// Prepare opencode serve command
|
|
229
|
-
const serveArguments = ['serve'];
|
|
230
|
-
if (options.port) {
|
|
231
|
-
serveArguments.push('--port', options.port);
|
|
232
|
-
}
|
|
233
|
-
if (options.host) {
|
|
234
|
-
serveArguments.push('--host', options.host);
|
|
235
|
-
}
|
|
236
|
-
// Spawn opencode serve process
|
|
237
|
-
const opencode = (0, node_child_process_1.spawn)('opencode', serveArguments, {
|
|
238
|
-
stdio: 'inherit',
|
|
239
|
-
});
|
|
240
|
-
opencode.on('close', (code) => {
|
|
241
|
-
if (code !== 0) {
|
|
242
|
-
console.log(chalk_1.default.red(`OpenCode server exited with code ${code}`));
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
opencode.on('error', (error) => {
|
|
246
|
-
console.error(chalk_1.default.red('Failed to start OpenCode server:'));
|
|
247
|
-
console.error(error.message);
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
catch (error) {
|
|
251
|
-
(0, error_handler_1.handleError)('Failed to start OpenCode server', error);
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
code
|
|
255
|
-
.command(command_structure_1.SUBCOMMANDS.CODE.UPDATE)
|
|
256
|
-
.description('Update OpenCode and agents to latest versions')
|
|
257
|
-
.option('-f, --force', 'Force update even if already latest')
|
|
258
|
-
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
259
|
-
.action(async (options) => {
|
|
260
|
-
try {
|
|
261
|
-
console.log(chalk_1.default.cyan('🔄 Updating OpenCode configuration...'));
|
|
262
|
-
// Ensure opencode is installed first
|
|
263
|
-
if (!(await ensureOpencodeInstalled(options.yes))) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const configPath = node_path_1.default.join(process.cwd(), 'opencode.json');
|
|
267
|
-
// Check if project is initialized
|
|
268
|
-
if (!fs.existsSync(configPath)) {
|
|
269
|
-
console.log(chalk_1.default.red('❌ No OpenCode configuration found.'));
|
|
270
|
-
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.`));
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
// Read current configuration
|
|
274
|
-
let currentConfig;
|
|
275
|
-
try {
|
|
276
|
-
const configContent = await (0, promises_1.readFile)(configPath, 'utf8');
|
|
277
|
-
currentConfig = JSON.parse(configContent);
|
|
278
|
-
}
|
|
279
|
-
catch (error) {
|
|
280
|
-
console.error(chalk_1.default.red('Failed to read current opencode.json:'));
|
|
281
|
-
(0, error_handler_1.handleError)('Config read failed', error);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
console.log(chalk_1.default.blue('📋 Current configuration:'));
|
|
285
|
-
if (currentConfig.model) {
|
|
286
|
-
console.log(chalk_1.default.dim(` Model: ${currentConfig.model}`));
|
|
287
|
-
}
|
|
288
|
-
const agentsDir = node_path_1.default.join(process.cwd(), '.opencode', 'agents');
|
|
289
|
-
const templatesDir = getAgentTemplatesDir();
|
|
290
|
-
const templateFiles = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
|
|
291
|
-
// Check if agent definitions need updating
|
|
292
|
-
let agentsNeedUpdate = false;
|
|
293
|
-
for (const file of templateFiles) {
|
|
294
|
-
const source = node_path_1.default.join(templatesDir, file);
|
|
295
|
-
const destination = node_path_1.default.join(agentsDir, file);
|
|
296
|
-
if (!fs.existsSync(destination)) {
|
|
297
|
-
agentsNeedUpdate = true;
|
|
298
|
-
break;
|
|
299
|
-
}
|
|
300
|
-
const sourceContent = fs.readFileSync(source, 'utf8');
|
|
301
|
-
const destinationContent = fs.readFileSync(destination, 'utf8');
|
|
302
|
-
if (sourceContent !== destinationContent) {
|
|
303
|
-
agentsNeedUpdate = true;
|
|
304
|
-
break;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
// Check if opencode.json still has inline agent config (needs migration)
|
|
308
|
-
const needsMigration = !!currentConfig.agent;
|
|
309
|
-
if (!agentsNeedUpdate && !needsMigration && !options.force) {
|
|
310
|
-
console.log(chalk_1.default.green('✅ Already using the latest configuration!'));
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
if (agentsNeedUpdate || needsMigration) {
|
|
314
|
-
console.log(chalk_1.default.blue('\n🔄 Updates available:'));
|
|
315
|
-
if (needsMigration) {
|
|
316
|
-
console.log(chalk_1.default.cyan(' • Migrate agents from opencode.json to .opencode/agents/'));
|
|
317
|
-
}
|
|
318
|
-
if (agentsNeedUpdate) {
|
|
319
|
-
console.log(chalk_1.default.cyan(' • Latest agent prompts and improvements'));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
if (options.force) {
|
|
323
|
-
console.log(chalk_1.default.yellow('🔧 Force update requested'));
|
|
324
|
-
}
|
|
325
|
-
if (!options.yes) {
|
|
326
|
-
console.log(chalk_1.default.blue('\nThis will update your agent definitions and OpenCode configuration.'));
|
|
327
|
-
const hasGitRepo = hasGit();
|
|
328
|
-
if (hasGitRepo) {
|
|
329
|
-
console.log(chalk_1.default.green('✓ Git repository detected - changes are tracked'));
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
console.log(chalk_1.default.yellow('⚠️ No .git repository detected - backup will be created'));
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (await confirm('\nProceed with update? (Y/n): ', options.yes)) {
|
|
336
|
-
try {
|
|
337
|
-
let backupPath = null;
|
|
338
|
-
if (!hasGit()) {
|
|
339
|
-
backupPath = `${configPath}.backup.${Date.now()}`;
|
|
340
|
-
await (0, promises_1.writeFile)(backupPath, JSON.stringify(currentConfig, null, 2));
|
|
341
|
-
console.log(chalk_1.default.green(`✓ Backed up current config to ${node_path_1.default.basename(backupPath)}`));
|
|
342
|
-
}
|
|
343
|
-
// Remove inline agent section from opencode.json if present
|
|
344
|
-
if (currentConfig.agent) {
|
|
345
|
-
delete currentConfig.agent;
|
|
346
|
-
await (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
|
|
347
|
-
console.log(chalk_1.default.green('✓ Removed inline agent config from opencode.json'));
|
|
348
|
-
}
|
|
349
|
-
// Sync agent markdown files from templates
|
|
350
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
351
|
-
let updatedCount = 0;
|
|
352
|
-
for (const file of templateFiles) {
|
|
353
|
-
const source = node_path_1.default.join(templatesDir, file);
|
|
354
|
-
const destination = node_path_1.default.join(agentsDir, file);
|
|
355
|
-
const agentName = node_path_1.default.basename(file, '.md');
|
|
356
|
-
if (!fs.existsSync(destination) ||
|
|
357
|
-
fs.readFileSync(source, 'utf8') !== fs.readFileSync(destination, 'utf8')) {
|
|
358
|
-
fs.copyFileSync(source, destination);
|
|
359
|
-
updatedCount++;
|
|
360
|
-
console.log(chalk_1.default.cyan(` • Updated agent: ${agentName}`));
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
if (updatedCount > 0) {
|
|
364
|
-
console.log(chalk_1.default.green(`✓ Updated ${updatedCount} agent definition(s)`));
|
|
365
|
-
}
|
|
366
|
-
// Update AGENTS.md if it doesn't exist
|
|
367
|
-
const agentsMdPath = node_path_1.default.join(process.cwd(), 'AGENTS.md');
|
|
368
|
-
if (!fs.existsSync(agentsMdPath)) {
|
|
369
|
-
const agentsMdContent = `# Berget Code Agents
|
|
370
|
-
|
|
371
|
-
This document describes the specialized agents available in this project for use with OpenCode.
|
|
372
|
-
|
|
373
|
-
Agents are defined as markdown files in \`.opencode/agents/\` with YAML frontmatter.
|
|
374
|
-
|
|
375
|
-
## Available Agents
|
|
376
|
-
|
|
377
|
-
### Primary Agents
|
|
378
|
-
|
|
379
|
-
| Agent | Description | Temperature |
|
|
380
|
-
|-------|-------------|-------------|
|
|
381
|
-
| fullstack | Router/coordinator for full-stack development | 0.3 |
|
|
382
|
-
| frontend | Scandinavian, type-safe UIs with React, Tailwind, Shadcn | 0.4 |
|
|
383
|
-
| backend | Functional, modular Koa + TypeScript services | 0.3 |
|
|
384
|
-
| devops | Declarative GitOps infra with FluxCD, Kustomize, Helm | 0.3 |
|
|
385
|
-
| app | Expo + React Native apps; props-first, offline-aware | 0.4 |
|
|
386
|
-
|
|
387
|
-
### Subagents
|
|
388
|
-
|
|
389
|
-
| Agent | Description | Temperature |
|
|
390
|
-
|-------|-------------|-------------|
|
|
391
|
-
| security | Security specialist for pentesting and OWASP compliance | 0.2 |
|
|
392
|
-
| quality | QA specialist for testing, building, and PR management | 0.1 |
|
|
393
|
-
|
|
394
|
-
## Usage
|
|
395
|
-
|
|
396
|
-
- **Tab** key to cycle between primary agents
|
|
397
|
-
- **@mention** to invoke subagents (e.g. \`@security review this code\`)
|
|
398
|
-
- \`/fullstack\`, \`/frontend\`, \`/backend\`, \`/devops\`, \`/app\` to switch agents
|
|
399
|
-
|
|
400
|
-
## Routing Rules
|
|
401
|
-
|
|
402
|
-
The fullstack agent automatically routes tasks based on file patterns:
|
|
403
|
-
|
|
404
|
-
- \`/apps/frontend\` or \`.tsx\` files → frontend
|
|
405
|
-
- \`/apps/app\` or Expo/React Native → app
|
|
406
|
-
- \`/infra\`, \`/k8s\`, FluxCD, Helm → devops
|
|
407
|
-
- \`/services\`, Koa routers → backend
|
|
408
|
-
|
|
409
|
-
## Customization
|
|
410
|
-
|
|
411
|
-
Edit the markdown files in \`.opencode/agents/\` to customize agent behavior.
|
|
412
|
-
See https://opencode.ai/docs/agents/ for available options.
|
|
413
|
-
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
*Updated by berget code update*
|
|
417
|
-
`;
|
|
418
|
-
await (0, promises_1.writeFile)(agentsMdPath, agentsMdContent);
|
|
419
|
-
console.log(chalk_1.default.green('✓ Created AGENTS.md documentation'));
|
|
420
|
-
}
|
|
421
|
-
console.log(chalk_1.default.green('\n✅ Update completed successfully!'));
|
|
422
|
-
}
|
|
423
|
-
catch (error) {
|
|
424
|
-
console.error(chalk_1.default.red('Failed to update configuration:'));
|
|
425
|
-
(0, error_handler_1.handleError)('Update failed', error);
|
|
426
|
-
try {
|
|
427
|
-
await (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
|
|
428
|
-
console.log(chalk_1.default.yellow('📁 Restored original configuration from backup'));
|
|
429
|
-
}
|
|
430
|
-
catch {
|
|
431
|
-
console.error(chalk_1.default.red('Failed to restore backup:'));
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
436
|
-
console.log(chalk_1.default.yellow('Update cancelled.'));
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
catch {
|
|
440
|
-
console.error(chalk_1.default.red('Failed to update OpenCode configuration'));
|
|
22
|
+
(0, error_handler_1.handleError)('Setup failed', error);
|
|
441
23
|
}
|
|
442
24
|
});
|
|
443
25
|
}
|
|
444
26
|
exports.registerCodeCommands = registerCodeCommands;
|
|
445
|
-
/**
|
|
446
|
-
* Check if opencode is installed
|
|
447
|
-
*/
|
|
448
|
-
function checkOpencodeInstalled() {
|
|
449
|
-
return new Promise((resolve) => {
|
|
450
|
-
const child = (0, node_child_process_1.spawn)('which', ['opencode'], {
|
|
451
|
-
stdio: 'pipe',
|
|
452
|
-
});
|
|
453
|
-
child.on('close', (code) => {
|
|
454
|
-
resolve(code === 0);
|
|
455
|
-
});
|
|
456
|
-
child.on('error', () => {
|
|
457
|
-
resolve(false);
|
|
458
|
-
});
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* Helper function to get user confirmation
|
|
463
|
-
*/
|
|
464
|
-
async function confirm(question, autoYes = false) {
|
|
465
|
-
if (autoYes) {
|
|
466
|
-
return true;
|
|
467
|
-
}
|
|
468
|
-
return new Promise((resolve) => {
|
|
469
|
-
const rl = node_readline_1.default.createInterface({
|
|
470
|
-
input: process.stdin,
|
|
471
|
-
output: process.stdout,
|
|
472
|
-
});
|
|
473
|
-
rl.question(question, (answer) => {
|
|
474
|
-
rl.close();
|
|
475
|
-
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes' || answer === '');
|
|
476
|
-
});
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* Ensure opencode is installed, offering to install if not
|
|
481
|
-
*/
|
|
482
|
-
async function ensureOpencodeInstalled(autoYes = false) {
|
|
483
|
-
let opencodeInstalled = await checkOpencodeInstalled();
|
|
484
|
-
if (!opencodeInstalled) {
|
|
485
|
-
if (!autoYes) {
|
|
486
|
-
console.log(chalk_1.default.red('OpenCode is not installed.'));
|
|
487
|
-
console.log(chalk_1.default.blue('OpenCode is required for the AI coding assistant.'));
|
|
488
|
-
}
|
|
489
|
-
if (await confirm('Would you like to install OpenCode automatically? (Y/n): ', autoYes)) {
|
|
490
|
-
opencodeInstalled = await installOpencode();
|
|
491
|
-
}
|
|
492
|
-
else {
|
|
493
|
-
if (!autoYes) {
|
|
494
|
-
console.log(chalk_1.default.blue('\nInstallation cancelled.'));
|
|
495
|
-
console.log(chalk_1.default.blue('To install manually: curl -fsSL https://opencode.ai/install | bash'));
|
|
496
|
-
console.log(chalk_1.default.blue('Or visit: https://opencode.ai/docs'));
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
return opencodeInstalled;
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Get the path to the bundled agent templates directory
|
|
504
|
-
*/
|
|
505
|
-
function getAgentTemplatesDir() {
|
|
506
|
-
return node_path_1.default.resolve(__dirname, '../../templates/agents');
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Get project name from current directory or package.json
|
|
510
|
-
*/
|
|
511
|
-
function getProjectName() {
|
|
512
|
-
try {
|
|
513
|
-
const packageJsonPath = node_path_1.default.join(process.cwd(), 'package.json');
|
|
514
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
515
|
-
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
|
|
516
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
517
|
-
return packageJson.name || node_path_1.default.basename(process.cwd());
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
catch {
|
|
521
|
-
// Ignore error and fallback to directory name
|
|
522
|
-
}
|
|
523
|
-
return node_path_1.default.basename(process.cwd());
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Check if current directory has git
|
|
527
|
-
*/
|
|
528
|
-
function hasGit() {
|
|
529
|
-
try {
|
|
530
|
-
return fs.existsSync(node_path_1.default.join(process.cwd(), '.git'));
|
|
531
|
-
}
|
|
532
|
-
catch {
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Install opencode via npm
|
|
538
|
-
*/
|
|
539
|
-
async function installOpencode() {
|
|
540
|
-
console.log(chalk_1.default.cyan('Installing OpenCode via npm...'));
|
|
541
|
-
try {
|
|
542
|
-
await new Promise((resolve, reject) => {
|
|
543
|
-
const install = (0, node_child_process_1.spawn)('npm', ['install', '-g', 'opencode-ai@1.3'], {
|
|
544
|
-
stdio: 'inherit',
|
|
545
|
-
});
|
|
546
|
-
install.on('close', (code) => {
|
|
547
|
-
if (code === 0) {
|
|
548
|
-
console.log(chalk_1.default.green('✓ OpenCode installed successfully!'));
|
|
549
|
-
resolve();
|
|
550
|
-
}
|
|
551
|
-
else {
|
|
552
|
-
reject(new Error(`Installation failed with code ${code}`));
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
install.on('error', reject);
|
|
556
|
-
});
|
|
557
|
-
// Verify installation
|
|
558
|
-
const opencodeInstalled = await checkOpencodeInstalled();
|
|
559
|
-
if (!opencodeInstalled) {
|
|
560
|
-
console.log(chalk_1.default.yellow('Installation completed but opencode command not found.'));
|
|
561
|
-
console.log(chalk_1.default.yellow('You may need to restart your terminal or check your PATH.'));
|
|
562
|
-
return false;
|
|
563
|
-
}
|
|
564
|
-
return true;
|
|
565
|
-
}
|
|
566
|
-
catch (error) {
|
|
567
|
-
console.error(chalk_1.default.red('Failed to install OpenCode:'));
|
|
568
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
569
|
-
console.log(chalk_1.default.blue('\nAlternative installation methods:'));
|
|
570
|
-
console.log(chalk_1.default.blue(' curl -fsSL https://opencode.ai/install | sh'));
|
|
571
|
-
console.log(chalk_1.default.blue(' Or visit: https://opencode.ai/docs'));
|
|
572
|
-
return false;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
@@ -71,10 +71,6 @@ exports.SUBCOMMANDS = {
|
|
|
71
71
|
// Code commands
|
|
72
72
|
CODE: {
|
|
73
73
|
INIT: 'init',
|
|
74
|
-
RUN: 'run',
|
|
75
|
-
SERVE: 'serve',
|
|
76
|
-
SETUP: 'setup',
|
|
77
|
-
UPDATE: 'update',
|
|
78
74
|
},
|
|
79
75
|
// Flux commands
|
|
80
76
|
FLUX: {
|
|
@@ -135,11 +131,7 @@ exports.COMMAND_DESCRIPTIONS = {
|
|
|
135
131
|
[`${exports.COMMAND_GROUPS.CLUSTERS} ${exports.SUBCOMMANDS.CLUSTERS.DESCRIBE}`]: 'Get detailed information about a cluster',
|
|
136
132
|
[`${exports.COMMAND_GROUPS.CLUSTERS} ${exports.SUBCOMMANDS.CLUSTERS.GET_USAGE}`]: 'Get resource usage for a cluster',
|
|
137
133
|
[`${exports.COMMAND_GROUPS.CLUSTERS} ${exports.SUBCOMMANDS.CLUSTERS.LIST}`]: 'List all clusters',
|
|
138
|
-
[`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.INIT}`]: '
|
|
139
|
-
[`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.RUN}`]: 'Run AI coding assistant',
|
|
140
|
-
[`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.SERVE}`]: 'Start OpenCode web server',
|
|
141
|
-
[`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.SETUP}`]: 'Interactive setup for Berget AI coding tools',
|
|
142
|
-
[`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.UPDATE}`]: 'Update OpenCode and agents to latest versions',
|
|
134
|
+
[`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.INIT}`]: 'Interactive setup for Berget AI coding tools',
|
|
143
135
|
[`${exports.COMMAND_GROUPS.FLUX} ${exports.SUBCOMMANDS.FLUX.BOOTSTRAP}`]: 'Bootstrap Flux CD',
|
|
144
136
|
[`${exports.COMMAND_GROUPS.FLUX} ${exports.SUBCOMMANDS.FLUX.INSTALL}`]: 'Install Flux CD',
|
|
145
137
|
[`${exports.COMMAND_GROUPS.HELM} ${exports.SUBCOMMANDS.HELM.ADD_REPO}`]: 'Add a Helm repository',
|
|
@@ -67,7 +67,7 @@ class AuthService {
|
|
|
67
67
|
}
|
|
68
68
|
console.log(chalk_1.default.cyan('\nNext steps:'));
|
|
69
69
|
console.log(chalk_1.default.cyan(' • Create an API key: berget api-keys create'));
|
|
70
|
-
console.log(chalk_1.default.cyan(' •
|
|
70
|
+
console.log(chalk_1.default.cyan(' • Initialize OpenCode: berget code init'));
|
|
71
71
|
return true;
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|