@agents-at-scale/ark 0.1.35-rc2 → 0.1.35

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 (215) hide show
  1. package/dist/commands/cluster/index.d.ts +1 -2
  2. package/dist/commands/cluster/index.js +5 -3
  3. package/dist/commands/completion.js +2 -159
  4. package/dist/commands/config.d.ts +3 -0
  5. package/dist/commands/config.js +321 -38
  6. package/dist/commands/generate/config.js +24 -5
  7. package/dist/commands/generate/generators/agent.js +2 -2
  8. package/dist/commands/generate/generators/mcpserver.d.ts +1 -2
  9. package/dist/commands/generate/generators/mcpserver.js +5 -26
  10. package/dist/commands/generate/generators/project.js +41 -22
  11. package/dist/commands/generate/generators/team.js +2 -2
  12. package/dist/commands/generate/index.d.ts +1 -2
  13. package/dist/commands/generate/index.js +1 -1
  14. package/dist/components/statusChecker.d.ts +23 -13
  15. package/dist/components/statusChecker.js +129 -295
  16. package/dist/config.d.ts +22 -3
  17. package/dist/config.js +161 -10
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +42 -44
  20. package/dist/lib/cluster.d.ts +1 -2
  21. package/dist/lib/cluster.js +16 -37
  22. package/dist/lib/config.d.ts +80 -28
  23. package/dist/lib/config.js +205 -70
  24. package/dist/lib/consts.d.ts +1 -0
  25. package/dist/lib/consts.js +2 -0
  26. package/dist/lib/errors.js +1 -1
  27. package/dist/lib/exec.d.ts +4 -0
  28. package/dist/lib/exec.js +11 -0
  29. package/dist/lib/types.d.ts +3 -17
  30. package/dist/ui/MainMenu.d.ts +1 -5
  31. package/dist/ui/MainMenu.js +91 -222
  32. package/dist/ui/statusFormatter.d.ts +7 -22
  33. package/dist/ui/statusFormatter.js +39 -39
  34. package/package.json +5 -17
  35. package/dist/arkServices.d.ts +0 -42
  36. package/dist/arkServices.js +0 -138
  37. package/dist/arkServices.spec.d.ts +0 -1
  38. package/dist/arkServices.spec.js +0 -24
  39. package/dist/charts/charts.d.ts +0 -5
  40. package/dist/charts/charts.js +0 -6
  41. package/dist/charts/dependencies.d.ts +0 -6
  42. package/dist/charts/dependencies.js +0 -50
  43. package/dist/charts/types.d.ts +0 -40
  44. package/dist/charts/types.js +0 -1
  45. package/dist/commands/agents/index.d.ts +0 -3
  46. package/dist/commands/agents/index.js +0 -51
  47. package/dist/commands/agents/index.spec.d.ts +0 -1
  48. package/dist/commands/agents/index.spec.js +0 -67
  49. package/dist/commands/agents/selector.d.ts +0 -8
  50. package/dist/commands/agents/selector.js +0 -53
  51. package/dist/commands/agents.d.ts +0 -2
  52. package/dist/commands/agents.js +0 -53
  53. package/dist/commands/chat/index.d.ts +0 -3
  54. package/dist/commands/chat/index.js +0 -29
  55. package/dist/commands/chat.d.ts +0 -2
  56. package/dist/commands/chat.js +0 -45
  57. package/dist/commands/cluster/get.d.ts +0 -2
  58. package/dist/commands/cluster/get.js +0 -39
  59. package/dist/commands/cluster/get.spec.d.ts +0 -1
  60. package/dist/commands/cluster/get.spec.js +0 -92
  61. package/dist/commands/cluster/index.spec.d.ts +0 -1
  62. package/dist/commands/cluster/index.spec.js +0 -24
  63. package/dist/commands/completion/index.d.ts +0 -3
  64. package/dist/commands/completion/index.js +0 -290
  65. package/dist/commands/completion/index.spec.d.ts +0 -1
  66. package/dist/commands/completion/index.spec.js +0 -34
  67. package/dist/commands/config/index.d.ts +0 -3
  68. package/dist/commands/config/index.js +0 -42
  69. package/dist/commands/config/index.spec.d.ts +0 -1
  70. package/dist/commands/config/index.spec.js +0 -78
  71. package/dist/commands/dashboard/index.d.ts +0 -4
  72. package/dist/commands/dashboard/index.js +0 -39
  73. package/dist/commands/dashboard.d.ts +0 -3
  74. package/dist/commands/dashboard.js +0 -39
  75. package/dist/commands/dev/index.d.ts +0 -3
  76. package/dist/commands/dev/index.js +0 -9
  77. package/dist/commands/dev/tool/check.d.ts +0 -2
  78. package/dist/commands/dev/tool/check.js +0 -142
  79. package/dist/commands/dev/tool/clean.d.ts +0 -2
  80. package/dist/commands/dev/tool/clean.js +0 -153
  81. package/dist/commands/dev/tool/generate.d.ts +0 -2
  82. package/dist/commands/dev/tool/generate.js +0 -28
  83. package/dist/commands/dev/tool/index.d.ts +0 -2
  84. package/dist/commands/dev/tool/index.js +0 -14
  85. package/dist/commands/dev/tool/init.d.ts +0 -2
  86. package/dist/commands/dev/tool/init.js +0 -320
  87. package/dist/commands/dev/tool/shared.d.ts +0 -5
  88. package/dist/commands/dev/tool/shared.js +0 -256
  89. package/dist/commands/dev/tool/status.d.ts +0 -2
  90. package/dist/commands/dev/tool/status.js +0 -136
  91. package/dist/commands/dev/tool-generate.spec.d.ts +0 -1
  92. package/dist/commands/dev/tool-generate.spec.js +0 -163
  93. package/dist/commands/dev/tool.d.ts +0 -2
  94. package/dist/commands/dev/tool.js +0 -559
  95. package/dist/commands/dev/tool.spec.d.ts +0 -1
  96. package/dist/commands/dev/tool.spec.js +0 -48
  97. package/dist/commands/docs/index.d.ts +0 -4
  98. package/dist/commands/docs/index.js +0 -18
  99. package/dist/commands/install/index.d.ts +0 -8
  100. package/dist/commands/install/index.js +0 -300
  101. package/dist/commands/install/index.spec.d.ts +0 -1
  102. package/dist/commands/install/index.spec.js +0 -143
  103. package/dist/commands/install.d.ts +0 -3
  104. package/dist/commands/install.js +0 -147
  105. package/dist/commands/models/create.d.ts +0 -1
  106. package/dist/commands/models/create.js +0 -213
  107. package/dist/commands/models/create.spec.d.ts +0 -1
  108. package/dist/commands/models/create.spec.js +0 -125
  109. package/dist/commands/models/index.d.ts +0 -3
  110. package/dist/commands/models/index.js +0 -60
  111. package/dist/commands/models/index.spec.d.ts +0 -1
  112. package/dist/commands/models/index.spec.js +0 -76
  113. package/dist/commands/models/selector.d.ts +0 -8
  114. package/dist/commands/models/selector.js +0 -53
  115. package/dist/commands/query/index.d.ts +0 -3
  116. package/dist/commands/query/index.js +0 -131
  117. package/dist/commands/routes/index.d.ts +0 -3
  118. package/dist/commands/routes/index.js +0 -93
  119. package/dist/commands/routes.d.ts +0 -2
  120. package/dist/commands/routes.js +0 -101
  121. package/dist/commands/status/index.d.ts +0 -4
  122. package/dist/commands/status/index.js +0 -262
  123. package/dist/commands/status.d.ts +0 -3
  124. package/dist/commands/status.js +0 -33
  125. package/dist/commands/targets/index.d.ts +0 -3
  126. package/dist/commands/targets/index.js +0 -65
  127. package/dist/commands/targets/index.spec.d.ts +0 -1
  128. package/dist/commands/targets/index.spec.js +0 -105
  129. package/dist/commands/targets.d.ts +0 -2
  130. package/dist/commands/targets.js +0 -65
  131. package/dist/commands/teams/index.d.ts +0 -3
  132. package/dist/commands/teams/index.js +0 -49
  133. package/dist/commands/teams/index.spec.d.ts +0 -1
  134. package/dist/commands/teams/index.spec.js +0 -70
  135. package/dist/commands/teams/selector.d.ts +0 -8
  136. package/dist/commands/teams/selector.js +0 -55
  137. package/dist/commands/tools/index.d.ts +0 -3
  138. package/dist/commands/tools/index.js +0 -49
  139. package/dist/commands/tools/index.spec.d.ts +0 -1
  140. package/dist/commands/tools/index.spec.js +0 -70
  141. package/dist/commands/tools/selector.d.ts +0 -8
  142. package/dist/commands/tools/selector.js +0 -53
  143. package/dist/commands/uninstall/index.d.ts +0 -3
  144. package/dist/commands/uninstall/index.js +0 -106
  145. package/dist/commands/uninstall/index.spec.d.ts +0 -1
  146. package/dist/commands/uninstall/index.spec.js +0 -125
  147. package/dist/commands/uninstall.d.ts +0 -2
  148. package/dist/commands/uninstall.js +0 -83
  149. package/dist/components/ChatUI.d.ts +0 -16
  150. package/dist/components/ChatUI.js +0 -801
  151. package/dist/components/StatusView.d.ts +0 -10
  152. package/dist/components/StatusView.js +0 -39
  153. package/dist/lib/arkApiClient.d.ts +0 -53
  154. package/dist/lib/arkApiClient.js +0 -102
  155. package/dist/lib/arkApiProxy.d.ts +0 -9
  156. package/dist/lib/arkApiProxy.js +0 -22
  157. package/dist/lib/arkServiceProxy.d.ts +0 -14
  158. package/dist/lib/arkServiceProxy.js +0 -95
  159. package/dist/lib/arkStatus.d.ts +0 -10
  160. package/dist/lib/arkStatus.js +0 -79
  161. package/dist/lib/arkStatus.spec.d.ts +0 -1
  162. package/dist/lib/arkStatus.spec.js +0 -49
  163. package/dist/lib/chatClient.d.ts +0 -33
  164. package/dist/lib/chatClient.js +0 -99
  165. package/dist/lib/cluster.spec.d.ts +0 -1
  166. package/dist/lib/cluster.spec.js +0 -338
  167. package/dist/lib/commandUtils.d.ts +0 -4
  168. package/dist/lib/commandUtils.js +0 -18
  169. package/dist/lib/commandUtils.test.d.ts +0 -1
  170. package/dist/lib/commandUtils.test.js +0 -44
  171. package/dist/lib/commands.d.ts +0 -16
  172. package/dist/lib/commands.js +0 -29
  173. package/dist/lib/commands.spec.d.ts +0 -1
  174. package/dist/lib/commands.spec.js +0 -146
  175. package/dist/lib/config.spec.d.ts +0 -1
  176. package/dist/lib/config.spec.js +0 -99
  177. package/dist/lib/config.test.d.ts +0 -1
  178. package/dist/lib/config.test.js +0 -93
  179. package/dist/lib/consts.spec.d.ts +0 -1
  180. package/dist/lib/consts.spec.js +0 -15
  181. package/dist/lib/dev/tools/analyzer.d.ts +0 -30
  182. package/dist/lib/dev/tools/analyzer.js +0 -190
  183. package/dist/lib/dev/tools/discover_tools.py +0 -392
  184. package/dist/lib/dev/tools/mcp-types.d.ts +0 -28
  185. package/dist/lib/dev/tools/mcp-types.js +0 -86
  186. package/dist/lib/dev/tools/types.d.ts +0 -50
  187. package/dist/lib/dev/tools/types.js +0 -1
  188. package/dist/lib/errors.spec.d.ts +0 -1
  189. package/dist/lib/errors.spec.js +0 -221
  190. package/dist/lib/nextSteps.d.ts +0 -4
  191. package/dist/lib/nextSteps.js +0 -20
  192. package/dist/lib/nextSteps.spec.d.ts +0 -1
  193. package/dist/lib/nextSteps.spec.js +0 -59
  194. package/dist/lib/output.d.ts +0 -36
  195. package/dist/lib/output.js +0 -89
  196. package/dist/lib/output.spec.d.ts +0 -1
  197. package/dist/lib/output.spec.js +0 -123
  198. package/dist/lib/portUtils.d.ts +0 -8
  199. package/dist/lib/portUtils.js +0 -39
  200. package/dist/lib/startup.d.ts +0 -9
  201. package/dist/lib/startup.js +0 -93
  202. package/dist/lib/startup.spec.d.ts +0 -1
  203. package/dist/lib/startup.spec.js +0 -168
  204. package/dist/types/types.d.ts +0 -40
  205. package/dist/types/types.js +0 -1
  206. package/dist/ui/AgentSelector.d.ts +0 -8
  207. package/dist/ui/AgentSelector.js +0 -53
  208. package/dist/ui/ModelSelector.d.ts +0 -8
  209. package/dist/ui/ModelSelector.js +0 -53
  210. package/dist/ui/TeamSelector.d.ts +0 -8
  211. package/dist/ui/TeamSelector.js +0 -55
  212. package/dist/ui/ToolSelector.d.ts +0 -8
  213. package/dist/ui/ToolSelector.js +0 -53
  214. package/dist/ui/statusFormatter.spec.d.ts +0 -1
  215. package/dist/ui/statusFormatter.spec.js +0 -58
