berget 2.0.2 → 2.0.4

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/AGENTS.md CHANGED
@@ -70,6 +70,35 @@ Declarative GitOps infrastructure with FluxCD, Kustomize, Helm, and operators.
70
70
  - Operator-first approach
71
71
  - SemVer with release candidates
72
72
 
73
+ **Helm Values Configuration Process:**
74
+
75
+ 1. **Documentation First Approach:**
76
+ - Always fetch official documentation for the specific chart version before writing values
77
+ - Search Artifact Hub for the exact chart version documentation
78
+ - Check the chart's GitHub repository for official docs and examples
79
+ - Verify the exact version being used in the deployment
80
+
81
+ 2. **Validation Requirements:**
82
+ - Check for available validation schemas before committing YAML files
83
+ - Use Helm's built-in validation tools (`helm lint`, `helm template`)
84
+ - Validate against JSON schema if available for the chart
85
+ - Ensure YAML syntax correctness with linters
86
+
87
+ 3. **Standard Workflow:**
88
+ - Identify chart name and exact version
89
+ - Fetch official documentation from Artifact Hub/GitHub
90
+ - Check for available schemas and validation tools
91
+ - Write values according to official documentation
92
+ - Validate against schema (if available)
93
+ - Test with `helm template` or `helm lint`
94
+ - Commit validated YAML files
95
+
96
+ 4. **Quality Assurance:**
97
+ - Never commit unvalidated Helm values
98
+ - Use `helm dependency update` when adding new charts
99
+ - Test rendering with `helm template --dry-run` before deployment
100
+ - Document any custom values with comments referencing official docs
101
+
73
102
  #### app
74
103
 
75
104
  Expo + React Native applications with props-first architecture and offline awareness.
package/dist/index.js CHANGED
@@ -9,6 +9,8 @@ const commands_1 = require("./src/commands");
9
9
  const config_checker_1 = require("./src/utils/config-checker");
10
10
  const chalk_1 = __importDefault(require("chalk"));
11
11
  const package_json_1 = require("./package.json");
12
+ process.env.DOTENV_CONFIG_OVERRIDE = 'true';
13
+ require("dotenv/config");
12
14
  // Set version and description
13
15
  commander_1.program
