@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,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,93 @@
|
|
|
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
|
+
'--namespace',
|
|
22
|
+
this.service.namespace,
|
|
23
|
+
];
|
|
24
|
+
this.kubectlProcess = spawn('kubectl', args, {
|
|
25
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
26
|
+
});
|
|
27
|
+
let setupComplete = false;
|
|
28
|
+
const setupTimeout = setTimeout(() => {
|
|
29
|
+
if (!setupComplete) {
|
|
30
|
+
this.stop();
|
|
31
|
+
reject(new Error(`${this.service.name} port forward setup timeout`));
|
|
32
|
+
}
|
|
33
|
+
}, 10000);
|
|
34
|
+
this.kubectlProcess.stdout?.on('data', (data) => {
|
|
35
|
+
const output = data.toString();
|
|
36
|
+
if (output.includes('Forwarding from') && !setupComplete) {
|
|
37
|
+
setupComplete = true;
|
|
38
|
+
clearTimeout(setupTimeout);
|
|
39
|
+
this.isReady = true;
|
|
40
|
+
const localUrl = `http://localhost:${this.localPort}`;
|
|
41
|
+
resolve(localUrl);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
this.kubectlProcess.stderr?.on('data', (data) => {
|
|
45
|
+
const errorOutput = data.toString();
|
|
46
|
+
if (!setupComplete) {
|
|
47
|
+
setupComplete = true;
|
|
48
|
+
clearTimeout(setupTimeout);
|
|
49
|
+
this.stop();
|
|
50
|
+
reject(new Error(`${this.service.name} port forward failed: ${errorOutput.trim()}`));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
this.kubectlProcess.on('error', (error) => {
|
|
54
|
+
if (!setupComplete) {
|
|
55
|
+
setupComplete = true;
|
|
56
|
+
clearTimeout(setupTimeout);
|
|
57
|
+
reject(new Error(`Failed to start ${this.service.name} port forward: ${error.message}`));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
this.kubectlProcess.on('exit', (code) => {
|
|
61
|
+
this.isReady = false;
|
|
62
|
+
if (!setupComplete && code !== 0) {
|
|
63
|
+
setupComplete = true;
|
|
64
|
+
clearTimeout(setupTimeout);
|
|
65
|
+
reject(new Error(`${this.service.name} port forward exited with code ${code}`));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
stop() {
|
|
71
|
+
if (this.kubectlProcess) {
|
|
72
|
+
// Use SIGTERM for graceful shutdown
|
|
73
|
+
this.kubectlProcess.kill('SIGTERM');
|
|
74
|
+
// Give it a second to clean up, then force kill if needed
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
if (this.kubectlProcess && !this.kubectlProcess.killed) {
|
|
77
|
+
this.kubectlProcess.kill('SIGKILL');
|
|
78
|
+
}
|
|
79
|
+
}, 1000);
|
|
80
|
+
this.kubectlProcess = undefined;
|
|
81
|
+
}
|
|
82
|
+
this.isReady = false;
|
|
83
|
+
}
|
|
84
|
+
isRunning() {
|
|
85
|
+
return this.isReady && this.kubectlProcess !== undefined;
|
|
86
|
+
}
|
|
87
|
+
getLocalUrl() {
|
|
88
|
+
return `http://localhost:${this.localPort}`;
|
|
89
|
+
}
|
|
90
|
+
getService() {
|
|
91
|
+
return this.service;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
/**
|
|
3
|
+
* Check if ARK is ready by verifying the ark-controller is running
|
|
4
|
+
* @returns true if ark-controller deployment exists and has ready replicas
|
|
5
|
+
*/
|
|
6
|
+
export async function isArkReady() {
|
|
7
|
+
try {
|
|
8
|
+
// Check if ark-controller deployment exists and get its status
|
|
9
|
+
const result = await execa('kubectl', ['get', 'deployment', 'ark-controller', '-n', 'ark-system', '-o', 'json'], { stdio: 'pipe' });
|
|
10
|
+
const deployment = JSON.parse(result.stdout);
|
|
11
|
+
const readyReplicas = deployment.status?.readyReplicas || 0;
|
|
12
|
+
const replicas = deployment.spec?.replicas || 0;
|
|
13
|
+
// ARK is ready if deployment exists and has at least one ready replica
|
|
14
|
+
return readyReplicas > 0 && readyReplicas === replicas;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Deployment doesn't exist or kubectl failed
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ArkApiClient, QueryTarget } from './arkApiClient.js';
|
|
2
|
+
export { QueryTarget };
|
|
3
|
+
export interface ChatConfig {
|
|
4
|
+
streamingEnabled: boolean;
|
|
5
|
+
currentTarget?: QueryTarget;
|
|
6
|
+
}
|
|
7
|
+
export interface ToolCall {
|
|
8
|
+
id: string;
|
|
9
|
+
type: 'function';
|
|
10
|
+
function: {
|
|
11
|
+
name: string;
|
|
12
|
+
arguments: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface ArkMetadata {
|
|
16
|
+
agent?: string;
|
|
17
|
+
team?: string;
|
|
18
|
+
model?: string;
|
|
19
|
+
query?: string;
|
|
20
|
+
target?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class ChatClient {
|
|
23
|
+
private arkApiClient;
|
|
24
|
+
constructor(arkApiClient: ArkApiClient);
|
|
25
|
+
getQueryTargets(): Promise<QueryTarget[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Send a chat completion request
|
|
28
|
+
*/
|
|
29
|
+
sendMessage(targetId: string, messages: Array<{
|
|
30
|
+
role: 'user' | 'assistant' | 'system';
|
|
31
|
+
content: string;
|
|
32
|
+
}>, config: ChatConfig, onChunk?: (chunk: string, toolCalls?: ToolCall[], arkMetadata?: ArkMetadata) => void, signal?: AbortSignal): Promise<string>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import output from './output.js';
|
|
2
|
+
export class ChatClient {
|
|
3
|
+
constructor(arkApiClient) {
|
|
4
|
+
this.arkApiClient = arkApiClient;
|
|
5
|
+
}
|
|
6
|
+
async getQueryTargets() {
|
|
7
|
+
return await this.arkApiClient.getQueryTargets();
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Send a chat completion request
|
|
11
|
+
*/
|
|
12
|
+
async sendMessage(targetId, messages, config, onChunk, signal) {
|
|
13
|
+
const shouldStream = config.streamingEnabled && !!onChunk;
|
|
14
|
+
try {
|
|
15
|
+
const params = {
|
|
16
|
+
model: targetId,
|
|
17
|
+
messages: messages,
|
|
18
|
+
signal: signal,
|
|
19
|
+
};
|
|
20
|
+
if (shouldStream) {
|
|
21
|
+
let fullResponse = '';
|
|
22
|
+
const toolCallsById = new Map();
|
|
23
|
+
const stream = this.arkApiClient.createChatCompletionStream(params);
|
|
24
|
+
for await (const chunk of stream) {
|
|
25
|
+
if (signal?.aborted) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
const delta = chunk.choices[0]?.delta;
|
|
29
|
+
// Extract ARK metadata if present
|
|
30
|
+
const arkMetadata = chunk.ark;
|
|
31
|
+
// Handle regular content
|
|
32
|
+
const content = delta?.content || '';
|
|
33
|
+
if (content) {
|
|
34
|
+
fullResponse += content;
|
|
35
|
+
if (onChunk) {
|
|
36
|
+
onChunk(content, undefined, arkMetadata);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Handle tool calls
|
|
40
|
+
if (delta?.tool_calls) {
|
|
41
|
+
for (const toolCallDelta of delta.tool_calls) {
|
|
42
|
+
const index = toolCallDelta.index;
|
|
43
|
+
// Initialize tool call if this is the first chunk for this index
|
|
44
|
+
if (!toolCallsById.has(index)) {
|
|
45
|
+
toolCallsById.set(index, {
|
|
46
|
+
id: toolCallDelta.id || '',
|
|
47
|
+
type: toolCallDelta.type || 'function',
|
|
48
|
+
function: {
|
|
49
|
+
name: toolCallDelta.function?.name || '',
|
|
50
|
+
arguments: '',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
// Accumulate function arguments
|
|
55
|
+
const toolCall = toolCallsById.get(index);
|
|
56
|
+
if (toolCallDelta.function?.arguments) {
|
|
57
|
+
toolCall.function.arguments += toolCallDelta.function.arguments;
|
|
58
|
+
}
|
|
59
|
+
// Send the current state of all tool calls
|
|
60
|
+
if (onChunk) {
|
|
61
|
+
const toolCallsArray = Array.from(toolCallsById.values());
|
|
62
|
+
onChunk('', toolCallsArray, arkMetadata);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return fullResponse;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const response = await this.arkApiClient.createChatCompletion(params);
|
|
71
|
+
const message = response.choices[0]?.message;
|
|
72
|
+
const content = message?.content || '';
|
|
73
|
+
// Handle tool calls in non-streaming mode
|
|
74
|
+
if (message?.tool_calls && message.tool_calls.length > 0) {
|
|
75
|
+
const toolCalls = message.tool_calls.map((tc) => ({
|
|
76
|
+
id: tc.id,
|
|
77
|
+
type: tc.type || 'function',
|
|
78
|
+
function: {
|
|
79
|
+
name: tc.function?.name || '',
|
|
80
|
+
arguments: tc.function?.arguments || '',
|
|
81
|
+
},
|
|
82
|
+
}));
|
|
83
|
+
// Send tool calls first
|
|
84
|
+
if (onChunk) {
|
|
85
|
+
onChunk('', toolCalls);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Send content after tool calls
|
|
89
|
+
if (content && onChunk) {
|
|
90
|
+
onChunk(content);
|
|
91
|
+
}
|
|
92
|
+
return content;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
97
|
+
output.error('failed to call openai api:', errorMessage);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
package/dist/lib/cluster.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ export interface ClusterInfo {
|
|
|
2
2
|
type: 'minikube' | 'kind' | 'k3s' | 'docker-desktop' | 'cloud' | 'unknown';
|
|
3
3
|
ip?: string;
|
|
4
4
|
context?: string;
|
|
5
|
+
namespace?: string;
|
|
5
6
|
error?: string;
|
|
6
7
|
}
|
|
7
8
|
export declare function detectClusterType(): Promise<ClusterInfo>;
|
|
8
|
-
export declare function
|
|
9
|
+
export declare function getClusterInfo(context?: string): Promise<ClusterInfo>;
|
package/dist/lib/cluster.js
CHANGED
|
@@ -28,12 +28,33 @@ export async function detectClusterType() {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
catch (error) {
|
|
31
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
type: 'unknown',
|
|
33
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
34
|
+
};
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
|
-
export async function
|
|
37
|
+
export async function getClusterInfo(context) {
|
|
35
38
|
try {
|
|
39
|
+
// If context is provided, use it
|
|
40
|
+
const contextArgs = context ? ['--context', context] : [];
|
|
41
|
+
// Get all config info in one command
|
|
42
|
+
const { stdout: configJson } = await executeCommand('kubectl', [
|
|
43
|
+
'config',
|
|
44
|
+
'view',
|
|
45
|
+
'--minify',
|
|
46
|
+
'-o',
|
|
47
|
+
'json',
|
|
48
|
+
...contextArgs,
|
|
49
|
+
]);
|
|
50
|
+
const config = JSON.parse(configJson);
|
|
51
|
+
const currentContext = config['current-context'] || '';
|
|
52
|
+
const contextData = config.contexts?.find((c) => c.name === currentContext);
|
|
53
|
+
const namespace = contextData?.context?.namespace || 'default';
|
|
54
|
+
// Detect cluster type from context name
|
|
36
55
|
const clusterInfo = await detectClusterType();
|
|
56
|
+
clusterInfo.context = currentContext;
|
|
57
|
+
clusterInfo.namespace = namespace;
|
|
37
58
|
if (clusterInfo.error) {
|
|
38
59
|
return clusterInfo;
|
|
39
60
|
}
|
|
@@ -129,6 +150,9 @@ export async function getClusterIp(_context) {
|
|
|
129
150
|
return { ...clusterInfo, ip };
|
|
130
151
|
}
|
|
131
152
|
catch (error) {
|
|
132
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
type: 'unknown',
|
|
155
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
156
|
+
};
|
|
133
157
|
}
|
|
134
158
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
const execAsync = promisify(exec);
|
|
4
|
+
/**
|
|
5
|
+
* Check if a command is available in the system
|
|
6
|
+
*/
|
|
7
|
+
export async function isCommandAvailable(command) {
|
|
8
|
+
try {
|
|
9
|
+
const checkCommand = process.platform === 'win32'
|
|
10
|
+
? `where ${command}`
|
|
11
|
+
: `command -v ${command}`;
|
|
12
|
+
await execAsync(checkCommand);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
catch (_error) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { isCommandAvailable } from './commandUtils';
|
|
3
|
+
jest.mock('child_process');
|
|
4
|
+
describe('commandUtils', () => {
|
|
5
|
+
describe('isCommandAvailable', () => {
|
|
6
|
+
const mockedExec = exec;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
jest.clearAllMocks();
|
|
9
|
+
});
|
|
10
|
+
it('should return true when command exists on unix', async () => {
|
|
11
|
+
const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
12
|
+
Object.defineProperty(process, 'platform', { value: 'darwin' });
|
|
13
|
+
mockedExec.mockImplementation((cmd, callback) => {
|
|
14
|
+
callback(null, '/usr/local/bin/helm', '');
|
|
15
|
+
});
|
|
16
|
+
const result = await isCommandAvailable('helm');
|
|
17
|
+
expect(result).toBe(true);
|
|
18
|
+
expect(mockedExec).toHaveBeenCalledWith('command -v helm', expect.any(Function));
|
|
19
|
+
if (originalPlatform) {
|
|
20
|
+
Object.defineProperty(process, 'platform', originalPlatform);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
it('should return true when command exists on windows', async () => {
|
|
24
|
+
const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
25
|
+
Object.defineProperty(process, 'platform', { value: 'win32' });
|
|
26
|
+
mockedExec.mockImplementation((cmd, callback) => {
|
|
27
|
+
callback(null, 'C:\\Program Files\\helm\\helm.exe', '');
|
|
28
|
+
});
|
|
29
|
+
const result = await isCommandAvailable('helm');
|
|
30
|
+
expect(result).toBe(true);
|
|
31
|
+
expect(mockedExec).toHaveBeenCalledWith('where helm', expect.any(Function));
|
|
32
|
+
if (originalPlatform) {
|
|
33
|
+
Object.defineProperty(process, 'platform', originalPlatform);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
it('should return false when command does not exist', async () => {
|
|
37
|
+
mockedExec.mockImplementation((cmd, callback) => {
|
|
38
|
+
callback(new Error('command not found'), null, 'command not found');
|
|
39
|
+
});
|
|
40
|
+
const result = await isCommandAvailable('nonexistent');
|
|
41
|
+
expect(result).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
});
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,82 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export interface ArkConfig {
|
|
5
|
-
defaultProjectType: 'empty' | 'with-samples';
|
|
6
|
-
defaultDestination: string;
|
|
7
|
-
skipGitByDefault: boolean;
|
|
8
|
-
skipModelsbyDefault: boolean;
|
|
9
|
-
preferredEditor: string;
|
|
10
|
-
colorOutput: boolean;
|
|
11
|
-
verboseOutput: boolean;
|
|
12
|
-
defaultModelProvider: 'azure' | 'openai' | 'claude' | 'gemini' | 'custom';
|
|
13
|
-
templateDirectory?: string;
|
|
14
|
-
customTemplates: Record<string, string>;
|
|
15
|
-
parallelOperations: boolean;
|
|
16
|
-
maxConcurrentFiles: number;
|
|
17
|
-
fileWatchingEnabled: boolean;
|
|
18
|
-
telemetryEnabled: boolean;
|
|
19
|
-
errorReporting: boolean;
|
|
1
|
+
export interface ChatConfig {
|
|
2
|
+
streaming?: boolean;
|
|
3
|
+
outputFormat?: 'text' | 'markdown';
|
|
20
4
|
}
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
private configPath;
|
|
24
|
-
private config;
|
|
25
|
-
constructor();
|
|
26
|
-
/**
|
|
27
|
-
* Get the path to the configuration file
|
|
28
|
-
*/
|
|
29
|
-
private getConfigPath;
|
|
30
|
-
/**
|
|
31
|
-
* Load configuration from file or create with defaults
|
|
32
|
-
*/
|
|
33
|
-
private loadConfig;
|
|
34
|
-
/**
|
|
35
|
-
* Save configuration to file
|
|
36
|
-
*/
|
|
37
|
-
private saveConfig;
|
|
38
|
-
/**
|
|
39
|
-
* Get the current configuration
|
|
40
|
-
*/
|
|
41
|
-
getConfig(): ArkConfig;
|
|
42
|
-
/**
|
|
43
|
-
* Update configuration
|
|
44
|
-
*/
|
|
45
|
-
updateConfig(updates: Partial<ArkConfig>): void;
|
|
46
|
-
/**
|
|
47
|
-
* Reset configuration to defaults
|
|
48
|
-
*/
|
|
49
|
-
resetConfig(): void;
|
|
50
|
-
/**
|
|
51
|
-
* Get a specific configuration value
|
|
52
|
-
*/
|
|
53
|
-
get<K extends keyof ArkConfig>(key: K): ArkConfig[K];
|
|
54
|
-
/**
|
|
55
|
-
* Set a specific configuration value
|
|
56
|
-
*/
|
|
57
|
-
set<K extends keyof ArkConfig>(key: K, value: ArkConfig[K]): void;
|
|
58
|
-
/**
|
|
59
|
-
* Validate configuration values
|
|
60
|
-
*/
|
|
61
|
-
validateConfig(): void;
|
|
62
|
-
/**
|
|
63
|
-
* Get environment variable overrides
|
|
64
|
-
*/
|
|
65
|
-
getEnvironmentOverrides(): Partial<ArkConfig>;
|
|
66
|
-
/**
|
|
67
|
-
* Get merged configuration with environment overrides
|
|
68
|
-
*/
|
|
69
|
-
getMergedConfig(): ArkConfig;
|
|
70
|
-
/**
|
|
71
|
-
* Export configuration for backup
|
|
72
|
-
*/
|
|
73
|
-
exportConfig(): string;
|
|
74
|
-
/**
|
|
75
|
-
* Import configuration from backup
|
|
76
|
-
*/
|
|
77
|
-
importConfig(configJson: string): void;
|
|
78
|
-
/**
|
|
79
|
-
* Get configuration file path for CLI display
|
|
80
|
-
*/
|
|
81
|
-
getConfigFilePath(): string;
|
|
5
|
+
export interface ArkConfig {
|
|
6
|
+
chat?: ChatConfig;
|
|
82
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Load configuration from multiple sources with proper precedence:
|
|
10
|
+
* 1. Defaults
|
|
11
|
+
* 2. ~/.arkrc.yaml (user config)
|
|
12
|
+
* 3. .arkrc.yaml (project config)
|
|
13
|
+
* 4. Environment variables (override all)
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadConfig(): ArkConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Get the paths checked for config files
|
|
18
|
+
*/
|
|
19
|
+
export declare function getConfigPaths(): {
|
|
20
|
+
user: string;
|
|
21
|
+
project: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Format config as YAML for display
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatConfig(config: ArkConfig): string;
|