berget 2.2.0 → 2.2.2

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.
@@ -2,22 +2,12 @@ import { Command } from 'commander'
2
2
  import chalk from 'chalk'
3
3
  import readline from 'readline'
4
4
  import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
5
- import { ApiKeyService, CreateApiKeyOptions } from '../services/api-key-service'
6
- import { AuthService } from '../services/auth-service'
7
5
  import { handleError } from '../utils/error-handler'
8
6
  import * as fs from 'fs'
9
7
  import { readFile, writeFile } from 'fs/promises'
10
8
  import path from 'path'
11
9
  import { spawn } from 'child_process'
12
- import { updateEnvFile } from '../utils/env-manager'
13
- import { createAuthenticatedClient, getAuthToken } from '../client'
14
- import {
15
- getConfigLoader,
16
- getModelConfig,
17
- getProviderModels,
18
- type OpenCodeConfig,
19
- type AgentConfig,
20
- } from '../utils/config-loader'
10
+ import { createAuthenticatedClient } from '../client'
21
11
 
22
12
  /**
23
13
  * Check if current directory has git
@@ -40,18 +30,6 @@ async function mergeConfigurations(
40
30
  try {
41
31
  const client = createAuthenticatedClient()
42
32
 
43
- // Get model config with fallback for init scenario
44
- let modelConfig: { primary: string; small: string }
45
- try {
46
- modelConfig = getModelConfig()
47
- } catch (error) {
48
- // Fallback to defaults when no config exists (init scenario)
49
- modelConfig = {
50
- primary: 'berget/glm-4.7',
51
- small: 'berget/gpt-oss',
52
- }
53
- }
54
-
55
33
  console.log(chalk.blue('🤖 Using AI to merge configurations...'))
56
34
 
57
35
  const mergePrompt = `You are a configuration merge specialist. Merge these two OpenCode configurations:
@@ -73,7 +51,7 @@ Return ONLY the merged JSON configuration, no explanations.`
73
51
 
74
52
  const response = await client.POST('/v1/chat/completions', {
75
53
  body: {
76
- model: modelConfig.primary,
54
+ model: 'glm-4.7',
77
55
  messages: [
78
56
  {
79
57
  role: 'user',
@@ -290,7 +268,6 @@ async function loadLatestAgentConfig(): Promise<any> {
290
268
  // Return the latest agent configuration directly - no file reading needed
291
269
  return {
292
270
  fullstack: {
293
- model: 'berget/glm-4.7',
294
271
  temperature: 0.3,
295
272
  top_p: 0.9,
296
273
  mode: 'primary',
@@ -301,7 +278,6 @@ async function loadLatestAgentConfig(): Promise<any> {
301
278
  "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.\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 implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.",
302
279
  },
303
280
  frontend: {
304
- model: 'berget/glm-4.7',
305
281
  temperature: 0.4,
306
282
  top_p: 0.9,
307
283
  mode: 'primary',
@@ -313,7 +289,6 @@ async function loadLatestAgentConfig(): Promise<any> {
313
289
  '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.',
314
290
  },
315
291
  backend: {
316
- model: 'berget/glm-4.7',
317
292
  temperature: 0.3,
318
293
  top_p: 0.9,
319
294
  mode: 'primary',
@@ -324,7 +299,6 @@ async function loadLatestAgentConfig(): Promise<any> {
324
299
  "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.",
325
300
  },
326
301
  devops: {
327
- model: 'berget/glm-4.7',
328
302
  temperature: 0.3,
329
303
  top_p: 0.8,
330
304
  mode: 'primary',
@@ -335,7 +309,6 @@ async function loadLatestAgentConfig(): Promise<any> {
335
309
  "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.",
336
310
  },
337
311
  app: {
338
- model: 'berget/glm-4.7',
339
312
  temperature: 0.4,
340
313
  top_p: 0.9,
341
314
  mode: 'primary',
@@ -347,7 +320,6 @@ async function loadLatestAgentConfig(): Promise<any> {
347
320
  "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.",
348
321
  },
349
322
  security: {
350
- model: 'berget/glm-4.7',
351
323
  temperature: 0.2,
352
324
  top_p: 0.8,
353
325
  mode: 'subagent',
@@ -358,7 +330,6 @@ async function loadLatestAgentConfig(): Promise<any> {
358
330
  "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",
359
331
  },
360
332
  quality: {
361
- model: 'berget/glm-4.7',
362
333
  temperature: 0.1,
363
334
  top_p: 0.9,
364
335
  mode: 'subagent',
@@ -398,7 +369,7 @@ async function installOpencode(): Promise<boolean> {
398
369
 
399
370
  try {
400
371
  await new Promise<void>((resolve, reject) => {
401
- const install = spawn('npm', ['install', '-g', 'opencode-ai'], {
372
+ const install = spawn('npm', ['install', '-g', 'opencode-ai@1.2.27'], {
402
373
  stdio: 'inherit',
403
374
  })
404
375
 
@@ -520,188 +491,24 @@ export function registerCodeCommands(program: Command): void {
520
491
  return
521
492
  }
522
493
 
523
- // Check if we have an API key in environment first
524
- if (process.env.BERGET_API_KEY) {
525
- console.log(
526
- chalk.blue(
527
- '🔑 Using BERGET_API_KEY from environment - no authentication required'
528
- )
529
- )
530
- } else {
531
- // Only require authentication if we don't have an API key
532
- const authService = AuthService.getInstance()
533
- const profile = await authService.whoami()
534
-
535
- if (!profile) {
536
- console.log(chalk.red('❌ Not authenticated with Berget AI.'))
537
- console.log(chalk.blue('To get started, you have two options:'))
538
- console.log('')
539
- console.log(
540
- chalk.yellow('Option 1: Use an existing API key (recommended)')
541
- )
542
- console.log(
543
- chalk.cyan(' Set BERGET_API_KEY environment variable:')
544
- )
545
- console.log(
546
- chalk.dim(' export BERGET_API_KEY=your_api_key_here')
547
- )
548
- console.log(chalk.cyan(' Or create a .env file in your project:'))
549
- console.log(
550
- chalk.dim(' echo "BERGET_API_KEY=your_api_key_here" > .env')
551
- )
552
- console.log('')
553
- console.log(
554
- chalk.yellow('Option 2: Login and create a new API key')
555
- )
556
- console.log(chalk.cyan(' berget auth login'))
557
- console.log(
558
- chalk.cyan(
559
- ` berget ${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.INIT}`
560
- )
561
- )
562
- console.log('')
563
- console.log(chalk.blue('Then try again.'))
564
- return
565
- }
566
- }
567
-
568
494
  console.log(
569
495
  chalk.cyan(`Initializing OpenCode for project: ${projectName}`)
570
496
  )
571
497
 
572
- // Handle API key selection or creation
573
- let apiKey: string
574
- let keyName: string
575
-
576
- try {
577
- const apiKeyService = ApiKeyService.getInstance()
578
-
579
- if (process.env.BERGET_API_KEY) {
580
- if (options.yes) {
581
- console.log(chalk.blue('🔑 Using BERGET_API_KEY from environment'))
582
- apiKey = process.env.BERGET_API_KEY
583
- keyName = `env-key-${projectName}`
584
- } else {
585
- console.log(chalk.blue('\n📋 API key setup:'))
586
- console.log(chalk.dim('─'.repeat(60)))
587
- console.log(
588
- `${chalk.cyan('1')} ${chalk.bold('Use existing API key')}`
589
- )
590
- console.log(chalk.dim(' Uses BERGET_API_KEY from environment'))
591
- console.log(
592
- `${chalk.cyan('2')} ${chalk.bold('Create a new API key')}`
593
- )
594
- console.log(chalk.dim('─'.repeat(60)))
595
-
596
- const choice = await new Promise<string>((resolve) => {
597
- const rl = readline.createInterface({
598
- input: process.stdin,
599
- output: process.stdout,
600
- })
601
- rl.question(chalk.blue('\nSelect an option (1-2, default: 1): '), (answer) => {
602
- rl.close()
603
- resolve(answer.trim() || '1')
604
- })
605
- })
606
-
607
- if (choice === '1') {
608
- console.log(chalk.blue('🔑 Using BERGET_API_KEY from environment'))
609
- apiKey = process.env.BERGET_API_KEY
610
- keyName = `env-key-${projectName}`
611
- } else if (choice === '2') {
612
- console.log(chalk.blue('\n🔑 Creating new API key...'))
613
-
614
- const defaultKeyName = `opencode-${projectName}-${Date.now()}`
615
- const customName = await getInput(
616
- chalk.blue(`Enter key name (default: ${defaultKeyName}): `),
617
- defaultKeyName,
618
- options.yes
619
- )
620
-
621
- keyName = customName
622
- const createOptions: CreateApiKeyOptions = { name: keyName }
623
- const keyData = await apiKeyService.create(createOptions)
624
- apiKey = keyData.key
625
- console.log(chalk.green(`✓ Created new API key: ${keyName}`))
626
- } else {
627
- console.log(chalk.red('Invalid selection.'))
628
- return
629
- }
630
- }
631
- } else {
632
- if (!options.yes) {
633
- console.log(chalk.yellow('No BERGET_API_KEY environment variable found.'))
634
- console.log(chalk.blue('Creating a new API key...'))
635
- console.log(chalk.dim('\n💡 Tip: Set BERGET_API_KEY environment variable to reuse an existing key:'))
636
- console.log(chalk.dim(' export BERGET_API_KEY=your_api_key_here'))
637
- }
638
-
639
- const defaultKeyName = `opencode-${projectName}-${Date.now()}`
640
- const customName = await getInput(
641
- chalk.blue(`Enter key name (default: ${defaultKeyName}): `),
642
- defaultKeyName,
643
- options.yes
644
- )
645
-
646
- keyName = customName
647
- const createOptions: CreateApiKeyOptions = { name: keyName }
648
- const keyData = await apiKeyService.create(createOptions)
649
- apiKey = keyData.key
650
- console.log(chalk.green(`✓ Created new API key: ${keyName}`))
651
- }
652
- } catch (error) {
653
- if (process.env.BERGET_API_KEY) {
654
- console.log(
655
- chalk.yellow(
656
- '⚠️ Could not verify API key with Berget API, but continuing with environment key'
657
- )
658
- )
659
- console.log(
660
- chalk.dim('This might be due to network issues or an invalid key')
661
- )
662
- } else {
663
- console.error(chalk.red('❌ Failed to handle API keys:'))
664
- console.log(chalk.blue('This could be due to:'))
665
- console.log(chalk.dim(' • Network connectivity issues'))
666
- console.log(chalk.dim(' • Invalid authentication credentials'))
667
- console.log(chalk.dim(' • API service temporarily unavailable'))
668
- console.log('')
669
- console.log(chalk.blue('Try using an API key directly:'))
670
- console.log(chalk.cyan(' export BERGET_API_KEY=your_api_key_here'))
671
- console.log(
672
- chalk.cyan(
673
- ` berget ${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.INIT} --yes`
674
- )
675
- )
676
- handleError('API key operation failed', error)
677
- }
678
- return
679
- }
680
-
681
- // Prepare .env file path for safe update
682
- const envPath = path.join(process.cwd(), '.env')
683
-
684
498
  // Load latest agent configuration from our own codebase
685
499
  const latestAgentConfig = await loadLatestAgentConfig()
686
500
 
687
501
  // Use hardcoded defaults for init - never try to load from project
688
- const modelConfig = {
689
- primary: 'berget/glm-4.7',
690
- small: 'berget/gpt-oss',
691
- }
692
-
693
- // Create opencode.json config with optimized agent-based format
502
+ // Create opencode.json config — plugin handles auth, models, and provider
694
503
  const config = {
695
504
  $schema: 'https://opencode.ai/config.json',
505
+ plugin: ['@bergetai/opencode-auth@1.0.9'],
696
506
  username: 'berget-code',
697
507
  theme: 'berget-dark',
698
508
  share: 'manual',
699
509
  autoupdate: true,
700
- model: modelConfig.primary,
701
- small_model: modelConfig.small,
702
510
  agent: {
703
511
  fullstack: {
704
- model: modelConfig.primary,
705
512
  temperature: 0.3,
706
513
  top_p: 0.9,
707
514
  mode: 'primary',
@@ -712,7 +519,6 @@ export function registerCodeCommands(program: Command): void {
712
519
  '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.',
713
520
  },
714
521
  frontend: {
715
- model: modelConfig.primary,
716
522
  temperature: 0.4,
717
523
  top_p: 0.9,
718
524
  mode: 'primary',
@@ -724,7 +530,6 @@ export function registerCodeCommands(program: Command): void {
724
530
  '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.',
725
531
  },
726
532
  backend: {
727
- model: modelConfig.primary,
728
533
  temperature: 0.3,
729
534
  top_p: 0.9,
730
535
  mode: 'primary',
@@ -736,7 +541,6 @@ export function registerCodeCommands(program: Command): void {
736
541
  },
737
542
  // Use centralized devops configuration with Helm guidelines
738
543
  devops: latestAgentConfig.devops || {
739
- model: modelConfig.primary,
740
544
  temperature: 0.3,
741
545
  top_p: 0.8,
742
546
  mode: 'primary',
@@ -747,7 +551,6 @@ export function registerCodeCommands(program: Command): void {
747
551
  '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.',
748
552
  },
749
553
  app: {
750
- model: modelConfig.primary,
751
554
  temperature: 0.4,
752
555
  top_p: 0.9,
753
556
  mode: 'primary',
@@ -759,7 +562,6 @@ export function registerCodeCommands(program: Command): void {
759
562
  '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.',
760
563
  },
761
564
  security: {
762
- model: modelConfig.primary,
763
565
  temperature: 0.2,
764
566
  top_p: 0.8,
765
567
  mode: 'subagent',
@@ -770,7 +572,6 @@ export function registerCodeCommands(program: Command): void {
770
572
  '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.',
771
573
  },
772
574
  quality: {
773
- model: modelConfig.primary,
774
575
  temperature: 0.1,
775
576
  top_p: 0.9,
776
577
  mode: 'subagent',
@@ -824,71 +625,14 @@ export function registerCodeCommands(program: Command): void {
824
625
  watcher: {
825
626
  ignore: ['node_modules', 'dist', '.git', 'coverage'],
826
627
  },
827
- provider: {
828
- berget: {
829
- npm: '@ai-sdk/openai-compatible',
830
- name: 'Berget AI',
831
- options: {
832
- baseURL: '{env:BERGET_API_URL}',
833
- apiKey: '{env:BERGET_API_KEY}',
834
- },
835
- models: {
836
- 'glm-4.7': {
837
- name: 'GLM-4.7',
838
- limit: { output: 4000, context: 200000 },
839
- modalities: { input: ['text'], output: ['text'] },
840
- },
841
- 'gpt-oss': {
842
- name: 'GPT-OSS',
843
- limit: { output: 4000, context: 128000 },
844
- modalities: { input: ['text', 'image'], output: ['text'] },
845
- },
846
- 'llama-8b': {
847
- name: 'llama-3.1-8b',
848
- limit: { output: 4000, context: 128000 },
849
- },
850
- },
851
- },
852
- },
853
628
  }
854
629
 
855
630
  // Ask for permission to create config files
856
631
  if (!options.yes) {
857
632
  console.log(chalk.blue('\nAbout to create configuration files:'))
858
633
  console.log(chalk.dim(`Config: ${configPath}`))
859
- console.log(chalk.dim(`Environment: ${envPath}`))
860
- console.log(
861
- chalk.dim(
862
- `Documentation: ${path.join(
863
- process.cwd(),
864
- 'AGENTS.md'
865
- )} (if not exists)`
866
- )
867
- )
868
634
  console.log(
869
- chalk.dim(
870
- `Environment: ${path.join(process.cwd(), '.env')} will be updated`
871
- )
872
- )
873
- console.log(
874
- chalk.dim('This will configure OpenCode to use Berget AI models.')
875
- )
876
- console.log(chalk.cyan('\n💡 Benefits:'))
877
- console.log(
878
- chalk.cyan(
879
- ' • API key stored separately in .env file (not committed to Git)'
880
- )
881
- )
882
- console.log(
883
- chalk.cyan(' • Easy cost separation per project/customer')
884
- )
885
- console.log(
886
- chalk.cyan(' • Secure key management with environment variables')
887
- )
888
- console.log(
889
- chalk.cyan(
890
- " • Project-specific agent documentation (won't overwrite existing)"
891
- )
635
+ chalk.dim('This will configure OpenCode with the Berget auth plugin.')
892
636
  )
893
637
  }
894
638
 
@@ -896,217 +640,11 @@ export function registerCodeCommands(program: Command): void {
896
640
  await confirm('\nCreate configuration files? (Y/n): ', options.yes)
897
641
  ) {
898
642
  try {
899
- // Safely update .env file using dotenv
900
- await updateEnvFile({
901
- envPath,
902
- key: 'BERGET_API_KEY',
903
- value: apiKey,
904
- comment: `Berget AI Configuration for ${projectName} - Generated by berget code init - Do not commit to version control`,
905
- })
906
-
907
643
  // Create opencode.json
908
644
  await writeFile(configPath, JSON.stringify(config, null, 2))
909
645
  console.log(chalk.green(`✓ Created opencode.json`))
910
- console.log(chalk.dim(` Model: ${config.model}`))
911
- console.log(chalk.dim(` Small Model: ${config.small_model}`))
646
+ console.log(chalk.dim(` Plugin: @bergetai/opencode-auth`))
912
647
  console.log(chalk.dim(` Theme: ${config.theme}`))
913
- console.log(
914
- chalk.dim(` API Key: Stored in .env as BERGET_API_KEY`)
915
- )
916
-
917
- // Create AGENTS.md documentation only if it doesn't exist
918
- const agentsMdPath = path.join(process.cwd(), 'AGENTS.md')
919
- if (!fs.existsSync(agentsMdPath)) {
920
- const agentsMdContent = `# Berget Code Agents
921
-
922
- This document describes the specialized agents available in this project for use with OpenCode.
923
-
924
- ## Available Agents
925
-
926
- ### Primary Agents
927
-
928
- #### fullstack
929
- Router/coordinator agent for full-stack development with schema-driven architecture. Handles routing between different personas based on file paths and task requirements.
930
-
931
- **Use when:**
932
- - Working across multiple parts of a monorepo
933
- - Need to coordinate between frontend, backend, devops, and app
934
- - Starting new projects and need to determine tech stack
935
-
936
- **Key features:**
937
- - Schema-driven development (database → OpenAPI → types)
938
- - Automatic routing to appropriate persona
939
- - Tech stack discovery and recommendations
940
-
941
- #### frontend
942
- Builds Scandinavian, type-safe UIs with React, Tailwind, and Shadcn.
943
-
944
- **Use when:**
945
- - Working with React components (.tsx files)
946
- - Frontend development in /apps/frontend
947
- - UI/UX implementation
948
-
949
- **Key features:**
950
- - Design system integration
951
- - Semantic tokens and accessibility
952
- - Props-first component architecture
953
-
954
- #### backend
955
- Functional, modular Koa + TypeScript services with schema-first approach and code quality focus.
956
-
957
- **Use when:**
958
- - Working with Koa routers and services
959
- - Backend development in /services
960
- - API development and database work
961
-
962
- **Key features:**
963
- - Zod validation and OpenAPI generation
964
- - Code quality and refactoring principles
965
- - PR workflow integration
966
-
967
- #### devops
968
- Declarative GitOps infrastructure with FluxCD, Kustomize, Helm, and operators.
969
-
970
- **Use when:**
971
- - Working with Kubernetes manifests
972
- - Infrastructure in /infra or /k8s
973
- - CI/CD and deployment configurations
974
-
975
- **Key features:**
976
- - GitOps workflows
977
- - Operator-first approach
978
- - SemVer with release candidates
979
-
980
- **Helm Values Configuration Process:**
981
- 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.
982
- 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.
983
- 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.
984
- 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.
985
-
986
- #### app
987
- Expo + React Native applications with props-first architecture and offline awareness.
988
-
989
- **Use when:**
990
- - Mobile app development with Expo
991
- - React Native projects in /apps/app
992
- - Cross-platform mobile development
993
-
994
- **Key features:**
995
- - Shared design tokens with frontend
996
- - Offline-first architecture
997
- - Expo integration
998
-
999
- ### Subagents
1000
-
1001
- #### security
1002
- Security specialist for penetration testing, OWASP compliance, and vulnerability assessments.
1003
-
1004
- **Use when:**
1005
- - Need security review of code changes
1006
- - OWASP Top 10 compliance checks
1007
- - Vulnerability assessments
1008
-
1009
- **Key features:**
1010
- - OWASP standards compliance
1011
- - Security best practices
1012
- - Actionable remediation strategies
1013
-
1014
- #### quality
1015
- Quality assurance specialist for testing, building, and PR management.
1016
-
1017
- **Use when:**
1018
- - Need to run test suites and build processes
1019
- - Creating or updating pull requests
1020
- - Monitoring GitHub for reviewer comments
1021
- - Ensuring code quality standards
1022
-
1023
- **Key features:**
1024
- - Comprehensive testing and building workflows
1025
- - PR creation and management
1026
- - GitHub integration for reviewer feedback
1027
- - CLI command expertise for quality assurance
1028
-
1029
- ## Usage
1030
-
1031
- ### Switching Agents
1032
- Use the \`<tab>\` key to cycle through primary agents during a session.
1033
-
1034
- ### Manual Agent Selection
1035
- Use commands to switch to specific agents:
1036
- - \`/fullstack\` - Switch to Fullstack agent
1037
- - \`/frontend\` - Switch to Frontend agent
1038
- - \`/backend\` - Switch to Backend agent
1039
- - \`/devops\` - Switch to DevOps agent
1040
- - \`/app\` - Switch to App agent
1041
- - \`/quality\` - Switch to Quality agent for testing and PR management
1042
-
1043
- ### Using Subagents
1044
- Mention subagents with \`@\` symbol:
1045
- - \`@security review this authentication implementation\`
1046
- - \`@quality run tests and create PR for these changes\`
1047
-
1048
- ## Routing Rules
1049
-
1050
- The fullstack agent automatically routes tasks based on file patterns:
1051
-
1052
- - \`/apps/frontend\` or \`.tsx\` files → frontend
1053
- - \`/apps/app\` or Expo/React Native → app
1054
- - \`/infra\`, \`/k8s\`, FluxCD, Helm → devops
1055
- - \`/services\`, Koa routers → backend
1056
-
1057
- ## Configuration
1058
-
1059
- All agents are configured in \`opencode.json\` with:
1060
- - Specialized prompts and temperature settings
1061
- - Appropriate tool permissions
1062
- - Model optimizations for their specific tasks
1063
-
1064
- ## Environment Setup
1065
-
1066
- Configure \`.env\` with your API key:
1067
- \`\`\`
1068
- BERGET_API_KEY=your_api_key_here
1069
- \`\`\`
1070
-
1071
- ## Workflow
1072
-
1073
- All agents follow these principles:
1074
- - Never work directly in main branch
1075
- - Follow branch strategy and commit conventions
1076
- - Create PRs for new functionality
1077
- - Run tests before committing
1078
- - Address reviewer feedback promptly
1079
-
1080
- ---
1081
-
1082
- *Generated by berget code init for ${projectName}*
1083
- `
1084
-
1085
- await writeFile(agentsMdPath, agentsMdContent)
1086
- console.log(chalk.green(`✓ Created AGENTS.md`))
1087
- console.log(
1088
- chalk.dim(` Documentation for available agents and usage`)
1089
- )
1090
- } else {
1091
- console.log(
1092
- chalk.yellow(`⚠ AGENTS.md already exists, skipping creation`)
1093
- )
1094
- }
1095
-
1096
- // Check if .gitignore exists and add .env if not already there
1097
- const gitignorePath = path.join(process.cwd(), '.gitignore')
1098
- let gitignoreContent = ''
1099
-
1100
- if (fs.existsSync(gitignorePath)) {
1101
- gitignoreContent = fs.readFileSync(gitignorePath, 'utf8')
1102
- }
1103
-
1104
- if (!gitignoreContent.includes('.env')) {
1105
- gitignoreContent +=
1106
- (gitignoreContent.endsWith('\n') ? '' : '\n') + '.env\n'
1107
- await writeFile(gitignorePath, gitignoreContent)
1108
- console.log(chalk.green(`✓ Added .env to .gitignore`))
1109
- }
1110
648
  } catch (error) {
1111
649
  console.error(chalk.red('Failed to create config files:'))
1112
650
  handleError('Config file creation failed', error)
@@ -1118,11 +656,12 @@ All agents follow these principles:
1118
656
  }
1119
657
 
1120
658
  console.log(chalk.green('\n✅ Project initialized successfully!'))
1121
- console.log(chalk.blue('Next steps:'))
1122
- console.log(
1123
- chalk.blue(` berget ${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.RUN}`)
1124
- )
1125
- console.log(chalk.blue(' Or run: opencode'))
659
+ console.log(chalk.blue('\nNext steps:'))
660
+ console.log(chalk.cyan(' 1. Run: opencode'))
661
+ console.log(chalk.cyan(' 2. Type: /connect'))
662
+ console.log(chalk.cyan(' 3. Choose your auth method:'))
663
+ console.log(chalk.dim(' "Login with Berget" — Berget Code team members (SSO)'))
664
+ console.log(chalk.dim(' • "Enter API Key" — API key users (console.berget.ai)'))
1126
665
  } catch (error) {
1127
666
  handleError('Failed to initialize project', error)
1128
667
  }
@@ -1178,38 +717,25 @@ All agents follow these principles:
1178
717
  return
1179
718
  }
1180
719
 
1181
- // Set environment variables for opencode
720
+ // Prepare opencode command
1182
721
  const env = { ...process.env }
722
+ const opencodeArgs: string[] = []
1183
723
 
1184
- // Set API base URL based on flags (default to production)
1185
- const isLocalMode = process.argv.includes('--local')
1186
- const isStageMode = process.argv.includes('--stage')
1187
- if (isLocalMode) {
1188
- env.BERGET_API_URL = 'http://localhost:3000/v1'
1189
- console.log(chalk.dim('Using local API: http://localhost:3000/v1'))
1190
- } else if (isStageMode) {
1191
- env.BERGET_API_URL = 'https://api.stage.berget.ai/v1'
1192
- console.log(chalk.dim('Using stage API: https://api.stage.berget.ai/v1'))
1193
- } else {
1194
- env.BERGET_API_URL = 'https://api.berget.ai/v1'
1195
- }
1196
-
1197
- // Auth resolution: JWT first (if valid), then API-key
1198
- // This ensures seat-based users get proper tracking
1199
- const jwtToken = getAuthToken()
1200
- if (jwtToken) {
1201
- env.BERGET_API_KEY = jwtToken
1202
- console.log(chalk.dim('Using JWT token for authentication'))
1203
- } else if (env.BERGET_API_KEY) {
1204
- console.log(chalk.dim('Using API key for authentication'))
1205
- } else {
1206
- console.log(chalk.yellow('Warning: No authentication found'))
1207
- console.log(chalk.dim(' Run `berget auth login` or set BERGET_API_KEY'))
724
+ // Read --stage and --local from root program options
725
+ // (these flags are registered at program level, not subcommand level)
726
+ const isStage = process.argv.includes('--stage')
727
+ const isLocal = process.argv.includes('--local')
728
+
729
+ if (isStage) {
730
+ console.log(chalk.cyan('Using Berget stage environment'))
731
+ env.BERGET_API_URL = 'https://api.stage.berget.ai'
732
+ env.BERGET_INFERENCE_URL = 'https://api.stage.berget.ai/v1'
733
+ } else if (isLocal) {
734
+ console.log(chalk.cyan('Using local development environment'))
735
+ env.BERGET_API_URL = 'http://localhost:3000'
736
+ env.BERGET_INFERENCE_URL = 'http://localhost:3000/v1'
1208
737
  }
1209
738
 
1210
- // Prepare opencode command
1211
- const opencodeArgs: string[] = []
1212
-
1213
739
  if (prompt) {
1214
740
  opencodeArgs.push('run', prompt)
1215
741
  }
@@ -1356,30 +882,16 @@ All agents follow these principles:
1356
882
  // Load latest agent configuration to ensure consistency
1357
883
  const latestAgentConfig = await loadLatestAgentConfig()
1358
884
 
1359
- // Get model config with fallback for init scenario
1360
- let modelConfig: { primary: string; small: string }
1361
- try {
1362
- modelConfig = getModelConfig()
1363
- } catch (error) {
1364
- // Fallback to defaults when no config exists (init scenario)
1365
- modelConfig = {
1366
- primary: 'berget/glm-4.7',
1367
- small: 'berget/gpt-oss',
1368
- }
1369
- }
1370
-
1371
- // Create latest configuration with all improvements
885
+ // Create latest configuration plugin handles auth, models, and provider
1372
886
  const latestConfig = {
1373
887
  $schema: 'https://opencode.ai/config.json',
888
+ plugin: ['@bergetai/opencode-auth@1.0.9'],
1374
889
  username: 'berget-code',
1375
890
  theme: 'berget-dark',
1376
891
  share: 'manual',
1377
892
  autoupdate: true,
1378
- model: modelConfig.primary,
1379
- small_model: modelConfig.small,
1380
893
  agent: {
1381
894
  fullstack: {
1382
- model: modelConfig.primary,
1383
895
  temperature: 0.3,
1384
896
  top_p: 0.9,
1385
897
  mode: 'primary',
@@ -1390,7 +902,6 @@ All agents follow these principles:
1390
902
  '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.',
1391
903
  },
1392
904
  frontend: {
1393
- model: modelConfig.primary,
1394
905
  temperature: 0.4,
1395
906
  top_p: 0.9,
1396
907
  mode: 'primary',
@@ -1402,7 +913,6 @@ All agents follow these principles:
1402
913
  '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.',
1403
914
  },
1404
915
  backend: {
1405
- model: modelConfig.primary,
1406
916
  temperature: 0.3,
1407
917
  top_p: 0.9,
1408
918
  mode: 'primary',
@@ -1414,7 +924,6 @@ All agents follow these principles:
1414
924
  },
1415
925
  // Use centralized devops configuration with Helm guidelines
1416
926
  devops: latestAgentConfig.devops || {
1417
- model: modelConfig.primary,
1418
927
  temperature: 0.3,
1419
928
  top_p: 0.8,
1420
929
  mode: 'primary',
@@ -1425,7 +934,6 @@ All agents follow these principles:
1425
934
  '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.',
1426
935
  },
1427
936
  app: {
1428
- model: modelConfig.primary,
1429
937
  temperature: 0.4,
1430
938
  top_p: 0.9,
1431
939
  mode: 'primary',
@@ -1437,7 +945,6 @@ All agents follow these principles:
1437
945
  '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.',
1438
946
  },
1439
947
  security: {
1440
- model: modelConfig.primary,
1441
948
  temperature: 0.2,
1442
949
  top_p: 0.8,
1443
950
  mode: 'subagent',
@@ -1448,7 +955,6 @@ All agents follow these principles:
1448
955
  '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.',
1449
956
  },
1450
957
  quality: {
1451
- model: modelConfig.primary,
1452
958
  temperature: 0.1,
1453
959
  top_p: 0.9,
1454
960
  mode: 'subagent',
@@ -1508,17 +1014,6 @@ All agents follow these principles:
1508
1014
  watcher: {
1509
1015
  ignore: ['node_modules', 'dist', '.git', 'coverage'],
1510
1016
  },
1511
- provider: {
1512
- berget: {
1513
- npm: '@ai-sdk/openai-compatible',
1514
- name: 'Berget AI',
1515
- options: {
1516
- baseURL: '{env:BERGET_API_URL}',
1517
- apiKey: '{env:BERGET_API_KEY}',
1518
- },
1519
- models: getProviderModels(),
1520
- },
1521
- },
1522
1017
  }
1523
1018
 
1524
1019
  // Check if update is needed
@@ -1558,14 +1053,10 @@ All agents follow these principles:
1558
1053
  )
1559
1054
  }
1560
1055
 
1561
- // Check for GLM-4.7 optimizations
1562
- if (
1563
- !currentConfig.provider?.berget?.models?.[
1564
- modelConfig.primary.replace('berget/', '')
1565
- ]?.limit?.context
1566
- ) {
1056
+ // Check for plugin migration
1057
+ if (!currentConfig.plugin) {
1567
1058
  console.log(
1568
- chalk.cyan(' • GLM-4.7 token limits and auto-compaction')
1059
+ chalk.cyan(' • Plugin-first auth (automatic token refresh + model discovery)')
1569
1060
  )
1570
1061
  }
1571
1062
 
@@ -1815,10 +1306,7 @@ All agents are configured in \`opencode.json\` with:
1815
1306
 
1816
1307
  ## Environment Setup
1817
1308
 
1818
- Configure \`.env\` with your API key:
1819
- \`\`\`
1820
- BERGET_API_KEY=your_api_key_here
1821
- \`\`\`
1309
+ Authentication is handled by the Berget plugin. Run \`/connect\` in OpenCode to authenticate.
1822
1310
 
1823
1311
  ## Workflow
1824
1312