@agents-at-scale/ark 0.1.34 → 0.1.35-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.
- package/dist/arkServices.d.ts +42 -0
- package/dist/arkServices.js +138 -0
- package/dist/arkServices.spec.d.ts +1 -0
- package/dist/arkServices.spec.js +24 -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 +3 -0
- package/dist/commands/agents/index.js +51 -0
- package/dist/commands/agents/index.spec.d.ts +1 -0
- package/dist/commands/agents/index.spec.js +67 -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 +3 -0
- package/dist/commands/chat/index.js +29 -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/get.spec.d.ts +1 -0
- package/dist/commands/cluster/get.spec.js +92 -0
- package/dist/commands/cluster/index.d.ts +2 -1
- package/dist/commands/cluster/index.js +3 -5
- package/dist/commands/cluster/index.spec.d.ts +1 -0
- package/dist/commands/cluster/index.spec.js +24 -0
- package/dist/commands/completion/index.d.ts +3 -0
- package/dist/commands/completion/index.js +268 -0
- package/dist/commands/completion/index.spec.d.ts +1 -0
- package/dist/commands/completion/index.spec.js +34 -0
- package/dist/commands/completion.js +159 -2
- package/dist/commands/config/index.d.ts +3 -0
- package/dist/commands/config/index.js +42 -0
- package/dist/commands/config/index.spec.d.ts +1 -0
- package/dist/commands/config/index.spec.js +78 -0
- package/dist/commands/config.d.ts +0 -3
- package/dist/commands/config.js +38 -321
- package/dist/commands/dashboard/index.d.ts +4 -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 +3 -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-generate.spec.d.ts +1 -0
- package/dist/commands/dev/tool-generate.spec.js +163 -0
- package/dist/commands/dev/tool.d.ts +2 -0
- package/dist/commands/dev/tool.js +559 -0
- package/dist/commands/dev/tool.spec.d.ts +1 -0
- package/dist/commands/dev/tool.spec.js +48 -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/generate/generators/project.js +22 -41
- package/dist/commands/generate/index.d.ts +2 -1
- package/dist/commands/generate/index.js +1 -1
- package/dist/commands/install/index.d.ts +8 -0
- package/dist/commands/install/index.js +302 -0
- package/dist/commands/install/index.spec.d.ts +1 -0
- package/dist/commands/install/index.spec.js +135 -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/create.spec.d.ts +1 -0
- package/dist/commands/models/create.spec.js +125 -0
- package/dist/commands/models/index.d.ts +3 -0
- package/dist/commands/models/index.js +60 -0
- package/dist/commands/models/index.spec.d.ts +1 -0
- package/dist/commands/models/index.spec.js +76 -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 +3 -0
- package/dist/commands/routes/index.js +93 -0
- package/dist/commands/routes.d.ts +2 -0
- package/dist/commands/routes.js +101 -0
- package/dist/commands/status/index.d.ts +4 -0
- package/dist/commands/status/index.js +232 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +33 -0
- package/dist/commands/targets/index.d.ts +3 -0
- package/dist/commands/targets/index.js +65 -0
- package/dist/commands/targets/index.spec.d.ts +1 -0
- package/dist/commands/targets/index.spec.js +105 -0
- package/dist/commands/targets.d.ts +2 -0
- package/dist/commands/targets.js +65 -0
- package/dist/commands/teams/index.d.ts +3 -0
- package/dist/commands/teams/index.js +49 -0
- package/dist/commands/teams/index.spec.d.ts +1 -0
- package/dist/commands/teams/index.spec.js +70 -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 +3 -0
- package/dist/commands/tools/index.js +49 -0
- package/dist/commands/tools/index.spec.d.ts +1 -0
- package/dist/commands/tools/index.spec.js +70 -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 +3 -0
- package/dist/commands/uninstall/index.js +107 -0
- package/dist/commands/uninstall/index.spec.d.ts +1 -0
- package/dist/commands/uninstall/index.spec.js +117 -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 +13 -23
- package/dist/components/statusChecker.js +275 -129
- package/dist/config.d.ts +3 -22
- package/dist/config.js +10 -161
- package/dist/index.d.ts +1 -1
- package/dist/index.js +40 -42
- 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 +95 -0
- package/dist/lib/arkStatus.d.ts +10 -0
- package/dist/lib/arkStatus.js +79 -0
- package/dist/lib/arkStatus.spec.d.ts +1 -0
- package/dist/lib/arkStatus.spec.js +49 -0
- package/dist/lib/chatClient.d.ts +33 -0
- package/dist/lib/chatClient.js +99 -0
- package/dist/lib/cluster.d.ts +2 -1
- package/dist/lib/cluster.js +37 -16
- package/dist/lib/cluster.spec.d.ts +1 -0
- package/dist/lib/cluster.spec.js +338 -0
- 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/commands.d.ts +16 -0
- package/dist/lib/commands.js +29 -0
- package/dist/lib/commands.spec.d.ts +1 -0
- package/dist/lib/commands.spec.js +146 -0
- package/dist/lib/config.d.ts +26 -80
- package/dist/lib/config.js +70 -205
- package/dist/lib/config.spec.d.ts +1 -0
- package/dist/lib/config.spec.js +99 -0
- package/dist/lib/config.test.d.ts +1 -0
- package/dist/lib/config.test.js +93 -0
- package/dist/lib/consts.d.ts +0 -1
- package/dist/lib/consts.js +0 -2
- package/dist/lib/consts.spec.d.ts +1 -0
- package/dist/lib/consts.spec.js +15 -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/errors.js +1 -1
- package/dist/lib/errors.spec.d.ts +1 -0
- package/dist/lib/errors.spec.js +221 -0
- package/dist/lib/exec.d.ts +0 -4
- package/dist/lib/exec.js +0 -11
- package/dist/lib/output.d.ts +36 -0
- package/dist/lib/output.js +89 -0
- package/dist/lib/output.spec.d.ts +1 -0
- package/dist/lib/output.spec.js +123 -0
- package/dist/lib/portUtils.d.ts +8 -0
- package/dist/lib/portUtils.js +39 -0
- package/dist/lib/startup.d.ts +5 -0
- package/dist/lib/startup.js +73 -0
- package/dist/lib/startup.spec.d.ts +1 -0
- package/dist/lib/startup.spec.js +168 -0
- package/dist/lib/types.d.ts +10 -3
- package/dist/types/types.d.ts +40 -0
- package/dist/types/types.js +1 -0
- package/dist/ui/AgentSelector.d.ts +8 -0
- package/dist/ui/AgentSelector.js +53 -0
- package/dist/ui/MainMenu.d.ts +5 -1
- package/dist/ui/MainMenu.js +222 -91
- package/dist/ui/ModelSelector.d.ts +8 -0
- package/dist/ui/ModelSelector.js +53 -0
- package/dist/ui/TeamSelector.d.ts +8 -0
- package/dist/ui/TeamSelector.js +55 -0
- package/dist/ui/ToolSelector.d.ts +8 -0
- package/dist/ui/ToolSelector.js +53 -0
- package/dist/ui/statusFormatter.d.ts +22 -7
- package/dist/ui/statusFormatter.js +39 -39
- package/dist/ui/statusFormatter.spec.d.ts +1 -0
- package/dist/ui/statusFormatter.spec.js +58 -0
- package/package.json +17 -5
package/dist/config.js
CHANGED
|
@@ -1,118 +1,22 @@
|
|
|
1
|
-
import { promises as fs } from 'fs';
|
|
2
|
-
import { homedir } from 'os';
|
|
3
|
-
import { join } from 'path';
|
|
4
1
|
import axios from 'axios';
|
|
5
2
|
import Debug from 'debug';
|
|
6
|
-
import {
|
|
7
|
-
import { DEFAULT_ADDRESS_ARK_API, CONFIG_DIR_NAME, CONFIG_FILE_NAME, } from './lib/consts.js';
|
|
8
|
-
import { GatewayManager } from './lib/gatewayManager.js';
|
|
3
|
+
import { DEFAULT_ADDRESS_ARK_API } from './lib/consts.js';
|
|
9
4
|
import { KubernetesConfigManager } from './lib/kubernetes.js';
|
|
5
|
+
import { getStatusCheckableServices } from './arkServices.js';
|
|
10
6
|
const debug = Debug('ark:config');
|
|
11
7
|
/**
|
|
12
|
-
* ConfigManager handles
|
|
13
|
-
*
|
|
14
|
-
* setting DEBUG=ark:config or DEBUG=ark:* environment variable.
|
|
8
|
+
* ConfigManager handles API URL discovery and cluster access testing.
|
|
9
|
+
* Complex discovery logic can be debugged by setting DEBUG=ark:config
|
|
15
10
|
*
|
|
16
11
|
* Example usage:
|
|
17
|
-
* DEBUG=ark:config ark
|
|
18
|
-
* DEBUG=ark:* ark dashboard
|
|
12
|
+
* DEBUG=ark:config ark status
|
|
19
13
|
*/
|
|
20
14
|
export class ConfigManager {
|
|
21
15
|
constructor() {
|
|
22
16
|
this.kubeConfig = null;
|
|
23
|
-
this.configDir = join(homedir(), '.config', CONFIG_DIR_NAME);
|
|
24
|
-
this.configFile = join(this.configDir, CONFIG_FILE_NAME);
|
|
25
17
|
this.kubernetesManager = new KubernetesConfigManager();
|
|
26
|
-
this.gatewayManager = new GatewayManager();
|
|
27
|
-
}
|
|
28
|
-
async ensureConfigDir() {
|
|
29
|
-
try {
|
|
30
|
-
await fs.mkdir(this.configDir, { recursive: true });
|
|
31
|
-
}
|
|
32
|
-
catch (_error) {
|
|
33
|
-
// Directory might already exist
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async loadConfig() {
|
|
37
|
-
await this.ensureConfigDir();
|
|
38
|
-
try {
|
|
39
|
-
// Check if config file exists
|
|
40
|
-
await fs.access(this.configFile);
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
// Config file doesn't exist - start with default config and enrich with kube config
|
|
44
|
-
if (error &&
|
|
45
|
-
typeof error === 'object' &&
|
|
46
|
-
'code' in error &&
|
|
47
|
-
error.code === 'ENOENT') {
|
|
48
|
-
return await this.getDefaultConfig();
|
|
49
|
-
}
|
|
50
|
-
// Other access errors (permissions, etc.) should be thrown
|
|
51
|
-
throw error;
|
|
52
|
-
}
|
|
53
|
-
try {
|
|
54
|
-
// Config file exists - try to read and parse it
|
|
55
|
-
const data = await fs.readFile(this.configFile, 'utf-8');
|
|
56
|
-
const config = JSON.parse(data);
|
|
57
|
-
// Merge with current Kubernetes config if not present
|
|
58
|
-
await this.initKubernetesConfig();
|
|
59
|
-
return {
|
|
60
|
-
...config,
|
|
61
|
-
kubeconfig: config.kubeconfig || this.kubeConfig?.kubeconfig,
|
|
62
|
-
currentContext: config.currentContext || this.kubeConfig?.currentContext,
|
|
63
|
-
kubeNamespace: config.kubeNamespace || this.kubeConfig?.namespace,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
// If it's a JSON parsing error, throw a clear error message
|
|
68
|
-
if (error instanceof SyntaxError) {
|
|
69
|
-
throw new Error(`Invalid JSON in config file ${this.configFile}: ${error.message}`);
|
|
70
|
-
}
|
|
71
|
-
// Other errors (read errors, etc.) should be thrown as-is
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
async saveConfig(config) {
|
|
76
|
-
await this.ensureConfigDir();
|
|
77
|
-
const jsonData = JSON.stringify(config, null, 2);
|
|
78
|
-
await fs.writeFile(this.configFile, jsonData);
|
|
79
|
-
}
|
|
80
|
-
async updateConfig(updates) {
|
|
81
|
-
const currentConfig = await this.loadConfig();
|
|
82
|
-
const newConfig = { ...currentConfig, ...updates };
|
|
83
|
-
await this.saveConfig(newConfig);
|
|
84
|
-
return newConfig;
|
|
85
|
-
}
|
|
86
|
-
async getDefaultConfig() {
|
|
87
|
-
// Initialize Kubernetes config to get defaults
|
|
88
|
-
await this.initKubernetesConfig();
|
|
89
|
-
return {
|
|
90
|
-
defaultAgent: 'default',
|
|
91
|
-
defaultModel: 'default',
|
|
92
|
-
defaultNamespace: this.kubeConfig?.namespace || 'default',
|
|
93
|
-
apiBaseUrl: DEFAULT_ADDRESS_ARK_API,
|
|
94
|
-
kubeconfig: this.kubeConfig?.kubeconfig,
|
|
95
|
-
currentContext: this.kubeConfig?.currentContext,
|
|
96
|
-
kubeNamespace: this.kubeConfig?.namespace,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
async initializeConfig() {
|
|
100
|
-
const config = await this.loadConfig();
|
|
101
|
-
const defaultConfig = await this.getDefaultConfig();
|
|
102
|
-
const mergedConfig = { ...defaultConfig, ...config };
|
|
103
|
-
await this.saveConfig(mergedConfig);
|
|
104
|
-
return mergedConfig;
|
|
105
|
-
}
|
|
106
|
-
getConfigPath() {
|
|
107
|
-
return this.configFile;
|
|
108
18
|
}
|
|
109
19
|
async getApiBaseUrl() {
|
|
110
|
-
const config = await this.loadConfig();
|
|
111
|
-
// If apiBaseUrl is explicitly set in config, use it
|
|
112
|
-
if (config.apiBaseUrl && config.apiBaseUrl !== DEFAULT_ADDRESS_ARK_API) {
|
|
113
|
-
debug('using explicit config apiBaseUrl: %s', config.apiBaseUrl);
|
|
114
|
-
return config.apiBaseUrl;
|
|
115
|
-
}
|
|
116
20
|
// First try to detect localhost-gateway (works for everyone with standard setup)
|
|
117
21
|
if (await this.isLocalhostGatewayRunning()) {
|
|
118
22
|
const gatewayUrls = this.getLocalhostGatewayUrls();
|
|
@@ -126,7 +30,7 @@ export class ConfigManager {
|
|
|
126
30
|
await this.initKubernetesConfig();
|
|
127
31
|
if (this.kubeConfig) {
|
|
128
32
|
try {
|
|
129
|
-
const namespace =
|
|
33
|
+
const namespace = 'default';
|
|
130
34
|
const discoveredUrl = await this.kubernetesManager.getArkApiUrl(namespace);
|
|
131
35
|
debug('kubernetes discovery successful in %s: %s', namespace, discoveredUrl);
|
|
132
36
|
return discoveredUrl;
|
|
@@ -136,9 +40,8 @@ export class ConfigManager {
|
|
|
136
40
|
// Fall back to default if discovery fails
|
|
137
41
|
}
|
|
138
42
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return fallbackUrl;
|
|
43
|
+
debug('falling back to default: %s', DEFAULT_ADDRESS_ARK_API);
|
|
44
|
+
return DEFAULT_ADDRESS_ARK_API;
|
|
142
45
|
}
|
|
143
46
|
/**
|
|
144
47
|
* Check if localhost-gateway is running by testing port 8080
|
|
@@ -163,16 +66,8 @@ export class ConfigManager {
|
|
|
163
66
|
* Construct standard localhost-gateway URLs for known ARK services
|
|
164
67
|
*/
|
|
165
68
|
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;
|
|
69
|
+
// Use centralized service definitions from arkServices
|
|
70
|
+
return getStatusCheckableServices();
|
|
176
71
|
}
|
|
177
72
|
async initKubernetesConfig() {
|
|
178
73
|
if (!this.kubeConfig) {
|
|
@@ -187,10 +82,6 @@ export class ConfigManager {
|
|
|
187
82
|
}
|
|
188
83
|
}
|
|
189
84
|
}
|
|
190
|
-
async getKubernetesConfig() {
|
|
191
|
-
await this.initKubernetesConfig();
|
|
192
|
-
return this.kubeConfig;
|
|
193
|
-
}
|
|
194
85
|
async testClusterAccess() {
|
|
195
86
|
await this.initKubernetesConfig();
|
|
196
87
|
if (!this.kubeConfig) {
|
|
@@ -198,46 +89,4 @@ export class ConfigManager {
|
|
|
198
89
|
}
|
|
199
90
|
return await this.kubernetesManager.testClusterAccess();
|
|
200
91
|
}
|
|
201
|
-
/**
|
|
202
|
-
* Discover service URLs from ark-api service discovery
|
|
203
|
-
*/
|
|
204
|
-
async discoverServicesFromApi() {
|
|
205
|
-
try {
|
|
206
|
-
const apiBaseUrl = await this.getApiBaseUrl();
|
|
207
|
-
const arkClient = new ArkClient(apiBaseUrl);
|
|
208
|
-
const config = await this.loadConfig();
|
|
209
|
-
const namespace = config.kubeNamespace || config.defaultNamespace || 'default';
|
|
210
|
-
debug('service discovery: querying ark-api at %s (namespace: %s)', apiBaseUrl, namespace);
|
|
211
|
-
const services = await arkClient.getArkServices(namespace);
|
|
212
|
-
const serviceUrls = {};
|
|
213
|
-
// Dynamically map all discovered services with HTTP routes
|
|
214
|
-
for (const service of services) {
|
|
215
|
-
if (service.httproutes && service.httproutes.length > 0) {
|
|
216
|
-
const serviceName = service.release_name || service.name;
|
|
217
|
-
const serviceUrl = service.httproutes[0].url; // Use first route URL
|
|
218
|
-
serviceUrls[serviceName] = serviceUrl;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
const discoveredServices = Object.entries(serviceUrls).map(([key, url]) => `${key}: ${url}`);
|
|
222
|
-
debug('service discovery: found %d services - %s', discoveredServices.length, discoveredServices.join(', ') || 'none');
|
|
223
|
-
return serviceUrls;
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
debug('service discovery failed: %s', error instanceof Error ? error.message : error);
|
|
227
|
-
// Return empty object if discovery fails - will fall back to config/defaults
|
|
228
|
-
return {};
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
async getServiceUrls() {
|
|
232
|
-
// Try localhost-gateway detection (works for everyone with standard setup)
|
|
233
|
-
if (await this.isLocalhostGatewayRunning()) {
|
|
234
|
-
const gatewayUrls = this.getLocalhostGatewayUrls();
|
|
235
|
-
debug('localhost-gateway detected, using: %o', gatewayUrls);
|
|
236
|
-
return gatewayUrls;
|
|
237
|
-
}
|
|
238
|
-
// Try to discover services from ark-api (requires kubeconfig)
|
|
239
|
-
const discoveredUrls = await this.discoverServicesFromApi();
|
|
240
|
-
debug('discovered services: %o', discoveredUrls);
|
|
241
|
-
return discoveredUrls;
|
|
242
|
-
}
|
|
243
92
|
}
|
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,67 +1,65 @@
|
|
|
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 { startup } from './lib/startup.js';
|
|
10
|
+
import { createAgentsCommand } from './commands/agents/index.js';
|
|
11
|
+
import { createChatCommand } from './commands/chat/index.js';
|
|
9
12
|
import { createClusterCommand } from './commands/cluster/index.js';
|
|
10
|
-
import { createCompletionCommand } from './commands/completion.js';
|
|
13
|
+
import { createCompletionCommand } from './commands/completion/index.js';
|
|
14
|
+
import { createDashboardCommand } from './commands/dashboard/index.js';
|
|
15
|
+
import { createDevCommand } from './commands/dev/index.js';
|
|
11
16
|
import { createGenerateCommand } from './commands/generate/index.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
17
|
+
import { createInstallCommand } from './commands/install/index.js';
|
|
18
|
+
import { createModelsCommand } from './commands/models/index.js';
|
|
19
|
+
import { createUninstallCommand } from './commands/uninstall/index.js';
|
|
20
|
+
import { createStatusCommand } from './commands/status/index.js';
|
|
21
|
+
import { createConfigCommand } from './commands/config/index.js';
|
|
22
|
+
import { createTargetsCommand } from './commands/targets/index.js';
|
|
23
|
+
import { createTeamsCommand } from './commands/teams/index.js';
|
|
24
|
+
import { createToolsCommand } from './commands/tools/index.js';
|
|
25
|
+
import { createRoutesCommand } from './commands/routes/index.js';
|
|
16
26
|
import MainMenu from './ui/MainMenu.js';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
render(_jsx(MainMenu, {}));
|
|
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
|
+
function showMainMenu(config) {
|
|
28
|
+
const app = render(_jsx(MainMenu, { config: config }));
|
|
29
|
+
globalThis.inkApp = app;
|
|
37
30
|
}
|
|
38
31
|
async function main() {
|
|
32
|
+
// Initialize CLI - check requirements and load config
|
|
33
|
+
const config = await startup();
|
|
39
34
|
const program = new Command();
|
|
40
35
|
program
|
|
41
36
|
.name(packageJson.name)
|
|
42
37
|
.description(packageJson.description)
|
|
43
38
|
.version(packageJson.version);
|
|
44
|
-
program.addCommand(
|
|
45
|
-
program.addCommand(
|
|
46
|
-
program.addCommand(
|
|
47
|
-
program.addCommand(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
program.addCommand(
|
|
39
|
+
program.addCommand(createAgentsCommand(config));
|
|
40
|
+
program.addCommand(createChatCommand(config));
|
|
41
|
+
program.addCommand(createClusterCommand(config));
|
|
42
|
+
program.addCommand(createCompletionCommand(config));
|
|
43
|
+
program.addCommand(createDashboardCommand(config));
|
|
44
|
+
program.addCommand(createDevCommand(config));
|
|
45
|
+
program.addCommand(createGenerateCommand(config));
|
|
46
|
+
program.addCommand(createInstallCommand(config));
|
|
47
|
+
program.addCommand(createModelsCommand(config));
|
|
48
|
+
program.addCommand(createUninstallCommand(config));
|
|
49
|
+
program.addCommand(createStatusCommand(config));
|
|
50
|
+
program.addCommand(createConfigCommand(config));
|
|
51
|
+
program.addCommand(createTargetsCommand(config));
|
|
52
|
+
program.addCommand(createTeamsCommand(config));
|
|
53
|
+
program.addCommand(createToolsCommand(config));
|
|
54
|
+
program.addCommand(createRoutesCommand(config));
|
|
56
55
|
// If no args provided, show interactive menu
|
|
57
56
|
if (process.argv.length === 2) {
|
|
58
|
-
|
|
59
|
-
showMainMenu();
|
|
57
|
+
showMainMenu(config);
|
|
60
58
|
return;
|
|
61
59
|
}
|
|
62
60
|
await program.parseAsync(process.argv);
|
|
63
61
|
}
|
|
64
62
|
main().catch((error) => {
|
|
65
|
-
|
|
63
|
+
output.error('failed to start ark cli: ', error);
|
|
66
64
|
process.exit(1);
|
|
67
65
|
});
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ArkApiClient } from './arkApiClient.js';
|
|
2
|
+
import { ArkServiceProxy } from './arkServiceProxy.js';
|
|
3
|
+
import { arkServices } from '../arkServices.js';
|
|
4
|
+
export class ArkApiProxy {
|
|
5
|
+
constructor(localPort) {
|
|
6
|
+
const arkApiService = arkServices['ark-api'];
|
|
7
|
+
this.serviceProxy = new ArkServiceProxy(arkApiService, localPort);
|
|
8
|
+
}
|
|
9
|
+
async start() {
|
|
10
|
+
const arkApiUrl = await this.serviceProxy.start();
|
|
11
|
+
return new ArkApiClient(arkApiUrl);
|
|
12
|
+
}
|
|
13
|
+
stop() {
|
|
14
|
+
this.serviceProxy.stop();
|
|
15
|
+
}
|
|
16
|
+
isRunning() {
|
|
17
|
+
return this.serviceProxy.isRunning();
|
|
18
|
+
}
|
|
19
|
+
getLocalUrl() {
|
|
20
|
+
return this.serviceProxy.getLocalUrl();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ArkService } from '../arkServices.js';
|
|
2
|
+
export declare class ArkServiceProxy {
|
|
3
|
+
private kubectlProcess?;
|
|
4
|
+
private localPort;
|
|
5
|
+
private isReady;
|
|
6
|
+
private service;
|
|
7
|
+
constructor(service: ArkService, localPort?: number);
|
|
8
|
+
private getRandomPort;
|
|
9
|
+
start(): Promise<string>;
|
|
10
|
+
stop(): void;
|
|
11
|
+
isRunning(): boolean;
|
|
12
|
+
getLocalUrl(): string;
|
|
13
|
+
getService(): ArkService;
|
|
14
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
export class ArkServiceProxy {
|
|
3
|
+
constructor(service, localPort) {
|
|
4
|
+
this.isReady = false;
|
|
5
|
+
this.service = service;
|
|
6
|
+
this.localPort =
|
|
7
|
+
localPort || service.k8sPortForwardLocalPort || this.getRandomPort();
|
|
8
|
+
}
|
|
9
|
+
getRandomPort() {
|
|
10
|
+
return Math.floor(Math.random() * (65535 - 1024) + 1024);
|
|
11
|
+
}
|
|
12
|
+
async start() {
|
|
13
|
+
if (!this.service.k8sServiceName || !this.service.k8sServicePort) {
|
|
14
|
+
throw new Error(`${this.service.name} service configuration missing k8sServiceName or k8sServicePort`);
|
|
15
|
+
}
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const args = [
|
|
18
|
+
'port-forward',
|
|
19
|
+
`service/${this.service.k8sServiceName}`,
|
|
20
|
+
`${this.localPort}:${this.service.k8sServicePort}`,
|
|
21
|
+
];
|
|
22
|
+
// Add namespace flag only if namespace is defined
|
|
23
|
+
if (this.service.namespace) {
|
|
24
|
+
args.push('--namespace', this.service.namespace);
|
|
25
|
+
}
|
|
26
|
+
this.kubectlProcess = spawn('kubectl', args, {
|
|
27
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
28
|
+
});
|
|
29
|
+
let setupComplete = false;
|
|
30
|
+
const setupTimeout = setTimeout(() => {
|
|
31
|
+
if (!setupComplete) {
|
|
32
|
+
this.stop();
|
|
33
|
+
reject(new Error(`${this.service.name} port forward setup timeout`));
|
|
34
|
+
}
|
|
35
|
+
}, 10000);
|
|
36
|
+
this.kubectlProcess.stdout?.on('data', (data) => {
|
|
37
|
+
const output = data.toString();
|
|
38
|
+
if (output.includes('Forwarding from') && !setupComplete) {
|
|
39
|
+
setupComplete = true;
|
|
40
|
+
clearTimeout(setupTimeout);
|
|
41
|
+
this.isReady = true;
|
|
42
|
+
const localUrl = `http://localhost:${this.localPort}`;
|
|
43
|
+
resolve(localUrl);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
this.kubectlProcess.stderr?.on('data', (data) => {
|
|
47
|
+
const errorOutput = data.toString();
|
|
48
|
+
if (!setupComplete) {
|
|
49
|
+
setupComplete = true;
|
|
50
|
+
clearTimeout(setupTimeout);
|
|
51
|
+
this.stop();
|
|
52
|
+
reject(new Error(`${this.service.name} port forward failed: ${errorOutput.trim()}`));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
this.kubectlProcess.on('error', (error) => {
|
|
56
|
+
if (!setupComplete) {
|
|
57
|
+
setupComplete = true;
|
|
58
|
+
clearTimeout(setupTimeout);
|
|
59
|
+
reject(new Error(`Failed to start ${this.service.name} port forward: ${error.message}`));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
this.kubectlProcess.on('exit', (code) => {
|
|
63
|
+
this.isReady = false;
|
|
64
|
+
if (!setupComplete && code !== 0) {
|
|
65
|
+
setupComplete = true;
|
|
66
|
+
clearTimeout(setupTimeout);
|
|
67
|
+
reject(new Error(`${this.service.name} port forward exited with code ${code}`));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
stop() {
|
|
73
|
+
if (this.kubectlProcess) {
|
|
74
|
+
// Use SIGTERM for graceful shutdown
|
|
75
|
+
this.kubectlProcess.kill('SIGTERM');
|
|
76
|
+
// Give it a second to clean up, then force kill if needed
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
if (this.kubectlProcess && !this.kubectlProcess.killed) {
|
|
79
|
+
this.kubectlProcess.kill('SIGKILL');
|
|
80
|
+
}
|
|
81
|
+
}, 1000);
|
|
82
|
+
this.kubectlProcess = undefined;
|
|
83
|
+
}
|
|
84
|
+
this.isReady = false;
|
|
85
|
+
}
|
|
86
|
+
isRunning() {
|
|
87
|
+
return this.isReady && this.kubectlProcess !== undefined;
|
|
88
|
+
}
|
|
89
|
+
getLocalUrl() {
|
|
90
|
+
return `http://localhost:${this.localPort}`;
|
|
91
|
+
}
|
|
92
|
+
getService() {
|
|
93
|
+
return this.service;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get current installed ARK version
|
|
3
|
+
* @returns version string if found, undefined otherwise
|
|
4
|
+
*/
|
|
5
|
+
export declare function getArkVersion(): Promise<string | undefined>;
|
|
6
|
+
/**
|
|
7
|
+
* Check if ARK is ready by verifying the ark-controller is running
|
|
8
|
+
* @returns true if ark-controller deployment exists and has ready replicas
|
|
9
|
+
*/
|
|
10
|
+
export declare function isArkReady(): Promise<boolean>;
|