berget 2.2.6 → 2.2.8

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.
Files changed (145) hide show
  1. package/.github/workflows/publish.yml +2 -2
  2. package/.github/workflows/test.yml +10 -4
  3. package/.husky/pre-commit +1 -0
  4. package/.prettierignore +15 -0
  5. package/.prettierrc +7 -3
  6. package/CONTRIBUTING.md +38 -0
  7. package/README.md +2 -148
  8. package/dist/index.js +10 -11
  9. package/dist/package.json +30 -2
  10. package/dist/src/agents/app.js +28 -0
  11. package/dist/src/agents/backend.js +25 -0
  12. package/dist/src/agents/devops.js +34 -0
  13. package/dist/src/agents/frontend.js +25 -0
  14. package/dist/src/agents/fullstack.js +25 -0
  15. package/dist/src/agents/index.js +61 -0
  16. package/dist/src/agents/quality.js +70 -0
  17. package/dist/src/agents/security.js +26 -0
  18. package/dist/src/agents/types.js +2 -0
  19. package/dist/src/client.js +97 -117
  20. package/dist/src/commands/api-keys.js +75 -90
  21. package/dist/src/commands/auth.js +7 -16
  22. package/dist/src/commands/autocomplete.js +1 -1
  23. package/dist/src/commands/billing.js +6 -17
  24. package/dist/src/commands/chat.js +68 -101
  25. package/dist/src/commands/clusters.js +9 -18
  26. package/dist/src/commands/code/__tests__/auth-sync.test.js +351 -0
  27. package/dist/src/commands/code/__tests__/fake-api-key-service.js +13 -0
  28. package/dist/src/commands/code/__tests__/fake-auth-service.js +47 -0
  29. package/dist/src/commands/code/__tests__/fake-command-runner.js +21 -34
  30. package/dist/src/commands/code/__tests__/fake-file-store.js +20 -33
  31. package/dist/src/commands/code/__tests__/fake-prompter.js +83 -57
  32. package/dist/src/commands/code/__tests__/setup-flow.test.js +359 -92
  33. package/dist/src/commands/code/adapters/clack-prompter.js +15 -22
  34. package/dist/src/commands/code/adapters/fs-file-store.js +26 -40
  35. package/dist/src/commands/code/adapters/spawn-command-runner.js +27 -37
  36. package/dist/src/commands/code/auth-sync.js +270 -0
  37. package/dist/src/commands/code/errors.js +12 -9
  38. package/dist/src/commands/code/ports/auth-services.js +2 -0
  39. package/dist/src/commands/code/setup.js +387 -281
  40. package/dist/src/commands/code.js +205 -332
  41. package/dist/src/commands/index.js +5 -5
  42. package/dist/src/commands/models.js +6 -17
  43. package/dist/src/commands/users.js +5 -16
  44. package/dist/src/constants/command-structure.js +104 -104
  45. package/dist/src/services/api-key-service.js +132 -157
  46. package/dist/src/services/auth-service.js +89 -342
  47. package/dist/src/services/browser-auth.js +268 -0
  48. package/dist/src/services/chat-service.js +371 -401
  49. package/dist/src/services/cluster-service.js +47 -62
  50. package/dist/src/services/collaborator-service.js +10 -25
  51. package/dist/src/services/flux-service.js +14 -29
  52. package/dist/src/services/helm-service.js +10 -25
  53. package/dist/src/services/kubectl-service.js +16 -33
  54. package/dist/src/utils/config-checker.js +3 -3
  55. package/dist/src/utils/config-loader.js +95 -95
  56. package/dist/src/utils/default-api-key.js +124 -134
  57. package/dist/src/utils/env-manager.js +55 -66
  58. package/dist/src/utils/error-handler.js +20 -21
  59. package/dist/src/utils/logger.js +72 -65
  60. package/dist/src/utils/markdown-renderer.js +27 -27
  61. package/dist/src/utils/opencode-validator.js +63 -68
  62. package/dist/src/utils/token-manager.js +74 -45
  63. package/dist/tests/commands/chat.test.js +16 -25
  64. package/dist/tests/commands/code.test.js +95 -104
  65. package/dist/tests/utils/config-loader.test.js +48 -48
  66. package/dist/tests/utils/env-manager.test.js +43 -52
  67. package/dist/tests/utils/opencode-validator.test.js +22 -21
  68. package/dist/vitest.config.js +1 -1
  69. package/eslint.config.mjs +67 -0
  70. package/index.ts +35 -42
  71. package/package.json +30 -2
  72. package/src/agents/app.ts +27 -0
  73. package/src/agents/backend.ts +24 -0
  74. package/src/agents/devops.ts +33 -0
  75. package/src/agents/frontend.ts +24 -0
  76. package/src/agents/fullstack.ts +24 -0
  77. package/src/agents/index.ts +73 -0
  78. package/src/agents/quality.ts +69 -0
  79. package/src/agents/security.ts +26 -0
  80. package/src/agents/types.ts +17 -0
  81. package/src/client.ts +118 -152
  82. package/src/commands/api-keys.ts +241 -333
  83. package/src/commands/auth.ts +22 -27
  84. package/src/commands/autocomplete.ts +9 -9
  85. package/src/commands/billing.ts +20 -24
  86. package/src/commands/chat.ts +248 -338
  87. package/src/commands/clusters.ts +27 -26
  88. package/src/commands/code/__tests__/auth-sync.test.ts +482 -0
  89. package/src/commands/code/__tests__/fake-api-key-service.ts +13 -0
  90. package/src/commands/code/__tests__/fake-auth-service.ts +50 -0
  91. package/src/commands/code/__tests__/fake-command-runner.ts +45 -42
  92. package/src/commands/code/__tests__/fake-file-store.ts +32 -23
  93. package/src/commands/code/__tests__/fake-prompter.ts +116 -77
  94. package/src/commands/code/__tests__/setup-flow.test.ts +624 -268
  95. package/src/commands/code/adapters/clack-prompter.ts +53 -39
  96. package/src/commands/code/adapters/fs-file-store.ts +32 -27
  97. package/src/commands/code/adapters/spawn-command-runner.ts +38 -29
  98. package/src/commands/code/auth-sync.ts +329 -0
  99. package/src/commands/code/errors.ts +18 -18
  100. package/src/commands/code/ports/auth-services.ts +14 -0
  101. package/src/commands/code/ports/command-runner.ts +8 -4
  102. package/src/commands/code/ports/file-store.ts +5 -4
  103. package/src/commands/code/ports/prompter.ts +24 -18
  104. package/src/commands/code/setup.ts +570 -340
  105. package/src/commands/code.ts +338 -539
  106. package/src/commands/index.ts +20 -19
  107. package/src/commands/models.ts +28 -32
  108. package/src/commands/users.ts +15 -21
  109. package/src/constants/command-structure.ts +134 -157
  110. package/src/services/api-key-service.ts +105 -122
  111. package/src/services/auth-service.ts +99 -345
  112. package/src/services/browser-auth.ts +296 -0
  113. package/src/services/chat-service.ts +265 -299
  114. package/src/services/cluster-service.ts +42 -45
  115. package/src/services/collaborator-service.ts +14 -19
  116. package/src/services/flux-service.ts +23 -25
  117. package/src/services/helm-service.ts +19 -21
  118. package/src/services/kubectl-service.ts +17 -19
  119. package/src/types/api.d.ts +1905 -1907
  120. package/src/types/json.d.ts +2 -2
  121. package/src/utils/config-checker.ts +10 -10
  122. package/src/utils/config-loader.ts +162 -178
  123. package/src/utils/default-api-key.ts +114 -125
  124. package/src/utils/env-manager.ts +53 -57
  125. package/src/utils/error-handler.ts +61 -56
  126. package/src/utils/logger.ts +79 -73
  127. package/src/utils/markdown-renderer.ts +31 -31
  128. package/src/utils/opencode-validator.ts +85 -89
  129. package/src/utils/token-manager.ts +108 -87
  130. package/templates/agents/app.md +1 -0
  131. package/templates/agents/backend.md +1 -0
  132. package/templates/agents/devops.md +2 -0
  133. package/templates/agents/frontend.md +1 -0
  134. package/templates/agents/fullstack.md +1 -0
  135. package/templates/agents/quality.md +45 -40
  136. package/templates/agents/security.md +1 -0
  137. package/tests/commands/chat.test.ts +53 -62
  138. package/tests/commands/code.test.ts +265 -310
  139. package/tests/utils/config-loader.test.ts +189 -188
  140. package/tests/utils/env-manager.test.ts +110 -113
  141. package/tests/utils/opencode-validator.test.ts +52 -56
  142. package/tsconfig.json +4 -3
  143. package/vitest.config.ts +3 -3
  144. package/AGENTS.md +0 -374
  145. package/TODO.md +0 -19
