@agents-at-scale/ark 0.1.35-rc.1 → 0.1.35-rc2

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 (130) hide show
  1. package/dist/arkServices.d.ts +4 -12
  2. package/dist/arkServices.js +19 -34
  3. package/dist/arkServices.spec.d.ts +1 -0
  4. package/dist/arkServices.spec.js +24 -0
  5. package/dist/commands/agents/index.d.ts +2 -1
  6. package/dist/commands/agents/index.js +2 -7
  7. package/dist/commands/agents/index.spec.d.ts +1 -0
  8. package/dist/commands/agents/index.spec.js +67 -0
  9. package/dist/commands/chat/index.d.ts +2 -1
  10. package/dist/commands/chat/index.js +5 -21
  11. package/dist/commands/cluster/get.spec.d.ts +1 -0
  12. package/dist/commands/cluster/get.spec.js +92 -0
  13. package/dist/commands/cluster/index.d.ts +2 -1
  14. package/dist/commands/cluster/index.js +1 -1
  15. package/dist/commands/cluster/index.spec.d.ts +1 -0
  16. package/dist/commands/cluster/index.spec.js +24 -0
  17. package/dist/commands/completion/index.d.ts +2 -1
  18. package/dist/commands/completion/index.js +24 -2
  19. package/dist/commands/completion/index.spec.d.ts +1 -0
  20. package/dist/commands/completion/index.spec.js +34 -0
  21. package/dist/commands/config/index.d.ts +2 -1
  22. package/dist/commands/config/index.js +2 -2
  23. package/dist/commands/config/index.spec.d.ts +1 -0
  24. package/dist/commands/config/index.spec.js +78 -0
  25. package/dist/commands/dashboard/index.d.ts +2 -1
  26. package/dist/commands/dashboard/index.js +1 -1
  27. package/dist/commands/dev/index.d.ts +2 -1
  28. package/dist/commands/dev/index.js +1 -1
  29. package/dist/commands/dev/tool-generate.spec.d.ts +1 -0
  30. package/dist/commands/dev/tool-generate.spec.js +163 -0
  31. package/dist/commands/dev/tool.spec.d.ts +1 -0
  32. package/dist/commands/dev/tool.spec.js +48 -0
  33. package/dist/commands/docs/index.d.ts +4 -0
  34. package/dist/commands/docs/index.js +18 -0
  35. package/dist/commands/generate/generators/project.js +22 -41
  36. package/dist/commands/generate/index.d.ts +2 -1
  37. package/dist/commands/generate/index.js +1 -1
  38. package/dist/commands/install/index.d.ts +4 -2
  39. package/dist/commands/install/index.js +225 -90
  40. package/dist/commands/install/index.spec.d.ts +1 -0
  41. package/dist/commands/install/index.spec.js +143 -0
  42. package/dist/commands/models/create.spec.d.ts +1 -0
  43. package/dist/commands/models/create.spec.js +125 -0
  44. package/dist/commands/models/index.d.ts +2 -1
  45. package/dist/commands/models/index.js +2 -7
  46. package/dist/commands/models/index.spec.d.ts +1 -0
  47. package/dist/commands/models/index.spec.js +76 -0
  48. package/dist/commands/query/index.d.ts +3 -0
  49. package/dist/commands/query/index.js +131 -0
  50. package/dist/commands/routes/index.d.ts +2 -1
  51. package/dist/commands/routes/index.js +1 -9
  52. package/dist/commands/status/index.d.ts +3 -2
  53. package/dist/commands/status/index.js +240 -11
  54. package/dist/commands/targets/index.d.ts +2 -1
  55. package/dist/commands/targets/index.js +1 -1
  56. package/dist/commands/targets/index.spec.d.ts +1 -0
  57. package/dist/commands/targets/index.spec.js +105 -0
  58. package/dist/commands/teams/index.d.ts +2 -1
  59. package/dist/commands/teams/index.js +2 -7
  60. package/dist/commands/teams/index.spec.d.ts +1 -0
  61. package/dist/commands/teams/index.spec.js +70 -0
  62. package/dist/commands/tools/index.d.ts +2 -1
  63. package/dist/commands/tools/index.js +2 -7
  64. package/dist/commands/tools/index.spec.d.ts +1 -0
  65. package/dist/commands/tools/index.spec.js +70 -0
  66. package/dist/commands/uninstall/index.d.ts +2 -1
  67. package/dist/commands/uninstall/index.js +66 -44
  68. package/dist/commands/uninstall/index.spec.d.ts +1 -0
  69. package/dist/commands/uninstall/index.spec.js +125 -0
  70. package/dist/components/ChatUI.js +4 -4
  71. package/dist/components/statusChecker.d.ts +5 -12
  72. package/dist/components/statusChecker.js +193 -90
  73. package/dist/config.d.ts +3 -22
  74. package/dist/config.js +7 -151
  75. package/dist/index.js +26 -19
  76. package/dist/lib/arkServiceProxy.js +4 -2
  77. package/dist/lib/arkStatus.d.ts +5 -0
  78. package/dist/lib/arkStatus.js +61 -2
  79. package/dist/lib/arkStatus.spec.d.ts +1 -0
  80. package/dist/lib/arkStatus.spec.js +49 -0
  81. package/dist/lib/chatClient.js +1 -3
  82. package/dist/lib/cluster.js +11 -14
  83. package/dist/lib/cluster.spec.d.ts +1 -0
  84. package/dist/lib/cluster.spec.js +338 -0
  85. package/dist/lib/commandUtils.js +7 -7
  86. package/dist/lib/commands.d.ts +16 -0
  87. package/dist/lib/commands.js +29 -0
  88. package/dist/lib/commands.spec.d.ts +1 -0
  89. package/dist/lib/commands.spec.js +146 -0
  90. package/dist/lib/config.d.ts +4 -0
  91. package/dist/lib/config.js +6 -4
  92. package/dist/lib/config.spec.d.ts +1 -0
  93. package/dist/lib/config.spec.js +99 -0
  94. package/dist/lib/consts.d.ts +0 -1
  95. package/dist/lib/consts.js +0 -2
  96. package/dist/lib/consts.spec.d.ts +1 -0
  97. package/dist/lib/consts.spec.js +15 -0
  98. package/dist/lib/errors.js +1 -1
  99. package/dist/lib/errors.spec.d.ts +1 -0
  100. package/dist/lib/errors.spec.js +221 -0
  101. package/dist/lib/exec.d.ts +0 -4
  102. package/dist/lib/exec.js +0 -11
  103. package/dist/lib/nextSteps.d.ts +4 -0
  104. package/dist/lib/nextSteps.js +20 -0
  105. package/dist/lib/nextSteps.spec.d.ts +1 -0
  106. package/dist/lib/nextSteps.spec.js +59 -0
  107. package/dist/lib/output.spec.d.ts +1 -0
  108. package/dist/lib/output.spec.js +123 -0
  109. package/dist/lib/portUtils.d.ts +8 -0
  110. package/dist/lib/portUtils.js +39 -0
  111. package/dist/lib/startup.d.ts +9 -0
  112. package/dist/lib/startup.js +93 -0
  113. package/dist/lib/startup.spec.d.ts +1 -0
  114. package/dist/lib/startup.spec.js +168 -0
  115. package/dist/lib/types.d.ts +9 -0
  116. package/dist/ui/AgentSelector.d.ts +8 -0
  117. package/dist/ui/AgentSelector.js +53 -0
  118. package/dist/ui/MainMenu.d.ts +5 -1
  119. package/dist/ui/MainMenu.js +117 -54
  120. package/dist/ui/ModelSelector.d.ts +8 -0
  121. package/dist/ui/ModelSelector.js +53 -0
  122. package/dist/ui/TeamSelector.d.ts +8 -0
  123. package/dist/ui/TeamSelector.js +55 -0
  124. package/dist/ui/ToolSelector.d.ts +8 -0
  125. package/dist/ui/ToolSelector.js +53 -0
  126. package/dist/ui/statusFormatter.d.ts +22 -10
  127. package/dist/ui/statusFormatter.js +37 -109
  128. package/dist/ui/statusFormatter.spec.d.ts +1 -0
  129. package/dist/ui/statusFormatter.spec.js +58 -0
  130. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -6,15 +6,18 @@ import { createRequire } from 'module';
