@agents-at-scale/ark 0.1.35 → 0.1.36-rc1

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 (223) hide show
  1. package/dist/arkServices.d.ts +42 -0
  2. package/dist/arkServices.js +138 -0
  3. package/dist/arkServices.spec.d.ts +1 -0
  4. package/dist/arkServices.spec.js +24 -0
  5. package/dist/charts/charts.d.ts +5 -0
  6. package/dist/charts/charts.js +6 -0
  7. package/dist/charts/dependencies.d.ts +6 -0
  8. package/dist/charts/dependencies.js +50 -0
  9. package/dist/charts/types.d.ts +40 -0
  10. package/dist/charts/types.js +1 -0
  11. package/dist/commands/agents/index.d.ts +3 -0
  12. package/dist/commands/agents/index.js +65 -0
  13. package/dist/commands/agents/index.spec.d.ts +1 -0
  14. package/dist/commands/agents/index.spec.js +67 -0
  15. package/dist/commands/agents/selector.d.ts +8 -0
  16. package/dist/commands/agents/selector.js +53 -0
  17. package/dist/commands/agents.d.ts +2 -0
  18. package/dist/commands/agents.js +53 -0
  19. package/dist/commands/chat/index.d.ts +3 -0
  20. package/dist/commands/chat/index.js +29 -0
  21. package/dist/commands/chat.d.ts +2 -0
  22. package/dist/commands/chat.js +45 -0
  23. package/dist/commands/cluster/get.d.ts +2 -0
  24. package/dist/commands/cluster/get.js +39 -0
  25. package/dist/commands/cluster/get.spec.d.ts +1 -0
  26. package/dist/commands/cluster/get.spec.js +92 -0
  27. package/dist/commands/cluster/index.d.ts +2 -1
  28. package/dist/commands/cluster/index.js +3 -5
  29. package/dist/commands/cluster/index.spec.d.ts +1 -0
  30. package/dist/commands/cluster/index.spec.js +24 -0
  31. package/dist/commands/completion/index.d.ts +3 -0
  32. package/dist/commands/completion/index.js +230 -0
  33. package/dist/commands/completion/index.spec.d.ts +1 -0
  34. package/dist/commands/completion/index.spec.js +34 -0
  35. package/dist/commands/completion.js +159 -2
  36. package/dist/commands/config/index.d.ts +3 -0
  37. package/dist/commands/config/index.js +42 -0
  38. package/dist/commands/config/index.spec.d.ts +1 -0
  39. package/dist/commands/config/index.spec.js +78 -0
  40. package/dist/commands/config.d.ts +0 -3
  41. package/dist/commands/config.js +38 -321
  42. package/dist/commands/dashboard/index.d.ts +4 -0
  43. package/dist/commands/dashboard/index.js +39 -0
  44. package/dist/commands/dashboard.d.ts +3 -0
  45. package/dist/commands/dashboard.js +39 -0
  46. package/dist/commands/dev/index.d.ts +3 -0
  47. package/dist/commands/dev/index.js +9 -0
  48. package/dist/commands/dev/tool/check.d.ts +2 -0
  49. package/dist/commands/dev/tool/check.js +142 -0
  50. package/dist/commands/dev/tool/clean.d.ts +2 -0
  51. package/dist/commands/dev/tool/clean.js +153 -0
  52. package/dist/commands/dev/tool/generate.d.ts +2 -0
  53. package/dist/commands/dev/tool/generate.js +28 -0
  54. package/dist/commands/dev/tool/index.d.ts +2 -0
  55. package/dist/commands/dev/tool/index.js +14 -0
  56. package/dist/commands/dev/tool/init.d.ts +2 -0
  57. package/dist/commands/dev/tool/init.js +320 -0
  58. package/dist/commands/dev/tool/shared.d.ts +5 -0
  59. package/dist/commands/dev/tool/shared.js +258 -0
  60. package/dist/commands/dev/tool/status.d.ts +2 -0
  61. package/dist/commands/dev/tool/status.js +136 -0
  62. package/dist/commands/dev/tool-generate.spec.d.ts +1 -0
  63. package/dist/commands/dev/tool-generate.spec.js +163 -0
  64. package/dist/commands/dev/tool.d.ts +2 -0
  65. package/dist/commands/dev/tool.js +559 -0
  66. package/dist/commands/dev/tool.spec.d.ts +1 -0
  67. package/dist/commands/dev/tool.spec.js +48 -0
  68. package/dist/commands/docs/index.d.ts +4 -0
  69. package/dist/commands/docs/index.js +18 -0
  70. package/dist/commands/generate/config.js +5 -24
  71. package/dist/commands/generate/generators/mcpserver.d.ts +2 -1
  72. package/dist/commands/generate/generators/mcpserver.js +26 -5
  73. package/dist/commands/generate/generators/project.js +22 -41
  74. package/dist/commands/generate/index.d.ts +2 -1
  75. package/dist/commands/generate/index.js +1 -1
  76. package/dist/commands/install/index.d.ts +8 -0
  77. package/dist/commands/install/index.js +295 -0
  78. package/dist/commands/install/index.spec.d.ts +1 -0
  79. package/dist/commands/install/index.spec.js +143 -0
  80. package/dist/commands/install.d.ts +3 -0
  81. package/dist/commands/install.js +147 -0
  82. package/dist/commands/models/create.d.ts +1 -0
  83. package/dist/commands/models/create.js +213 -0
  84. package/dist/commands/models/create.spec.d.ts +1 -0
  85. package/dist/commands/models/create.spec.js +125 -0
  86. package/dist/commands/models/index.d.ts +3 -0
  87. package/dist/commands/models/index.js +75 -0
  88. package/dist/commands/models/index.spec.d.ts +1 -0
  89. package/dist/commands/models/index.spec.js +96 -0
  90. package/dist/commands/models/selector.d.ts +8 -0
  91. package/dist/commands/models/selector.js +53 -0
  92. package/dist/commands/query/index.d.ts +3 -0
  93. package/dist/commands/query/index.js +24 -0
  94. package/dist/commands/query/index.spec.d.ts +1 -0
  95. package/dist/commands/query/index.spec.js +53 -0
  96. package/dist/commands/routes/index.d.ts +3 -0
  97. package/dist/commands/routes/index.js +93 -0
  98. package/dist/commands/routes.d.ts +2 -0
  99. package/dist/commands/routes.js +101 -0
  100. package/dist/commands/status/index.d.ts +3 -0
  101. package/dist/commands/status/index.js +281 -0
  102. package/dist/commands/status.d.ts +3 -0
  103. package/dist/commands/status.js +33 -0
  104. package/dist/commands/targets/index.d.ts +3 -0
  105. package/dist/commands/targets/index.js +72 -0
  106. package/dist/commands/targets/index.spec.d.ts +1 -0
  107. package/dist/commands/targets/index.spec.js +154 -0
  108. package/dist/commands/targets.d.ts +2 -0
  109. package/dist/commands/targets.js +65 -0
  110. package/dist/commands/teams/index.d.ts +3 -0
  111. package/dist/commands/teams/index.js +64 -0
  112. package/dist/commands/teams/index.spec.d.ts +1 -0
  113. package/dist/commands/teams/index.spec.js +70 -0
  114. package/dist/commands/teams/selector.d.ts +8 -0
  115. package/dist/commands/teams/selector.js +55 -0
  116. package/dist/commands/tools/index.d.ts +3 -0
  117. package/dist/commands/tools/index.js +49 -0
  118. package/dist/commands/tools/index.spec.d.ts +1 -0
  119. package/dist/commands/tools/index.spec.js +70 -0
  120. package/dist/commands/tools/selector.d.ts +8 -0
  121. package/dist/commands/tools/selector.js +53 -0
  122. package/dist/commands/uninstall/index.d.ts +3 -0
  123. package/dist/commands/uninstall/index.js +101 -0
  124. package/dist/commands/uninstall/index.spec.d.ts +1 -0
  125. package/dist/commands/uninstall/index.spec.js +125 -0
  126. package/dist/commands/uninstall.d.ts +2 -0
  127. package/dist/commands/uninstall.js +83 -0
  128. package/dist/components/ChatUI.d.ts +16 -0
  129. package/dist/components/ChatUI.js +801 -0
  130. package/dist/components/StatusView.d.ts +10 -0
  131. package/dist/components/StatusView.js +39 -0
  132. package/dist/components/statusChecker.d.ts +14 -24
  133. package/dist/components/statusChecker.js +295 -129
  134. package/dist/config.d.ts +3 -22
  135. package/dist/config.js +10 -161
  136. package/dist/index.d.ts +1 -1
  137. package/dist/index.js +42 -42
  138. package/dist/lib/arkApiClient.d.ts +53 -0
  139. package/dist/lib/arkApiClient.js +102 -0
  140. package/dist/lib/arkApiProxy.d.ts +9 -0
  141. package/dist/lib/arkApiProxy.js +22 -0
  142. package/dist/lib/arkServiceProxy.d.ts +14 -0
  143. package/dist/lib/arkServiceProxy.js +95 -0
  144. package/dist/lib/arkStatus.d.ts +10 -0
  145. package/dist/lib/arkStatus.js +79 -0
  146. package/dist/lib/arkStatus.spec.d.ts +1 -0
  147. package/dist/lib/arkStatus.spec.js +49 -0
  148. package/dist/lib/chatClient.d.ts +33 -0
  149. package/dist/lib/chatClient.js +93 -0
  150. package/dist/lib/cluster.d.ts +2 -1
  151. package/dist/lib/cluster.js +37 -16
  152. package/dist/lib/cluster.spec.d.ts +1 -0
  153. package/dist/lib/cluster.spec.js +338 -0
  154. package/dist/lib/commandUtils.d.ts +4 -0
  155. package/dist/lib/commandUtils.js +18 -0
  156. package/dist/lib/commandUtils.test.d.ts +1 -0
  157. package/dist/lib/commandUtils.test.js +44 -0
  158. package/dist/lib/commands.d.ts +16 -0
  159. package/dist/lib/commands.js +29 -0
  160. package/dist/lib/commands.spec.d.ts +1 -0
  161. package/dist/lib/commands.spec.js +146 -0
  162. package/dist/lib/config.d.ts +26 -80
  163. package/dist/lib/config.js +70 -205
  164. package/dist/lib/config.spec.d.ts +1 -0
  165. package/dist/lib/config.spec.js +99 -0
  166. package/dist/lib/config.test.d.ts +1 -0
  167. package/dist/lib/config.test.js +93 -0
  168. package/dist/lib/consts.d.ts +0 -1
  169. package/dist/lib/consts.js +0 -2
  170. package/dist/lib/consts.spec.d.ts +1 -0
  171. package/dist/lib/consts.spec.js +15 -0
  172. package/dist/lib/dev/tools/analyzer.d.ts +30 -0
  173. package/dist/lib/dev/tools/analyzer.js +190 -0
  174. package/dist/lib/dev/tools/discover_tools.py +392 -0
  175. package/dist/lib/dev/tools/mcp-types.d.ts +28 -0
  176. package/dist/lib/dev/tools/mcp-types.js +86 -0
  177. package/dist/lib/dev/tools/types.d.ts +50 -0
  178. package/dist/lib/dev/tools/types.js +1 -0
  179. package/dist/lib/errors.js +1 -1
  180. package/dist/lib/errors.spec.d.ts +1 -0
  181. package/dist/lib/errors.spec.js +221 -0
  182. package/dist/lib/exec.d.ts +0 -4
  183. package/dist/lib/exec.js +0 -11
  184. package/dist/lib/executeQuery.d.ts +20 -0
  185. package/dist/lib/executeQuery.js +135 -0
  186. package/dist/lib/executeQuery.spec.d.ts +1 -0
  187. package/dist/lib/executeQuery.spec.js +170 -0
  188. package/dist/lib/nextSteps.d.ts +4 -0
  189. package/dist/lib/nextSteps.js +20 -0
  190. package/dist/lib/nextSteps.spec.d.ts +1 -0
  191. package/dist/lib/nextSteps.spec.js +59 -0
  192. package/dist/lib/output.d.ts +36 -0
  193. package/dist/lib/output.js +89 -0
  194. package/dist/lib/output.spec.d.ts +1 -0
  195. package/dist/lib/output.spec.js +123 -0
  196. package/dist/lib/portUtils.d.ts +8 -0
  197. package/dist/lib/portUtils.js +39 -0
  198. package/dist/lib/queryRunner.d.ts +22 -0
  199. package/dist/lib/queryRunner.js +142 -0
  200. package/dist/lib/startup.d.ts +9 -0
  201. package/dist/lib/startup.js +87 -0
  202. package/dist/lib/startup.spec.d.ts +1 -0
  203. package/dist/lib/startup.spec.js +152 -0
  204. package/dist/lib/types.d.ts +87 -3
  205. package/dist/lib/versions.d.ts +23 -0
  206. package/dist/lib/versions.js +51 -0
  207. package/dist/types/types.d.ts +40 -0
  208. package/dist/types/types.js +1 -0
  209. package/dist/ui/AgentSelector.d.ts +8 -0
  210. package/dist/ui/AgentSelector.js +53 -0
  211. package/dist/ui/MainMenu.d.ts +5 -1
  212. package/dist/ui/MainMenu.js +226 -91
  213. package/dist/ui/ModelSelector.d.ts +8 -0
  214. package/dist/ui/ModelSelector.js +53 -0
  215. package/dist/ui/TeamSelector.d.ts +8 -0
  216. package/dist/ui/TeamSelector.js +55 -0
  217. package/dist/ui/ToolSelector.d.ts +8 -0
  218. package/dist/ui/ToolSelector.js +53 -0
  219. package/dist/ui/statusFormatter.d.ts +22 -7
  220. package/dist/ui/statusFormatter.js +39 -39
  221. package/dist/ui/statusFormatter.spec.d.ts +1 -0
  222. package/dist/ui/statusFormatter.spec.js +58 -0
  223. package/package.json +16 -5
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { StatusData } from '../lib/types.js';
3
+ interface StatusViewProps {
4
+ statusData: StatusData | null;
5
+ isLoading: boolean;
6
+ error: string | null;
7
+ onBack: () => void;
8
+ }
9
+ declare const StatusView: React.FC<StatusViewProps>;
10
+ export default StatusView;
@@ -0,0 +1,39 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text, useInput } from 'ink';
3
+ const StatusView = ({ statusData, isLoading, error, onBack, }) => {
4
+ useInput((input, key) => {
5
+ if (key.escape || input === 'q' || key.return) {
6
+ onBack();
7
+ }
8
+ });
9
+ const renderServiceStatus = (service) => {
10
+ const statusColor = service.status === 'healthy'
11
+ ? 'green'
12
+ : service.status === 'unhealthy'
13
+ ? 'red'
14
+ : 'yellow';
15
+ const statusIcon = service.status === 'healthy'
16
+ ? '✓'
17
+ : service.status === 'unhealthy'
18
+ ? '✗'
19
+ : '?';
20
+ return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [statusIcon, " "] }), _jsxs(Text, { bold: true, children: [service.name, ": "] }), _jsx(Text, { color: statusColor, children: service.status })] }), service.url && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: "gray", children: ["URL: ", service.url] }) })), service.details && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "gray", children: service.details }) }))] }, service.name));
21
+ };
22
+ const renderDependencyStatus = (dep) => {
23
+ const statusColor = dep.installed ? 'green' : 'red';
24
+ const statusIcon = dep.installed ? '✓' : '✗';
25
+ const statusText = dep.installed ? 'installed' : 'missing';
26
+ return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [statusIcon, " "] }), _jsxs(Text, { bold: true, children: [dep.name, ": "] }), _jsx(Text, { color: statusColor, children: statusText })] }), dep.version && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: "gray", children: ["Version: ", dep.version] }) })), dep.details && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "gray", children: dep.details }) }))] }, dep.name));
27
+ };
28
+ if (isLoading) {
29
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "\uD83D\uDD0D Checking ARK system status..." }), _jsx(Text, { color: "gray", children: "Please wait while we verify services and dependencies." })] }));
30
+ }
31
+ if (error) {
32
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: "\u274C Error checking status:" }), _jsx(Text, { color: "red", children: error }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press ESC, 'q', or Enter to return to menu..." }) })] }));
33
+ }
34
+ if (!statusData) {
35
+ return null;
36
+ }
37
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDD0D ARK System Status" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDCE1 ARK Services:" }) }), statusData.services.map(renderServiceStatus), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDEE0\uFE0F System Dependencies:" }) }), statusData.dependencies.map(renderDependencyStatus), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press ESC, 'q', or Enter to return to menu..." }) })] }));
38
+ };
39
+ export default StatusView;
@@ -1,38 +1,29 @@
1
- import { StatusData, CommandVersionConfig } from '../lib/types.js';
2
- import { ArkClient } from '../lib/arkClient.js';
1
+ import { StatusData, CommandVersionConfig, ClusterInfo } from '../lib/types.js';
3
2
  export declare const getNodeVersion: () => CommandVersionConfig;
