berget 2.0.6 → 2.1.1
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 +163 -2
- package/dist/package.json +1 -1
- package/dist/src/commands/chat.js +1 -2
- package/dist/src/commands/code.js +152 -87
- package/dist/src/services/auth-service.js +1 -2
- package/dist/src/services/chat-service.js +77 -5
- package/dist/src/utils/config-loader.js +83 -27
- package/dist/tests/commands/chat.test.js +2 -2
- package/dist/tests/commands/code.test.js +4 -4
- package/dist/tests/utils/config-loader.test.js +248 -163
- package/opencode.json +31 -71
- package/package.json +1 -1
- package/src/commands/chat.ts +68 -61
- package/src/commands/code.ts +304 -213
- package/src/services/auth-service.ts +1 -4
- package/src/services/chat-service.ts +86 -5
- package/src/utils/config-loader.ts +113 -38
- package/tests/commands/chat.test.ts +2 -2
- package/tests/commands/code.test.ts +4 -4
- package/tests/utils/config-loader.test.ts +320 -0
- package/blog-post.md +0 -176
package/opencode.json
CHANGED
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
"theme": "berget-dark",
|
|
5
5
|
"share": "manual",
|
|
6
6
|
"autoupdate": true,
|
|
7
|
-
"model": "berget/
|
|
7
|
+
"model": "berget/glm-4.7",
|
|
8
8
|
"small_model": "berget/gpt-oss",
|
|
9
9
|
"agent": {
|
|
10
10
|
"fullstack": {
|
|
11
|
-
"model": "berget/
|
|
12
|
-
"temperature": 0.3,
|
|
13
|
-
"top_p": 0.9,
|
|
11
|
+
"model": "berget/glm-4.7",
|
|
14
12
|
"mode": "primary",
|
|
15
13
|
"permission": {
|
|
16
14
|
"edit": "allow",
|
|
@@ -18,12 +16,10 @@
|
|
|
18
16
|
"webfetch": "allow"
|
|
19
17
|
},
|
|
20
18
|
"description": "Router/coordinator agent for full-stack development with schema-driven architecture",
|
|
21
|
-
"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.
|
|
19
|
+
"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.\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."
|
|
22
20
|
},
|
|
23
21
|
"frontend": {
|
|
24
|
-
"model": "berget/
|
|
25
|
-
"temperature": 0.4,
|
|
26
|
-
"top_p": 0.9,
|
|
22
|
+
"model": "berget/glm-4.7",
|
|
27
23
|
"mode": "primary",
|
|
28
24
|
"permission": {
|
|
29
25
|
"edit": "allow",
|
|
@@ -32,12 +28,10 @@
|
|
|
32
28
|
},
|
|
33
29
|
"note": "Bash access is denied for frontend persona to prevent shell command execution in UI environments. This restriction enforces security and architectural boundaries.",
|
|
34
30
|
"description": "Builds Scandinavian, type-safe UIs with React, Tailwind, Shadcn.",
|
|
35
|
-
"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.
|
|
31
|
+
"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."
|
|
36
32
|
},
|
|
37
33
|
"backend": {
|
|
38
|
-
"model": "berget/
|
|
39
|
-
"temperature": 0.3,
|
|
40
|
-
"top_p": 0.9,
|
|
34
|
+
"model": "berget/glm-4.7",
|
|
41
35
|
"mode": "primary",
|
|
42
36
|
"permission": {
|
|
43
37
|
"edit": "allow",
|
|
@@ -45,12 +39,10 @@
|
|
|
45
39
|
"webfetch": "allow"
|
|
46
40
|
},
|
|
47
41
|
"description": "Functional, modular Koa + TypeScript services; schema-first with code quality focus.",
|
|
48
|
-
"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.
|
|
42
|
+
"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."
|
|
49
43
|
},
|
|
50
44
|
"devops": {
|
|
51
|
-
"model": "berget/
|
|
52
|
-
"temperature": 0.3,
|
|
53
|
-
"top_p": 0.8,
|
|
45
|
+
"model": "berget/glm-4.7",
|
|
54
46
|
"mode": "primary",
|
|
55
47
|
"permission": {
|
|
56
48
|
"edit": "allow",
|
|
@@ -58,12 +50,10 @@
|
|
|
58
50
|
"webfetch": "allow"
|
|
59
51
|
},
|
|
60
52
|
"description": "Declarative GitOps infra with FluxCD, Kustomize, Helm, operators.",
|
|
61
|
-
"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
|
|
53
|
+
"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."
|
|
62
54
|
},
|
|
63
55
|
"app": {
|
|
64
|
-
"model": "berget/
|
|
65
|
-
"temperature": 0.4,
|
|
66
|
-
"top_p": 0.9,
|
|
56
|
+
"model": "berget/glm-4.7",
|
|
67
57
|
"mode": "primary",
|
|
68
58
|
"permission": {
|
|
69
59
|
"edit": "allow",
|
|
@@ -72,12 +62,10 @@
|
|
|
72
62
|
},
|
|
73
63
|
"note": "Bash access is denied for app persona to prevent shell command execution in mobile/Expo environments. This restriction enforces security and architectural boundaries.",
|
|
74
64
|
"description": "Expo + React Native apps; props-first, offline-aware, shared tokens.",
|
|
75
|
-
"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."
|
|
65
|
+
"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\\nIMPORTANT: You have NO bash access and cannot run git commands. When your app 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 React Native code\\n- Follow Expo and TypeScript best practices\\n- Ensure cross-platform compatibility\\n- Test your components manually when possible\\n- Document any complex logic with comments\\n- Handle offline scenarios gracefully\\n\\nCRITICAL: When app implementation is complete, ALWAYS inform the user to use '/pr' command to handle testing, building, and pull request creation."
|
|
76
66
|
},
|
|
77
67
|
"security": {
|
|
78
|
-
"model": "berget/
|
|
79
|
-
"temperature": 0.2,
|
|
80
|
-
"top_p": 0.8,
|
|
68
|
+
"model": "berget/glm-4.7",
|
|
81
69
|
"mode": "subagent",
|
|
82
70
|
"permission": {
|
|
83
71
|
"edit": "deny",
|
|
@@ -85,12 +73,10 @@
|
|
|
85
73
|
"webfetch": "allow"
|
|
86
74
|
},
|
|
87
75
|
"description": "Security specialist for pentesting, OWASP compliance, and vulnerability assessments.",
|
|
88
|
-
"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."
|
|
76
|
+
"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"
|
|
89
77
|
},
|
|
90
78
|
"quality": {
|
|
91
|
-
"model": "berget/
|
|
92
|
-
"temperature": 0.1,
|
|
93
|
-
"top_p": 0.9,
|
|
79
|
+
"model": "berget/glm-4.7",
|
|
94
80
|
"mode": "subagent",
|
|
95
81
|
"permission": {
|
|
96
82
|
"edit": "allow",
|
|
@@ -98,54 +84,23 @@
|
|
|
98
84
|
"webfetch": "allow"
|
|
99
85
|
},
|
|
100
86
|
"description": "Quality assurance specialist for testing, building, and PR management.",
|
|
101
|
-
"prompt": "Voice: Scandinavian calm—precise, concise, confident. You are Berget Code Quality agent. Specialist in code quality assurance, testing, building, and pull request management
|
|
87
|
+
"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."
|
|
102
88
|
}
|
|
103
89
|
},
|
|
104
90
|
"command": {
|
|
105
|
-
"
|
|
106
|
-
"description": "
|
|
107
|
-
"template": "
|
|
108
|
-
"agent": "
|
|
109
|
-
},
|
|
110
|
-
"route": {
|
|
111
|
-
"description": "Let Fullstack auto-route to the right persona based on files/intent",
|
|
112
|
-
"template": "ROUTE {{input}}",
|
|
113
|
-
"agent": "fullstack",
|
|
114
|
-
"subtask": true
|
|
115
|
-
},
|
|
116
|
-
"frontend": {
|
|
117
|
-
"description": "Switch to Frontend persona",
|
|
118
|
-
"template": "{{input}}",
|
|
119
|
-
"agent": "frontend"
|
|
120
|
-
},
|
|
121
|
-
"backend": {
|
|
122
|
-
"description": "Switch to Backend persona",
|
|
123
|
-
"template": "{{input}}",
|
|
124
|
-
"agent": "backend"
|
|
125
|
-
},
|
|
126
|
-
"devops": {
|
|
127
|
-
"description": "Switch to DevOps persona",
|
|
128
|
-
"template": "{{input}}",
|
|
129
|
-
"agent": "devops"
|
|
130
|
-
},
|
|
131
|
-
"app": {
|
|
132
|
-
"description": "Switch to App persona",
|
|
133
|
-
"template": "{{input}}",
|
|
134
|
-
"agent": "app"
|
|
91
|
+
"pr": {
|
|
92
|
+
"description": "Prepare and create a pull request with testing and quality checks",
|
|
93
|
+
"template": "@quality Prepare a pull request for the current changes. Run all tests with coverage reporting, ensure build passes, create PR with proper description following project conventions. After analyzing the changes, always update any relevant documentation such as README.md or other documentation files to reflect the changes made. Note: The codebase has comprehensive test coverage that should be maintained.",
|
|
94
|
+
"agent": "quality"
|
|
135
95
|
},
|
|
136
|
-
"
|
|
137
|
-
"description": "
|
|
138
|
-
"template": "
|
|
96
|
+
"test": {
|
|
97
|
+
"description": "Run tests with coverage and fix any issues or write new tests for current changes",
|
|
98
|
+
"template": "@quality Run the complete test suite with coverage reporting. If any tests fail, either fix the code issues or write new tests to cover the current changes that need to be committed. Ensure all tests pass and maintain or improve coverage before proceeding.",
|
|
139
99
|
"agent": "quality"
|
|
140
100
|
}
|
|
141
101
|
},
|
|
142
102
|
"watcher": {
|
|
143
|
-
"ignore": [
|
|
144
|
-
"node_modules",
|
|
145
|
-
"dist",
|
|
146
|
-
".git",
|
|
147
|
-
"coverage"
|
|
148
|
-
]
|
|
103
|
+
"ignore": ["node_modules", "dist", ".git", "coverage"]
|
|
149
104
|
},
|
|
150
105
|
"provider": {
|
|
151
106
|
"berget": {
|
|
@@ -155,18 +110,23 @@
|
|
|
155
110
|
"baseURL": "https://api.berget.ai/v1"
|
|
156
111
|
},
|
|
157
112
|
"models": {
|
|
158
|
-
"
|
|
159
|
-
"name": "GLM-4.
|
|
113
|
+
"glm-4.7": {
|
|
114
|
+
"name": "GLM-4.7",
|
|
160
115
|
"limit": {
|
|
161
116
|
"output": 4000,
|
|
162
117
|
"context": 90000
|
|
163
118
|
}
|
|
164
119
|
},
|
|
120
|
+
|
|
165
121
|
"gpt-oss": {
|
|
166
122
|
"name": "GPT-OSS",
|
|
167
123
|
"limit": {
|
|
168
124
|
"output": 4000,
|
|
169
125
|
"context": 128000
|
|
126
|
+
},
|
|
127
|
+
"modalities": {
|
|
128
|
+
"input": ["text", "image"],
|
|
129
|
+
"output": ["text"]
|
|
170
130
|
}
|
|
171
131
|
},
|
|
172
132
|
"llama-8b": {
|
|
@@ -179,4 +139,4 @@
|
|
|
179
139
|
}
|
|
180
140
|
}
|
|
181
141
|
}
|
|
182
|
-
}
|
|
142
|
+
}
|
package/package.json
CHANGED
package/src/commands/chat.ts
CHANGED
|
@@ -42,18 +42,18 @@ export function registerChatCommands(program: Command): void {
|
|
|
42
42
|
.command(SUBCOMMANDS.CHAT.RUN)
|
|
43
43
|
.description('Run a chat session with a specified model')
|
|
44
44
|
.argument('[message]', 'Message to send directly (skips interactive mode)')
|
|
45
|
-
.option('-m, --model <model>', 'Model to use (default:
|
|
46
|
-
|
|
45
|
+
.option('-m, --model <model>', 'Model to use (default: glm-4.7)')
|
|
46
|
+
|
|
47
47
|
.option('-t, --temperature <temp>', 'Temperature (0-1)', parseFloat)
|
|
48
48
|
.option('--max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
|
|
49
49
|
.option('-k, --api-key <key>', 'API key to use for this chat session')
|
|
50
50
|
.option(
|
|
51
51
|
'--api-key-id <id>',
|
|
52
|
-
'ID of the API key to use from your saved keys'
|
|
52
|
+
'ID of the API key to use from your saved keys'
|
|
53
53
|
)
|
|
54
54
|
.option(
|
|
55
55
|
'--no-stream',
|
|
56
|
-
'Disable streaming (streaming is enabled by default)'
|
|
56
|
+
'Disable streaming (streaming is enabled by default)'
|
|
57
57
|
)
|
|
58
58
|
.action(async (message, options) => {
|
|
59
59
|
try {
|
|
@@ -67,7 +67,7 @@ export function registerChatCommands(program: Command): void {
|
|
|
67
67
|
const envApiKey = process.env.BERGET_API_KEY
|
|
68
68
|
if (envApiKey) {
|
|
69
69
|
console.log(
|
|
70
|
-
chalk.dim(`Using API key from BERGET_API_KEY environment variable`)
|
|
70
|
+
chalk.dim(`Using API key from BERGET_API_KEY environment variable`)
|
|
71
71
|
)
|
|
72
72
|
apiKey = envApiKey
|
|
73
73
|
|
|
@@ -75,8 +75,11 @@ export function registerChatCommands(program: Command): void {
|
|
|
75
75
|
if (process.argv.includes('--debug')) {
|
|
76
76
|
console.log(
|
|
77
77
|
chalk.yellow(
|
|
78
|
-
`DEBUG: API key from env starts with: ${envApiKey.substring(
|
|
79
|
-
|
|
78
|
+
`DEBUG: API key from env starts with: ${envApiKey.substring(
|
|
79
|
+
0,
|
|
80
|
+
4
|
|
81
|
+
)}...`
|
|
82
|
+
)
|
|
80
83
|
)
|
|
81
84
|
}
|
|
82
85
|
}
|
|
@@ -98,18 +101,18 @@ export function registerChatCommands(program: Command): void {
|
|
|
98
101
|
|
|
99
102
|
if (apiKey) {
|
|
100
103
|
console.log(
|
|
101
|
-
chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
|
|
104
|
+
chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
|
|
102
105
|
)
|
|
103
106
|
} else {
|
|
104
107
|
console.log(
|
|
105
108
|
chalk.yellow(
|
|
106
|
-
`Default API key "${defaultApiKeyData.name}" exists but the key value is missing
|
|
107
|
-
)
|
|
109
|
+
`Default API key "${defaultApiKeyData.name}" exists but the key value is missing.`
|
|
110
|
+
)
|
|
108
111
|
)
|
|
109
112
|
console.log(
|
|
110
113
|
chalk.yellow(
|
|
111
|
-
`Try rotating the key with: berget api-keys rotate ${defaultApiKeyData.id}
|
|
112
|
-
)
|
|
114
|
+
`Try rotating the key with: berget api-keys rotate ${defaultApiKeyData.id}`
|
|
115
|
+
)
|
|
113
116
|
)
|
|
114
117
|
}
|
|
115
118
|
} else {
|
|
@@ -122,24 +125,24 @@ export function registerChatCommands(program: Command): void {
|
|
|
122
125
|
if (!apiKey) {
|
|
123
126
|
console.log(
|
|
124
127
|
chalk.red(
|
|
125
|
-
'Error: An API key is required to use the chat command.'
|
|
126
|
-
)
|
|
128
|
+
'Error: An API key is required to use the chat command.'
|
|
129
|
+
)
|
|
127
130
|
)
|
|
128
131
|
console.log(chalk.yellow('You can:'))
|
|
129
132
|
console.log(
|
|
130
133
|
chalk.yellow(
|
|
131
|
-
'1. Create an API key with: berget api-keys create --name "My Key"'
|
|
132
|
-
)
|
|
134
|
+
'1. Create an API key with: berget api-keys create --name "My Key"'
|
|
135
|
+
)
|
|
133
136
|
)
|
|
134
137
|
console.log(
|
|
135
138
|
chalk.yellow(
|
|
136
|
-
'2. Set a default API key with: berget api-keys set-default <id>'
|
|
137
|
-
)
|
|
139
|
+
'2. Set a default API key with: berget api-keys set-default <id>'
|
|
140
|
+
)
|
|
138
141
|
)
|
|
139
142
|
console.log(
|
|
140
143
|
chalk.yellow(
|
|
141
|
-
'3. Provide an API key with the --api-key option'
|
|
142
|
-
)
|
|
144
|
+
'3. Provide an API key with the --api-key option'
|
|
145
|
+
)
|
|
143
146
|
)
|
|
144
147
|
return
|
|
145
148
|
}
|
|
@@ -147,7 +150,7 @@ export function registerChatCommands(program: Command): void {
|
|
|
147
150
|
} catch (error) {
|
|
148
151
|
if (process.argv.includes('--debug')) {
|
|
149
152
|
console.log(
|
|
150
|
-
chalk.yellow('DEBUG: Error checking default API key:')
|
|
153
|
+
chalk.yellow('DEBUG: Error checking default API key:')
|
|
151
154
|
)
|
|
152
155
|
console.log(chalk.yellow(String(error)))
|
|
153
156
|
}
|
|
@@ -160,14 +163,14 @@ export function registerChatCommands(program: Command): void {
|
|
|
160
163
|
const apiKeyService = ApiKeyService.getInstance()
|
|
161
164
|
const keys = await apiKeyService.list()
|
|
162
165
|
const selectedKey = keys.find(
|
|
163
|
-
(key) => key.id.toString() === options.apiKeyId
|
|
166
|
+
(key) => key.id.toString() === options.apiKeyId
|
|
164
167
|
)
|
|
165
168
|
|
|
166
169
|
if (!selectedKey) {
|
|
167
170
|
console.log(
|
|
168
171
|
chalk.yellow(
|
|
169
|
-
`API key with ID ${options.apiKeyId} not found. Using default authentication
|
|
170
|
-
)
|
|
172
|
+
`API key with ID ${options.apiKeyId} not found. Using default authentication.`
|
|
173
|
+
)
|
|
171
174
|
)
|
|
172
175
|
} else {
|
|
173
176
|
console.log(chalk.dim(`Using API key: ${selectedKey.name}`))
|
|
@@ -176,20 +179,20 @@ export function registerChatCommands(program: Command): void {
|
|
|
176
179
|
if (
|
|
177
180
|
await confirm(
|
|
178
181
|
chalk.yellow(
|
|
179
|
-
`To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)
|
|
180
|
-
)
|
|
182
|
+
`To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)`
|
|
183
|
+
)
|
|
181
184
|
)
|
|
182
185
|
) {
|
|
183
186
|
const rotatedKey = await apiKeyService.rotate(options.apiKeyId)
|
|
184
187
|
apiKey = rotatedKey.key
|
|
185
188
|
console.log(
|
|
186
189
|
chalk.green(
|
|
187
|
-
`API key "${selectedKey.name}" rotated successfully
|
|
188
|
-
)
|
|
190
|
+
`API key "${selectedKey.name}" rotated successfully.`
|
|
191
|
+
)
|
|
189
192
|
)
|
|
190
193
|
} else {
|
|
191
194
|
console.log(
|
|
192
|
-
chalk.yellow('Using default authentication instead.')
|
|
195
|
+
chalk.yellow('Using default authentication instead.')
|
|
193
196
|
)
|
|
194
197
|
}
|
|
195
198
|
}
|
|
@@ -205,8 +208,8 @@ export function registerChatCommands(program: Command): void {
|
|
|
205
208
|
if (isAuthError) {
|
|
206
209
|
console.log(
|
|
207
210
|
chalk.yellow(
|
|
208
|
-
'Authentication required. Please run `berget auth login` first.'
|
|
209
|
-
)
|
|
211
|
+
'Authentication required. Please run `berget auth login` first.'
|
|
212
|
+
)
|
|
210
213
|
)
|
|
211
214
|
} else {
|
|
212
215
|
console.error(chalk.red('Error fetching API key:'))
|
|
@@ -226,12 +229,12 @@ export function registerChatCommands(program: Command): void {
|
|
|
226
229
|
console.log(chalk.yellow('1. Log in with `berget auth login`'))
|
|
227
230
|
console.log(chalk.yellow('2. Provide an API key with `--api-key`'))
|
|
228
231
|
console.log(
|
|
229
|
-
chalk.yellow('3. Provide an API key ID with `--api-key-id`')
|
|
232
|
+
chalk.yellow('3. Provide an API key ID with `--api-key-id`')
|
|
230
233
|
)
|
|
231
234
|
console.log(
|
|
232
235
|
chalk.yellow(
|
|
233
|
-
'4. Set a default API key with `berget api-keys set-default <id>`'
|
|
234
|
-
)
|
|
236
|
+
'4. Set a default API key with `berget api-keys set-default <id>`'
|
|
237
|
+
)
|
|
235
238
|
)
|
|
236
239
|
return
|
|
237
240
|
}
|
|
@@ -326,13 +329,14 @@ export function registerChatCommands(program: Command): void {
|
|
|
326
329
|
|
|
327
330
|
// Fallback to non-streaming if streaming fails
|
|
328
331
|
console.log(
|
|
329
|
-
chalk.yellow('Falling back to non-streaming mode...')
|
|
332
|
+
chalk.yellow('Falling back to non-streaming mode...')
|
|
330
333
|
)
|
|
331
334
|
completionOptions.stream = false
|
|
332
335
|
delete completionOptions.onChunk
|
|
333
336
|
|
|
334
|
-
const response =
|
|
335
|
-
|
|
337
|
+
const response = await chatService.createCompletion(
|
|
338
|
+
completionOptions
|
|
339
|
+
)
|
|
336
340
|
|
|
337
341
|
if (
|
|
338
342
|
response &&
|
|
@@ -348,8 +352,9 @@ export function registerChatCommands(program: Command): void {
|
|
|
348
352
|
return
|
|
349
353
|
}
|
|
350
354
|
|
|
351
|
-
const response =
|
|
352
|
-
|
|
355
|
+
const response = await chatService.createCompletion(
|
|
356
|
+
completionOptions
|
|
357
|
+
)
|
|
353
358
|
|
|
354
359
|
// Check if response has the expected structure
|
|
355
360
|
if (
|
|
@@ -359,10 +364,10 @@ export function registerChatCommands(program: Command): void {
|
|
|
359
364
|
!response.choices[0].message
|
|
360
365
|
) {
|
|
361
366
|
console.error(
|
|
362
|
-
chalk.red('Error: Unexpected response format from API')
|
|
367
|
+
chalk.red('Error: Unexpected response format from API')
|
|
363
368
|
)
|
|
364
369
|
console.error(
|
|
365
|
-
chalk.red('Response:', JSON.stringify(response, null, 2))
|
|
370
|
+
chalk.red('Response:', JSON.stringify(response, null, 2))
|
|
366
371
|
)
|
|
367
372
|
throw new Error('Unexpected response format from API')
|
|
368
373
|
}
|
|
@@ -463,13 +468,14 @@ export function registerChatCommands(program: Command): void {
|
|
|
463
468
|
|
|
464
469
|
// Fallback to non-streaming if streaming fails
|
|
465
470
|
console.log(
|
|
466
|
-
chalk.yellow('Falling back to non-streaming mode...')
|
|
471
|
+
chalk.yellow('Falling back to non-streaming mode...')
|
|
467
472
|
)
|
|
468
473
|
completionOptions.stream = false
|
|
469
474
|
delete completionOptions.onChunk
|
|
470
475
|
|
|
471
|
-
const response =
|
|
472
|
-
|
|
476
|
+
const response = await chatService.createCompletion(
|
|
477
|
+
completionOptions
|
|
478
|
+
)
|
|
473
479
|
|
|
474
480
|
if (
|
|
475
481
|
response &&
|
|
@@ -494,8 +500,9 @@ export function registerChatCommands(program: Command): void {
|
|
|
494
500
|
return
|
|
495
501
|
}
|
|
496
502
|
|
|
497
|
-
const response =
|
|
498
|
-
|
|
503
|
+
const response = await chatService.createCompletion(
|
|
504
|
+
completionOptions
|
|
505
|
+
)
|
|
499
506
|
|
|
500
507
|
// Debug output
|
|
501
508
|
if (program.opts().debug) {
|
|
@@ -511,10 +518,10 @@ export function registerChatCommands(program: Command): void {
|
|
|
511
518
|
!response.choices[0].message
|
|
512
519
|
) {
|
|
513
520
|
console.error(
|
|
514
|
-
chalk.red('Error: Unexpected response format from API')
|
|
521
|
+
chalk.red('Error: Unexpected response format from API')
|
|
515
522
|
)
|
|
516
523
|
console.error(
|
|
517
|
-
chalk.red('Response:', JSON.stringify(response, null, 2))
|
|
524
|
+
chalk.red('Response:', JSON.stringify(response, null, 2))
|
|
518
525
|
)
|
|
519
526
|
throw new Error('Unexpected response format from API')
|
|
520
527
|
}
|
|
@@ -566,7 +573,7 @@ export function registerChatCommands(program: Command): void {
|
|
|
566
573
|
.option('-k, --api-key <key>', 'API key to use for this request')
|
|
567
574
|
.option(
|
|
568
575
|
'--api-key-id <id>',
|
|
569
|
-
'ID of the API key to use from your saved keys'
|
|
576
|
+
'ID of the API key to use from your saved keys'
|
|
570
577
|
)
|
|
571
578
|
.action(async (options) => {
|
|
572
579
|
try {
|
|
@@ -582,7 +589,7 @@ export function registerChatCommands(program: Command): void {
|
|
|
582
589
|
if (defaultApiKeyData) {
|
|
583
590
|
apiKeyId = defaultApiKeyData.id
|
|
584
591
|
console.log(
|
|
585
|
-
chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
|
|
592
|
+
chalk.dim(`Using default API key: ${defaultApiKeyData.name}`)
|
|
586
593
|
)
|
|
587
594
|
}
|
|
588
595
|
}
|
|
@@ -592,14 +599,14 @@ export function registerChatCommands(program: Command): void {
|
|
|
592
599
|
const apiKeyService = ApiKeyService.getInstance()
|
|
593
600
|
const keys = await apiKeyService.list()
|
|
594
601
|
const selectedKey = keys.find(
|
|
595
|
-
(key) => key.id.toString() === options.apiKeyId
|
|
602
|
+
(key) => key.id.toString() === options.apiKeyId
|
|
596
603
|
)
|
|
597
604
|
|
|
598
605
|
if (!selectedKey) {
|
|
599
606
|
console.log(
|
|
600
607
|
chalk.yellow(
|
|
601
|
-
`API key with ID ${options.apiKeyId} not found. Using default authentication
|
|
602
|
-
)
|
|
608
|
+
`API key with ID ${options.apiKeyId} not found. Using default authentication.`
|
|
609
|
+
)
|
|
603
610
|
)
|
|
604
611
|
} else {
|
|
605
612
|
console.log(chalk.dim(`Using API key: ${selectedKey.name}`))
|
|
@@ -608,20 +615,20 @@ export function registerChatCommands(program: Command): void {
|
|
|
608
615
|
if (
|
|
609
616
|
await confirm(
|
|
610
617
|
chalk.yellow(
|
|
611
|
-
`To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)
|
|
612
|
-
)
|
|
618
|
+
`To use API key "${selectedKey.name}", it needs to be rotated. This will invalidate the current key. Continue? (y/n)`
|
|
619
|
+
)
|
|
613
620
|
)
|
|
614
621
|
) {
|
|
615
622
|
const rotatedKey = await apiKeyService.rotate(options.apiKeyId)
|
|
616
623
|
apiKey = rotatedKey.key
|
|
617
624
|
console.log(
|
|
618
625
|
chalk.green(
|
|
619
|
-
`API key "${selectedKey.name}" rotated successfully
|
|
620
|
-
)
|
|
626
|
+
`API key "${selectedKey.name}" rotated successfully.`
|
|
627
|
+
)
|
|
621
628
|
)
|
|
622
629
|
} else {
|
|
623
630
|
console.log(
|
|
624
|
-
chalk.yellow('Using default authentication instead.')
|
|
631
|
+
chalk.yellow('Using default authentication instead.')
|
|
625
632
|
)
|
|
626
633
|
}
|
|
627
634
|
}
|
|
@@ -644,13 +651,13 @@ export function registerChatCommands(program: Command): void {
|
|
|
644
651
|
console.log(chalk.bold('Available Chat Models:'))
|
|
645
652
|
console.log(chalk.dim('─'.repeat(70)))
|
|
646
653
|
console.log(
|
|
647
|
-
chalk.dim('MODEL ID'.padEnd(40)) + chalk.dim('CAPABILITIES')
|
|
654
|
+
chalk.dim('MODEL ID'.padEnd(40)) + chalk.dim('CAPABILITIES')
|
|
648
655
|
)
|
|
649
656
|
console.log(chalk.dim('─'.repeat(70)))
|
|
650
657
|
|
|
651
658
|
// Filter to only show active models
|
|
652
659
|
const activeModels = models.data.filter(
|
|
653
|
-
(model: any) => model.active === true
|
|
660
|
+
(model: any) => model.active === true
|
|
654
661
|
)
|
|
655
662
|
|
|
656
663
|
activeModels.forEach((model: any) => {
|
|
@@ -662,7 +669,7 @@ export function registerChatCommands(program: Command): void {
|
|
|
662
669
|
|
|
663
670
|
// Format model ID in Huggingface compatible format (owner/model)
|
|
664
671
|
const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(
|
|
665
|
-
40
|
|
672
|
+
40
|
|
666
673
|
)
|
|
667
674
|
|
|
668
675
|
console.log(modelId + capabilities.join(', '))
|