@@ -1,12 +1,12 @@
1
- import { createAuthenticatedClient } from '../client'
2
- import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
1
+ import { createAuthenticatedClient } from '../client';
2
+ import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
3
3
 
4
4
  export interface Cluster {
5
- id: string
6
- name: string
7
- status: string
8
- nodes: number
9
- created: string
5
+ created: string;
6
+ id: string;
7
+ name: string;
8
+ nodes: number;
9
+ status: string;
10
10
  }
11
11
 
12
12
  /**
@@ -14,72 +14,69 @@ export interface Cluster {
14
14
  * Command group: clusters
15
15
  */
16
16
  export class ClusterService {
17
- private static instance: ClusterService
18
- private client = createAuthenticatedClient()
19
-
20
17
  // Command group name for this service
21
- public static readonly COMMAND_GROUP = COMMAND_GROUPS.CLUSTERS
22
-
18
+ public static readonly COMMAND_GROUP = COMMAND_GROUPS.CLUSTERS;
23
19
  // Subcommands for this service
24
- public static readonly COMMANDS = SUBCOMMANDS.CLUSTERS
20
+ public static readonly COMMANDS = SUBCOMMANDS.CLUSTERS;
21
+
22
+ private static instance: ClusterService;
23
+
24
+ private client = createAuthenticatedClient();
25
25
 
26
26
  private constructor() {}
27
27
 
28
28
  public static getInstance(): ClusterService {
29
29
  if (!ClusterService.instance) {
30
- ClusterService.instance = new ClusterService()
30
+ ClusterService.instance = new ClusterService();
31
31
  }
32
- return ClusterService.instance
32
+ return ClusterService.instance;
33
33
  }
34
34
 
35
35
  /**
36
- * Get resource usage for a cluster
37
- * Command: berget clusters get-usage
36
+ * Get detailed information about a cluster
37
+ * Command: berget clusters describe
38
38
  */
39
- public async getUsage(clusterId: string): Promise<any> {
39
+ public async describe(clusterId: string): Promise<Cluster | null> {
40
40
  try {
41
- const { data, error } = await this.client.GET(
42
- '/v1/clusters/{clusterId}/usage',
43
- {
44
- params: { path: { clusterId } },
45
- },
46
- )
47
- if (error) throw new Error(JSON.stringify(error))
48
- return data
41
+ // This is a placeholder since the API doesn't have a specific endpoint
42
+ // In a real implementation, this would call a specific endpoint
43
+ const clusters = await this.list();
44
+ return clusters.find((cluster) => cluster.id === clusterId) || null;
49
45
  } catch (error) {
50
- console.error('Failed to get cluster usage:', error)
51
- throw error
46
+ console.error('Failed to describe cluster:', error);
47
+ throw error;
52
48
  }
53
49
  }
54
50
 
55
51
  /**
56
- * List all clusters
57
- * Command: berget clusters list
52
+ * Get resource usage for a cluster
53
+ * Command: berget clusters get-usage
58
54
  */
59
- public async list(): Promise<Cluster[]> {
55
+ public async getUsage(clusterId: string): Promise<any> {
60
56
  try {
61
- const { data, error } = await this.client.GET('/v1/clusters')
62
- if (error) throw new Error(JSON.stringify(error))
63
- return data?.data || []
57
+ const { data, error } = await this.client.GET('/v1/clusters/{clusterId}/usage', {
58
+ params: { path: { clusterId } },
59
+ });
60
+ if (error) throw new Error(JSON.stringify(error));
61
+ return data;
64
62
  } catch (error) {
65
- console.error('Failed to list clusters:', error)
66
- throw error
63
+ console.error('Failed to get cluster usage:', error);
64
+ throw error;
67
65
  }
68
66
  }
69
67
 
70
68
  /**
71
- * Get detailed information about a cluster
72
- * Command: berget clusters describe
69
+ * List all clusters
70
+ * Command: berget clusters list
73
71
  */
74
- public async describe(clusterId: string): Promise<Cluster | null> {
72
+ public async list(): Promise<Cluster[]> {
75
73
  try {
76
- // This is a placeholder since the API doesn't have a specific endpoint
77
- // In a real implementation, this would call a specific endpoint
78
- const clusters = await this.list()
79
- return clusters.find((cluster) => cluster.id === clusterId) || null
74
+ const { data, error } = await this.client.GET('/v1/clusters');
75
+ if (error) throw new Error(JSON.stringify(error));
76
+ return data?.data || [];
80
77
  } catch (error) {
81
- console.error('Failed to describe cluster:', error)
82
- throw error
78
+ console.error('Failed to list clusters:', error);
79
+ throw error;
83
80
  }
84
81
  }
85
82
  }
@@ -1,10 +1,9 @@
1
- import { createAuthenticatedClient } from '../client'
2
- import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
1
+ import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
3
2
 
4
3
  export interface Collaborator {
5
- username: string
6
- role: string
7
- status: string
4
+ role: string;
5
+ status: string;
6
+ username: string;
8
7
  }
9
8
 
10
9
  /**
@@ -12,22 +11,21 @@ export interface Collaborator {
12
11
  * Command group: users
13
12
  */
14
13
  export class CollaboratorService {
15
- private static instance: CollaboratorService
16
- private client = createAuthenticatedClient()
17
-
18
14
  // Command group name for this service
19
- public static readonly COMMAND_GROUP = COMMAND_GROUPS.USERS
15
+ public static readonly COMMAND_GROUP = COMMAND_GROUPS.USERS;
20
16
 
21
17
  // Subcommands for this service
22
- public static readonly COMMANDS = SUBCOMMANDS.USERS
18
+ public static readonly COMMANDS = SUBCOMMANDS.USERS;
19
+
20
+ private static instance: CollaboratorService;
23
21
 
24
22
  private constructor() {}
25
23
 
26
24
  public static getInstance(): CollaboratorService {
27
25
  if (!CollaboratorService.instance) {
28
- CollaboratorService.instance = new CollaboratorService()
26
+ CollaboratorService.instance = new CollaboratorService();
29
27
  }
30
- return CollaboratorService.instance
28
+ return CollaboratorService.instance;
31
29
  }
32
30
 
33
31
  /**
@@ -35,11 +33,8 @@ export class CollaboratorService {
35
33
  * Command: berget users invite
36
34
  * This endpoint is not available in the API
37
35
  */
38
- public async invite(
39
- clusterId: string,
40
- githubUsername: string,
41
- ): Promise<Collaborator[]> {
42
- throw new Error('This functionality is not available in the API')
36
+ public async invite(_clusterId: string, _githubUsername: string): Promise<Collaborator[]> {
37
+ throw new Error('This functionality is not available in the API');
43
38
  }
44
39
 
45
40
  /**
@@ -47,7 +42,7 @@ export class CollaboratorService {
47
42
  * Command: berget users list
48
43
  * This endpoint is not available in the API
49
44
  */
50
- public async list(clusterId: string): Promise<Collaborator[]> {
51
- throw new Error('This functionality is not available in the API')
45
+ public async list(_clusterId: string): Promise<Collaborator[]> {
46
+ throw new Error('This functionality is not available in the API');
52
47
  }
53
48
  }
@@ -1,16 +1,15 @@
1
- import { createAuthenticatedClient } from '../client'
2
- import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
1
+ import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
3
2
 
4
- export interface FluxInstallOptions {
5
- cluster: string
3
+ export interface FluxBootstrapOptions {
4
+ owner?: string;
5
+ path?: string;
6
+ personal?: boolean;
7
+ provider: string;
8
+ repository?: string;
6
9
  }
7
10
 
8
- export interface FluxBootstrapOptions {
9
- provider: string
10
- owner?: string
11
- repository?: string
12
- path?: string
13
- personal?: boolean
11
+ export interface FluxInstallOptions {
12
+ cluster: string;
14
13
  }
15
14
 
16
15
  /**
@@ -18,39 +17,38 @@ export interface FluxBootstrapOptions {
18
17
  * Command group: flux
19
18
  */
20
19
  export class FluxService {
21
- private static instance: FluxService
22
- private client = createAuthenticatedClient()
23
-
24
20
  // Command group name for this service
25
- public static readonly COMMAND_GROUP = COMMAND_GROUPS.FLUX
21
+ public static readonly COMMAND_GROUP = COMMAND_GROUPS.FLUX;
26
22
 
27
23
  // Subcommands for this service
28
- public static readonly COMMANDS = SUBCOMMANDS.FLUX
24
+ public static readonly COMMANDS = SUBCOMMANDS.FLUX;
25
+
26
+ private static instance: FluxService;
29
27
 
30
28
  private constructor() {}
31
29
 
32
30
  public static getInstance(): FluxService {
33
31
  if (!FluxService.instance) {
34
- FluxService.instance = new FluxService()
32
+ FluxService.instance = new FluxService();
35
33
  }
36
- return FluxService.instance
34
+ return FluxService.instance;
37
35
  }
38
36
 
39
37
  /**
40
- * Install Flux CD
41
- * Command: berget flux install
38
+ * Bootstrap Flux CD
39
+ * Command: berget flux bootstrap
42
40
  * This endpoint is not available in the API
43
41
  */
44
- public async install(options: FluxInstallOptions): Promise<boolean> {
45
- throw new Error('This functionality is not available in the API')
42
+ public async bootstrap(_options: FluxBootstrapOptions): Promise<boolean> {
43
+ throw new Error('This functionality is not available in the API');
46
44
  }
47
45
 
48
46
  /**
49
- * Bootstrap Flux CD
50
- * Command: berget flux bootstrap
47
+ * Install Flux CD
48
+ * Command: berget flux install
51
49
  * This endpoint is not available in the API
52
50
  */
53
- public async bootstrap(options: FluxBootstrapOptions): Promise<boolean> {
54
- throw new Error('This functionality is not available in the API')
51
+ public async install(_options: FluxInstallOptions): Promise<boolean> {
52
+ throw new Error('This functionality is not available in the API');
55
53
  }
56
54
  }
@@ -1,16 +1,15 @@
1
- import { createAuthenticatedClient } from '../client'
2
- import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
1
+ import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
3
2
 
4
- export interface HelmRepoAddOptions {
5
- name: string
6
- url: string
3
+ export interface HelmInstallOptions {
4
+ chart: string;
5
+ name: string;
6
+ namespace?: string;
7
+ values?: Record<string, string>;
7
8
  }
8
9
 
9
- export interface HelmInstallOptions {
10
- name: string
11
- chart: string
12
- namespace?: string
13
- values?: Record<string, string>
10
+ export interface HelmRepoAddOptions {
11
+ name: string;
12
+ url: string;
14
13
  }
15
14
 
16
15
  /**
@@ -18,22 +17,21 @@ export interface HelmInstallOptions {
18
17
  * Command group: helm
19
18
  */
20
19
  export class HelmService {
21
- private static instance: HelmService
22
- private client = createAuthenticatedClient()
23
-
24
20
  // Command group name for this service
25
- public static readonly COMMAND_GROUP = COMMAND_GROUPS.HELM
21
+ public static readonly COMMAND_GROUP = COMMAND_GROUPS.HELM;
26
22
 
27
23
  // Subcommands for this service
28
- public static readonly COMMANDS = SUBCOMMANDS.HELM
24
+ public static readonly COMMANDS = SUBCOMMANDS.HELM;
25
+
26
+ private static instance: HelmService;
29
27
 
30
28
  private constructor() {}
31
29
 
32
30
  public static getInstance(): HelmService {
33
31
  if (!HelmService.instance) {
34
- HelmService.instance = new HelmService()
32
+ HelmService.instance = new HelmService();
35
33
  }
36
- return HelmService.instance
34
+ return HelmService.instance;
37
35
  }
38
36
 
39
37
  /**
@@ -41,8 +39,8 @@ export class HelmService {
41
39
  * Command: berget helm add-repo
42
40
  * This endpoint is not available in the API
43
41
  */
44
- public async addRepo(options: HelmRepoAddOptions): Promise<boolean> {
45
- throw new Error('This functionality is not available in the API')
42
+ public async addRepo(_options: HelmRepoAddOptions): Promise<boolean> {
43
+ throw new Error('This functionality is not available in the API');
46
44
  }
47
45
 
48
46
  /**
@@ -50,7 +48,7 @@ export class HelmService {
50
48
  * Command: berget helm install
51
49
  * This endpoint is not available in the API
52
50
  */
53
- public async install(options: HelmInstallOptions): Promise<any> {
54
- throw new Error('This functionality is not available in the API')
51
+ public async install(_options: HelmInstallOptions): Promise<any> {
52
+ throw new Error('This functionality is not available in the API');
55
53
  }
56
54
  }
@@ -1,45 +1,43 @@
1
- import { createAuthenticatedClient } from '../client'
2
- import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure'
1
+ import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
3
2
 
4
3
  /**
5
4
  * Service for managing Kubernetes resources
6
5
  * Command group: kubectl
7
6
  */
8
7
  export class KubectlService {
9
- private static instance: KubectlService
10
- private client = createAuthenticatedClient()
11
-
12
8
  // Command group name for this service
13
- public static readonly COMMAND_GROUP = COMMAND_GROUPS.KUBECTL
9
+ public static readonly COMMAND_GROUP = COMMAND_GROUPS.KUBECTL;
14
10
 
15
11
  // Subcommands for this service
16
- public static readonly COMMANDS = SUBCOMMANDS.KUBECTL
12
+ public static readonly COMMANDS = SUBCOMMANDS.KUBECTL;
13
+
14
+ private static instance: KubectlService;
17
15
 
18
16
  private constructor() {}
19
17
 
20
18
  public static getInstance(): KubectlService {
21
19
  if (!KubectlService.instance) {
22
- KubectlService.instance = new KubectlService()
20
+ KubectlService.instance = new KubectlService();
23
21
  }
24
- return KubectlService.instance
22
+ return KubectlService.instance;
25
23
  }
26
24
 
27
25
  /**
28
- * Create a Kubernetes namespace
29
- * Command: berget kubectl create-namespace
26
+ * Apply a Kubernetes configuration
27
+ * Command: berget kubectl apply
30
28
  * This endpoint is not available in the API
31
29
  */
32
- public async createNamespace(name: string): Promise<boolean> {
33
- throw new Error('This functionality is not available in the API')
30
+ public async apply(_filename: string): Promise<boolean> {
31
+ throw new Error('This functionality is not available in the API');
34
32
  }
35
33
 
36
34
  /**
37
- * Apply a Kubernetes configuration
38
- * Command: berget kubectl apply
35
+ * Create a Kubernetes namespace
36
+ * Command: berget kubectl create-namespace
39
37
  * This endpoint is not available in the API
40
38
  */
41
- public async apply(filename: string): Promise<boolean> {
42
- throw new Error('This functionality is not available in the API')
39
+ public async createNamespace(_name: string): Promise<boolean> {
40
+ throw new Error('This functionality is not available in the API');
43
41
  }
44
42
 
45
43
  /**
@@ -47,7 +45,7 @@ export class KubectlService {
47
45
  * Command: berget kubectl get
48
46
  * This endpoint is not available in the API
49
47
  */
50
- public async get(resource: string, namespace?: string): Promise<any[]> {
51
- throw new Error('This functionality is not available in the API')
48
+ public async get(_resource: string, _namespace?: string): Promise<any[]> {
49
+ throw new Error('This functionality is not available in the API');
52
50
  }
53
51
  }