4
3
  export declare const getNpmVersion: () => CommandVersionConfig;
5
4
  export declare const getKubectlVersion: () => CommandVersionConfig;
6
5
  export declare const getDockerVersion: () => CommandVersionConfig;
7
6
  export declare const getHelmVersion: () => CommandVersionConfig;
7
+ export declare const getMinikubeVersion: () => CommandVersionConfig;
8
+ export declare const getKindVersion: () => CommandVersionConfig;
8
9
  export declare class StatusChecker {
9
- private arkClient;
10
- private kubernetesManager;
11
- constructor(arkClient: ArkClient);
12
- /**
13
- * Check if a command is available in the system
14
- */
15
- private isCommandAvailable;
16
10
  /**
17
11
  * Get version of a command
18
12
  */
19
13
  private getCommandVersion;
20
14
  /**
21
- * Check health of a service by URL
22
- */
23
- private checkServiceHealth;
24
- /**
25
- * Check if ark-api is running and healthy
15
+ * Check combined deployment and helm status
16
+ * Gets health from deployment, version/revision from Helm
26
17
  */
27
- private checkArkApi;
18
+ private checkCombinedStatus;
28
19
  /**
29
- * Return a "not installed" status for a service
20
+ * Check deployment status
30
21
  */
31
- private createNotInstalledStatus;
22
+ private checkDeploymentStatus;
32
23
  /**
33
- * Check Kubernetes service health via pods and endpoints
24
+ * Check helm release status (fallback for services without deployments)
34
25
  */
35
- private checkKubernetesService;
26
+ private checkHelmStatus;
36
27
  /**
37
28
  * Check system dependencies
38
29
  */
@@ -40,9 +31,8 @@ export declare class StatusChecker {
40
31
  /**
41
32
  * Run all checks and return results
42
33
  */
43
- checkAll(serviceUrls?: Record<string, string>, arkApiUrl?: string): Promise<StatusData>;
44
- /**
45
- * Get appropriate health check path for different service types
46
- */
47
- private getHealthPath;
34
+ checkAll(): Promise<StatusData & {
35
+ clusterAccess: boolean;
36
+ clusterInfo?: ClusterInfo;
37
+ }>;
48
38
  }
@@ -1,9 +1,7 @@
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);
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';
7
5
  export const getNodeVersion = () => ({
8
6
  command: 'node',
9
7
  versionArgs: '--version',
@@ -40,6 +38,20 @@ export const getHelmVersion = () => ({
40
38
  versionArgs: 'version --short',
41
39
  versionExtract: (output) => output.trim(),
42
40
  });
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
+ });
43
55
  function createErrorServiceStatus(name, url, error, defaultStatus = 'unhealthy', defaultDetails) {
44
56
  const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
45
57
  return {
@@ -50,32 +62,13 @@ function createErrorServiceStatus(name, url, error, defaultStatus = 'unhealthy',
50
62
  };
51
63
  }
52
64
  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
- }
72
65
  /**
73
66
  * Get version of a command
74
67
  */
