@agents-at-scale/ark 0.1.33 → 0.1.35-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/arkServices.d.ts +50 -0
- package/dist/arkServices.js +153 -0
- package/dist/charts/charts.d.ts +5 -0
- package/dist/charts/charts.js +6 -0
- package/dist/charts/dependencies.d.ts +6 -0
- package/dist/charts/dependencies.js +50 -0
- package/dist/charts/types.d.ts +40 -0
- package/dist/charts/types.js +1 -0
- package/dist/commands/agents/index.d.ts +2 -0
- package/dist/commands/agents/index.js +56 -0
- package/dist/commands/agents/selector.d.ts +8 -0
- package/dist/commands/agents/selector.js +53 -0
- package/dist/commands/agents.d.ts +2 -0
- package/dist/commands/agents.js +53 -0
- package/dist/commands/chat/index.d.ts +2 -0
- package/dist/commands/chat/index.js +45 -0
- package/dist/commands/chat.d.ts +2 -0
- package/dist/commands/chat.js +45 -0
- package/dist/commands/cluster/get.d.ts +2 -0
- package/dist/commands/cluster/get.js +39 -0
- package/dist/commands/cluster/index.js +2 -4
- package/dist/commands/completion/index.d.ts +2 -0
- package/dist/commands/completion/index.js +268 -0
- package/dist/commands/completion.js +159 -2
- package/dist/commands/config/index.d.ts +2 -0
- package/dist/commands/config/index.js +42 -0
- package/dist/commands/config.d.ts +0 -3
- package/dist/commands/config.js +38 -321
- package/dist/commands/dashboard/index.d.ts +3 -0
- package/dist/commands/dashboard/index.js +39 -0
- package/dist/commands/dashboard.d.ts +3 -0
- package/dist/commands/dashboard.js +39 -0
- package/dist/commands/dev/index.d.ts +2 -0
- package/dist/commands/dev/index.js +9 -0
- package/dist/commands/dev/tool/check.d.ts +2 -0
- package/dist/commands/dev/tool/check.js +142 -0
- package/dist/commands/dev/tool/clean.d.ts +2 -0
- package/dist/commands/dev/tool/clean.js +153 -0
- package/dist/commands/dev/tool/generate.d.ts +2 -0
- package/dist/commands/dev/tool/generate.js +28 -0
- package/dist/commands/dev/tool/index.d.ts +2 -0
- package/dist/commands/dev/tool/index.js +14 -0
- package/dist/commands/dev/tool/init.d.ts +2 -0
- package/dist/commands/dev/tool/init.js +320 -0
- package/dist/commands/dev/tool/shared.d.ts +5 -0
- package/dist/commands/dev/tool/shared.js +256 -0
- package/dist/commands/dev/tool/status.d.ts +2 -0
- package/dist/commands/dev/tool/status.js +136 -0
- package/dist/commands/dev/tool.d.ts +2 -0
- package/dist/commands/dev/tool.js +559 -0
- package/dist/commands/generate/config.js +5 -24
- package/dist/commands/generate/generators/mcpserver.d.ts +2 -1
- package/dist/commands/generate/generators/mcpserver.js +26 -5
- package/dist/commands/install/index.d.ts +6 -0
- package/dist/commands/install/index.js +165 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.js +147 -0
- package/dist/commands/models/create.d.ts +1 -0
- package/dist/commands/models/create.js +213 -0
- package/dist/commands/models/index.d.ts +2 -0
- package/dist/commands/models/index.js +65 -0
- package/dist/commands/models/selector.d.ts +8 -0
- package/dist/commands/models/selector.js +53 -0
- package/dist/commands/routes/index.d.ts +2 -0
- package/dist/commands/routes/index.js +101 -0
- package/dist/commands/routes.d.ts +2 -0
- package/dist/commands/routes.js +101 -0
- package/dist/commands/status/index.d.ts +3 -0
- package/dist/commands/status/index.js +33 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +33 -0
- package/dist/commands/targets/index.d.ts +2 -0
- package/dist/commands/targets/index.js +65 -0
- package/dist/commands/targets.d.ts +2 -0
- package/dist/commands/targets.js +65 -0
- package/dist/commands/teams/index.d.ts +2 -0
- package/dist/commands/teams/index.js +54 -0
- package/dist/commands/teams/selector.d.ts +8 -0
- package/dist/commands/teams/selector.js +55 -0
- package/dist/commands/tools/index.d.ts +2 -0
- package/dist/commands/tools/index.js +54 -0
- package/dist/commands/tools/selector.d.ts +8 -0
- package/dist/commands/tools/selector.js +53 -0
- package/dist/commands/uninstall/index.d.ts +2 -0
- package/dist/commands/uninstall/index.js +84 -0
- package/dist/commands/uninstall.d.ts +2 -0
- package/dist/commands/uninstall.js +83 -0
- package/dist/components/ChatUI.d.ts +16 -0
- package/dist/components/ChatUI.js +801 -0
- package/dist/components/StatusView.d.ts +10 -0
- package/dist/components/StatusView.js +39 -0
- package/dist/components/statusChecker.d.ts +10 -13
- package/dist/components/statusChecker.js +128 -65
- package/dist/config.js +3 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.js +31 -36
- package/dist/lib/arkApiClient.d.ts +53 -0
- package/dist/lib/arkApiClient.js +102 -0
- package/dist/lib/arkApiProxy.d.ts +9 -0
- package/dist/lib/arkApiProxy.js +22 -0
- package/dist/lib/arkServiceProxy.d.ts +14 -0
- package/dist/lib/arkServiceProxy.js +93 -0
- package/dist/lib/arkStatus.d.ts +5 -0
- package/dist/lib/arkStatus.js +20 -0
- package/dist/lib/chatClient.d.ts +33 -0
- package/dist/lib/chatClient.js +101 -0
- package/dist/lib/cluster.d.ts +2 -1
- package/dist/lib/cluster.js +27 -3
- package/dist/lib/commandUtils.d.ts +4 -0
- package/dist/lib/commandUtils.js +18 -0
- package/dist/lib/commandUtils.test.d.ts +1 -0
- package/dist/lib/commandUtils.test.js +44 -0
- package/dist/lib/config.d.ts +24 -80
- package/dist/lib/config.js +68 -205
- package/dist/lib/config.test.d.ts +1 -0
- package/dist/lib/config.test.js +93 -0
- package/dist/lib/dev/tools/analyzer.d.ts +30 -0
- package/dist/lib/dev/tools/analyzer.js +190 -0
- package/dist/lib/dev/tools/discover_tools.py +392 -0
- package/dist/lib/dev/tools/mcp-types.d.ts +28 -0
- package/dist/lib/dev/tools/mcp-types.js +86 -0
- package/dist/lib/dev/tools/types.d.ts +50 -0
- package/dist/lib/dev/tools/types.js +1 -0
- package/dist/lib/output.d.ts +36 -0
- package/dist/lib/output.js +89 -0
- package/dist/lib/types.d.ts +8 -3
- package/dist/types/types.d.ts +40 -0
- package/dist/types/types.js +1 -0
- package/dist/ui/MainMenu.js +158 -90
- package/dist/ui/statusFormatter.d.ts +4 -1
- package/dist/ui/statusFormatter.js +91 -19
- package/package.json +16 -4
|
@@ -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;
|
|
@@ -5,26 +5,24 @@ export declare const getNpmVersion: () => CommandVersionConfig;
|
|
|
5
5
|
export declare const getKubectlVersion: () => CommandVersionConfig;
|
|
6
6
|
export declare const getDockerVersion: () => CommandVersionConfig;
|
|
7
7
|
export declare const getHelmVersion: () => CommandVersionConfig;
|
|
8
|
+
export declare const getMinikubeVersion: () => CommandVersionConfig;
|
|
9
|
+
export declare const getKindVersion: () => CommandVersionConfig;
|
|
8
10
|
export declare class StatusChecker {
|
|
9
11
|
private arkClient;
|
|
10
12
|
private kubernetesManager;
|
|
11
13
|
constructor(arkClient: ArkClient);
|
|
12
|
-
/**
|
|
13
|
-
* Check if a command is available in the system
|
|
14
|
-
*/
|
|
15
|
-
private isCommandAvailable;
|
|
16
14
|
/**
|
|
17
15
|
* Get version of a command
|
|
18
16
|
*/
|
|
19
17
|
private getCommandVersion;
|
|
20
18
|
/**
|
|
21
|
-
* Check
|
|
19
|
+
* Check deployment status
|
|
22
20
|
*/
|
|
23
|
-
private
|
|
21
|
+
private checkDeploymentStatus;
|
|
24
22
|
/**
|
|
25
|
-
* Check
|
|
23
|
+
* Check helm release status (fallback for services without deployments)
|
|
26
24
|
*/
|
|
27
|
-
private
|
|
25
|
+
private checkHelmStatus;
|
|
28
26
|
/**
|
|
29
27
|
* Return a "not installed" status for a service
|
|
30
28
|
*/
|
|
@@ -40,9 +38,8 @@ export declare class StatusChecker {
|
|
|
40
38
|
/**
|
|
41
39
|
* Run all checks and return results
|
|
42
40
|
*/
|
|
43
|
-
checkAll(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
private getHealthPath;
|
|
41
|
+
checkAll(): Promise<StatusData & {
|
|
42
|
+
clusterAccess: boolean;
|
|
43
|
+
clusterInfo?: any;
|
|
44
|
+
}>;
|
|
48
45
|
}
|
|
@@ -2,7 +2,9 @@ import { exec } from 'child_process';
|
|
|
2
2
|
import { promisify } from 'util';
|
|
3
3
|
import { KubernetesConfigManager } from '../lib/kubernetes.js';
|
|
4
4
|
import * as k8s from '@kubernetes/client-node';
|
|
5
|
-
import
|
|
5
|
+
import { isCommandAvailable } from '../lib/commandUtils.js';
|
|
6
|
+
import { arkServices } from '../arkServices.js';
|
|
7
|
+
import { isArkReady } from '../lib/arkStatus.js';
|
|
6
8
|
const execAsync = promisify(exec);
|
|
7
9
|
export const getNodeVersion = () => ({
|
|
8
10
|
command: 'node',
|
|
@@ -40,6 +42,20 @@ export const getHelmVersion = () => ({
|
|
|
40
42
|
versionArgs: 'version --short',
|
|
41
43
|
versionExtract: (output) => output.trim(),
|
|
42
44
|
});
|
|
45
|
+
export const getMinikubeVersion = () => ({
|
|
46
|
+
command: 'minikube',
|
|
47
|
+
versionArgs: 'version --short',
|
|
48
|
+
versionExtract: (output) => output.trim(),
|
|
49
|
+
});
|
|
50
|
+
export const getKindVersion = () => ({
|
|
51
|
+
command: 'kind',
|
|
52
|
+
versionArgs: 'version',
|
|
53
|
+
versionExtract: (output) => {
|
|
54
|
+
// kind version output is like "kind v0.20.0 go1.21.0 linux/amd64"
|
|
55
|
+
const match = output.match(/kind (v[\d.]+)/);
|
|
56
|
+
return match ? match[1] : output.trim();
|
|
57
|
+
},
|
|
58
|
+
});
|
|
43
59
|
function createErrorServiceStatus(name, url, error, defaultStatus = 'unhealthy', defaultDetails) {
|
|
44
60
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
45
61
|
return {
|
|
@@ -54,21 +70,6 @@ export class StatusChecker {
|
|
|
54
70
|
this.arkClient = arkClient;
|
|
55
71
|
this.kubernetesManager = new KubernetesConfigManager();
|
|
56
72
|
}
|
|
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
73
|
/**
|
|
73
74
|
* Get version of a command
|
|
74
75
|
*/
|
|
@@ -83,29 +84,81 @@ export class StatusChecker {
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
/**
|
|
86
|
-
* Check
|
|
87
|
+
* Check deployment status
|
|
87
88
|
*/
|
|
88
|
-
async
|
|
89
|
-
const fullUrl = `${serviceUrl}${healthPath}`;
|
|
89
|
+
async checkDeploymentStatus(serviceName, deploymentName, namespace) {
|
|
90
90
|
try {
|
|
91
|
-
|
|
91
|
+
const cmd = `kubectl get deployment ${deploymentName} --namespace ${namespace} -o json`;
|
|
92
|
+
const { stdout } = await execAsync(cmd);
|
|
93
|
+
const deployment = JSON.parse(stdout);
|
|
94
|
+
const replicas = deployment.spec?.replicas || 0;
|
|
95
|
+
const readyReplicas = deployment.status?.readyReplicas || 0;
|
|
96
|
+
const availableReplicas = deployment.status?.availableReplicas || 0;
|
|
97
|
+
// Check Kubernetes 'Available' condition - only 'available' deployments are healthy
|
|
98
|
+
const availableCondition = deployment.status?.conditions?.find((condition) => condition.type === 'Available');
|
|
99
|
+
const isAvailable = availableCondition?.status === 'True';
|
|
100
|
+
const allReplicasReady = readyReplicas === replicas && availableReplicas === replicas;
|
|
101
|
+
// Determine status: not ready if 0 replicas, healthy if available and all ready, warning otherwise
|
|
102
|
+
let status;
|
|
103
|
+
if (replicas === 0 || readyReplicas === 0) {
|
|
104
|
+
status = 'not ready';
|
|
105
|
+
}
|
|
106
|
+
else if (isAvailable && allReplicasReady) {
|
|
107
|
+
status = 'healthy';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
status = 'warning';
|
|
111
|
+
}
|
|
92
112
|
return {
|
|
93
113
|
name: serviceName,
|
|
94
|
-
status
|
|
95
|
-
|
|
96
|
-
details: successMessage,
|
|
114
|
+
status,
|
|
115
|
+
details: `${readyReplicas}/${replicas} replicas ready`,
|
|
97
116
|
};
|
|
98
117
|
}
|
|
99
118
|
catch (error) {
|
|
100
|
-
|
|
119
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
120
|
+
if (errorMessage.includes('not found')) {
|
|
121
|
+
return {
|
|
122
|
+
name: serviceName,
|
|
123
|
+
status: 'not installed',
|
|
124
|
+
details: `Deployment '${deploymentName}' not found in namespace '${namespace}'`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return createErrorServiceStatus(serviceName, '', error, 'unhealthy', `Failed to check deployment: ${errorMessage}`);
|
|
101
128
|
}
|
|
102
129
|
}
|
|
103
130
|
/**
|
|
104
|
-
* Check
|
|
131
|
+
* Check helm release status (fallback for services without deployments)
|
|
105
132
|
*/
|
|
106
|
-
async
|
|
107
|
-
|
|
108
|
-
|
|
133
|
+
async checkHelmStatus(serviceName, helmReleaseName, namespace) {
|
|
134
|
+
try {
|
|
135
|
+
const cmd = `helm list --filter ${helmReleaseName} --namespace ${namespace} --output json`;
|
|
136
|
+
const { stdout } = await execAsync(cmd);
|
|
137
|
+
const helmList = JSON.parse(stdout);
|
|
138
|
+
if (helmList.length === 0) {
|
|
139
|
+
return {
|
|
140
|
+
name: serviceName,
|
|
141
|
+
status: 'not installed',
|
|
142
|
+
details: `Helm release '${helmReleaseName}' not found in namespace '${namespace}'`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const release = helmList[0];
|
|
146
|
+
const status = release.status?.toLowerCase() || 'unknown';
|
|
147
|
+
const revision = release.revision || 'unknown';
|
|
148
|
+
const appVersion = release.app_version || 'unknown';
|
|
149
|
+
const isHealthy = status === 'deployed';
|
|
150
|
+
return {
|
|
151
|
+
name: serviceName,
|
|
152
|
+
status: isHealthy ? 'healthy' : 'unhealthy',
|
|
153
|
+
version: appVersion,
|
|
154
|
+
revision: revision,
|
|
155
|
+
details: `Status: ${status}`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
160
|
+
return createErrorServiceStatus(serviceName, '', error, 'unhealthy', `Failed to check helm status: ${errorMessage}`);
|
|
161
|
+
}
|
|
109
162
|
}
|
|
110
163
|
/**
|
|
111
164
|
* Return a "not installed" status for a service
|
|
@@ -180,10 +233,12 @@ export class StatusChecker {
|
|
|
180
233
|
{ name: 'kubectl', ...getKubectlVersion() },
|
|
181
234
|
{ name: 'docker', ...getDockerVersion() },
|
|
182
235
|
{ name: 'helm', ...getHelmVersion() },
|
|
236
|
+
{ name: 'minikube', ...getMinikubeVersion() },
|
|
237
|
+
{ name: 'kind', ...getKindVersion() },
|
|
183
238
|
];
|
|
184
239
|
const results = [];
|
|
185
240
|
for (const dep of dependencies) {
|
|
186
|
-
const installed = await
|
|
241
|
+
const installed = await isCommandAvailable(dep.command);
|
|
187
242
|
const version = installed
|
|
188
243
|
? await this.getCommandVersion({
|
|
189
244
|
command: dep.command,
|
|
@@ -205,47 +260,55 @@ export class StatusChecker {
|
|
|
205
260
|
/**
|
|
206
261
|
* Run all checks and return results
|
|
207
262
|
*/
|
|
208
|
-
async checkAll(
|
|
209
|
-
//
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
263
|
+
async checkAll() {
|
|
264
|
+
// Check dependencies first
|
|
265
|
+
const dependencies = await this.checkDependencies();
|
|
266
|
+
// Test cluster access
|
|
267
|
+
const configManager = new (await import('../config.js')).ConfigManager();
|
|
268
|
+
const clusterAccess = await configManager.testClusterAccess();
|
|
269
|
+
// Get cluster info if accessible
|
|
270
|
+
let clusterInfo;
|
|
271
|
+
if (clusterAccess) {
|
|
272
|
+
const { getClusterInfo } = await import('../lib/cluster.js');
|
|
273
|
+
clusterInfo = await getClusterInfo();
|
|
274
|
+
}
|
|
275
|
+
let services = [];
|
|
276
|
+
// Only check ARK services if we have cluster access
|
|
277
|
+
if (clusterAccess) {
|
|
278
|
+
const serviceChecks = [];
|
|
279
|
+
for (const [serviceName, service] of Object.entries(arkServices)) {
|
|
280
|
+
if (service.k8sDeploymentName) {
|
|
281
|
+
serviceChecks.push(this.checkDeploymentStatus(serviceName, service.k8sDeploymentName, service.namespace));
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
serviceChecks.push(this.checkHelmStatus(serviceName, service.helmReleaseName, service.namespace));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
services = await Promise.all(serviceChecks);
|
|
213
288
|
}
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
289
|
+
// Check if ARK is ready (controller is running)
|
|
290
|
+
let arkReady = false;
|
|
291
|
+
let defaultModelExists = false;
|
|
292
|
+
if (clusterAccess) {
|
|
293
|
+
arkReady = await isArkReady();
|
|
294
|
+
// Check for default model
|
|
295
|
+
if (arkReady) {
|
|
296
|
+
try {
|
|
297
|
+
await execAsync('kubectl get model default -o name');
|
|
298
|
+
defaultModelExists = true;
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
defaultModelExists = false;
|
|
302
|
+
}
|
|
219
303
|
}
|
|
220
|
-
serviceChecks.push(this.checkServiceHealth(serviceName, serviceUrl, `${serviceName} is running`, this.getHealthPath(serviceName)));
|
|
221
304
|
}
|
|
222
|
-
// Always check dependencies
|
|
223
|
-
const dependenciesCheck = this.checkDependencies();
|
|
224
|
-
const [dependencies, ...serviceStatuses] = await Promise.all([
|
|
225
|
-
dependenciesCheck,
|
|
226
|
-
...serviceChecks,
|
|
227
|
-
]);
|
|
228
305
|
return {
|
|
229
|
-
services
|
|
306
|
+
services,
|
|
230
307
|
dependencies,
|
|
308
|
+
clusterAccess,
|
|
309
|
+
clusterInfo,
|
|
310
|
+
arkReady,
|
|
311
|
+
defaultModelExists,
|
|
231
312
|
};
|
|
232
313
|
}
|
|
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
314
|
}
|
package/dist/config.js
CHANGED
|
@@ -7,6 +7,7 @@ import { ArkClient } from './lib/arkClient.js';
|
|
|
7
7
|
import { DEFAULT_ADDRESS_ARK_API, CONFIG_DIR_NAME, CONFIG_FILE_NAME, } from './lib/consts.js';
|
|
8
8
|
import { GatewayManager } from './lib/gatewayManager.js';
|
|
9
9
|
import { KubernetesConfigManager } from './lib/kubernetes.js';
|
|
10
|
+
import { getStatusCheckableServices } from './arkServices.js';
|
|
10
11
|
const debug = Debug('ark:config');
|
|
11
12
|
/**
|
|
12
13
|
* ConfigManager handles ARK CLI configuration with automatic service discovery
|
|
@@ -163,16 +164,8 @@ export class ConfigManager {
|
|
|
163
164
|
* Construct standard localhost-gateway URLs for known ARK services
|
|
164
165
|
*/
|
|
165
166
|
getLocalhostGatewayUrls() {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const knownServices = {
|
|
169
|
-
'ark-api': `http://ark-api.127.0.0.1.nip.io:${port}`,
|
|
170
|
-
'ark-dashboard': `http://dashboard.127.0.0.1.nip.io:${port}`,
|
|
171
|
-
'ark-api-a2a': `http://ark-api-a2a.127.0.0.1.nip.io:${port}`,
|
|
172
|
-
langfuse: `http://langfuse.telemetry.127.0.0.1.nip.io:${port}`, // Fixed URL to match HTTPRoute
|
|
173
|
-
// Add other services as they become available via gateway
|
|
174
|
-
};
|
|
175
|
-
return knownServices;
|
|
167
|
+
// Use centralized service definitions from arkServices
|
|
168
|
+
return getStatusCheckableServices();
|
|
176
169
|
}
|
|
177
170
|
async initKubernetesConfig() {
|
|
178
171
|
if (!this.kubeConfig) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env NODE_NO_WARNINGS=1 node
|
|
2
2
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,39 +1,31 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env NODE_NO_WARNINGS=1 node
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import chalk from 'chalk';
|
|
4
3
|
import { Command } from 'commander';
|
|
5
4
|
import { render } from 'ink';
|
|
6
5
|
import { createRequire } from 'module';
|
|
7
6
|
const require = createRequire(import.meta.url);
|
|
8
7
|
const packageJson = require('../package.json');
|
|
8
|
+
import output from './lib/output.js';
|
|
9
|
+
import { createAgentsCommand } from './commands/agents/index.js';
|
|
10
|
+
import { createChatCommand } from './commands/chat/index.js';
|
|
9
11
|
import { createClusterCommand } from './commands/cluster/index.js';
|
|
10
|
-
import { createCompletionCommand } from './commands/completion.js';
|
|
12
|
+
import { createCompletionCommand } from './commands/completion/index.js';
|
|
13
|
+
import { createDashboardCommand } from './commands/dashboard/index.js';
|
|
14
|
+
import { createDevCommand } from './commands/dev/index.js';
|
|
11
15
|
import { createGenerateCommand } from './commands/generate/index.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
+
import { createInstallCommand } from './commands/install/index.js';
|
|
17
|
+
import { createModelsCommand } from './commands/models/index.js';
|
|
18
|
+
import { createUninstallCommand } from './commands/uninstall/index.js';
|
|
19
|
+
import { createStatusCommand } from './commands/status/index.js';
|
|
20
|
+
import { createConfigCommand } from './commands/config/index.js';
|
|
21
|
+
import { createTargetsCommand } from './commands/targets/index.js';
|
|
22
|
+
import { createTeamsCommand } from './commands/teams/index.js';
|
|
23
|
+
import { createToolsCommand } from './commands/tools/index.js';
|
|
24
|
+
import { createRoutesCommand } from './commands/routes/index.js';
|
|
16
25
|
import MainMenu from './ui/MainMenu.js';
|
|
17
|
-
import { StatusFormatter } from './ui/statusFormatter.js';
|
|
18
26
|
function showMainMenu() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
async function handleStatusCheck() {
|
|
23
|
-
try {
|
|
24
|
-
const configManager = new ConfigManager();
|
|
25
|
-
const apiBaseUrl = await configManager.getApiBaseUrl();
|
|
26
|
-
const serviceUrls = await configManager.getServiceUrls();
|
|
27
|
-
const arkClient = new ArkClient(apiBaseUrl);
|
|
28
|
-
const statusChecker = new StatusChecker(arkClient);
|
|
29
|
-
const statusData = await statusChecker.checkAll(serviceUrls, apiBaseUrl);
|
|
30
|
-
StatusFormatter.printStatus(statusData);
|
|
31
|
-
process.exit(0); // Exit cleanly after showing status
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
console.error(chalk.red('Failed to check status:'), error);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
27
|
+
const app = render(_jsx(MainMenu, {}));
|
|
28
|
+
globalThis.inkApp = app;
|
|
37
29
|
}
|
|
38
30
|
async function main() {
|
|
39
31
|
const program = new Command();
|
|
@@ -41,27 +33,30 @@ async function main() {
|
|
|
41
33
|
.name(packageJson.name)
|
|
42
34
|
.description(packageJson.description)
|
|
43
35
|
.version(packageJson.version);
|
|
36
|
+
program.addCommand(createAgentsCommand());
|
|
37
|
+
program.addCommand(createChatCommand());
|
|
44
38
|
program.addCommand(createClusterCommand());
|
|
45
39
|
program.addCommand(createCompletionCommand());
|
|
40
|
+
program.addCommand(createDashboardCommand());
|
|
41
|
+
program.addCommand(createDevCommand());
|
|
46
42
|
program.addCommand(createGenerateCommand());
|
|
43
|
+
program.addCommand(createInstallCommand());
|
|
44
|
+
program.addCommand(createModelsCommand());
|
|
45
|
+
program.addCommand(createUninstallCommand());
|
|
46
|
+
program.addCommand(createStatusCommand());
|
|
47
47
|
program.addCommand(createConfigCommand());
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.command('status')
|
|
53
|
-
.description('Check system status')
|
|
54
|
-
.action(handleStatusCheck);
|
|
55
|
-
program.addCommand(checkCommand);
|
|
48
|
+
program.addCommand(createTargetsCommand());
|
|
49
|
+
program.addCommand(createTeamsCommand());
|
|
50
|
+
program.addCommand(createToolsCommand());
|
|
51
|
+
program.addCommand(createRoutesCommand());
|
|
56
52
|
// If no args provided, show interactive menu
|
|
57
53
|
if (process.argv.length === 2) {
|
|
58
|
-
console.log();
|
|
59
54
|
showMainMenu();
|
|
60
55
|
return;
|
|
61
56
|
}
|
|
62
57
|
await program.parseAsync(process.argv);
|
|
63
58
|
}
|
|
64
59
|
main().catch((error) => {
|
|
65
|
-
|
|
60
|
+
output.error('failed to start ark cli: ', error);
|
|
66
61
|
process.exit(1);
|
|
67
62
|
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
export interface QueryTarget {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
type: 'agent' | 'model' | 'tool' | string;
|
|
6
|
+
description?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Agent {
|
|
9
|
+
name: string;
|
|
10
|
+
namespace: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
model_ref?: string;
|
|
13
|
+
prompt?: string;
|
|
14
|
+
status?: string;
|
|
15
|
+
annotations?: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
export interface Model {
|
|
18
|
+
name: string;
|
|
19
|
+
namespace: string;
|
|
20
|
+
type: string;
|
|
21
|
+
model: string;
|
|
22
|
+
status: string;
|
|
23
|
+
annotations?: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
export interface Tool {
|
|
26
|
+
name: string;
|
|
27
|
+
namespace: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
labels?: Record<string, string>;
|
|
30
|
+
annotations?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
export interface Team {
|
|
33
|
+
name: string;
|
|
34
|
+
namespace: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
strategy?: string;
|
|
37
|
+
members_count?: number;
|
|
38
|
+
status?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare class ArkApiClient {
|
|
41
|
+
private openai;
|
|
42
|
+
private baseUrl;
|
|
43
|
+
private namespace;
|
|
44
|
+
constructor(arkApiUrl: string, namespace?: string);
|
|
45
|
+
getBaseUrl(): string;
|
|
46
|
+
getQueryTargets(): Promise<QueryTarget[]>;
|
|
47
|
+
getAgents(): Promise<Agent[]>;
|
|
48
|
+
getModels(): Promise<Model[]>;
|
|
49
|
+
getTools(): Promise<Tool[]>;
|
|
50
|
+
getTeams(): Promise<Team[]>;
|
|
51
|
+
createChatCompletion(params: OpenAI.Chat.Completions.ChatCompletionCreateParams): Promise<OpenAI.Chat.Completions.ChatCompletion>;
|
|
52
|
+
createChatCompletionStream(params: OpenAI.Chat.Completions.ChatCompletionCreateParams): AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
export class ArkApiClient {
|
|
3
|
+
constructor(arkApiUrl, namespace = 'default') {
|
|
4
|
+
this.baseUrl = arkApiUrl;
|
|
5
|
+
this.namespace = namespace;
|
|
6
|
+
this.openai = new OpenAI({
|
|
7
|
+
baseURL: `${arkApiUrl}/openai/v1`,
|
|
8
|
+
apiKey: 'dummy', // ark-api doesn't require an API key
|
|
9
|
+
dangerouslyAllowBrowser: false,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
getBaseUrl() {
|
|
13
|
+
return this.baseUrl;
|
|
14
|
+
}
|
|
15
|
+
async getQueryTargets() {
|
|
16
|
+
try {
|
|
17
|
+
const models = await this.openai.models.list();
|
|
18
|
+
const targets = models.data.map((model) => {
|
|
19
|
+
const parts = model.id.split('/');
|
|
20
|
+
const type = parts[0] || 'model';
|
|
21
|
+
const name = parts.slice(1).join('/') || model.id;
|
|
22
|
+
return {
|
|
23
|
+
id: model.id,
|
|
24
|
+
name,
|
|
25
|
+
type,
|
|
26
|
+
description: model.id,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
return targets;
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new Error(`Failed to get query targets: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async getAgents() {
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(`${this.baseUrl}/v1/namespaces/${this.namespace}/agents`);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
40
|
+
}
|
|
41
|
+
const data = (await response.json());
|
|
42
|
+
return data.items || [];
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new Error(`Failed to get agents: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async getModels() {
|
|
49
|
+
try {
|
|
50
|
+
const response = await fetch(`${this.baseUrl}/v1/namespaces/${this.namespace}/models`);
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
53
|
+
}
|
|
54
|
+
const data = (await response.json());
|
|
55
|
+
return data.items || [];
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw new Error(`Failed to get models: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async getTools() {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`${this.baseUrl}/v1/namespaces/${this.namespace}/tools`);
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
66
|
+
}
|
|
67
|
+
const data = (await response.json());
|
|
68
|
+
return data.items || [];
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new Error(`Failed to get tools: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async getTeams() {
|
|
75
|
+
try {
|
|
76
|
+
const response = await fetch(`${this.baseUrl}/v1/namespaces/${this.namespace}/teams`);
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
79
|
+
}
|
|
80
|
+
const data = (await response.json());
|
|
81
|
+
return data.items || [];
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw new Error(`Failed to get teams: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async createChatCompletion(params) {
|
|
88
|
+
return (await this.openai.chat.completions.create({
|
|
89
|
+
...params,
|
|
90
|
+
stream: false,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
async *createChatCompletionStream(params) {
|
|
94
|
+
const stream = await this.openai.chat.completions.create({
|
|
95
|
+
...params,
|
|
96
|
+
stream: true,
|
|
97
|
+
});
|
|
98
|
+
for await (const chunk of stream) {
|
|
99
|
+
yield chunk;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|