@@ -1,7 +1,9 @@
1
- import { execa } from 'execa';
2
- import { checkCommandExists } from '../lib/commands.js';
3
- import { arkServices } from '../arkServices.js';
4
- import { isArkReady } from '../lib/arkStatus.js';
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import { KubernetesConfigManager } from '../lib/kubernetes.js';
4
+ import * as k8s from '@kubernetes/client-node';
5
+ import axios from 'axios';
6
+ const execAsync = promisify(exec);
5
7
  export const getNodeVersion = () => ({
6
8
  command: 'node',
7
9
  versionArgs: '--version',
@@ -38,20 +40,6 @@ export const getHelmVersion = () => ({
38
40
  versionArgs: 'version --short',
39
41
  versionExtract: (output) => output.trim(),
40
42
  });
41
- export const getMinikubeVersion = () => ({
42
- command: 'minikube',
43
- versionArgs: 'version --short',
44
- versionExtract: (output) => output.trim(),
45
- });
46
- export const getKindVersion = () => ({
47
- command: 'kind',
48
- versionArgs: 'version',
49
- versionExtract: (output) => {
50
- // kind version output is like "kind v0.20.0 go1.21.0 linux/amd64"
51
- const match = output.match(/kind (v[\d.]+)/);
52
- return match ? match[1] : output.trim();
53
- },
54
- });
55
43
  function createErrorServiceStatus(name, url, error, defaultStatus = 'unhealthy', defaultDetails) {
56
44
  const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
57
45
  return {
@@ -62,13 +50,32 @@ function createErrorServiceStatus(name, url, error, defaultStatus = 'unhealthy',
62
50
  };
63
51
  }
64
52
  export class StatusChecker {
53
+ constructor(arkClient) {
54
+ this.arkClient = arkClient;
55
+ this.kubernetesManager = new KubernetesConfigManager();
56
+ }
57
+ /**
58
+ * Check if a command is available in the system
59
+ */
60
+ async isCommandAvailable(command) {
61
+ try {
62
+ const checkCommand = process.platform === 'win32'
63
+ ? `where ${command}`
64
+ : `command -v ${command}`;
65
+ await execAsync(checkCommand);
66
+ return true;
67
+ }
68
+ catch (_error) {
69
+ return false;
70
+ }
71
+ }
65
72
  /**
66
73
  * Get version of a command
67
74
  */
68
75
  async getCommandVersion(config) {
69
76
  try {
70
- const args = config.versionArgs.split(' ');
71
- const { stdout } = await execa(config.command, args);
77
+ const cmd = `${config.command} ${config.versionArgs}`;
78
+ const { stdout } = await execAsync(cmd);
72
79
  return config.versionExtract(stdout);
73
80
  }
74
81
  catch (error) {
@@ -76,219 +83,91 @@ export class StatusChecker {
76
83
  }
77
84
  }
78
85
  /**
79
- * Check combined deployment and helm status
80
- * Gets health from deployment, version/revision from Helm
86
+ * Check health of a service by URL
81
87
  */
82
- async checkCombinedStatus(serviceName, deploymentName, helmReleaseName, namespace, devDeploymentName) {
83
- // Get deployment status for health
84
- const deploymentStatus = await this.checkDeploymentStatus(serviceName, deploymentName, namespace, devDeploymentName);
85
- // Try to get version info from Helm if it's a healthy deployment
86
- if (deploymentStatus.status === 'healthy' ||
87
- deploymentStatus.status === 'warning') {
88
- try {
89
- const { stdout } = await execa('helm', ['list', '-n', namespace, '-o', 'json'], { timeout: 5000 });
90
- const releases = JSON.parse(stdout);
91
- const release = releases.find((r) => r.name === helmReleaseName);
92
- if (release) {
93
- // Merge Helm version info into deployment status
94
- return {
95
- ...deploymentStatus,
96
- version: release.app_version,
97
- revision: release.revision,
98
- };
99
- }
100
- }
101
- catch {
102
- // If Helm check fails, return deployment status as-is
103
- }
104
- }
105
- return deploymentStatus;
106
- }
107
- /**
108
- * Check deployment status
109
- */
110
- async checkDeploymentStatus(serviceName, deploymentName, namespace, devDeploymentName) {
88
+ async checkServiceHealth(serviceName, serviceUrl, successMessage, healthPath = '') {
89
+ const fullUrl = `${serviceUrl}${healthPath}`;
111
90
  try {
112
- const { stdout } = await execa('kubectl', [
113
- 'get',
114
- 'deployment',
115
- deploymentName,
116
- '--namespace',
117
- namespace,
118
- '-o',
119
- 'json',
120
- ]);
121
- const deployment = JSON.parse(stdout);
122
- const replicas = deployment.spec?.replicas || 0;
123
- const readyReplicas = deployment.status?.readyReplicas || 0;
124
- const availableReplicas = deployment.status?.availableReplicas || 0;
125
- // Check Kubernetes 'Available' condition - only 'available' deployments are healthy
126
- const availableCondition = deployment.status?.conditions?.find((condition) => condition.type === 'Available');
127
- const isAvailable = availableCondition?.status === 'True';
128
- const allReplicasReady = readyReplicas === replicas && availableReplicas === replicas;
129
- // Determine status: not ready if 0 replicas, healthy if available and all ready, warning otherwise
130
- let status;
131
- if (replicas === 0 || readyReplicas === 0) {
132
- status = 'not ready';
133
- }
134
- else if (isAvailable && allReplicasReady) {
135
- status = 'healthy';
136
- }
137
- else {
138
- status = 'warning';
139
- }
140
- // If main deployment has 0 replicas and we have a dev deployment, check it
141
- if (replicas === 0 && devDeploymentName) {
142
- try {
143
- const { stdout: devStdout } = await execa('kubectl', [
144
- 'get',
145
- 'deployment',
146
- devDeploymentName,
147
- '--namespace',
148
- namespace,
149
- '-o',
150
- 'json',
151
- ]);
152
- const devDeployment = JSON.parse(devStdout);
153
- const devReplicas = devDeployment.spec?.replicas || 0;
154
- const devReadyReplicas = devDeployment.status?.readyReplicas || 0;
155
- const devAvailableReplicas = devDeployment.status?.availableReplicas || 0;
156
- if (devReplicas > 0) {
157
- const devAvailableCondition = devDeployment.status?.conditions?.find((condition) => condition.type === 'Available');
158
- const devIsAvailable = devAvailableCondition?.status === 'True';
159
- const devAllReplicasReady = devReadyReplicas === devReplicas &&
160
- devAvailableReplicas === devReplicas;
161
- let devStatus;
162
- if (devReplicas === 0 || devReadyReplicas === 0) {
163
- devStatus = 'not ready';
164
- }
165
- else if (devIsAvailable && devAllReplicasReady) {
166
- devStatus = 'healthy';
167
- }
168
- else {
169
- devStatus = 'warning';
170
- }
171
- return {
172
- name: serviceName,
173
- status: devStatus,
174
- details: `${devReadyReplicas}/${devReplicas} replicas ready`,
175
- isDev: true,
176
- namespace,
177
- };
178
- }
179
- }
180
- catch {
181
- // If dev deployment check fails, return the original status
182
- }
183
- }
91
+ await axios.get(fullUrl, { timeout: 5000 });
184
92
  return {
185
93
  name: serviceName,
186
- status,
187
- details: `${readyReplicas}/${replicas} replicas ready`,
188
- namespace,
94
+ status: 'healthy',
95
+ url: serviceUrl,
96
+ details: successMessage,
189
97
  };
190
98
  }
191
99
  catch (error) {
192
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
193
- // If main deployment not found or not healthy, try dev deployment
194
- if (errorMessage.includes('not found') ||
195
- errorMessage.includes('NotFound')) {
196
- if (devDeploymentName) {
197
- try {
198
- const { stdout } = await execa('kubectl', [
199
- 'get',
200
- 'deployment',
201
- devDeploymentName,
202
- '--namespace',
203
- namespace,
204
- '-o',
205
- 'json',
206
- ]);
207
- const devDeployment = JSON.parse(stdout);
208
- const replicas = devDeployment.spec?.replicas || 0;
209
- const readyReplicas = devDeployment.status?.readyReplicas || 0;
210
- const availableReplicas = devDeployment.status?.availableReplicas || 0;
211
- const availableCondition = devDeployment.status?.conditions?.find((condition) => condition.type === 'Available');
212
- const isAvailable = availableCondition?.status === 'True';
213
- const allReplicasReady = readyReplicas === replicas && availableReplicas === replicas;
214
- let status;
215
- if (replicas === 0 || readyReplicas === 0) {
216
- status = 'not ready';
217
- }
218
- else if (isAvailable && allReplicasReady) {
219
- status = 'healthy';
220
- }
221
- else {
222
- status = 'warning';
223
- }
224
- return {
225
- name: serviceName,
226
- status,
227
- details: `${readyReplicas}/${replicas} replicas ready`,
228
- isDev: true,
229
- namespace,
230
- };
231
- }
232
- catch {
233
- // If dev deployment also not found, return not installed
234
- return {
235
- name: serviceName,
236
- status: 'not installed',
237
- details: `Deployment '${deploymentName}' not found`,
238
- namespace,
239
- };
240
- }
241
- }
242
- return {
243
- name: serviceName,
244
- status: 'not installed',
245
- details: `Deployment '${deploymentName}' not found`,
246
- namespace,
247
- };
248
- }
249
- return createErrorServiceStatus(serviceName, '', error, 'unhealthy', `Failed to check deployment: ${errorMessage}`);
100
+ return createErrorServiceStatus(serviceName, serviceUrl, error, 'unhealthy', `${serviceName} is not running or not accessible`);
250
101
  }
251
102
  }
252
103
  /**
253
- * Check helm release status (fallback for services without deployments)
104
+ * Check if ark-api is running and healthy
254
105
  */
255
- async checkHelmStatus(serviceName, helmReleaseName, namespace) {
106
+ async checkArkApi(customUrl) {
107
+ const url = customUrl || this.arkClient.getBaseURL();
108
+ return this.checkServiceHealth('ark-api', url, 'ARK API is running', '/health');
109
+ }
110
+ /**
111
+ * Return a "not installed" status for a service
112
+ */
113
+ createNotInstalledStatus(serviceName) {
114
+ return {
115
+ name: serviceName,
116
+ status: 'not installed',
117
+ details: `${serviceName} is not configured or not part of this deployment`,
118
+ };
119
+ }
120
+ /**
121
+ * Check Kubernetes service health via pods and endpoints
122
+ */
123
+ async checkKubernetesService(serviceName, kubernetesServiceName, namespace = 'default') {
256
124
  try {
257
- const { stdout } = await execa('helm', [
258
- 'list',
259
- '--filter',
260
- helmReleaseName,
261
- '--namespace',
125
+ await this.kubernetesManager.initializeConfig();
126
+ const kc = this.kubernetesManager.getKubeConfig();
127
+ const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
128
+ // Check if service exists and has endpoints
129
+ const service = await k8sApi.readNamespacedService({
130
+ name: kubernetesServiceName,
131
+ namespace,
132
+ });
133
+ const endpoints = await k8sApi.readNamespacedEndpoints({
134
+ name: kubernetesServiceName,
262
135
  namespace,
263
- '--output',
264
- 'json',
265
- ]);
266
- const helmList = JSON.parse(stdout);
267
- if (helmList.length === 0) {
136
+ });
137
+ // Check if service has ready endpoints
138
+ const readyAddresses = endpoints.subsets?.reduce((total, subset) => {
139
+ return total + (subset.addresses?.length || 0);
140
+ }, 0) || 0;
141
+ if (readyAddresses > 0) {
142
+ const serviceIP = service.spec?.clusterIP;
143
+ const servicePort = service.spec?.ports?.[0]?.port;
268
144
  return {
269
145
  name: serviceName,
270
- status: 'not installed',
271
- details: `Helm release '${helmReleaseName}' not found`,
272
- namespace,
146
+ status: 'healthy',
147
+ url: `cluster://${serviceIP}:${servicePort}`,
148
+ details: `${serviceName} running in cluster (${readyAddresses} ready endpoints)`,
149
+ };
150
+ }
151
+ else {
152
+ return {
153
+ name: serviceName,
154
+ status: 'unhealthy',
155
+ details: `${serviceName} service exists but has no ready endpoints`,
273
156
  };
274
157
  }
275
- const release = helmList[0];
276
- const status = release.status?.toLowerCase() || 'unknown';
277
- const revision = release.revision || 'unknown';
278
- const appVersion = release.app_version || 'unknown';
279
- const isHealthy = status === 'deployed';
280
- return {
281
- name: serviceName,
282
- status: isHealthy ? 'healthy' : 'unhealthy',
283
- version: appVersion,
284
- revision: revision,
285
- details: `Status: ${status}`,
286
- namespace,
287
- };
288
158
  }
289
159
  catch (error) {
290
160
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
291
- return createErrorServiceStatus(serviceName, '', error, 'unhealthy', `Failed to check helm status: ${errorMessage}`);
161
+ // If service not found, it's not installed
162
+ if (errorMessage.includes('not found')) {
163
+ return this.createNotInstalledStatus(serviceName);
164
+ }
165
+ // Other errors indicate unhealthy
166
+ return {
167
+ name: serviceName,
168
+ status: 'unhealthy',
169
+ details: `Failed to check ${serviceName}: ${errorMessage}`,
170
+ };
292
171
  }
293
172
  }
294
173
  /**
@@ -301,13 +180,10 @@ export class StatusChecker {
301
180
  { name: 'kubectl', ...getKubectlVersion() },
302
181
  { name: 'docker', ...getDockerVersion() },
303
182
  { name: 'helm', ...getHelmVersion() },
304
- { name: 'minikube', ...getMinikubeVersion() },
305
- { name: 'kind', ...getKindVersion() },
306
183
  ];
307
184
  const results = [];
308
185
  for (const dep of dependencies) {
309
- const args = dep.versionArgs.split(' ');
310
- const installed = await checkCommandExists(dep.command, args);
186
+ const installed = await this.isCommandAvailable(dep.command);
311
187
  const version = installed
312
188
  ? await this.getCommandVersion({
313
189
  command: dep.command,
@@ -329,89 +205,47 @@ export class StatusChecker {
329
205
  /**
330
206
  * Run all checks and return results
331
207
  */
332
- async checkAll() {
333
- // Check dependencies first
334
- const dependencies = await this.checkDependencies();
335
- // Test cluster access
336
- let clusterAccess = false;
337
- try {
338
- await execa('kubectl', ['get', 'namespaces', '-o', 'name'], {
339
- timeout: 5000,
340
- });
341
- clusterAccess = true;
208
+ async checkAll(serviceUrls = {}, arkApiUrl) {
209
+ // Always check ark-api if provided
210
+ const serviceChecks = [];
211
+ if (arkApiUrl) {
212
+ serviceChecks.push(this.checkArkApi(arkApiUrl));
342
213
  }
343
- catch {
344
- clusterAccess = false;
345
- }
346
- // Get cluster info if accessible
347
- let clusterInfo;
348
- if (clusterAccess) {
349
- const { getClusterInfo } = await import('../lib/cluster.js');
350
- clusterInfo = await getClusterInfo();
351
- }
352
- let services = [];
353
- // Only check ARK services if we have cluster access
354
- if (clusterAccess) {
355
- const serviceChecks = [];
356
- for (const [serviceName, service] of Object.entries(arkServices)) {
357
- // Skip disabled services
358
- if (!service.enabled)
359
- continue;
360
- // Use service namespace if defined, otherwise use current namespace from clusterInfo
361
- const namespace = service.namespace || clusterInfo?.namespace || 'default';
362
- if (service.k8sDeploymentName) {
363
- // For deployments, get health from deployment and version from Helm
364
- serviceChecks.push(this.checkCombinedStatus(serviceName, service.k8sDeploymentName, service.helmReleaseName, namespace, service.k8sDevDeploymentName));
365
- }
366
- else {
367
- serviceChecks.push(this.checkHelmStatus(serviceName, service.helmReleaseName, namespace));
368
- }
369
- }
370
- services = await Promise.all(serviceChecks);
371
- }
372
- // Check if ARK is ready (controller is running)
373
- let arkReady = false;
374
- let defaultModelExists = false;
375
- let defaultModel;
376
- if (clusterAccess) {
377
- arkReady = await isArkReady();
378
- // Check for default model with detailed status
379
- if (arkReady) {
380
- try {
381
- const { stdout } = await execa('kubectl', [
382
- 'get',
383
- 'model',
384
- 'default',
385
- '-o',
386
- 'json',
387
- ]);
388
- const model = JSON.parse(stdout);
389
- defaultModelExists = true;
390
- // Extract model details
391
- const available = model.status?.conditions?.find((c) => c.type === 'Available')?.status === 'True';
392
- defaultModel = {
393
- exists: true,
394
- available,
395
- provider: model.spec?.provider,
396
- details: model.spec?.model || model.spec?.apiEndpoint,
397
- };
398
- }
399
- catch {
400
- defaultModelExists = false;
401
- defaultModel = {
402
- exists: false,
403
- };
404
- }
214
+ // Dynamically check all discovered services
215
+ for (const [serviceName, serviceUrl] of Object.entries(serviceUrls)) {
216
+ if (serviceName === 'ark-api' && arkApiUrl) {
217
+ // Skip if we already added ark-api above
218
+ continue;
405
219
  }
220
+ serviceChecks.push(this.checkServiceHealth(serviceName, serviceUrl, `${serviceName} is running`, this.getHealthPath(serviceName)));
406
221
  }
222
+ // Always check dependencies
223
+ const dependenciesCheck = this.checkDependencies();
224
+ const [dependencies, ...serviceStatuses] = await Promise.all([
225
+ dependenciesCheck,
226
+ ...serviceChecks,
227
+ ]);
407
228
  return {
408
- services,
229
+ services: serviceStatuses,
409
230
  dependencies,
410
- clusterAccess,
411
- clusterInfo,
412
- arkReady,
413
- defaultModelExists,
414
- defaultModel,
415
231
  };
416
232
  }
233
+ /**
234
+ * Get appropriate health check path for different service types
235
+ */
236
+ getHealthPath(serviceName) {
237
+ // Some services might need specific health check paths
238
+ switch (serviceName) {
239
+ case 'ark-api':
240
+ return '/health';
241
+ case 'ark-api-a2a':
242
+ return '/health'; // ark-api-a2a has a working /health endpoint
243
+ case 'ark-dashboard':
244
+ return ''; // Dashboard typically responds to root
245
+ case 'langfuse':
246
+ return ''; // Langfuse responds to root path
247
+ default:
248
+ return ''; // Default to root path
249
+ }
250
+ }
417
251
  }
package/dist/config.d.ts CHANGED
@@ -1,14 +1,27 @@
1
+ import { ArkConfig, KubernetesConfig } from './lib/types.js';
1
2
  /**
2
- * ConfigManager handles API URL discovery and cluster access testing.
3
- * Complex discovery logic can be debugged by setting DEBUG=ark:config
3
+ * ConfigManager handles ARK CLI configuration with automatic service discovery
4
+ * and multiple fallback mechanisms. Complex discovery logic can be debugged by
5
+ * setting DEBUG=ark:config or DEBUG=ark:* environment variable.
4
6
  *
5
7
  * Example usage:
6
- * DEBUG=ark:config ark status
8
+ * DEBUG=ark:config ark check status
9
+ * DEBUG=ark:* ark dashboard
7
10
  */
8
11
  export declare class ConfigManager {
12
+ private configDir;
13
+ private configFile;
9
14
  private kubernetesManager;
15
+ private gatewayManager;
10
16
  private kubeConfig;
11
17
  constructor();
18
+ ensureConfigDir(): Promise<void>;
19
+ loadConfig(): Promise<ArkConfig>;
20
+ saveConfig(config: ArkConfig): Promise<void>;
21
+ updateConfig(updates: Partial<ArkConfig>): Promise<ArkConfig>;
22
+ private getDefaultConfig;
23
+ initializeConfig(): Promise<ArkConfig>;
24
+ getConfigPath(): string;
12
25
  getApiBaseUrl(): Promise<string>;
13
26
  /**
14
27
  * Check if localhost-gateway is running by testing port 8080
@@ -19,5 +32,11 @@ export declare class ConfigManager {
19
32
  */
20
33
  private getLocalhostGatewayUrls;
21
34
  private initKubernetesConfig;
35
+ getKubernetesConfig(): Promise<KubernetesConfig | null>;
22
36
  testClusterAccess(): Promise<boolean>;
37
+ /**
38
+ * Discover service URLs from ark-api service discovery
39
+ */
40
+ private discoverServicesFromApi;
41
+ getServiceUrls(): Promise<Record<string, string>>;
23
42
  }