75
68
  async getCommandVersion(config) {
76
69
  try {
77
- const cmd = `${config.command} ${config.versionArgs}`;
78
- const { stdout } = await execAsync(cmd);
70
+ const args = config.versionArgs.split(' ');
71
+ const { stdout } = await execa(config.command, args);
79
72
  return config.versionExtract(stdout);
80
73
  }
81
74
  catch (error) {
@@ -83,92 +76,220 @@ export class StatusChecker {
83
76
  }
84
77
  }
85
78
  /**
86
- * Check health of a service by URL
79
+ * Check combined deployment and helm status
80
+ * Gets health from deployment, version/revision from Helm
87
81
  */
88
- async checkServiceHealth(serviceName, serviceUrl, successMessage, healthPath = '') {
89
- const fullUrl = `${serviceUrl}${healthPath}`;
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) {
90
111
  try {
91
- await axios.get(fullUrl, { timeout: 5000 });
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
+ }
92
184
  return {
93
185
  name: serviceName,
94
- status: 'healthy',
95
- url: serviceUrl,
96
- details: successMessage,
186
+ status,
187
+ details: `${readyReplicas}/${replicas} replicas ready`,
188
+ namespace,
97
189
  };
98
190
  }
99
191
  catch (error) {
100
- return createErrorServiceStatus(serviceName, serviceUrl, error, 'unhealthy', `${serviceName} is not running or not accessible`);
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}`);
101
250
  }
102
251
  }
103
252
  /**
104
- * Check if ark-api is running and healthy
253
+ * Check helm release status (fallback for services without deployments)
105
254
  */
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') {
255
+ async checkHelmStatus(serviceName, helmReleaseName, namespace) {
124
256
  try {
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,
257
+ const { stdout } = await execa('helm', [
258
+ 'list',
259
+ '--filter',
260
+ helmReleaseName,
261
+ '--namespace',
135
262
  namespace,
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;
144
- return {
145
- name: serviceName,
146
- status: 'healthy',
147
- url: `cluster://${serviceIP}:${servicePort}`,
148
- details: `${serviceName} running in cluster (${readyAddresses} ready endpoints)`,
149
- };
150
- }
151
- else {
263
+ '--output',
264
+ 'json',
265
+ ]);
266
+ const helmList = JSON.parse(stdout);
267
+ if (helmList.length === 0) {
152
268
  return {
153
269
  name: serviceName,
154
- status: 'unhealthy',
155
- details: `${serviceName} service exists but has no ready endpoints`,
270
+ status: 'not installed',
271
+ details: `Helm release '${helmReleaseName}' not found`,
272
+ namespace,
156
273
  };
157
274
  }