6
6
  const require = createRequire(import.meta.url);
7
7
  const packageJson = require('../package.json');
8
8
  import output from './lib/output.js';
9
+ import { startup } from './lib/startup.js';
9
10
  import { createAgentsCommand } from './commands/agents/index.js';
10
11
  import { createChatCommand } from './commands/chat/index.js';
11
12
  import { createClusterCommand } from './commands/cluster/index.js';
12
13
  import { createCompletionCommand } from './commands/completion/index.js';
13
14
  import { createDashboardCommand } from './commands/dashboard/index.js';
15
+ import { createDocsCommand } from './commands/docs/index.js';
14
16
  import { createDevCommand } from './commands/dev/index.js';
15
17
  import { createGenerateCommand } from './commands/generate/index.js';
16
18
  import { createInstallCommand } from './commands/install/index.js';
17
19
  import { createModelsCommand } from './commands/models/index.js';
20
+ import { createQueryCommand } from './commands/query/index.js';
18
21
  import { createUninstallCommand } from './commands/uninstall/index.js';
19
22
  import { createStatusCommand } from './commands/status/index.js';
20
23
  import { createConfigCommand } from './commands/config/index.js';
@@ -23,35 +26,39 @@ import { createTeamsCommand } from './commands/teams/index.js';
23
26
  import { createToolsCommand } from './commands/tools/index.js';