14
16
  .name('berget')
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "berget",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "berget": "dist/index.js"
@@ -38,7 +38,7 @@ function registerApiKeyCommands(program) {
38
38
  console.log(chalk_1.default.bold('Your API keys:'));
39
39
  console.log('');
40
40
  // Create a table-like format with headers
41
- console.log(chalk_1.default.dim('ID'.padEnd(10)) +
41
+ console.log(chalk_1.default.dim('ID (8)'.padEnd(8)) +
42
42
  chalk_1.default.dim('NAME'.padEnd(25)) +
43
43
  chalk_1.default.dim('PREFIX'.padEnd(12)) +
44
44
  chalk_1.default.dim('STATUS'.padEnd(12)) +
@@ -52,11 +52,13 @@ function registerApiKeyCommands(program) {
52
52
  const status = key.active
53
53
  ? chalk_1.default.green('● Active')
54
54
  : chalk_1.default.red('● Inactive');
55
+ // Show only first 8 characters of ID for easier reading
56
+ const shortId = String(key.id).substring(0, 8);
55
57
  // Format the prefix to ensure it's not too long
56
58
  const prefixStr = key.prefix.length > 12
57
59
  ? key.prefix.substring(0, 12) + '...'
58
60
  : key.prefix;
59
- console.log(String(key.id).padEnd(10) +
61
+ console.log(shortId.padEnd(8) +
60
62
  key.name.padEnd(25) +
61
63
  prefixStr.padEnd(15) +
62
64
  status.padEnd(12) +
@@ -118,13 +120,59 @@ function registerApiKeyCommands(program) {
118
120
  apiKey
119
121
  .command(api_key_service_1.ApiKeyService.COMMANDS.DELETE)
120
122
  .description('Delete an API key')
121
- .argument('<id>', 'ID of the API key to delete')
122
- .action((id) => __awaiter(this, void 0, void 0, function* () {
123
+ .argument('<identifier>', 'ID (first 8 chars), full ID, or name of the API key to delete')
124
+ .action((identifier) => __awaiter(this, void 0, void 0, function* () {
123
125
  try {
124
- console.log(chalk_1.default.blue(`Deleting API key ${id}...`));
125
126
  const apiKeyService = api_key_service_1.ApiKeyService.getInstance();
126
- yield apiKeyService.delete(id);
127
- console.log(chalk_1.default.green(`✓ API key ${id} has been deleted`));
127
+ // First, get all API keys to find the matching one
128
+ const keys = yield apiKeyService.list();
129
+ // Try to find the key by:
130
+ // 1. Full ID match
131
+ // 2. Short ID (first 8 chars) match
132
+ // 3. Exact name match
133
+ // 4. Partial name match
134
+ // Check for exact matches first (full ID or exact name)
135
+ let exactMatches = keys.filter((key) => String(key.id) === identifier || key.name === identifier);
136
+ // If no exact matches, check for short ID matches
137
+ if (exactMatches.length === 0) {
138
+ exactMatches = keys.filter((key) => String(key.id).substring(0, 8) === identifier);
139
+ }
140
+ // If still no matches, check for partial name matches
141
+ if (exactMatches.length === 0) {
142
+ exactMatches = keys.filter((key) => key.name.toLowerCase().includes(identifier.toLowerCase()));
143
+ }
144
+ // Handle multiple matches
145
+ if (exactMatches.length > 1) {
146
+ console.error(chalk_1.default.red(`Error: Multiple API keys found matching "${identifier}"`));
147
+ console.log('');
148
+ console.log('Please be more specific. Matching keys:');
149
+ exactMatches.forEach((key) => {
150
+ const shortId = String(key.id).substring(0, 8);
151
+ console.log(` ${shortId.padEnd(8)} ${key.name}`);
152
+ });
153
+ console.log('');
154
+ console.log('Use the first 8 characters of the ID to specify which key to delete.');
155
+ return;
156
+ }
157
+ // Handle no matches
158
+ if (exactMatches.length === 0) {
159
+ console.error(chalk_1.default.red(`Error: No API key found matching "${identifier}"`));
160
+ console.log('');
161
+ console.log('Available API keys:');
162
+ keys.forEach((key) => {
163
+ const shortId = String(key.id).substring(0, 8);
164
+ console.log(` ${shortId.padEnd(8)} ${key.name}`);
165
+ });
166
+ console.log('');
167
+ console.log('Use the first 8 characters of the ID, full ID, or name to delete.');
168
+ return;
169
+ }
170
+ const matchingKey = exactMatches[0];
171
+ const keyId = String(matchingKey.id);
172
+ const shortId = keyId.substring(0, 8);
173
+ console.log(chalk_1.default.blue(`Deleting API key ${shortId} (${matchingKey.name})...`));
174
+ yield apiKeyService.delete(keyId);
175
+ console.log(chalk_1.default.green(`✓ API key ${shortId} (${matchingKey.name}) has been deleted`));
128
176
  console.log('');
129
177
  console.log(chalk_1.default.dim('Applications using this key will no longer be able to authenticate.'));
130
178
  console.log(chalk_1.default.dim('Use `berget api-key list` to see your remaining API keys.'));
@@ -48,38 +48,7 @@ const path_1 = __importDefault(require("path"));
48
48
  const child_process_1 = require("child_process");
49
49
  const env_manager_1 = require("../utils/env-manager");
50
50
  const client_1 = require("../client");
51
- // Centralized model configuration
52
- const MODEL_CONFIG = {
53
- // Model names used in agent configurations (with provider prefix)
54
- AGENT_MODELS: {
55
- primary: 'berget/deepseek-r1',
56
- small: 'berget/gpt-oss',
57
- },
58
- // Model definitions in provider configuration (without prefix)
59
- PROVIDER_MODELS: {
60
- 'deepseek-r1': {
61
- name: 'GLM-4.6',
62
- limit: {
63
- output: 4000,
64
- context: 90000,
65
- },
66
- },
67
- 'gpt-oss': {
68
- name: 'GPT-OSS',
69
- limit: {
70
- output: 4000,
71
- context: 128000,
72
- },
73
- },
74
- 'llama-8b': {
75
- name: 'llama-3.1-8b',
76
- limit: {
77
- output: 4000,
78
- context: 128000,
79
- },
80
- },
81
- },
82
- };
51
+ const config_loader_1 = require("../utils/config-loader");
83
52
  /**
84
53
  * Check if current directory has git
85
54
  */
@@ -99,6 +68,7 @@ function mergeConfigurations(currentConfig, latestConfig) {
99
68
  return __awaiter(this, void 0, void 0, function* () {
100
69
  try {
101
70
  const client = (0, client_1.createAuthenticatedClient)();
71
+ const modelConfig = (0, config_loader_1.getModelConfig)();
102
72
  console.log(chalk_1.default.blue('🤖 Using AI to merge configurations...'));
103
73
  const mergePrompt = `You are a configuration merge specialist. Merge these two OpenCode configurations:
104
74
 
@@ -118,7 +88,7 @@ Merge rules:
118
88
  Return ONLY the merged JSON configuration, no explanations.`;
119
89
  const response = yield client.POST('/v1/chat/completions', {
120
90
  body: {
121
- model: MODEL_CONFIG.AGENT_MODELS.primary,
91
+ model: modelConfig.primary,
122
92
  messages: [
123
93
  {
124
94
  role: 'user',
@@ -296,6 +266,23 @@ function getProjectName() {
296
266
  }
297
267
  return path_1.default.basename(process.cwd());
298
268
  }
269
+ /**
270
+ * Load the latest agent configuration from opencode.json
271
+ */
272
+ function loadLatestAgentConfig() {
273
+ return __awaiter(this, void 0, void 0, function* () {
274
+ try {
275
+ const configPath = path_1.default.join(__dirname, '../../opencode.json');
276
+ const configContent = yield (0, promises_1.readFile)(configPath, 'utf8');
277
+ const config = JSON.parse(configContent);
278
+ return config.agent || {};
279
+ }
280
+ catch (error) {
281
+ console.warn(chalk_1.default.yellow('⚠️ Could not load latest agent config, using fallback'));
282
+ return {};
283
+ }
284
+ });
285
+ }
299
286
  /**
300
287
  * Check if opencode is installed
301
288
  */
@@ -556,6 +543,9 @@ function registerCodeCommands(program) {
556
543
  }
557
544
  // Prepare .env file path for safe update
558
545
  const envPath = path_1.default.join(process.cwd(), '.env');
546
+ // Load latest agent configuration to ensure consistency
547
+ const latestAgentConfig = yield loadLatestAgentConfig();
548
+ const modelConfig = (0, config_loader_1.getModelConfig)();
559
549
  // Create opencode.json config with optimized agent-based format
560
550
  const config = {
561
551
  $schema: 'https://opencode.ai/config.json',
@@ -563,11 +553,11 @@ function registerCodeCommands(program) {
563
553
  theme: 'berget-dark',
564
554
  share: 'manual',
565
555
  autoupdate: true,
566
- model: MODEL_CONFIG.AGENT_MODELS.primary,
567
- small_model: MODEL_CONFIG.AGENT_MODELS.small,
556
+ model: modelConfig.primary,
557
+ small_model: modelConfig.small,
568
558
  agent: {
569
559
  fullstack: {
570
- model: MODEL_CONFIG.AGENT_MODELS.primary,
560
+ model: modelConfig.primary,
571
561
  temperature: 0.3,
572
562
  top_p: 0.9,
573
563
  mode: 'primary',
@@ -576,7 +566,7 @@ function registerCodeCommands(program) {
576
566
  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.',
577
567
  },
578
568
  frontend: {
579
- model: MODEL_CONFIG.AGENT_MODELS.primary,
569
+ model: modelConfig.primary,
580
570
  temperature: 0.4,
581
571
  top_p: 0.9,
582
572
  mode: 'primary',
@@ -586,7 +576,7 @@ function registerCodeCommands(program) {
586
576
  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.',
587
577
  },
588
578
  backend: {
589
- model: MODEL_CONFIG.AGENT_MODELS.primary,
579
+ model: modelConfig.primary,
590
580
  temperature: 0.3,
591
581
  top_p: 0.9,
592
582
  mode: 'primary',
@@ -594,8 +584,9 @@ function registerCodeCommands(program) {
594
584
  description: 'Functional, modular Koa + TypeScript services; schema-first with code quality focus.',
595
585
  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.',
596
586
  },
597
- devops: {
598
- model: MODEL_CONFIG.AGENT_MODELS.primary,
587
+ // Use centralized devops configuration with Helm guidelines
588
+ devops: latestAgentConfig.devops || {
589
+ model: modelConfig.primary,
599
590
  temperature: 0.3,
600
591
  top_p: 0.8,
601
592
  mode: 'primary',
@@ -604,7 +595,7 @@ function registerCodeCommands(program) {
604
595
  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.',
605
596
  },
606
597
  app: {
607
- model: MODEL_CONFIG.AGENT_MODELS.primary,
598
+ model: modelConfig.primary,
608
599
  temperature: 0.4,
609
600
  top_p: 0.9,
610
601
  mode: 'primary',
@@ -614,7 +605,7 @@ function registerCodeCommands(program) {
614
605
  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.',
615
606
  },
616
607
  security: {
617
- model: MODEL_CONFIG.AGENT_MODELS.primary,
608
+ model: modelConfig.primary,
618
609
  temperature: 0.2,
619
610
  top_p: 0.8,
620
611
  mode: 'subagent',
@@ -623,7 +614,7 @@ function registerCodeCommands(program) {
623
614
  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.',
624
615
  },
625
616
  quality: {
626
- model: MODEL_CONFIG.AGENT_MODELS.primary,
617
+ model: modelConfig.primary,
627
618
  temperature: 0.1,
628
619
  top_p: 0.9,
629
620
  mode: 'subagent',
@@ -681,7 +672,7 @@ function registerCodeCommands(program) {
681
672
  baseURL: 'https://api.berget.ai/v1',
682
673
  apiKey: '{env:BERGET_API_KEY}',
683
674
  },
684
- models: MODEL_CONFIG.PROVIDER_MODELS,
675
+ models: (0, config_loader_1.getProviderModels)(),
685
676
  },
686
677
  },
687
678
  };
@@ -778,6 +769,12 @@ Declarative GitOps infrastructure with FluxCD, Kustomize, Helm, and operators.
778
769
  - Operator-first approach
779
770
  - SemVer with release candidates
780
771
 
772
+ **Helm Values Configuration Process:**
773
+ 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.
774
+ 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.
775
+ 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.
776
+ 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.
777
+
781
778
  #### app
782
779
  Expo + React Native applications with props-first architecture and offline awareness.
783
780
 
@@ -949,7 +946,6 @@ All agents follow these principles:
949
946
  }
950
947
  // Set environment variables for opencode
951
948
  const env = Object.assign({}, process.env);
952
- env.OPENCODE_API_KEY = config.apiKey;
953
949
  // Prepare opencode command
954
950
  const opencodeArgs = [];
955
951
  if (prompt) {
@@ -984,6 +980,46 @@ All agents follow these principles:
984
980
  (0, error_handler_1.handleError)('Failed to run OpenCode', error);
985
981
  }
986
982
  }));
983
+ code
984
+ .command(command_structure_1.SUBCOMMANDS.CODE.SERVE)
985
+ .description('Start OpenCode web server')
986
+ .option('-p, --port <port>', 'Port to run the server on (default: 3000)')
987
+ .option('-h, --host <host>', 'Host to bind the server to (default: localhost)')
988
+ .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
989
+ .action((options) => __awaiter(this, void 0, void 0, function* () {
990
+ try {
991
+ // Ensure opencode is installed
992
+ if (!(yield ensureOpencodeInstalled(options.yes))) {
993
+ return;
994
+ }
995
+ console.log(chalk_1.default.cyan('🚀 Starting OpenCode web server...'));
996
+ // Prepare opencode serve command
997
+ const serveArgs = ['serve'];
998
+ if (options.port) {
999
+ serveArgs.push('--port', options.port);
1000
+ }
1001
+ if (options.host) {
1002
+ serveArgs.push('--host', options.host);
1003
+ }
1004
+ // Spawn opencode serve process
1005
+ const opencode = (0, child_process_1.spawn)('opencode', serveArgs, {
1006
+ stdio: 'inherit',
1007
+ shell: true,
1008
+ });
1009
+ opencode.on('close', (code) => {
1010
+ if (code !== 0) {
1011
+ console.log(chalk_1.default.red(`OpenCode server exited with code ${code}`));
1012
+ }
1013
+ });
1014
+ opencode.on('error', (error) => {
1015
+ console.error(chalk_1.default.red('Failed to start OpenCode server:'));
1016
+ console.error(error.message);
1017
+ });
1018
+ }
1019
+ catch (error) {
1020
+ (0, error_handler_1.handleError)('Failed to start OpenCode server', error);
1021
+ }
1022
+ }));
987
1023
  code
988
1024
  .command(command_structure_1.SUBCOMMANDS.CODE.UPDATE)
989
1025
  .description('Update OpenCode and agents to latest versions')
@@ -1019,6 +1055,9 @@ All agents follow these principles:
1019
1055
  console.log(chalk_1.default.dim(` Model: ${currentConfig.model}`));
1020
1056
  console.log(chalk_1.default.dim(` Theme: ${currentConfig.theme}`));
1021
1057
  console.log(chalk_1.default.dim(` Agents: ${Object.keys(currentConfig.agent || {}).length} configured`));
1058
+ // Load latest agent configuration to ensure consistency
1059
+ const latestAgentConfig = yield loadLatestAgentConfig();
1060
+ const modelConfig = (0, config_loader_1.getModelConfig)();
1022
1061
  // Create latest configuration with all improvements
1023
1062
  const latestConfig = {
1024
1063
  $schema: 'https://opencode.ai/config.json',
@@ -1026,11 +1065,11 @@ All agents follow these principles:
1026
1065
  theme: 'berget-dark',
1027
1066
  share: 'manual',
1028
1067
  autoupdate: true,
1029
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1030
- small_model: MODEL_CONFIG.AGENT_MODELS.small,
1068
+ model: modelConfig.primary,
1069
+ small_model: modelConfig.small,
1031
1070
  agent: {
1032
1071
  fullstack: {
1033
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1072
+ model: modelConfig.primary,
1034
1073
  temperature: 0.3,
1035
1074
  top_p: 0.9,
1036
1075
  mode: 'primary',
@@ -1039,7 +1078,7 @@ All agents follow these principles:
1039
1078
  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.',
1040
1079
  },
1041
1080
  frontend: {
1042
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1081
+ model: modelConfig.primary,
1043
1082
  temperature: 0.4,
1044
1083
  top_p: 0.9,
1045
1084
  mode: 'primary',
@@ -1049,7 +1088,7 @@ All agents follow these principles:
1049
1088
  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.',
1050
1089
  },
1051
1090
  backend: {
1052
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1091
+ model: modelConfig.primary,
1053
1092
  temperature: 0.3,
1054
1093
  top_p: 0.9,
1055
1094
  mode: 'primary',
@@ -1057,8 +1096,9 @@ All agents follow these principles:
1057
1096
  description: 'Functional, modular Koa + TypeScript services; schema-first with code quality focus.',
1058
1097
  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.',
1059
1098
  },
1060
- devops: {
1061
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1099
+ // Use centralized devops configuration with Helm guidelines
1100
+ devops: latestAgentConfig.devops || {
1101
+ model: modelConfig.primary,
1062
1102
  temperature: 0.3,
1063
1103
  top_p: 0.8,
1064
1104
  mode: 'primary',
@@ -1067,7 +1107,7 @@ All agents follow these principles:
1067
1107
  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.',
1068
1108
  },
1069
1109
  app: {
1070
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1110
+ model: modelConfig.primary,
1071
1111
  temperature: 0.4,
1072
1112
  top_p: 0.9,
1073
1113
  mode: 'primary',
@@ -1077,7 +1117,7 @@ All agents follow these principles:
1077
1117
  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.',
1078
1118
  },
1079
1119
  security: {
1080
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1120
+ model: modelConfig.primary,
1081
1121
  temperature: 0.2,
1082
1122
  top_p: 0.8,
1083
1123
  mode: 'subagent',
@@ -1086,7 +1126,7 @@ All agents follow these principles:
1086
1126
  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.',
1087
1127
  },
1088
1128
  quality: {
1089
- model: MODEL_CONFIG.AGENT_MODELS.primary,
1129
+ model: modelConfig.primary,
1090
1130
  temperature: 0.1,
1091
1131
  top_p: 0.9,
1092
1132
  mode: 'subagent',
@@ -1149,7 +1189,7 @@ All agents follow these principles:
1149
1189
  baseURL: 'https://api.berget.ai/v1',
1150
1190
  apiKey: '{env:BERGET_API_KEY}',
1151
1191
  },
1152
- models: MODEL_CONFIG.PROVIDER_MODELS,
1192
+ models: (0, config_loader_1.getProviderModels)(),
1153
1193
  },
1154
1194
  },
1155
1195
  };
@@ -1177,7 +1217,7 @@ All agents follow these principles:
1177
1217
  console.log(chalk_1.default.cyan(' • Security agent converted to subagent (read-only)'));
1178
1218
  }
1179
1219
  // Check for GLM-4.6 optimizations
1180
- if (!((_h = (_g = (_f = (_e = (_d = currentConfig.provider) === null || _d === void 0 ? void 0 : _d.berget) === null || _e === void 0 ? void 0 : _e.models) === null || _f === void 0 ? void 0 : _f[MODEL_CONFIG.AGENT_MODELS.primary.replace('berget/', '')]) === null || _g === void 0 ? void 0 : _g.limit) === null || _h === void 0 ? void 0 : _h.context)) {
1220
+ if (!((_h = (_g = (_f = (_e = (_d = currentConfig.provider) === null || _d === void 0 ? void 0 : _d.berget) === null || _e === void 0 ? void 0 : _e.models) === null || _f === void 0 ? void 0 : _f[modelConfig.primary.replace('berget/', '')]) === null || _g === void 0 ? void 0 : _g.limit) === null || _h === void 0 ? void 0 : _h.context)) {
1181
1221
  console.log(chalk_1.default.cyan(' • GLM-4.6 token limits and auto-compaction'));
1182
1222
  }
1183
1223
  console.log(chalk_1.default.cyan(' • Latest agent prompts and improvements'));
@@ -1291,6 +1331,12 @@ Declarative GitOps infrastructure with FluxCD, Kustomize, Helm, and operators.
1291
1331
  - Operator-first approach
1292
1332
  - SemVer with release candidates
1293
1333
 
1334
+ **Helm Values Configuration Process:**
1335
+ 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.
1336
+ 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.
1337
+ 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.
1338
+ 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.
1339
+
1294
1340
  #### app
1295
1341
  Expo + React Native applications with props-first architecture and offline awareness.
1296
1342
 
@@ -38,6 +38,7 @@ exports.SUBCOMMANDS = {
38
38
  INIT: 'init',
39
39
  RUN: 'run',
40
40
  UPDATE: 'update',
41
+ SERVE: 'serve',
41
42
  },
42
43
  // API Keys commands
43
44
  API_KEYS: {
@@ -172,5 +173,6 @@ exports.COMMAND_DESCRIPTIONS = {
172
173
  [exports.COMMAND_GROUPS.CODE]: 'AI-powered coding assistant with OpenCode',
173
174
  [`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.INIT}`]: 'Initialize project for AI coding assistant',
174
175
  [`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.RUN}`]: 'Run AI coding assistant',
176
+ [`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.SERVE}`]: 'Start OpenCode web server',
175
177
  [`${exports.COMMAND_GROUPS.CODE} ${exports.SUBCOMMANDS.CODE.UPDATE}`]: 'Update OpenCode and agents to latest versions',
176
178
  };
@@ -50,17 +50,80 @@ class ApiKeyService {
50
50
  * Command: berget api-keys create
51
51
  */
52
52
  create(options) {
53
+ var _a, _b, _c, _d;
53
54
  return __awaiter(this, void 0, void 0, function* () {
54
55
  try {
56
+ // Validate input before sending request
57
+ if (!options.name || options.name.trim().length === 0) {
58
+ throw new Error('API key name is required and cannot be empty');
59
+ }
60
+ if (options.name.length > 100) {
61
+ throw new Error('API key name must be 100 characters or less');
62
+ }
63
+ if (options.description && options.description.length > 500) {
64
+ throw new Error('API key description must be 500 characters or less');
65
+ }
55
66
  const { data, error } = yield this.client.POST('/v1/api-keys', {
56
67
  body: options,
57
68
  });
58
- if (error)
69
+ if (error) {
70
+ // Enhanced error handling with specific troubleshooting
71
+ // Handle specific error cases
72
+ if (typeof error === 'object' && error !== null) {
73
+ const errorObj = error;
74
+ if (((_a = errorObj.error) === null || _a === void 0 ? void 0 : _a.code) === 'API_KEY_CREATION_FAILED') {
75
+ let detailedMessage = 'Failed to create API key. This could be due to:\n';
76
+ detailedMessage += '• Account limits or quota restrictions\n';
77
+ detailedMessage +=
78
+ '• Insufficient permissions for API key creation\n';
79
+ detailedMessage += '• Temporary server issues\n';
80
+ detailedMessage += '• Billing or subscription issues\n\n';
81
+ detailedMessage += 'Troubleshooting steps:\n';
82
+ detailedMessage +=
83
+ '1. Check if you have reached your API key limit\n';
84
+ detailedMessage +=
85
+ '2. Verify your account has API key creation permissions\n';
86
+ detailedMessage += '3. Check your billing status and subscription\n';
87
+ detailedMessage +=
88
+ '4. Try again in a few minutes if this is a temporary issue\n';
89
+ detailedMessage += '5. Contact support if the problem persists';
90
+ throw new Error(detailedMessage);
91
+ }
92
+ if (((_b = errorObj.error) === null || _b === void 0 ? void 0 : _b.code) === 'QUOTA_EXCEEDED') {
93
+ throw new Error('You have reached your API key limit. Please delete existing keys or contact support to increase your quota.');
94
+ }
95
+ if (((_c = errorObj.error) === null || _c === void 0 ? void 0 : _c.code) === 'INSUFFICIENT_PERMISSIONS') {
96
+ throw new Error('Your account does not have permission to create API keys. Please contact your administrator.');
97
+ }
98
+ if (((_d = errorObj.error) === null || _d === void 0 ? void 0 : _d.code) === 'BILLING_REQUIRED') {
99
+ throw new Error('A valid billing method is required to create API keys. Please add a payment method.');
100
+ }
101
+ }
59
102
  throw new Error(JSON.stringify(error));
103
+ }
104
+ if (!data) {
105
+ throw new Error('No data received from server');
106
+ }
60
107
  return data;
61
108
  }
62
109
  catch (error) {
63
110
  console.error('Failed to create API key:', error);
111
+ // Add additional context for common issues
112
+ if (error instanceof Error) {
113
+ if (error.message.includes('ECONNREFUSED')) {
114
+ throw new Error('Cannot connect to Berget API. Please check your internet connection.');
115
+ }
116
+ if (error.message.includes('ENOTFOUND')) {
117
+ throw new Error('Cannot resolve Berget API hostname. Please check your DNS settings.');
118
+ }
119
+ if (error.message.includes('401') ||
120
+ error.message.includes('Unauthorized')) {
121
+ throw new Error('Authentication failed. Please run `berget auth login` to log in again.');
122
+ }
123
+ if (error.message.includes('403')) {
124
+ throw new Error('Access forbidden. Your account may not have permission to create API keys.');
125
+ }
126
+ }
64
127
  throw error;
65
128
  }
66
129
  });
@@ -86,6 +86,20 @@ class ChatService {
86
86
  logger_1.logger.error('Failed to stringify options:', error);
87
87
  }
88
88
  const headers = {};
89
+ // First try to use the authenticated client (with refresh token support)
90
+ // Only fall back to API key flow if explicitly requested or no auth tokens available
91
+ const { TokenManager } = yield Promise.resolve().then(() => __importStar(require('../utils/token-manager')));
92
+ const tokenManagerInstance = TokenManager.getInstance();
93
+ const hasValidAuth = tokenManagerInstance.getAccessToken() && !tokenManagerInstance.isTokenExpired();
94
+ const envApiKeyForAuth = process.env.BERGET_API_KEY;
95
+ const hasExplicitApiKey = !!optionsCopy.apiKey || !!envApiKeyForAuth;
96
+ // If we have valid auth tokens and no explicit API key, use authenticated client
97
+ if (hasValidAuth && !hasExplicitApiKey) {
98
+ logger_1.logger.debug('Using authenticated client with refresh token support');
99
+ // Create a copy without apiKey to let the authenticated client handle auth automatically
100
+ const { apiKey } = optionsCopy, optionsWithoutKey = __rest(optionsCopy, ["apiKey"]);
101
+ return this.executeCompletion(optionsWithoutKey, {});
102
+ }
89
103
  // Check for environment variables first - prioritize this over everything else
90
104
  const envApiKey = process.env.BERGET_API_KEY;
91
105
  if (envApiKey) {