berget 2.2.4 ā 2.2.6
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/.github/workflows/publish.yml +2 -2
- package/.github/workflows/test.yml +1 -1
- package/dist/package.json +3 -1
- package/dist/src/commands/code/__tests__/fake-command-runner.js +52 -0
- package/dist/src/commands/code/__tests__/fake-file-store.js +46 -0
- package/dist/src/commands/code/__tests__/fake-prompter.js +91 -0
- package/dist/src/commands/code/__tests__/setup-flow.test.js +238 -0
- package/dist/src/commands/code/adapters/clack-prompter.js +71 -0
- package/dist/src/commands/code/adapters/fs-file-store.js +75 -0
- package/dist/src/commands/code/adapters/spawn-command-runner.js +49 -0
- package/dist/src/commands/code/errors.js +27 -0
- package/dist/src/commands/code/ports/command-runner.js +2 -0
- package/dist/src/commands/code/ports/file-store.js +2 -0
- package/dist/src/commands/code/ports/prompter.js +2 -0
- package/dist/src/commands/code/setup.js +392 -0
- package/dist/src/commands/code.js +189 -633
- package/dist/src/constants/command-structure.js +2 -0
- package/dist/tests/commands/code.test.js +31 -0
- package/dist/tests/utils/opencode-validator.test.js +15 -14
- package/package.json +3 -1
- package/src/commands/code/__tests__/fake-command-runner.ts +47 -0
- package/src/commands/code/__tests__/fake-file-store.ts +35 -0
- package/src/commands/code/__tests__/fake-prompter.ts +83 -0
- package/src/commands/code/__tests__/setup-flow.test.ts +274 -0
- package/src/commands/code/adapters/clack-prompter.ts +43 -0
- package/src/commands/code/adapters/fs-file-store.ts +33 -0
- package/src/commands/code/adapters/spawn-command-runner.ts +36 -0
- package/src/commands/code/errors.ts +23 -0
- package/src/commands/code/ports/command-runner.ts +6 -0
- package/src/commands/code/ports/file-store.ts +6 -0
- package/src/commands/code/ports/prompter.ts +23 -0
- package/src/commands/code/setup.ts +402 -0
- package/src/commands/code.ts +211 -748
- package/src/constants/command-structure.ts +3 -0
- package/templates/agents/app.md +22 -0
- package/templates/agents/backend.md +22 -0
- package/templates/agents/devops.md +28 -0
- package/templates/agents/frontend.md +24 -0
- package/templates/agents/fullstack.md +22 -0
- package/templates/agents/quality.md +64 -0
- package/templates/agents/security.md +20 -0
- package/tests/commands/code.test.ts +47 -0
- package/tests/utils/opencode-validator.test.ts +16 -15
- package/opencode.json +0 -146
|
@@ -40,11 +40,11 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
40
40
|
const readline_1 = __importDefault(require("readline"));
|
|
41
41
|
const command_structure_1 = require("../constants/command-structure");
|
|
42
42
|
const error_handler_1 = require("../utils/error-handler");
|
|
43
|
+
const setup_1 = require("./code/setup");
|
|
43
44
|
const fs = __importStar(require("fs"));
|
|
44
45
|
const promises_1 = require("fs/promises");
|
|
45
46
|
const path_1 = __importDefault(require("path"));
|
|
46
47
|
const child_process_1 = require("child_process");
|
|
47
|
-
const client_1 = require("../client");
|
|
48
48
|
/**
|
|
49
49
|
* Check if current directory has git
|
|
50
50
|
*/
|
|
@@ -56,118 +56,6 @@ function hasGit() {
|
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Merge opencode configurations using chat completions API
|
|
61
|
-
*/
|
|
62
|
-
function mergeConfigurations(currentConfig, latestConfig) {
|
|
63
|
-
var _a, _b, _c, _d;
|
|
64
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
-
try {
|
|
66
|
-
const client = (0, client_1.createAuthenticatedClient)();
|
|
67
|
-
console.log(chalk_1.default.blue('š¤ Using AI to merge configurations...'));
|
|
68
|
-
const mergePrompt = `You are a configuration merge specialist. Merge these two OpenCode configurations:
|
|
69
|
-
|
|
70
|
-
CURRENT CONFIG (user's customizations):
|
|
71
|
-
${JSON.stringify(currentConfig, null, 2)}
|
|
72
|
-
|
|
73
|
-
LATEST CONFIG (new updates):
|
|
74
|
-
${JSON.stringify(latestConfig, null, 2)}
|
|
75
|
-
|
|
76
|
-
Merge rules:
|
|
77
|
-
1. Preserve ALL user customizations from current config
|
|
78
|
-
2. Add ALL new features and improvements from latest config
|
|
79
|
-
3. For conflicts, prefer user's customizations but add new latest features
|
|
80
|
-
4. Maintain valid JSON structure
|
|
81
|
-
5. Keep the merged configuration complete and functional
|
|
82
|
-
|
|
83
|
-
Return ONLY the merged JSON configuration, no explanations.`;
|
|
84
|
-
const response = yield client.POST('/v1/chat/completions', {
|
|
85
|
-
body: {
|
|
86
|
-
model: 'glm-4.7',
|
|
87
|
-
messages: [
|
|
88
|
-
{
|
|
89
|
-
role: 'user',
|
|
90
|
-
content: mergePrompt,
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
temperature: 0.1,
|
|
94
|
-
max_tokens: 8000,
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
if (response.error) {
|
|
98
|
-
console.warn(chalk_1.default.yellow('ā ļø AI merge failed, using fallback merge'));
|
|
99
|
-
return fallbackMerge(currentConfig, latestConfig);
|
|
100
|
-
}
|
|
101
|
-
const content = (_d = (_c = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.choices) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.content;
|
|
102
|
-
if (!content) {
|
|
103
|
-
console.warn(chalk_1.default.yellow('ā ļø No AI response, using fallback merge'));
|
|
104
|
-
return fallbackMerge(currentConfig, latestConfig);
|
|
105
|
-
}
|
|
106
|
-
try {
|
|
107
|
-
const mergedConfig = JSON.parse(content.trim());
|
|
108
|
-
console.log(chalk_1.default.green('ā AI merge completed successfully'));
|
|
109
|
-
return mergedConfig;
|
|
110
|
-
}
|
|
111
|
-
catch (parseError) {
|
|
112
|
-
console.warn(chalk_1.default.yellow('ā ļø AI response invalid, using fallback merge'));
|
|
113
|
-
return fallbackMerge(currentConfig, latestConfig);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
console.warn(chalk_1.default.yellow('ā ļø AI merge unavailable, using fallback merge'));
|
|
118
|
-
return fallbackMerge(currentConfig, latestConfig);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Fallback merge logic when AI merge is unavailable
|
|
124
|
-
*/
|
|
125
|
-
function fallbackMerge(currentConfig, latestConfig) {
|
|
126
|
-
console.log(chalk_1.default.blue('š Using fallback merge logic...'));
|
|
127
|
-
const merged = Object.assign({}, latestConfig);
|
|
128
|
-
// Preserve user customizations
|
|
129
|
-
if (currentConfig.theme && currentConfig.theme !== latestConfig.theme) {
|
|
130
|
-
merged.theme = currentConfig.theme;
|
|
131
|
-
}
|
|
132
|
-
if (currentConfig.share && currentConfig.share !== latestConfig.share) {
|
|
133
|
-
merged.share = currentConfig.share;
|
|
134
|
-
}
|
|
135
|
-
// Merge custom agents while preserving new ones
|
|
136
|
-
if (currentConfig.agent) {
|
|
137
|
-
merged.agent = Object.assign({}, latestConfig.agent);
|
|
138
|
-
// Add any custom agents from current config
|
|
139
|
-
Object.keys(currentConfig.agent).forEach((agentName) => {
|
|
140
|
-
if (!latestConfig.agent[agentName]) {
|
|
141
|
-
merged.agent[agentName] = currentConfig.agent[agentName];
|
|
142
|
-
console.log(chalk_1.default.cyan(` ⢠Preserved custom agent: ${agentName}`));
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
// Merge custom commands while preserving new ones
|
|
147
|
-
if (currentConfig.commands) {
|
|
148
|
-
merged.commands = Object.assign({}, latestConfig.commands);
|
|
149
|
-
Object.keys(currentConfig.commands).forEach((commandName) => {
|
|
150
|
-
if (!latestConfig.commands[commandName]) {
|
|
151
|
-
merged.commands[commandName] = currentConfig.commands[commandName];
|
|
152
|
-
console.log(chalk_1.default.cyan(` ⢠Preserved custom command: ${commandName}`));
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
// Preserve custom provider settings if user has modified them
|
|
157
|
-
if (currentConfig.provider) {
|
|
158
|
-
merged.provider = Object.assign({}, latestConfig.provider);
|
|
159
|
-
// Deep merge provider settings
|
|
160
|
-
Object.keys(currentConfig.provider).forEach((providerName) => {
|
|
161
|
-
if (merged.provider[providerName]) {
|
|
162
|
-
merged.provider[providerName] = Object.assign(Object.assign({}, merged.provider[providerName]), currentConfig.provider[providerName]);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
merged.provider[providerName] = currentConfig.provider[providerName];
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
return merged;
|
|
170
|
-
}
|
|
171
59
|
/**
|
|
172
60
|
* Helper function to get user confirmation
|
|
173
61
|
*/
|
|
@@ -190,40 +78,6 @@ function confirm(question, autoYes = false) {
|
|
|
190
78
|
});
|
|
191
79
|
});
|
|
192
80
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Helper function to get user choice from options
|
|
195
|
-
*/
|
|
196
|
-
function askChoice(question, options, defaultChoice) {
|
|
197
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
198
|
-
return new Promise((resolve) => {
|
|
199
|
-
const rl = readline_1.default.createInterface({
|
|
200
|
-
input: process.stdin,
|
|
201
|
-
output: process.stdout,
|
|
202
|
-
});
|
|
203
|
-
rl.question(question, (answer) => {
|
|
204
|
-
rl.close();
|
|
205
|
-
const trimmed = answer.trim().toLowerCase();
|
|
206
|
-
// Handle numeric input (1, 2, etc.)
|
|
207
|
-
const numericIndex = parseInt(trimmed) - 1;
|
|
208
|
-
if (numericIndex >= 0 && numericIndex < options.length) {
|
|
209
|
-
resolve(options[numericIndex]);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// Handle text input
|
|
213
|
-
const matchingOption = options.find((option) => option.toLowerCase().startsWith(trimmed));
|
|
214
|
-
if (matchingOption) {
|
|
215
|
-
resolve(matchingOption);
|
|
216
|
-
}
|
|
217
|
-
else if (defaultChoice) {
|
|
218
|
-
resolve(defaultChoice);
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
resolve(options[0]); // Default to first option
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
81
|
/**
|
|
228
82
|
* Helper function to get user input
|
|
229
83
|
*/
|
|
@@ -262,71 +116,88 @@ function getProjectName() {
|
|
|
262
116
|
return path_1.default.basename(process.cwd());
|
|
263
117
|
}
|
|
264
118
|
/**
|
|
265
|
-
*
|
|
119
|
+
* Get the path to the bundled agent templates directory
|
|
120
|
+
*/
|
|
121
|
+
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
|
|
266
183
|
*/
|
|
267
184
|
function loadLatestAgentConfig() {
|
|
268
185
|
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
note: 'Bash access is denied for frontend persona to prevent shell command execution in UI environments. This restriction enforces security and architectural boundaries.',
|
|
285
|
-
description: 'Builds Scandinavian, type-safe UIs with React, Tailwind, Shadcn.',
|
|
286
|
-
prompt: 'You are Berget Code Frontend agent. Voice: Scandinavian calmāprecise, concise, confident. React 18 + TypeScript. Tailwind + Shadcn UI only via the design system (index.css, tailwind.config.ts). Use semantic tokens for color/spacing/typography/motion; never ad-hoc classes or inline colors. Components are pure and responsive; props-first data; minimal global state (Zustand/Jotai). Accessibility and keyboard navigation mandatory. Mock data only at init under /data via typed hooks (e.g., useProducts() reading /data/products.json). Design: minimal, balanced, quiet motion.\n\nIMPORTANT: You have NO bash access and cannot run git commands. When your frontend implementation tasks are complete, inform the user that changes are ready and suggest using /pr command to create a pull request with proper testing and quality checks.\n\nCODE QUALITY RULES:\n- Write clean, production-ready code\n- Follow React and TypeScript best practices\n- Ensure accessibility and responsive design\n- Use semantic tokens from design system\n- Test your components manually when possible\n- Document any complex logic with comments\n\nCRITICAL: When frontend implementation is complete, ALWAYS inform the user to use "/pr" command to handle testing, building, and pull request creation.',
|
|
287
|
-
},
|
|
288
|
-
backend: {
|
|
289
|
-
temperature: 0.3,
|
|
290
|
-
top_p: 0.9,
|
|
291
|
-
mode: 'primary',
|
|
292
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
293
|
-
description: 'Functional, modular Koa + TypeScript services; schema-first with code quality focus.',
|
|
294
|
-
prompt: "You are Berget Code Backend agent. Voice: Scandinavian calmāprecise, concise, confident. TypeScript + Koa. Prefer many small pure functions; avoid big try/catch blocks. Routes thin; logic in services/adapters/domain. Validate with Zod; auto-generate OpenAPI. Adapters isolate external systems; domain never depends on framework. Test with supertest; idempotent and stateless by default. Each microservice emits an OpenAPI contract; changes propagate upward to types. Code Quality & Refactoring Principles: Apply Single Responsibility Principle, fail fast with explicit errors, eliminate code duplication, remove nested complexity, use descriptive error codes, keep functions under 30 lines. Always leave code cleaner and more readable than you found it.\n\nGIT WORKFLOW RULES (CRITICAL):\n- NEVER push directly to main branch - ALWAYS use pull requests\n- NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'\n- ALWAYS clean up test files, documentation files, and temporary artifacts before committing\n- ALWAYS ensure git history maintains production quality - no test commits, no debugging code\n- ALWAYS create descriptive commit messages following project conventions\n- ALWAYS run tests and build before creating PR\n\nCRITICAL: When all backend implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.",
|
|
295
|
-
},
|
|
296
|
-
devops: {
|
|
297
|
-
temperature: 0.3,
|
|
298
|
-
top_p: 0.8,
|
|
299
|
-
mode: 'primary',
|
|
300
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
301
|
-
description: 'Declarative GitOps infra with FluxCD, Kustomize, Helm, operators.',
|
|
302
|
-
prompt: "You are Berget Code DevOps agent. Voice: Scandinavian calmāprecise, concise, confident. Start simple: k8s/{deployment,service,ingress}. Add FluxCD sync to repo and image automation. Use Kustomize bases/overlays (staging, production). Add dependencies via Helm from upstream sources; prefer native operators when available (CloudNativePG, cert-manager, external-dns). SemVer with -rc tags keeps CI environments current. Observability with Prometheus/Grafana. No manual kubectl in productionāGit is the source of truth.\n\nGIT WORKFLOW RULES (CRITICAL):\n- NEVER push directly to main branch - ALWAYS use pull requests\n- NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'\n- ALWAYS clean up test files, documentation files, and temporary artifacts before committing\n- ALWAYS ensure git history maintains production quality - no test commits, no debugging code\n- ALWAYS create descriptive commit messages following project conventions\n- ALWAYS run tests and build before creating PR\n\nHelm Values Configuration Process:\n1. Documentation First Approach: Always fetch official documentation from Artifact Hub/GitHub for the specific chart version before writing values. Search Artifact Hub for exact chart version documentation, check the chart's GitHub repository for official docs and examples, verify the exact version being used in the deployment.\n2. Validation Requirements: Check for available validation schemas before committing YAML files. Use Helm's built-in validation tools (helm lint, helm template). Validate against JSON schema if available for the chart. Ensure YAML syntax correctness with linters.\n3. Standard Workflow: Identify chart name and exact version. Fetch official documentation from Artifact Hub/GitHub. Check for available schemas and validation tools. Write values according to official documentation. Validate against schema (if available). Test with helm template or helm lint. Commit validated YAML files.\n4. Quality Assurance: Never commit unvalidated Helm values. Use helm dependency update when adding new charts. Test rendering with helm template --dry-run before deployment. Document any custom values with comments referencing official docs.",
|
|
303
|
-
},
|
|
304
|
-
app: {
|
|
305
|
-
temperature: 0.4,
|
|
306
|
-
top_p: 0.9,
|
|
307
|
-
mode: 'primary',
|
|
308
|
-
permission: { edit: 'allow', bash: 'deny', webfetch: 'allow' },
|
|
309
|
-
note: 'Bash access is denied for app persona to prevent shell command execution in mobile/Expo environments. This restriction enforces security and architectural boundaries.',
|
|
310
|
-
description: 'Expo + React Native apps; props-first, offline-aware, shared tokens.',
|
|
311
|
-
prompt: "You are Berget Code App agent. Voice: Scandinavian calmāprecise, concise, confident. Expo + React Native + TypeScript. Structure by components/hooks/services/navigation. Components are pure; data via props; refactor shared logic into hooks/stores. Share tokens with frontend. Mock data in /data via typed hooks; later replace with live APIs. Offline via SQLite/MMKV; notifications via Expo. Request permissions only when needed. Subtle, meaningful motion; light/dark parity.\n\nGIT WORKFLOW RULES (CRITICAL):\n- NEVER push directly to main branch - ALWAYS use pull requests\n- NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'\n- ALWAYS clean up test files, documentation files, and temporary artifacts before committing\n- ALWAYS ensure git history maintains production quality - no test commits, no debugging code\n- ALWAYS create descriptive commit messages following project conventions\n- ALWAYS run tests and build before creating PR\n\nCRITICAL: When all app implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.",
|
|
312
|
-
},
|
|
313
|
-
security: {
|
|
314
|
-
temperature: 0.2,
|
|
315
|
-
top_p: 0.8,
|
|
316
|
-
mode: 'subagent',
|
|
317
|
-
permission: { edit: 'deny', bash: 'allow', webfetch: 'allow' },
|
|
318
|
-
description: 'Security specialist for pentesting, OWASP compliance, and vulnerability assessments.',
|
|
319
|
-
prompt: "Voice: Scandinavian calmāprecise, concise, confident. You are Berget Code Security agent. Expert in application security, penetration testing, and OWASP standards. Core responsibilities: Conduct security assessments and penetration tests, Validate OWASP Top 10 compliance, Review code for security vulnerabilities, Implement security headers and Content Security Policy (CSP), Audit API security, Check for sensitive data exposure, Validate input sanitization and output encoding, Assess dependency security and supply chain risks. Tools and techniques: OWASP ZAP, Burp Suite, security linters, dependency scanners, manual code review. Always provide specific, actionable security recommendations with priority levels.\n\nGIT WORKFLOW RULES (CRITICAL):\n- NEVER push directly to main branch - ALWAYS use pull requests\n- NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'\n- ALWAYS clean up test files, documentation files, and temporary artifacts before committing\n- ALWAYS ensure git history maintains production quality - no test commits, no debugging code\n- ALWAYS create descriptive commit messages following project conventions\n- ALWAYS run tests and build before creating PR",
|
|
320
|
-
},
|
|
321
|
-
quality: {
|
|
322
|
-
temperature: 0.1,
|
|
323
|
-
top_p: 0.9,
|
|
324
|
-
mode: 'subagent',
|
|
325
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
326
|
-
description: 'Quality assurance specialist for testing, building, and PR management.',
|
|
327
|
-
prompt: "Voice: Scandinavian calmāprecise, concise, confident. You are Berget Code Quality agent. Specialist in code quality assurance, testing, building, and pull request management.\\n\\nCore responsibilities:\\n - Run comprehensive test suites (npm test, npm run test, jest, vitest)\\n - Execute build processes (npm run build, webpack, vite, tsc)\\n - Create and manage pull requests with proper descriptions\\n - Monitor GitHub for Copilot/reviewer comments\\n - Ensure code quality standards are met\\n - Validate linting and formatting (npm run lint, prettier)\\n - Check test coverage and performance benchmarks\\n - Handle CI/CD pipeline validation\\n\\nGIT WORKFLOW RULES (CRITICAL - ENFORCE STRICTLY):\\n - NEVER push directly to main branch - ALWAYS use pull requests\\n - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'\\n - ALWAYS clean up test files, documentation files, and temporary artifacts before committing\\n - ALWAYS ensure git history maintains production quality - no test commits, no debugging code\\n - ALWAYS create descriptive commit messages following project conventions\\n - ALWAYS run tests and build before creating PR\\n\\nCommon CLI commands:\\n - npm test or npm run test (run test suite)\\n - npm run build (build project)\\n - npm run lint (run linting)\\n - npm run format (format code)\\n - npm run test:coverage (check coverage)\\n - gh pr create (create pull request)\\n - gh pr view --comments (check PR comments)\\n - git add specific/files && git commit -m \\\"message\\\" && git push (NEVER use git add .)\\n\\nPR Workflow:\\n 1. Ensure all tests pass: npm test\\n 2. Build successfully: npm run build\\n 3. Create/update PR with clear description\\n 4. Monitor for reviewer comments\\n 5. Address feedback promptly\\n 6. Update PR with fixes\\n 7. Ensure CI checks pass\\n\\nAlways provide specific command examples and wait for processes to complete before proceeding.",
|
|
328
|
-
},
|
|
329
|
-
};
|
|
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;
|
|
330
201
|
});
|
|
331
202
|
}
|
|
332
203
|
/**
|
|
@@ -418,6 +289,19 @@ function registerCodeCommands(program) {
|
|
|
418
289
|
const code = program
|
|
419
290
|
.command(command_structure_1.COMMAND_GROUPS.CODE)
|
|
420
291
|
.description('AI-powered coding assistant with OpenCode');
|
|
292
|
+
if (process.env.BERGET_EXPERIMENTAL) {
|
|
293
|
+
code
|
|
294
|
+
.command('setup')
|
|
295
|
+
.description('Interactive setup for Berget AI coding tools')
|
|
296
|
+
.action(() => __awaiter(this, void 0, void 0, function* () {
|
|
297
|
+
try {
|
|
298
|
+
yield (0, setup_1.runSetupCommand)();
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
(0, error_handler_1.handleError)('Setup failed', error);
|
|
302
|
+
}
|
|
303
|
+
}));
|
|
304
|
+
}
|
|
421
305
|
code
|
|
422
306
|
.command(command_structure_1.SUBCOMMANDS.CODE.INIT)
|
|
423
307
|
.description('Initialize project for AI coding assistant')
|
|
@@ -446,133 +330,33 @@ function registerCodeCommands(program) {
|
|
|
446
330
|
return;
|
|
447
331
|
}
|
|
448
332
|
console.log(chalk_1.default.cyan(`Initializing OpenCode for project: ${projectName}`));
|
|
449
|
-
// Load latest agent configuration from our own codebase
|
|
450
|
-
const latestAgentConfig = yield loadLatestAgentConfig();
|
|
451
|
-
// Use hardcoded defaults for init - never try to load from project
|
|
452
|
-
// Create opencode.json config ā plugin handles auth, models, and provider
|
|
453
333
|
const config = {
|
|
454
334
|
$schema: 'https://opencode.ai/config.json',
|
|
455
|
-
plugin: ['@bergetai/opencode-auth@1.0.
|
|
456
|
-
username: 'berget-code',
|
|
457
|
-
theme: 'berget-dark',
|
|
458
|
-
share: 'manual',
|
|
459
|
-
autoupdate: true,
|
|
460
|
-
agent: {
|
|
461
|
-
fullstack: {
|
|
462
|
-
temperature: 0.3,
|
|
463
|
-
top_p: 0.9,
|
|
464
|
-
mode: 'primary',
|
|
465
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
466
|
-
description: 'Router/coordinator agent for full-stack development with schema-driven architecture',
|
|
467
|
-
prompt: 'Voice: Scandinavian calmāprecise, concise, confident; no fluff. You are Berget Code Fullstack agent. Act as a router and coordinator in a monorepo. Bottom-up schema: database ā OpenAPI ā generated types. Top-down types: API ā UI ā components. Use openapi-fetch and Zod at every boundary; compile-time errors are desired when contracts change. Routing rules: if task/paths match /apps/frontend or React (.tsx) ā use frontend; if /apps/app or Expo/React Native ā app; if /infra, /k8s, flux-system, kustomization.yaml, Helm values ā devops; if /services, Koa routers, services/adapters/domain ā backend. If ambiguous, remain fullstack and outline the end-to-end plan, then delegate subtasks to the right persona. Security: validate inputs; secrets via FluxCD SOPS/Sealed Secrets. Documentation is generated from codeānever duplicated. CRITICAL: When all implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.',
|
|
468
|
-
},
|
|
469
|
-
frontend: {
|
|
470
|
-
temperature: 0.4,
|
|
471
|
-
top_p: 0.9,
|
|
472
|
-
mode: 'primary',
|
|
473
|
-
permission: { edit: 'allow', bash: 'deny', webfetch: 'allow' },
|
|
474
|
-
note: 'Bash access is denied for frontend persona to prevent shell command execution in UI environments. This restriction enforces security and architectural boundaries.',
|
|
475
|
-
description: 'Builds Scandinavian, type-safe UIs with React, Tailwind, Shadcn.',
|
|
476
|
-
prompt: 'You are Berget Code Frontend agent. Voice: Scandinavian calmāprecise, concise, confident. React 18 + TypeScript. Tailwind + Shadcn UI only via the design system (index.css, tailwind.config.ts). Use semantic tokens for color/spacing/typography/motion; never ad-hoc classes or inline colors. Components are pure and responsive; props-first data; minimal global state (Zustand/Jotai). Accessibility and keyboard navigation mandatory. Mock data only at init under /data via typed hooks (e.g., useProducts() reading /data/products.json). Design: minimal, balanced, quiet motion. CRITICAL: When all frontend implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.',
|
|
477
|
-
},
|
|
478
|
-
backend: {
|
|
479
|
-
temperature: 0.3,
|
|
480
|
-
top_p: 0.9,
|
|
481
|
-
mode: 'primary',
|
|
482
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
483
|
-
description: 'Functional, modular Koa + TypeScript services; schema-first with code quality focus.',
|
|
484
|
-
prompt: 'You are Berget Code Backend agent. Voice: Scandinavian calmāprecise, concise, confident. TypeScript + Koa. Prefer many small pure functions; avoid big try/catch blocks. Routes thin; logic in services/adapters/domain. Validate with Zod; auto-generate OpenAPI. Adapters isolate external systems; domain never depends on framework. Test with supertest; idempotent and stateless by default. Each microservice emits an OpenAPI contract; changes propagate upward to types. Code Quality & Refactoring Principles: Apply Single Responsibility Principle, fail fast with explicit errors, eliminate code duplication, remove nested complexity, use descriptive error codes, keep functions under 30 lines. Always leave code cleaner and more readable than you found it. CRITICAL: When all backend implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.',
|
|
485
|
-
},
|
|
486
|
-
// Use centralized devops configuration with Helm guidelines
|
|
487
|
-
devops: latestAgentConfig.devops || {
|
|
488
|
-
temperature: 0.3,
|
|
489
|
-
top_p: 0.8,
|
|
490
|
-
mode: 'primary',
|
|
491
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
492
|
-
description: 'Declarative GitOps infra with FluxCD, Kustomize, Helm, operators.',
|
|
493
|
-
prompt: 'You are Berget Code DevOps agent. Voice: Scandinavian calmāprecise, concise, confident. Start simple: k8s/{deployment,service,ingress}. Add FluxCD sync to repo and image automation. Use Kustomize bases/overlays (staging, production). Add dependencies via Helm from upstream sources; prefer native operators when available (CloudNativePG, cert-manager, external-dns). SemVer with -rc tags keeps CI environments current. Observability with Prometheus/Grafana. No manual kubectl in productionāGit is the source of truth.',
|
|
494
|
-
},
|
|
495
|
-
app: {
|
|
496
|
-
temperature: 0.4,
|
|
497
|
-
top_p: 0.9,
|
|
498
|
-
mode: 'primary',
|
|
499
|
-
permission: { edit: 'allow', bash: 'deny', webfetch: 'allow' },
|
|
500
|
-
note: 'Bash access is denied for app persona to prevent shell command execution in mobile/Expo environments. This restriction enforces security and architectural boundaries.',
|
|
501
|
-
description: 'Expo + React Native apps; props-first, offline-aware, shared tokens.',
|
|
502
|
-
prompt: 'You are Berget Code App agent. Voice: Scandinavian calmāprecise, concise, confident. Expo + React Native + TypeScript. Structure by components/hooks/services/navigation. Components are pure; data via props; refactor shared logic into hooks/stores. Share tokens with frontend. Mock data in /data via typed hooks; later replace with live APIs. Offline via SQLite/MMKV; notifications via Expo. Request permissions only when needed. Subtle, meaningful motion; light/dark parity.',
|
|
503
|
-
},
|
|
504
|
-
security: {
|
|
505
|
-
temperature: 0.2,
|
|
506
|
-
top_p: 0.8,
|
|
507
|
-
mode: 'subagent',
|
|
508
|
-
permission: { edit: 'deny', bash: 'allow', webfetch: 'allow' },
|
|
509
|
-
description: 'Security specialist for pentesting, OWASP compliance, and vulnerability assessments.',
|
|
510
|
-
prompt: 'Voice: Scandinavian calmāprecise, concise, confident. You are Berget Code Security agent. Expert in application security, penetration testing, and OWASP standards. Core responsibilities: Conduct security assessments and penetration tests, Validate OWASP Top 10 compliance, Review code for security vulnerabilities, Implement security headers and Content Security Policy (CSP), Audit API security, Check for sensitive data exposure, Validate input sanitization and output encoding, Assess dependency security and supply chain risks. Tools and techniques: OWASP ZAP, Burp Suite, security linters, dependency scanners, manual code review. Always provide specific, actionable security recommendations with priority levels.',
|
|
511
|
-
},
|
|
512
|
-
quality: {
|
|
513
|
-
temperature: 0.1,
|
|
514
|
-
top_p: 0.9,
|
|
515
|
-
mode: 'subagent',
|
|
516
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
517
|
-
description: 'Quality assurance specialist for testing, building, and PR management.',
|
|
518
|
-
prompt: 'Voice: Scandinavian calmāprecise, concise, confident. You are Berget Code Quality agent. Specialist in code quality assurance, testing, building, and pull request management.\n\nCore responsibilities:\n - Run comprehensive test suites (npm test, npm run test, jest, vitest)\n - Execute build processes (npm run build, webpack, vite, tsc)\n - Create and manage pull requests with proper descriptions\n - Monitor GitHub for Copilot/reviewer comments\n - Ensure code quality standards are met\n - Validate linting and formatting (npm run lint, prettier)\n - Check test coverage and performance benchmarks\n - Handle CI/CD pipeline validation\n\nCommon CLI commands:\n - npm test or npm run test (run test suite)\n - npm run build (build project)\n - npm run lint (run linting)\n - npm run format (format code)\n - npm run test:coverage (check coverage)\n - gh pr create (create pull request)\n - gh pr view --comments (check PR comments)\n - git add . && git commit -m "message" && git push (commit and push)\n\nPR Workflow:\n 1. Ensure all tests pass: npm test\n 2. Build successfully: npm run build\n 3. Create/update PR with clear description\n 4. Monitor for reviewer comments\n 5. Address feedback promptly\n 6. Update PR with fixes\n 7. Ensure CI checks pass\n\nAlways provide specific command examples and wait for processes to complete before proceeding.',
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
command: {
|
|
522
|
-
fullstack: {
|
|
523
|
-
description: 'Switch to Fullstack (router)',
|
|
524
|
-
template: '{{input}}',
|
|
525
|
-
agent: 'fullstack',
|
|
526
|
-
},
|
|
527
|
-
route: {
|
|
528
|
-
description: 'Let Fullstack auto-route to the right persona based on files/intent',
|
|
529
|
-
template: 'ROUTE {{input}}',
|
|
530
|
-
agent: 'fullstack',
|
|
531
|
-
subtask: true,
|
|
532
|
-
},
|
|
533
|
-
frontend: {
|
|
534
|
-
description: 'Switch to Frontend persona',
|
|
535
|
-
template: '{{input}}',
|
|
536
|
-
agent: 'frontend',
|
|
537
|
-
},
|
|
538
|
-
backend: {
|
|
539
|
-
description: 'Switch to Backend persona',
|
|
540
|
-
template: '{{input}}',
|
|
541
|
-
agent: 'backend',
|
|
542
|
-
},
|
|
543
|
-
devops: {
|
|
544
|
-
description: 'Switch to DevOps persona',
|
|
545
|
-
template: '{{input}}',
|
|
546
|
-
agent: 'devops',
|
|
547
|
-
},
|
|
548
|
-
app: {
|
|
549
|
-
description: 'Switch to App persona',
|
|
550
|
-
template: '{{input}}',
|
|
551
|
-
agent: 'app',
|
|
552
|
-
},
|
|
553
|
-
quality: {
|
|
554
|
-
description: 'Switch to Quality agent for testing, building, and PR management',
|
|
555
|
-
template: '{{input}}',
|
|
556
|
-
agent: 'quality',
|
|
557
|
-
},
|
|
558
|
-
},
|
|
559
|
-
watcher: {
|
|
560
|
-
ignore: ['node_modules', 'dist', '.git', 'coverage'],
|
|
561
|
-
},
|
|
335
|
+
plugin: ['@bergetai/opencode-auth@1.0.16'],
|
|
562
336
|
};
|
|
563
|
-
|
|
337
|
+
const agentsDir = path_1.default.join(process.cwd(), '.opencode', 'agents');
|
|
338
|
+
const templatesDir = getAgentTemplatesDir();
|
|
564
339
|
if (!options.yes) {
|
|
565
340
|
console.log(chalk_1.default.blue('\nAbout to create configuration files:'));
|
|
566
341
|
console.log(chalk_1.default.dim(`Config: ${configPath}`));
|
|
342
|
+
console.log(chalk_1.default.dim(`Agents: ${agentsDir}/`));
|
|
567
343
|
console.log(chalk_1.default.dim('This will configure OpenCode with the Berget auth plugin.'));
|
|
568
344
|
}
|
|
569
345
|
if (yield confirm('\nCreate configuration files? (Y/n): ', options.yes)) {
|
|
570
346
|
try {
|
|
571
|
-
// Create opencode.json
|
|
572
347
|
yield (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2));
|
|
573
|
-
console.log(chalk_1.default.green(
|
|
574
|
-
console.log(chalk_1.default.dim(
|
|
575
|
-
|
|
348
|
+
console.log(chalk_1.default.green('ā Created opencode.json'));
|
|
349
|
+
console.log(chalk_1.default.dim(' Plugin: @bergetai/opencode-auth'));
|
|
350
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
351
|
+
const templateFiles = fs
|
|
352
|
+
.readdirSync(templatesDir)
|
|
353
|
+
.filter((f) => f.endsWith('.md'));
|
|
354
|
+
for (const file of templateFiles) {
|
|
355
|
+
const src = path_1.default.join(templatesDir, file);
|
|
356
|
+
const dest = path_1.default.join(agentsDir, file);
|
|
357
|
+
fs.copyFileSync(src, dest);
|
|
358
|
+
}
|
|
359
|
+
console.log(chalk_1.default.green(`ā Created ${templateFiles.length} agent definitions in .opencode/agents/`));
|
|
576
360
|
}
|
|
577
361
|
catch (error) {
|
|
578
362
|
console.error(chalk_1.default.red('Failed to create config files:'));
|
|
@@ -721,7 +505,6 @@ function registerCodeCommands(program) {
|
|
|
721
505
|
.option('-f, --force', 'Force update even if already latest')
|
|
722
506
|
.option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
|
|
723
507
|
.action((options) => __awaiter(this, void 0, void 0, function* () {
|
|
724
|
-
var _a, _b, _c;
|
|
725
508
|
try {
|
|
726
509
|
console.log(chalk_1.default.cyan('š Updating OpenCode configuration...'));
|
|
727
510
|
// Ensure opencode is installed first
|
|
@@ -747,162 +530,57 @@ function registerCodeCommands(program) {
|
|
|
747
530
|
return;
|
|
748
531
|
}
|
|
749
532
|
console.log(chalk_1.default.blue('š Current configuration:'));
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
const
|
|
755
|
-
|
|
533
|
+
if (currentConfig.model) {
|
|
534
|
+
console.log(chalk_1.default.dim(` Model: ${currentConfig.model}`));
|
|
535
|
+
}
|
|
536
|
+
const agentsDir = path_1.default.join(process.cwd(), '.opencode', 'agents');
|
|
537
|
+
const templatesDir = getAgentTemplatesDir();
|
|
538
|
+
const templateFiles = fs
|
|
539
|
+
.readdirSync(templatesDir)
|
|
540
|
+
.filter((f) => f.endsWith('.md'));
|
|
756
541
|
const latestConfig = {
|
|
757
542
|
$schema: 'https://opencode.ai/config.json',
|
|
758
|
-
plugin: ['@bergetai/opencode-auth@1.0.
|
|
759
|
-
username: 'berget-code',
|
|
760
|
-
theme: 'berget-dark',
|
|
761
|
-
share: 'manual',
|
|
762
|
-
autoupdate: true,
|
|
763
|
-
agent: {
|
|
764
|
-
fullstack: {
|
|
765
|
-
temperature: 0.3,
|
|
766
|
-
top_p: 0.9,
|
|
767
|
-
mode: 'primary',
|
|
768
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
769
|
-
description: 'Router/coordinator agent for full-stack development with schema-driven architecture',
|
|
770
|
-
prompt: 'Voice: Scandinavian calmāprecise, concise, confident; no fluff. You are Berget Code Fullstack agent. Act as a router and coordinator in a monorepo. Bottom-up schema: database ā OpenAPI ā generated types. Top-down types: API ā UI ā components. Use openapi-fetch and Zod at every boundary; compile-time errors are desired when contracts change. Routing rules: if task/paths match /apps/frontend or React (.tsx) ā use frontend; if /apps/app or Expo/React Native ā app; if /infra, /k8s, flux-system, kustomization.yaml, Helm values ā devops; if /services, Koa routers, services/adapters/domain ā backend. If ambiguous, remain fullstack and outline the end-to-end plan, then delegate subtasks to the right persona. Security: validate inputs; secrets via FluxCD SOPS/Sealed Secrets. Documentation is generated from codeānever duplicated. CRITICAL: When all implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.',
|
|
771
|
-
},
|
|
772
|
-
frontend: {
|
|
773
|
-
temperature: 0.4,
|
|
774
|
-
top_p: 0.9,
|
|
775
|
-
mode: 'primary',
|
|
776
|
-
permission: { edit: 'allow', bash: 'deny', webfetch: 'allow' },
|
|
777
|
-
note: 'Bash access is denied for frontend persona to prevent shell command execution in UI environments. This restriction enforces security and architectural boundaries.',
|
|
778
|
-
description: 'Builds Scandinavian, type-safe UIs with React, Tailwind, Shadcn.',
|
|
779
|
-
prompt: 'You are Berget Code Frontend agent. Voice: Scandinavian calmāprecise, concise, confident. React 18 + TypeScript. Tailwind + Shadcn UI only via the design system (index.css, tailwind.config.ts). Use semantic tokens for color/spacing/typography/motion; never ad-hoc classes or inline colors. Components are pure and responsive; props-first data; minimal global state (Zustand/Jotai). Accessibility and keyboard navigation mandatory. Mock data only at init under /data via typed hooks (e.g., useProducts() reading /data/products.json). Design: minimal, balanced, quiet motion. CRITICAL: When all frontend implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.',
|
|
780
|
-
},
|
|
781
|
-
backend: {
|
|
782
|
-
temperature: 0.3,
|
|
783
|
-
top_p: 0.9,
|
|
784
|
-
mode: 'primary',
|
|
785
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
786
|
-
description: 'Functional, modular Koa + TypeScript services; schema-first with code quality focus.',
|
|
787
|
-
prompt: 'You are Berget Code Backend agent. Voice: Scandinavian calmāprecise, concise, confident. TypeScript + Koa. Prefer many small pure functions; avoid big try/catch blocks. Routes thin; logic in services/adapters/domain. Validate with Zod; auto-generate OpenAPI. Adapters isolate external systems; domain never depends on framework. Test with supertest; idempotent and stateless by default. Each microservice emits an OpenAPI contract; changes propagate upward to types. Code Quality & Refactoring Principles: Apply Single Responsibility Principle, fail fast with explicit errors, eliminate code duplication, remove nested complexity, use descriptive error codes, keep functions under 30 lines. Always leave code cleaner and more readable than you found it. CRITICAL: When all backend implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.',
|
|
788
|
-
},
|
|
789
|
-
// Use centralized devops configuration with Helm guidelines
|
|
790
|
-
devops: latestAgentConfig.devops || {
|
|
791
|
-
temperature: 0.3,
|
|
792
|
-
top_p: 0.8,
|
|
793
|
-
mode: 'primary',
|
|
794
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
795
|
-
description: 'Declarative GitOps infra with FluxCD, Kustomize, Helm, operators.',
|
|
796
|
-
prompt: 'You are Berget Code DevOps agent. Voice: Scandinavian calmāprecise, concise, confident. Start simple: k8s/{deployment,service,ingress}. Add FluxCD sync to repo and image automation. Use Kustomize bases/overlays (staging, production). Add dependencies via Helm from upstream sources; prefer native operators when available (CloudNativePG, cert-manager, external-dns). SemVer with -rc tags keeps CI environments current. Observability with Prometheus/Grafana. No manual kubectl in productionāGit is the source of truth. For testing, building, and PR management, use @quality subagent.',
|
|
797
|
-
},
|
|
798
|
-
app: {
|
|
799
|
-
temperature: 0.4,
|
|
800
|
-
top_p: 0.9,
|
|
801
|
-
mode: 'primary',
|
|
802
|
-
permission: { edit: 'allow', bash: 'deny', webfetch: 'allow' },
|
|
803
|
-
note: 'Bash access is denied for app persona to prevent shell command execution in mobile/Expo environments. This restriction enforces security and architectural boundaries.',
|
|
804
|
-
description: 'Expo + React Native apps; props-first, offline-aware, shared tokens.',
|
|
805
|
-
prompt: 'You are Berget Code App agent. Voice: Scandinavian calmāprecise, concise, confident. Expo + React Native + TypeScript. Structure by components/hooks/services/navigation. Components are pure; data via props; refactor shared logic into hooks/stores. Share tokens with frontend. Mock data in /data via typed hooks; later replace with live APIs. Offline via SQLite/MMKV; notifications via Expo. Request permissions only when needed. Subtle, meaningful motion; light/dark parity. For testing, building, and PR management, use @quality subagent.',
|
|
806
|
-
},
|
|
807
|
-
security: {
|
|
808
|
-
temperature: 0.2,
|
|
809
|
-
top_p: 0.8,
|
|
810
|
-
mode: 'subagent',
|
|
811
|
-
permission: { edit: 'deny', bash: 'allow', webfetch: 'allow' },
|
|
812
|
-
description: 'Security specialist for pentesting, OWASP compliance, and vulnerability assessments.',
|
|
813
|
-
prompt: 'Voice: Scandinavian calmāprecise, concise, confident. You are Berget Code Security agent. Expert in application security, penetration testing, and OWASP standards. Core responsibilities: Conduct security assessments and penetration tests, Validate OWASP Top 10 compliance, Review code for security vulnerabilities, Implement security headers and Content Security Policy (CSP), Audit API security, Check for sensitive data exposure, Validate input sanitization and output encoding, Assess dependency security and supply chain risks. Tools and techniques: OWASP ZAP, Burp Suite, security linters, dependency scanners, manual code review. Always provide specific, actionable security recommendations with priority levels. Workflow: Always follow branch_strategy and commit_convention from workflow section. Never work directly in main. Agent awareness: Review code from all personas (frontend, backend, app, devops). If implementation changes are needed, suggest <tab> to switch to appropriate persona after security assessment.',
|
|
814
|
-
},
|
|
815
|
-
quality: {
|
|
816
|
-
temperature: 0.1,
|
|
817
|
-
top_p: 0.9,
|
|
818
|
-
mode: 'subagent',
|
|
819
|
-
permission: { edit: 'allow', bash: 'allow', webfetch: 'allow' },
|
|
820
|
-
description: 'Quality assurance specialist for testing, building, and complete PR management.',
|
|
821
|
-
prompt: 'Voice: Scandinavian calmāprecise, concise, confident. You are Berget Code Quality agent. Specialist in code quality assurance, testing, building, and complete pull request lifecycle management.\n\nCore responsibilities:\n - Run comprehensive test suites (npm test, npm run test, jest, vitest)\n - Execute build processes (npm run build, webpack, vite, tsc)\n - Create and manage pull requests with proper descriptions\n - Handle merge conflicts and keep main updated\n - Monitor GitHub for reviewer comments and address them\n - Ensure code quality standards are met\n - Validate linting and formatting (npm run lint, prettier)\n - Check test coverage and performance benchmarks\n - Handle CI/CD pipeline validation\n\nComplete PR Workflow:\n 1. Ensure all tests pass: npm test\n 2. Build successfully: npm run build\n 3. Commit all changes with proper message\n 4. Push to feature branch\n 5. Update main branch and handle merge conflicts\n 6. Create or update PR with comprehensive description\n 7. Monitor for reviewer comments\n 8. Address feedback and push updates\n 9. Always provide PR URL for user review\n\nEssential CLI commands:\n - npm test or npm run test (run test suite)\n - npm run build (build project)\n - npm run lint (run linting)\n - npm run format (format code)\n - npm run test:coverage (check coverage)\n - git add . && git commit -m "message" && git push (commit and push)\n - git checkout main && git pull origin main (update main)\n - git checkout feature-branch && git merge main (handle conflicts)\n - gh pr create --title "title" --body "body" (create PR)\n - gh pr view --comments (check PR comments)\n - gh pr edit --title "title" --body "body" (update PR)\n\nPR Creation Process:\n - Always include clear summary of changes\n - List technical details and improvements\n - Include testing and validation results\n - Add any breaking changes or migration notes\n - Provide PR URL immediately after creation\n\nMerge Conflict Resolution:\n - Always update main before creating/updating PR\n - Handle conflicts automatically when possible\n - If conflicts require human input, clearly explain what\'s needed\n - Re-run tests after conflict resolution\n - Ensure CI checks pass before finalizing\n\nReviewer Comment Handling:\n - Monitor PR for new comments regularly\n - Address each comment specifically\n - Push fixes and update PR accordingly\n - Always provide updated PR URL after changes\n - Continue monitoring until all feedback is addressed\n\nCRITICAL: When invoked by other agents (@quality), you MUST:\n - Complete all testing and building tasks\n - Handle entire PR creation/update process\n - Provide PR URL at the end\n - Ensure main branch is properly merged\n - Handle any merge conflicts automatically\n\nAlways provide specific command examples and wait for processes to complete before proceeding.\nWorkflow: Always follow branch_strategy and commit_convention from workflow section. Never work directly in main.\nAgent awareness: Can be invoked by any primary agent (@quality) for complete testing, building, and PR management. You are the final step before user review - ensure everything is perfect.',
|
|
822
|
-
},
|
|
823
|
-
},
|
|
824
|
-
command: {
|
|
825
|
-
fullstack: {
|
|
826
|
-
description: 'Switch to Fullstack (router)',
|
|
827
|
-
template: '{{input}}',
|
|
828
|
-
agent: 'fullstack',
|
|
829
|
-
},
|
|
830
|
-
route: {
|
|
831
|
-
description: 'Let Fullstack auto-route to the right persona based on files/intent',
|
|
832
|
-
template: 'ROUTE {{input}}',
|
|
833
|
-
agent: 'fullstack',
|
|
834
|
-
subtask: true,
|
|
835
|
-
},
|
|
836
|
-
frontend: {
|
|
837
|
-
description: 'Switch to Frontend persona',
|
|
838
|
-
template: '{{input}}',
|
|
839
|
-
agent: 'frontend',
|
|
840
|
-
},
|
|
841
|
-
backend: {
|
|
842
|
-
description: 'Switch to Backend persona',
|
|
843
|
-
template: '{{input}}',
|
|
844
|
-
agent: 'backend',
|
|
845
|
-
},
|
|
846
|
-
devops: {
|
|
847
|
-
description: 'Switch to DevOps persona',
|
|
848
|
-
template: '{{input}}',
|
|
849
|
-
agent: 'devops',
|
|
850
|
-
},
|
|
851
|
-
app: {
|
|
852
|
-
description: 'Switch to App persona',
|
|
853
|
-
template: '{{input}}',
|
|
854
|
-
agent: 'app',
|
|
855
|
-
},
|
|
856
|
-
security: {
|
|
857
|
-
description: 'Switch to Security persona for pentesting and OWASP compliance',
|
|
858
|
-
template: '{{input}}',
|
|
859
|
-
agent: 'security',
|
|
860
|
-
},
|
|
861
|
-
quality: {
|
|
862
|
-
description: 'Switch to Quality agent for testing, building, and PR management',
|
|
863
|
-
template: '{{input}}',
|
|
864
|
-
agent: 'quality',
|
|
865
|
-
},
|
|
866
|
-
},
|
|
867
|
-
watcher: {
|
|
868
|
-
ignore: ['node_modules', 'dist', '.git', 'coverage'],
|
|
869
|
-
},
|
|
543
|
+
plugin: ['@bergetai/opencode-auth@1.0.16'],
|
|
870
544
|
};
|
|
871
|
-
// Check if
|
|
872
|
-
|
|
873
|
-
|
|
545
|
+
// Check if agent definitions need updating
|
|
546
|
+
let agentsNeedUpdate = false;
|
|
547
|
+
const existingAgentFiles = fs.existsSync(agentsDir)
|
|
548
|
+
? fs.readdirSync(agentsDir).filter((f) => f.endsWith('.md'))
|
|
549
|
+
: [];
|
|
550
|
+
for (const file of templateFiles) {
|
|
551
|
+
const src = path_1.default.join(templatesDir, file);
|
|
552
|
+
const dest = path_1.default.join(agentsDir, file);
|
|
553
|
+
if (!fs.existsSync(dest)) {
|
|
554
|
+
agentsNeedUpdate = true;
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
557
|
+
const srcContent = fs.readFileSync(src, 'utf8');
|
|
558
|
+
const destContent = fs.readFileSync(dest, 'utf8');
|
|
559
|
+
if (srcContent !== destContent) {
|
|
560
|
+
agentsNeedUpdate = true;
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
// Check if opencode.json still has inline agent config (needs migration)
|
|
565
|
+
const needsMigration = !!currentConfig.agent;
|
|
566
|
+
if (!agentsNeedUpdate && !needsMigration && !options.force) {
|
|
874
567
|
console.log(chalk_1.default.green('ā
Already using the latest configuration!'));
|
|
875
568
|
return;
|
|
876
569
|
}
|
|
877
|
-
if (
|
|
570
|
+
if (agentsNeedUpdate || needsMigration) {
|
|
878
571
|
console.log(chalk_1.default.blue('\nš Updates available:'));
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
const latestAgents = Object.keys(latestConfig.agent);
|
|
882
|
-
const newAgents = latestAgents.filter((agent) => !currentAgents.includes(agent));
|
|
883
|
-
if (newAgents.length > 0) {
|
|
884
|
-
console.log(chalk_1.default.cyan(` ⢠New agents: ${newAgents.join(', ')}`));
|
|
885
|
-
}
|
|
886
|
-
// Check for quality agent specifically
|
|
887
|
-
if (!((_a = currentConfig.agent) === null || _a === void 0 ? void 0 : _a.quality) && latestConfig.agent.quality) {
|
|
888
|
-
console.log(chalk_1.default.cyan(' ⢠Quality subagent for testing and PR management'));
|
|
889
|
-
}
|
|
890
|
-
// Check for security subagent mode
|
|
891
|
-
if (((_c = (_b = currentConfig.agent) === null || _b === void 0 ? void 0 : _b.security) === null || _c === void 0 ? void 0 : _c.mode) !== 'subagent') {
|
|
892
|
-
console.log(chalk_1.default.cyan(' ⢠Security agent converted to subagent (read-only)'));
|
|
572
|
+
if (needsMigration) {
|
|
573
|
+
console.log(chalk_1.default.cyan(' ⢠Migrate agents from opencode.json to .opencode/agents/'));
|
|
893
574
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
console.log(chalk_1.default.cyan(' ⢠Plugin-first auth (automatic token refresh + model discovery)'));
|
|
575
|
+
if (agentsNeedUpdate) {
|
|
576
|
+
console.log(chalk_1.default.cyan(' ⢠Latest agent prompts and improvements'));
|
|
897
577
|
}
|
|
898
|
-
console.log(chalk_1.default.cyan(' ⢠Latest agent prompts and improvements'));
|
|
899
578
|
}
|
|
900
579
|
if (options.force) {
|
|
901
580
|
console.log(chalk_1.default.yellow('š§ Force update requested'));
|
|
902
581
|
}
|
|
903
582
|
if (!options.yes) {
|
|
904
|
-
console.log(chalk_1.default.blue('\nThis will update your
|
|
905
|
-
// Check if user has git for backup
|
|
583
|
+
console.log(chalk_1.default.blue('\nThis will update your agent definitions and OpenCode configuration.'));
|
|
906
584
|
const hasGitRepo = hasGit();
|
|
907
585
|
if (!hasGitRepo) {
|
|
908
586
|
console.log(chalk_1.default.yellow('ā ļø No .git repository detected - backup will be created'));
|
|
@@ -911,38 +589,37 @@ function registerCodeCommands(program) {
|
|
|
911
589
|
console.log(chalk_1.default.green('ā Git repository detected - changes are tracked'));
|
|
912
590
|
}
|
|
913
591
|
}
|
|
914
|
-
|
|
915
|
-
console.log(chalk_1.default.blue('\nChoose update strategy:'));
|
|
916
|
-
console.log(chalk_1.default.cyan('1) Replace - Use latest configuration (your customizations will be lost)'));
|
|
917
|
-
console.log(chalk_1.default.cyan('2) Merge - Combine latest updates with your customizations (recommended)'));
|
|
918
|
-
let mergeChoice = 'merge';
|
|
919
|
-
if (!options.yes) {
|
|
920
|
-
const choice = yield askChoice('\nYour choice (1-2, default: 2): ', ['replace', 'merge'], 'merge');
|
|
921
|
-
mergeChoice = choice;
|
|
922
|
-
}
|
|
923
|
-
if (yield confirm(`\nProceed with ${mergeChoice}? (Y/n): `, options.yes)) {
|
|
592
|
+
if (yield confirm('\nProceed with update? (Y/n): ', options.yes)) {
|
|
924
593
|
try {
|
|
925
|
-
let finalConfig;
|
|
926
594
|
let backupPath = null;
|
|
927
|
-
// Create backup if no git
|
|
928
595
|
if (!hasGit()) {
|
|
929
596
|
backupPath = `${configPath}.backup.${Date.now()}`;
|
|
930
597
|
yield (0, promises_1.writeFile)(backupPath, JSON.stringify(currentConfig, null, 2));
|
|
931
598
|
console.log(chalk_1.default.green(`ā Backed up current config to ${path_1.default.basename(backupPath)}`));
|
|
932
599
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
600
|
+
// Remove inline agent section from opencode.json if present
|
|
601
|
+
if (currentConfig.agent) {
|
|
602
|
+
delete currentConfig.agent;
|
|
603
|
+
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'));
|
|
937
605
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
606
|
+
// Sync agent markdown files from templates
|
|
607
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
608
|
+
let updatedCount = 0;
|
|
609
|
+
for (const file of templateFiles) {
|
|
610
|
+
const src = path_1.default.join(templatesDir, file);
|
|
611
|
+
const dest = path_1.default.join(agentsDir, file);
|
|
612
|
+
const agentName = path_1.default.basename(file, '.md');
|
|
613
|
+
if (!fs.existsSync(dest) ||
|
|
614
|
+
fs.readFileSync(src, 'utf8') !== fs.readFileSync(dest, 'utf8')) {
|
|
615
|
+
fs.copyFileSync(src, dest);
|
|
616
|
+
updatedCount++;
|
|
617
|
+
console.log(chalk_1.default.cyan(` ⢠Updated agent: ${agentName}`));
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (updatedCount > 0) {
|
|
621
|
+
console.log(chalk_1.default.green(`ā Updated ${updatedCount} agent definition(s)`));
|
|
942
622
|
}
|
|
943
|
-
// Write final configuration
|
|
944
|
-
yield (0, promises_1.writeFile)(configPath, JSON.stringify(finalConfig, null, 2));
|
|
945
|
-
console.log(chalk_1.default.green(`ā Updated opencode.json with ${mergeChoice} strategy`));
|
|
946
623
|
// Update AGENTS.md if it doesn't exist
|
|
947
624
|
const agentsMdPath = path_1.default.join(process.cwd(), 'AGENTS.md');
|
|
948
625
|
if (!fs.existsSync(agentsMdPath)) {
|
|
@@ -950,180 +627,59 @@ function registerCodeCommands(program) {
|
|
|
950
627
|
|
|
951
628
|
This document describes the specialized agents available in this project for use with OpenCode.
|
|
952
629
|
|
|
630
|
+
Agents are defined as markdown files in \`.opencode/agents/\` with YAML frontmatter.
|
|
631
|
+
|
|
953
632
|
## Available Agents
|
|
954
633
|
|
|
955
634
|
### Primary Agents
|
|
956
635
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
**Key features:**
|
|
966
|
-
- Schema-driven development (database ā OpenAPI ā types)
|
|
967
|
-
- Automatic routing to appropriate persona
|
|
968
|
-
- Tech stack discovery and recommendations
|
|
969
|
-
|
|
970
|
-
#### frontend
|
|
971
|
-
Builds Scandinavian, type-safe UIs with React, Tailwind, and Shadcn.
|
|
972
|
-
|
|
973
|
-
**Use when:**
|
|
974
|
-
- Working with React components (.tsx files)
|
|
975
|
-
- Frontend development in /apps/frontend
|
|
976
|
-
- UI/UX implementation
|
|
977
|
-
|
|
978
|
-
**Key features:**
|
|
979
|
-
- Design system integration
|
|
980
|
-
- Semantic tokens and accessibility
|
|
981
|
-
- Props-first component architecture
|
|
982
|
-
|
|
983
|
-
#### backend
|
|
984
|
-
Functional, modular Koa + TypeScript services with schema-first approach and code quality focus.
|
|
985
|
-
|
|
986
|
-
**Use when:**
|
|
987
|
-
- Working with Koa routers and services
|
|
988
|
-
- Backend development in /services
|
|
989
|
-
- API development and database work
|
|
990
|
-
|
|
991
|
-
**Key features:**
|
|
992
|
-
- Zod validation and OpenAPI generation
|
|
993
|
-
- Code quality and refactoring principles
|
|
994
|
-
- PR workflow integration
|
|
995
|
-
|
|
996
|
-
#### devops
|
|
997
|
-
Declarative GitOps infrastructure with FluxCD, Kustomize, Helm, and operators.
|
|
998
|
-
|
|
999
|
-
**Use when:**
|
|
1000
|
-
- Working with Kubernetes manifests
|
|
1001
|
-
- Infrastructure in /infra or /k8s
|
|
1002
|
-
- CI/CD and deployment configurations
|
|
1003
|
-
|
|
1004
|
-
**Key features:**
|
|
1005
|
-
- GitOps workflows
|
|
1006
|
-
- Operator-first approach
|
|
1007
|
-
- SemVer with release candidates
|
|
1008
|
-
|
|
1009
|
-
**Helm Values Configuration Process:**
|
|
1010
|
-
1. Documentation First Approach: Always fetch official documentation from Artifact Hub/GitHub for the specific chart version before writing values. Search Artifact Hub for exact chart version documentation, check the chart's GitHub repository for official docs and examples, verify the exact version being used in the deployment.
|
|
1011
|
-
2. Validation Requirements: Check for available validation schemas before committing YAML files. Use Helm's built-in validation tools (helm lint, helm template). Validate against JSON schema if available for the chart. Ensure YAML syntax correctness with linters.
|
|
1012
|
-
3. Standard Workflow: Identify chart name and exact version. Fetch official documentation from Artifact Hub/GitHub. Check for available schemas and validation tools. Write values according to official documentation. Validate against schema (if available). Test with helm template or helm lint. Commit validated YAML files.
|
|
1013
|
-
4. Quality Assurance: Never commit unvalidated Helm values. Use helm dependency update when adding new charts. Test rendering with helm template --dry-run before deployment. Document any custom values with comments referencing official docs.
|
|
1014
|
-
|
|
1015
|
-
#### app
|
|
1016
|
-
Expo + React Native applications with props-first architecture and offline awareness.
|
|
1017
|
-
|
|
1018
|
-
**Use when:**
|
|
1019
|
-
- Mobile app development with Expo
|
|
1020
|
-
- React Native projects in /apps/app
|
|
1021
|
-
- Cross-platform mobile development
|
|
1022
|
-
|
|
1023
|
-
**Key features:**
|
|
1024
|
-
- Shared design tokens with frontend
|
|
1025
|
-
- Offline-first architecture
|
|
1026
|
-
- Expo integration
|
|
636
|
+
| Agent | Description | Temperature |
|
|
637
|
+
|-------|-------------|-------------|
|
|
638
|
+
| fullstack | Router/coordinator for full-stack development | 0.3 |
|
|
639
|
+
| frontend | Scandinavian, type-safe UIs with React, Tailwind, Shadcn | 0.4 |
|
|
640
|
+
| backend | Functional, modular Koa + TypeScript services | 0.3 |
|
|
641
|
+
| devops | Declarative GitOps infra with FluxCD, Kustomize, Helm | 0.3 |
|
|
642
|
+
| app | Expo + React Native apps; props-first, offline-aware | 0.4 |
|
|
1027
643
|
|
|
1028
644
|
### Subagents
|
|
1029
645
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
- Need security review of code changes
|
|
1035
|
-
- OWASP Top 10 compliance checks
|
|
1036
|
-
- Vulnerability assessments
|
|
1037
|
-
|
|
1038
|
-
**Key features:**
|
|
1039
|
-
- OWASP standards compliance
|
|
1040
|
-
- Security best practices
|
|
1041
|
-
- Actionable remediation strategies
|
|
1042
|
-
|
|
1043
|
-
#### quality
|
|
1044
|
-
Quality assurance specialist for testing, building, and PR management.
|
|
1045
|
-
|
|
1046
|
-
**Use when:**
|
|
1047
|
-
- Need to run test suites and build processes
|
|
1048
|
-
- Creating or updating pull requests
|
|
1049
|
-
- Monitoring GitHub for reviewer comments
|
|
1050
|
-
- Ensuring code quality standards
|
|
1051
|
-
|
|
1052
|
-
**Key features:**
|
|
1053
|
-
- Comprehensive testing and building workflows
|
|
1054
|
-
- PR creation and management
|
|
1055
|
-
- GitHub integration for reviewer feedback
|
|
1056
|
-
- CLI command expertise for quality assurance
|
|
646
|
+
| Agent | Description | Temperature |
|
|
647
|
+
|-------|-------------|-------------|
|
|
648
|
+
| security | Security specialist for pentesting and OWASP compliance | 0.2 |
|
|
649
|
+
| quality | QA specialist for testing, building, and PR management | 0.1 |
|
|
1057
650
|
|
|
1058
651
|
## Usage
|
|
1059
652
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
### Manual Agent Selection
|
|
1064
|
-
Use commands to switch to specific agents:
|
|
1065
|
-
- \`/fullstack\` - Switch to Fullstack agent
|
|
1066
|
-
- \`/frontend\` - Switch to Frontend agent
|
|
1067
|
-
- \`/backend\` - Switch to Backend agent
|
|
1068
|
-
- \`/devops\` - Switch to DevOps agent
|
|
1069
|
-
- \`/app\` - Switch to App agent
|
|
1070
|
-
- \`/quality\` - Switch to Quality agent for testing and PR management
|
|
1071
|
-
|
|
1072
|
-
### Using Subagents
|
|
1073
|
-
Mention subagents with \`@\` symbol:
|
|
1074
|
-
- \`@security review this authentication implementation\`
|
|
1075
|
-
- \`@quality run tests and create PR for these changes\`
|
|
653
|
+
- **Tab** key to cycle between primary agents
|
|
654
|
+
- **@mention** to invoke subagents (e.g. \`@security review this code\`)
|
|
655
|
+
- \`/fullstack\`, \`/frontend\`, \`/backend\`, \`/devops\`, \`/app\` to switch agents
|
|
1076
656
|
|
|
1077
657
|
## Routing Rules
|
|
1078
658
|
|
|
1079
659
|
The fullstack agent automatically routes tasks based on file patterns:
|
|
1080
660
|
|
|
1081
661
|
- \`/apps/frontend\` or \`.tsx\` files ā frontend
|
|
1082
|
-
- \`/apps/app\` or Expo/React Native ā app
|
|
662
|
+
- \`/apps/app\` or Expo/React Native ā app
|
|
1083
663
|
- \`/infra\`, \`/k8s\`, FluxCD, Helm ā devops
|
|
1084
664
|
- \`/services\`, Koa routers ā backend
|
|
1085
665
|
|
|
1086
|
-
##
|
|
1087
|
-
|
|
1088
|
-
All agents are configured in \`opencode.json\` with:
|
|
1089
|
-
- Specialized prompts and temperature settings
|
|
1090
|
-
- Appropriate tool permissions
|
|
1091
|
-
- Model optimizations for their specific tasks
|
|
1092
|
-
|
|
1093
|
-
## Environment Setup
|
|
1094
|
-
|
|
1095
|
-
Authentication is handled by the Berget plugin. Run \`/connect\` in OpenCode to authenticate.
|
|
1096
|
-
|
|
1097
|
-
## Workflow
|
|
666
|
+
## Customization
|
|
1098
667
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
- Follow branch strategy and commit conventions
|
|
1102
|
-
- Create PRs for new functionality
|
|
1103
|
-
- Run tests before committing
|
|
1104
|
-
- Address reviewer feedback promptly
|
|
668
|
+
Edit the markdown files in \`.opencode/agents/\` to customize agent behavior.
|
|
669
|
+
See https://opencode.ai/docs/agents/ for available options.
|
|
1105
670
|
|
|
1106
671
|
---
|
|
1107
672
|
|
|
1108
673
|
*Updated by berget code update*
|
|
1109
674
|
`;
|
|
1110
675
|
yield (0, promises_1.writeFile)(agentsMdPath, agentsMdContent);
|
|
1111
|
-
console.log(chalk_1.default.green('ā
|
|
676
|
+
console.log(chalk_1.default.green('ā Created AGENTS.md documentation'));
|
|
1112
677
|
}
|
|
1113
678
|
console.log(chalk_1.default.green('\nā
Update completed successfully!'));
|
|
1114
|
-
console.log(chalk_1.default.blue('New features available:'));
|
|
1115
|
-
console.log(chalk_1.default.cyan(' ⢠@quality subagent for testing and PR management'));
|
|
1116
|
-
console.log(chalk_1.default.cyan(' ⢠@security subagent for security reviews'));
|
|
1117
|
-
console.log(chalk_1.default.cyan(' ⢠Improved agent prompts and routing'));
|
|
1118
|
-
console.log(chalk_1.default.cyan(' ⢠GLM-4.7 token optimizations'));
|
|
1119
|
-
console.log(chalk_1.default.blue('\nTry these new commands:'));
|
|
1120
|
-
console.log(chalk_1.default.cyan(' @quality run tests and create PR'));
|
|
1121
|
-
console.log(chalk_1.default.cyan(' @security review this code'));
|
|
1122
679
|
}
|
|
1123
680
|
catch (error) {
|
|
1124
681
|
console.error(chalk_1.default.red('Failed to update configuration:'));
|
|
1125
682
|
(0, error_handler_1.handleError)('Update failed', error);
|
|
1126
|
-
// Restore from backup if update failed
|
|
1127
683
|
try {
|
|
1128
684
|
yield (0, promises_1.writeFile)(configPath, JSON.stringify(currentConfig, null, 2));
|
|
1129
685
|
console.log(chalk_1.default.yellow('š Restored original configuration from backup'));
|