24
27
  import { createRoutesCommand } from './commands/routes/index.js';
25
28
  import MainMenu from './ui/MainMenu.js';
26
- function showMainMenu() {
27
- const app = render(_jsx(MainMenu, {}));
29
+ function showMainMenu(config) {
30
+ const app = render(_jsx(MainMenu, { config: config }));
28
31
  globalThis.inkApp = app;
29
32
  }
30
33
  async function main() {
34
+ // Initialize CLI - check requirements and load config
35
+ const config = await startup();
31
36
  const program = new Command();
32
37
  program
33
38
  .name(packageJson.name)
34
39
  .description(packageJson.description)
35
40
  .version(packageJson.version);
36
- program.addCommand(createAgentsCommand());
37
- program.addCommand(createChatCommand());
38
- program.addCommand(createClusterCommand());
39
- program.addCommand(createCompletionCommand());
40
- program.addCommand(createDashboardCommand());
41
- program.addCommand(createDevCommand());
42
- program.addCommand(createGenerateCommand());
43
- program.addCommand(createInstallCommand());
44
- program.addCommand(createModelsCommand());
45
- program.addCommand(createUninstallCommand());
46
- program.addCommand(createStatusCommand());
47
- program.addCommand(createConfigCommand());
48
- program.addCommand(createTargetsCommand());
49
- program.addCommand(createTeamsCommand());
50
- program.addCommand(createToolsCommand());
51
- program.addCommand(createRoutesCommand());
41
+ program.addCommand(createAgentsCommand(config));
42
+ program.addCommand(createChatCommand(config));
43
+ program.addCommand(createClusterCommand(config));
44
+ program.addCommand(createCompletionCommand(config));
45
+ program.addCommand(createDashboardCommand(config));
46
+ program.addCommand(createDocsCommand(config));
47
+ program.addCommand(createDevCommand(config));
48
+ program.addCommand(createGenerateCommand(config));
49
+ program.addCommand(createInstallCommand(config));
50
+ program.addCommand(createModelsCommand(config));
51
+ program.addCommand(createQueryCommand(config));
52
+ program.addCommand(createUninstallCommand(config));
53
+ program.addCommand(createStatusCommand(config));
54
+ program.addCommand(createConfigCommand(config));
55
+ program.addCommand(createTargetsCommand(config));
56
+ program.addCommand(createTeamsCommand(config));
57
+ program.addCommand(createToolsCommand(config));
58
+ program.addCommand(createRoutesCommand(config));
52
59
  // If no args provided, show interactive menu
53
60
  if (process.argv.length === 2) {
54
- showMainMenu();
61
+ showMainMenu(config);
55
62
  return;
56
63
  }
57
64
  await program.parseAsync(process.argv);
@@ -18,9 +18,11 @@ export class ArkServiceProxy {
18
18
  'port-forward',
19
19
  `service/${this.service.k8sServiceName}`,
20
20
  `${this.localPort}:${this.service.k8sServicePort}`,
21
- '--namespace',
22
- this.service.namespace,
23
21
  ];
22
+ // Add namespace flag only if namespace is defined
23
+ if (this.service.namespace) {
24
+ args.push('--namespace', this.service.namespace);
25
+ }
24
26
  this.kubectlProcess = spawn('kubectl', args, {
25
27
  stdio: ['ignore', 'pipe', 'pipe'],
26
28
  });
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Get current installed ARK version
3
+ * @returns version string if found, undefined otherwise
4
+ */
5
+ export declare function getArkVersion(): Promise<string | undefined>;
1
6
  /**
2
7
  * Check if ARK is ready by verifying the ark-controller is running
3
8
  * @returns true if ark-controller deployment exists and has ready replicas
@@ -1,4 +1,21 @@
1
1
  import { execa } from 'execa';
2
+ import { arkServices } from '../arkServices.js';
3
+ /**
4
+ * Get current installed ARK version
5
+ * @returns version string if found, undefined otherwise
6
+ */
7
+ export async function getArkVersion() {
8
+ try {
9
+ const controller = arkServices['ark-controller'];
10
+ const { stdout } = await execa('helm', ['list', '-n', controller.namespace, '-o', 'json'], { stdio: 'pipe' });
11
+ const releases = JSON.parse(stdout);
12
+ const arkController = releases.find((r) => r.name === controller.helmReleaseName);
13
+ return arkController?.app_version;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ }
2
19
  /**
3
20
  * Check if ARK is ready by verifying the ark-controller is running
4
21
  * @returns true if ark-controller deployment exists and has ready replicas
@@ -10,11 +27,53 @@ export async function isArkReady() {
10
27
  const deployment = JSON.parse(result.stdout);
11
28
  const readyReplicas = deployment.status?.readyReplicas || 0;
12
29
  const replicas = deployment.spec?.replicas || 0;
30
+ // If main deployment has 0 replicas, check devspace deployment
31
+ if (replicas === 0) {
32
+ try {
33
+ const devResult = await execa('kubectl', [
34
+ 'get',
35
+ 'deployment',
36
+ 'ark-controller-devspace',
37
+ '-n',
38
+ 'ark-system',
39
+ '-o',
40
+ 'json',
41
+ ], { stdio: 'pipe' });
42
+ const devDeployment = JSON.parse(devResult.stdout);
43
+ const devReadyReplicas = devDeployment.status?.readyReplicas || 0;
44
+ const devReplicas = devDeployment.spec?.replicas || 0;
45
+ // ARK is ready if devspace deployment has ready replicas
46
+ return devReadyReplicas > 0 && devReadyReplicas === devReplicas;
47
+ }
48
+ catch {
49
+ // Devspace deployment doesn't exist
50
+ return false;
51
+ }
52
+ }
13
53
  // ARK is ready if deployment exists and has at least one ready replica
14
54
  return readyReplicas > 0 && readyReplicas === replicas;
15
55
  }
16
56
  catch {
17
- // Deployment doesn't exist or kubectl failed
18
- return false;
57
+ // Main deployment doesn't exist, try devspace deployment
58
+ try {
59
+ const devResult = await execa('kubectl', [
60
+ 'get',
61
+ 'deployment',
62
+ 'ark-controller-devspace',
63
+ '-n',
64
+ 'ark-system',
65
+ '-o',
66
+ 'json',
67
+ ], { stdio: 'pipe' });
68
+ const devDeployment = JSON.parse(devResult.stdout);
69
+ const devReadyReplicas = devDeployment.status?.readyReplicas || 0;
70
+ const devReplicas = devDeployment.spec?.replicas || 0;
71
+ // ARK is ready if devspace deployment has ready replicas
72
+ return devReadyReplicas > 0 && devReadyReplicas === devReplicas;
73
+ }
74
+ catch {
75
+ // Neither deployment exists or kubectl failed
76
+ return false;
77
+ }
19
78
  }
20
79
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ import { describe, it, expect, jest, beforeEach } from '@jest/globals';
2
+ // Mock execa using unstable_mockModule
3
+ jest.unstable_mockModule('execa', () => ({
4
+ execa: jest.fn(),
5
+ }));
6
+ // Dynamic imports after mock
7
+ const { execa } = await import('execa');
8
+ const { isArkReady } = await import('./arkStatus.js');
9
+ describe('arkStatus with __mocks__', () => {
10
+ describe('isArkReady', () => {
11
+ beforeEach(() => {
12
+ jest.clearAllMocks();
13
+ });
14
+ it('should return true when ark-controller is deployed and ready', async () => {
15
+ // Mock successful kubectl response with ready deployment
16
+ const mockDeployment = {
17
+ metadata: { name: 'ark-controller' },
18
+ spec: { replicas: 3 },
19
+ status: {
20
+ readyReplicas: 3,
21
+ availableReplicas: 3,
22
+ },
23
+ };
24
+ execa.mockResolvedValue({
25
+ stdout: JSON.stringify(mockDeployment),
26
+ stderr: '',
27
+ exitCode: 0,
28
+ failed: false,
29
+ });
30
+ const result = await isArkReady();
31
+ expect(result).toBe(true);
32
+ expect(execa).toHaveBeenCalledWith('kubectl', [
33
+ 'get',
34
+ 'deployment',
35
+ 'ark-controller',
36
+ '-n',
37
+ 'ark-system',
38
+ '-o',
39
+ 'json',
40
+ ], { stdio: 'pipe' });
41
+ });
42
+ it('should return false when kubectl fails', async () => {
43
+ // Mock kubectl failure
44
+ execa.mockRejectedValue(new Error('kubectl not found'));
45
+ const result = await isArkReady();
46
+ expect(result).toBe(false);
47
+ });
48
+ });
49
+ });
@@ -1,4 +1,3 @@
1
- import output from './output.js';
2
1
  export class ChatClient {
3
2
  constructor(arkApiClient) {
4
3
  this.arkApiClient = arkApiClient;
@@ -93,8 +92,7 @@ export class ChatClient {
93
92
  }
94
93
  }
95
94
  catch (error) {
96
- const errorMessage = error instanceof Error ? error.message : String(error);
97
- output.error('failed to call openai api:', errorMessage);
95
+ // Don't log here - error will be displayed in the message thread
98
96
  throw error;
99
97
  }
100
98
  }
@@ -1,10 +1,7 @@
1
- import { executeCommand } from './exec.js';
1
+ import { execa } from 'execa';
2
2
  export async function detectClusterType() {
3
3
  try {
4
- const { stdout } = await executeCommand('kubectl', [
5
- 'config',
6
- 'current-context',
7
- ]);
4
+ const { stdout } = await execa('kubectl', ['config', 'current-context']);
8
5
  const context = stdout.trim();
9
6
  if (context.includes('minikube')) {
10
7
  return { type: 'minikube', context };
@@ -39,7 +36,7 @@ export async function getClusterInfo(context) {
39
36
  // If context is provided, use it
40
37
  const contextArgs = context ? ['--context', context] : [];
41
38
  // Get all config info in one command
42
- const { stdout: configJson } = await executeCommand('kubectl', [
39
+ const { stdout: configJson } = await execa('kubectl', [
43
40
  'config',
44
41
  'view',
45
42
  '--minify',
@@ -62,12 +59,12 @@ export async function getClusterInfo(context) {
62
59
  switch (clusterInfo.type) {
63
60
  case 'minikube':
64
61
  try {
65
- const { stdout } = await executeCommand('minikube', ['ip']);
62
+ const { stdout } = await execa('minikube', ['ip']);
66
63
  ip = stdout.trim();
67
64
  }
68
65
  catch {
69
66
  // Fallback to kubectl if minikube command fails
70
- const { stdout } = await executeCommand('kubectl', [
67
+ const { stdout } = await execa('kubectl', [
71
68
  'get',
72
69
  'nodes',
73
70
  '-o',
@@ -77,7 +74,7 @@ export async function getClusterInfo(context) {
77
74
  }
78
75
  break;
79
76
  case 'kind': {
80
- const { stdout: kindOutput } = await executeCommand('kubectl', [
77
+ const { stdout: kindOutput } = await execa('kubectl', [
81
78
  'get',
82
79
  'nodes',
83
80
  '-o',
@@ -90,7 +87,7 @@ export async function getClusterInfo(context) {
90
87
  ip = 'localhost';
91
88
  break;
92
89
  case 'k3s': {
93
- const { stdout: k3sOutput } = await executeCommand('kubectl', [
90
+ const { stdout: k3sOutput } = await execa('kubectl', [
94
91
  'get',
95
92
  'nodes',
96
93
  '-o',
@@ -102,7 +99,7 @@ export async function getClusterInfo(context) {
102
99
  case 'cloud':
103
100
  // For cloud clusters, try to get the external IP or load balancer IP
104
101
  try {
105
- const { stdout: lbOutput } = await executeCommand('kubectl', [
102
+ const { stdout: lbOutput } = await execa('kubectl', [
106
103
  'get',
107
104
  'svc',
108
105
  '-n',
@@ -113,7 +110,7 @@ export async function getClusterInfo(context) {
113
110
  ]);
114
111
  ip = lbOutput.trim();
115
112
  if (!ip) {
116
- const { stdout: hostnameOutput } = await executeCommand('kubectl', [
113
+ const { stdout: hostnameOutput } = await execa('kubectl', [
117
114
  'get',
118
115
  'svc',
119
116
  '-n',
@@ -127,7 +124,7 @@ export async function getClusterInfo(context) {
127
124
  }
128
125
  catch {
129
126
  // Fallback to node IP
130
- const { stdout: nodeOutput } = await executeCommand('kubectl', [
127
+ const { stdout: nodeOutput } = await execa('kubectl', [
131
128
  'get',
132
129
  'nodes',
133
130
  '-o',
@@ -137,7 +134,7 @@ export async function getClusterInfo(context) {
137
134
  }
138
135
  break;
139
136
  default: {
140
- const { stdout: defaultOutput } = await executeCommand('kubectl', [
137
+ const { stdout: defaultOutput } = await execa('kubectl', [
141
138
  'get',
142
139
  'nodes',
143
140
  '-o',
@@ -0,0 +1 @@
1
+ export {};