158
- }
159
- catch (error) {
160
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
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
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';
166
280
  return {
167
281
  name: serviceName,
168
- status: 'unhealthy',
169
- details: `Failed to check ${serviceName}: ${errorMessage}`,
282
+ status: isHealthy ? 'healthy' : 'unhealthy',
283
+ version: appVersion,
284
+ revision: revision,
285
+ details: `Status: ${status}`,
286
+ namespace,
170
287
  };
171
288
  }
289
+ catch (error) {
290
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
291
+ return createErrorServiceStatus(serviceName, '', error, 'unhealthy', `Failed to check helm status: ${errorMessage}`);
292
+ }
172
293
  }
173
294
  /**
174
295
  * Check system dependencies
@@ -180,10 +301,13 @@ export class StatusChecker {
180
301
  { name: 'kubectl', ...getKubectlVersion() },
181
302
  { name: 'docker', ...getDockerVersion() },
182
303
  { name: 'helm', ...getHelmVersion() },
304
+ { name: 'minikube', ...getMinikubeVersion() },
305
+ { name: 'kind', ...getKindVersion() },
183
306
  ];
184
307
  const results = [];
185
308
  for (const dep of dependencies) {
186
- const installed = await this.isCommandAvailable(dep.command);
309
+ const args = dep.versionArgs.split(' ');
310
+ const installed = await checkCommandExists(dep.command, args);
187
311
  const version = installed
188
312
  ? await this.getCommandVersion({
189
313
  command: dep.command,
@@ -205,47 +329,89 @@ export class StatusChecker {
205
329
  /**
206
330
  * Run all checks and return results
207
331
  */
208
- async checkAll(serviceUrls = {}, arkApiUrl) {
209
- // Always check ark-api if provided
210
- const serviceChecks = [];
211
- if (arkApiUrl) {
212
- serviceChecks.push(this.checkArkApi(arkApiUrl));
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;
213
342
  }
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;
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
+ }
219
405
  }
220
- serviceChecks.push(this.checkServiceHealth(serviceName, serviceUrl, `${serviceName} is running`, this.getHealthPath(serviceName)));
221
406
  }
222
- // Always check dependencies
223
- const dependenciesCheck = this.checkDependencies();
224
- const [dependencies, ...serviceStatuses] = await Promise.all([
225
- dependenciesCheck,
226
- ...serviceChecks,
227
- ]);
228
407
  return {
229
- services: serviceStatuses,
408
+ services,
230
409
  dependencies,
410
+ clusterAccess,
411
+ clusterInfo,
412
+ arkReady,
413
+ defaultModelExists,
414
+ defaultModel,
231
415
  };
232
416
  }
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
- }
251
417
  }
package/dist/config.d.ts CHANGED
@@ -1,27 +1,14 @@
1
- import { ArkConfig, KubernetesConfig } from './lib/types.js';
2
1
  /**
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.
2
+ * ConfigManager handles API URL discovery and cluster access testing.
3
+ * Complex discovery logic can be debugged by setting DEBUG=ark:config
6
4
  *
7
5
  * Example usage:
8
- * DEBUG=ark:config ark check status
9
- * DEBUG=ark:* ark dashboard
6
+ * DEBUG=ark:config ark status
10
7
  */
11
8
  export declare class ConfigManager {
12
- private configDir;
13
- private configFile;
14
9
  private kubernetesManager;
15
- private gatewayManager;
16
10
  private kubeConfig;
17
11
  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;
25
12
  getApiBaseUrl(): Promise<string>;
26
13
  /**
27
14
  * Check if localhost-gateway is running by testing port 8080
@@ -32,11 +19,5 @@ export declare class ConfigManager {
32
19
  */
33
20
  private getLocalhostGatewayUrls;
34
21
  private initKubernetesConfig;
35
- getKubernetesConfig(): Promise<KubernetesConfig | null>;
36
22
  testClusterAccess(): Promise<boolean>;
37
- /**
38
- * Discover service URLs from ark-api service discovery
39
- */
40
- private discoverServicesFromApi;
41
- getServiceUrls(): Promise<Record<string, string>>;
42
23
  }