@agents-at-scale/ark 0.1.35-rc.1 → 0.1.35-rc2
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 +4 -12
- package/dist/arkServices.js +19 -34
- package/dist/arkServices.spec.d.ts +1 -0
- package/dist/arkServices.spec.js +24 -0
- package/dist/commands/agents/index.d.ts +2 -1
- package/dist/commands/agents/index.js +2 -7
- package/dist/commands/agents/index.spec.d.ts +1 -0
- package/dist/commands/agents/index.spec.js +67 -0
- package/dist/commands/chat/index.d.ts +2 -1
- package/dist/commands/chat/index.js +5 -21
- 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 +1 -1
- 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 +2 -1
- package/dist/commands/completion/index.js +24 -2
- package/dist/commands/completion/index.spec.d.ts +1 -0
- package/dist/commands/completion/index.spec.js +34 -0
- package/dist/commands/config/index.d.ts +2 -1
- package/dist/commands/config/index.js +2 -2
- package/dist/commands/config/index.spec.d.ts +1 -0
- package/dist/commands/config/index.spec.js +78 -0
- package/dist/commands/dashboard/index.d.ts +2 -1
- package/dist/commands/dashboard/index.js +1 -1
- package/dist/commands/dev/index.d.ts +2 -1
- package/dist/commands/dev/index.js +1 -1
- 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.spec.d.ts +1 -0
- package/dist/commands/dev/tool.spec.js +48 -0
- package/dist/commands/docs/index.d.ts +4 -0
- package/dist/commands/docs/index.js +18 -0
- 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 +4 -2
- package/dist/commands/install/index.js +225 -90
- package/dist/commands/install/index.spec.d.ts +1 -0
- package/dist/commands/install/index.spec.js +143 -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 +2 -1
- package/dist/commands/models/index.js +2 -7
- package/dist/commands/models/index.spec.d.ts +1 -0
- package/dist/commands/models/index.spec.js +76 -0
- package/dist/commands/query/index.d.ts +3 -0
- package/dist/commands/query/index.js +131 -0
- package/dist/commands/routes/index.d.ts +2 -1
- package/dist/commands/routes/index.js +1 -9
- package/dist/commands/status/index.d.ts +3 -2
- package/dist/commands/status/index.js +240 -11
- package/dist/commands/targets/index.d.ts +2 -1
- package/dist/commands/targets/index.js +1 -1
- package/dist/commands/targets/index.spec.d.ts +1 -0
- package/dist/commands/targets/index.spec.js +105 -0
- package/dist/commands/teams/index.d.ts +2 -1
- package/dist/commands/teams/index.js +2 -7
- package/dist/commands/teams/index.spec.d.ts +1 -0
- package/dist/commands/teams/index.spec.js +70 -0
- package/dist/commands/tools/index.d.ts +2 -1
- package/dist/commands/tools/index.js +2 -7
- package/dist/commands/tools/index.spec.d.ts +1 -0
- package/dist/commands/tools/index.spec.js +70 -0
- package/dist/commands/uninstall/index.d.ts +2 -1
- package/dist/commands/uninstall/index.js +66 -44
- package/dist/commands/uninstall/index.spec.d.ts +1 -0
- package/dist/commands/uninstall/index.spec.js +125 -0
- package/dist/components/ChatUI.js +4 -4
- package/dist/components/statusChecker.d.ts +5 -12
- package/dist/components/statusChecker.js +193 -90
- package/dist/config.d.ts +3 -22
- package/dist/config.js +7 -151
- package/dist/index.js +26 -19
- package/dist/lib/arkServiceProxy.js +4 -2
- package/dist/lib/arkStatus.d.ts +5 -0
- package/dist/lib/arkStatus.js +61 -2
- package/dist/lib/arkStatus.spec.d.ts +1 -0
- package/dist/lib/arkStatus.spec.js +49 -0
- package/dist/lib/chatClient.js +1 -3
- package/dist/lib/cluster.js +11 -14
- package/dist/lib/cluster.spec.d.ts +1 -0
- package/dist/lib/cluster.spec.js +338 -0
- package/dist/lib/commandUtils.js +7 -7
- 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 +4 -0
- package/dist/lib/config.js +6 -4
- package/dist/lib/config.spec.d.ts +1 -0
- package/dist/lib/config.spec.js +99 -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/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/nextSteps.d.ts +4 -0
- package/dist/lib/nextSteps.js +20 -0
- package/dist/lib/nextSteps.spec.d.ts +1 -0
- package/dist/lib/nextSteps.spec.js +59 -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 +9 -0
- package/dist/lib/startup.js +93 -0
- package/dist/lib/startup.spec.d.ts +1 -0
- package/dist/lib/startup.spec.js +168 -0
- package/dist/lib/types.d.ts +9 -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 +117 -54
- 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 -10
- package/dist/ui/statusFormatter.js +37 -109
- package/dist/ui/statusFormatter.spec.d.ts +1 -0
- package/dist/ui/statusFormatter.spec.js +58 -0
- package/package.json +3 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Model, ArkApiClient } from '../lib/arkApiClient.js';
|
|
2
|
+
interface ModelSelectorProps {
|
|
3
|
+
arkApiClient: ArkApiClient;
|
|
4
|
+
onSelect: (model: Model) => void;
|
|
5
|
+
onExit: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function ModelSelector({ arkApiClient, onSelect, onExit, }: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
export function ModelSelector({ arkApiClient, onSelect, onExit, }) {
|
|
5
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6
|
+
const [models, setModels] = useState([]);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
arkApiClient
|
|
11
|
+
.getModels()
|
|
12
|
+
.then((fetchedModels) => {
|
|
13
|
+
setModels(fetchedModels);
|
|
14
|
+
setLoading(false);
|
|
15
|
+
})
|
|
16
|
+
.catch((err) => {
|
|
17
|
+
setError(err.message || 'Failed to fetch models');
|
|
18
|
+
setLoading(false);
|
|
19
|
+
});
|
|
20
|
+
}, [arkApiClient]);
|
|
21
|
+
useInput((input, key) => {
|
|
22
|
+
if (key.escape) {
|
|
23
|
+
onExit();
|
|
24
|
+
}
|
|
25
|
+
else if (key.upArrow || input === 'k') {
|
|
26
|
+
setSelectedIndex((prev) => (prev === 0 ? models.length - 1 : prev - 1));
|
|
27
|
+
}
|
|
28
|
+
else if (key.downArrow || input === 'j') {
|
|
29
|
+
setSelectedIndex((prev) => (prev === models.length - 1 ? 0 : prev + 1));
|
|
30
|
+
}
|
|
31
|
+
else if (key.return) {
|
|
32
|
+
onSelect(models[selectedIndex]);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Handle number keys for quick selection
|
|
36
|
+
const num = parseInt(input, 10);
|
|
37
|
+
if (!isNaN(num) && num >= 1 && num <= models.length) {
|
|
38
|
+
onSelect(models[num - 1]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (loading) {
|
|
43
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "Loading models..." }) }));
|
|
44
|
+
}
|
|
45
|
+
if (error) {
|
|
46
|
+
return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
|
|
47
|
+
}
|
|
48
|
+
if (models.length === 0) {
|
|
49
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "No models available" }) }));
|
|
50
|
+
}
|
|
51
|
+
const selectedModel = models[selectedIndex];
|
|
52
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Model" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a model to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: models.map((model, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", model.name, model.type ? ` (${model.type})` : ''] }) }, model.name))) }), selectedModel && selectedModel.model && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsxs(Text, { dimColor: true, wrap: "wrap", children: ["Model: ", selectedModel.model] }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Team, ArkApiClient } from '../lib/arkApiClient.js';
|
|
2
|
+
interface TeamSelectorProps {
|
|
3
|
+
arkApiClient: ArkApiClient;
|
|
4
|
+
onSelect: (team: Team) => void;
|
|
5
|
+
onExit: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function TeamSelector({ arkApiClient, onSelect, onExit, }: TeamSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
export function TeamSelector({ arkApiClient, onSelect, onExit, }) {
|
|
5
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6
|
+
const [teams, setTeams] = useState([]);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
arkApiClient
|
|
11
|
+
.getTeams()
|
|
12
|
+
.then((fetchedTeams) => {
|
|
13
|
+
setTeams(fetchedTeams);
|
|
14
|
+
setLoading(false);
|
|
15
|
+
})
|
|
16
|
+
.catch((err) => {
|
|
17
|
+
setError(err.message || 'Failed to fetch teams');
|
|
18
|
+
setLoading(false);
|
|
19
|
+
});
|
|
20
|
+
}, [arkApiClient]);
|
|
21
|
+
useInput((input, key) => {
|
|
22
|
+
if (key.escape) {
|
|
23
|
+
onExit();
|
|
24
|
+
}
|
|
25
|
+
else if (key.upArrow || input === 'k') {
|
|
26
|
+
setSelectedIndex((prev) => (prev === 0 ? teams.length - 1 : prev - 1));
|
|
27
|
+
}
|
|
28
|
+
else if (key.downArrow || input === 'j') {
|
|
29
|
+
setSelectedIndex((prev) => (prev === teams.length - 1 ? 0 : prev + 1));
|
|
30
|
+
}
|
|
31
|
+
else if (key.return) {
|
|
32
|
+
onSelect(teams[selectedIndex]);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Handle number keys for quick selection
|
|
36
|
+
const num = parseInt(input, 10);
|
|
37
|
+
if (!isNaN(num) && num >= 1 && num <= teams.length) {
|
|
38
|
+
onSelect(teams[num - 1]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (loading) {
|
|
43
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "Loading teams..." }) }));
|
|
44
|
+
}
|
|
45
|
+
if (error) {
|
|
46
|
+
return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
|
|
47
|
+
}
|
|
48
|
+
if (teams.length === 0) {
|
|
49
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "No teams available" }) }));
|
|
50
|
+
}
|
|
51
|
+
const selectedTeam = teams[selectedIndex];
|
|
52
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Team" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a team to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: teams.map((team, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", team.name, team.strategy ? ` (${team.strategy})` : ''] }) }, team.name))) }), selectedTeam &&
|
|
53
|
+
(selectedTeam.description || selectedTeam.members_count) && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: selectedTeam.description ||
|
|
54
|
+
`Members: ${selectedTeam.members_count}` }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
|
|
55
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Tool, ArkApiClient } from '../lib/arkApiClient.js';
|
|
2
|
+
interface ToolSelectorProps {
|
|
3
|
+
arkApiClient: ArkApiClient;
|
|
4
|
+
onSelect: (tool: Tool) => void;
|
|
5
|
+
onExit: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function ToolSelector({ arkApiClient, onSelect, onExit, }: ToolSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
export function ToolSelector({ arkApiClient, onSelect, onExit, }) {
|
|
5
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
6
|
+
const [tools, setTools] = useState([]);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
arkApiClient
|
|
11
|
+
.getTools()
|
|
12
|
+
.then((fetchedTools) => {
|
|
13
|
+
setTools(fetchedTools);
|
|
14
|
+
setLoading(false);
|
|
15
|
+
})
|
|
16
|
+
.catch((err) => {
|
|
17
|
+
setError(err.message || 'Failed to fetch tools');
|
|
18
|
+
setLoading(false);
|
|
19
|
+
});
|
|
20
|
+
}, [arkApiClient]);
|
|
21
|
+
useInput((input, key) => {
|
|
22
|
+
if (key.escape) {
|
|
23
|
+
onExit();
|
|
24
|
+
}
|
|
25
|
+
else if (key.upArrow || input === 'k') {
|
|
26
|
+
setSelectedIndex((prev) => (prev === 0 ? tools.length - 1 : prev - 1));
|
|
27
|
+
}
|
|
28
|
+
else if (key.downArrow || input === 'j') {
|
|
29
|
+
setSelectedIndex((prev) => (prev === tools.length - 1 ? 0 : prev + 1));
|
|
30
|
+
}
|
|
31
|
+
else if (key.return) {
|
|
32
|
+
onSelect(tools[selectedIndex]);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Handle number keys for quick selection
|
|
36
|
+
const num = parseInt(input, 10);
|
|
37
|
+
if (!isNaN(num) && num >= 1 && num <= tools.length) {
|
|
38
|
+
onSelect(tools[num - 1]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (loading) {
|
|
43
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "Loading tools..." }) }));
|
|
44
|
+
}
|
|
45
|
+
if (error) {
|
|
46
|
+
return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
|
|
47
|
+
}
|
|
48
|
+
if (tools.length === 0) {
|
|
49
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "No tools available" }) }));
|
|
50
|
+
}
|
|
51
|
+
const selectedTool = tools[selectedIndex];
|
|
52
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Tool" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a tool to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: tools.map((tool, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", tool.name] }) }, tool.name))) }), selectedTool && selectedTool.description && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: selectedTool.description }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
|
|
53
|
+
}
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
export type StatusColor = 'green' | 'red' | 'yellow' | 'gray' | 'white' | 'cyan' | 'bold';
|
|
2
|
+
export interface StatusLine {
|
|
3
|
+
icon: string;
|
|
4
|
+
iconColor?: StatusColor;
|
|
5
|
+
status: string;
|
|
6
|
+
statusColor?: StatusColor;
|
|
7
|
+
name: string;
|
|
8
|
+
nameColor?: StatusColor;
|
|
9
|
+
details?: string;
|
|
10
|
+
subtext?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface StatusSection {
|
|
13
|
+
title: string;
|
|
14
|
+
lines: StatusLine[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Simple status formatter that just formats sections and lines
|
|
18
|
+
* The caller is responsible for deciding what to show
|
|
19
|
+
*/
|
|
2
20
|
export declare class StatusFormatter {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
static printStatus(statusData: StatusData & {
|
|
7
|
-
clusterAccess?: boolean;
|
|
8
|
-
clusterInfo?: any;
|
|
9
|
-
}): void;
|
|
10
|
-
private static printService;
|
|
11
|
-
private static printDependency;
|
|
21
|
+
static printSections(sections: StatusSection[]): void;
|
|
22
|
+
private static applyColor;
|
|
23
|
+
private static printLine;
|
|
12
24
|
}
|
|
@@ -1,119 +1,47 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
/**
|
|
3
|
+
* Simple status formatter that just formats sections and lines
|
|
4
|
+
* The caller is responsible for deciding what to show
|
|
5
|
+
*/
|
|
2
6
|
export class StatusFormatter {
|
|
3
|
-
|
|
4
|
-
* Print status check results to console
|
|
5
|
-
*/
|
|
6
|
-
static printStatus(statusData) {
|
|
7
|
+
static printSections(sections) {
|
|
7
8
|
console.log();
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// Print cluster status
|
|
14
|
-
console.log(chalk.cyan.bold('\ncluster access:'));
|
|
15
|
-
if (statusData.clusterAccess && statusData.clusterInfo) {
|
|
16
|
-
const clusterName = statusData.clusterInfo.context || 'kubernetes cluster';
|
|
17
|
-
const clusterDetails = [];
|
|
18
|
-
if (statusData.clusterInfo.type &&
|
|
19
|
-
statusData.clusterInfo.type !== 'unknown') {
|
|
20
|
-
clusterDetails.push(statusData.clusterInfo.type);
|
|
21
|
-
}
|
|
22
|
-
if (statusData.clusterInfo.ip) {
|
|
23
|
-
clusterDetails.push(statusData.clusterInfo.ip);
|
|
24
|
-
}
|
|
25
|
-
console.log(` ${chalk.green('✓ accessible')} ${chalk.bold.white(clusterName)}${clusterDetails.length > 0 ? chalk.gray(' ' + clusterDetails.join(', ')) : ''}`);
|
|
26
|
-
}
|
|
27
|
-
else if (statusData.clusterAccess) {
|
|
28
|
-
console.log(` ${chalk.green('✓ accessible')} ${chalk.bold('kubernetes cluster')}`);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
console.log(` ${chalk.red('✗ unreachable')} ${chalk.bold('kubernetes cluster')}`);
|
|
32
|
-
console.log(` ${chalk.gray('Install minikube: https://minikube.sigs.k8s.io/docs/start')}`);
|
|
33
|
-
}
|
|
34
|
-
// Only show ARK services if we have cluster access
|
|
35
|
-
if (statusData.clusterAccess) {
|
|
36
|
-
console.log(chalk.cyan.bold('\nark services:'));
|
|
37
|
-
// Show all services except ark-controller (already shown in ark status)
|
|
38
|
-
for (const service of statusData.services) {
|
|
39
|
-
if (service.name !== 'ark-controller') {
|
|
40
|
-
StatusFormatter.printService(service);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
console.log(chalk.cyan.bold('\nark services:'));
|
|
46
|
-
console.log(` ${chalk.gray('Cannot check ARK services - cluster not accessible')}`);
|
|
47
|
-
}
|
|
48
|
-
// Print ARK status section
|
|
49
|
-
console.log(chalk.cyan.bold('\nark status:'));
|
|
50
|
-
if (!statusData.clusterAccess) {
|
|
51
|
-
console.log(` ${chalk.red('✗ no cluster access')}`);
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
// Show ark-controller status
|
|
55
|
-
const controllerStatus = statusData.services?.find(s => s.name === 'ark-controller');
|
|
56
|
-
if (controllerStatus) {
|
|
57
|
-
// Show the actual status but replace "not installed" with "not ready" for display
|
|
58
|
-
if (controllerStatus.status === 'not installed') {
|
|
59
|
-
console.log(` ${chalk.yellow('○ not ready')} ${chalk.bold('ark-controller')} ${chalk.gray(controllerStatus.details || '')}`);
|
|
60
|
-
}
|
|
61
|
-
else if (controllerStatus.status === 'healthy') {
|
|
62
|
-
// Controller is healthy - show ready status with model info
|
|
63
|
-
if (!statusData.defaultModelExists) {
|
|
64
|
-
console.log(` ${chalk.green('✓ ready')} ${chalk.bold('ark-controller')} ${chalk.gray(controllerStatus.details || '')}`);
|
|
65
|
-
console.log(` ${chalk.gray(' (no default model configured)')}`);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
console.log(` ${chalk.green('✓ ready')} ${chalk.bold('ark-controller')} ${chalk.gray(controllerStatus.details || '')}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
StatusFormatter.printService(controllerStatus);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
console.log(` ${chalk.yellow('○ not ready')} ${chalk.bold('ark-controller')}`);
|
|
9
|
+
sections.forEach((section, index) => {
|
|
10
|
+
console.log(chalk.cyan.bold(section.title));
|
|
11
|
+
section.lines.forEach((line) => this.printLine(line));
|
|
12
|
+
if (index < sections.length - 1) {
|
|
13
|
+
console.log();
|
|
77
14
|
}
|
|
78
|
-
}
|
|
15
|
+
});
|
|
79
16
|
console.log();
|
|
80
17
|
}
|
|
81
|
-
static
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const parts = [];
|
|
95
|
-
if (service.version)
|
|
96
|
-
parts.push(`v${service.version}`);
|
|
97
|
-
if (service.revision)
|
|
98
|
-
parts.push(`revision ${service.revision}`);
|
|
99
|
-
versionInfo = chalk.gray(` ${parts.join(', ')}`);
|
|
100
|
-
}
|
|
101
|
-
// Show details inline in grey for all statuses
|
|
102
|
-
let inlineDetails = '';
|
|
103
|
-
if (service.details) {
|
|
104
|
-
inlineDetails = chalk.gray(` ${service.details}`);
|
|
105
|
-
}
|
|
106
|
-
console.log(` ${statusColor} ${chalk.bold(service.name)}${versionInfo}${inlineDetails}`);
|
|
18
|
+
static applyColor(text, color) {
|
|
19
|
+
if (!color)
|
|
20
|
+
return text;
|
|
21
|
+
const colorMap = {
|
|
22
|
+
green: chalk.green,
|
|
23
|
+
red: chalk.red,
|
|
24
|
+
yellow: chalk.yellow,
|
|
25
|
+
gray: chalk.gray,
|
|
26
|
+
white: chalk.white,
|
|
27
|
+
cyan: chalk.cyan,
|
|
28
|
+
bold: chalk.bold,
|
|
29
|
+
};
|
|
30
|
+
return colorMap[color](text);
|
|
107
31
|
}
|
|
108
|
-
static
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
32
|
+
static printLine(line) {
|
|
33
|
+
const icon = this.applyColor(line.icon, line.iconColor);
|
|
34
|
+
const status = this.applyColor(line.status, line.statusColor);
|
|
35
|
+
// Name formatting is now handled where the name is assembled
|
|
36
|
+
const name = this.applyColor(line.name, line.nameColor || 'white');
|
|
37
|
+
const parts = [
|
|
38
|
+
` ${icon} ${status}`,
|
|
39
|
+
name,
|
|
40
|
+
line.details ? chalk.gray(line.details) : '',
|
|
41
|
+
].filter(Boolean);
|
|
42
|
+
console.log(parts.join(' '));
|
|
43
|
+
if (line.subtext) {
|
|
44
|
+
console.log(` ${chalk.gray(line.subtext)}`);
|
|
117
45
|
}
|
|
118
46
|
}
|
|
119
47
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, jest, beforeEach, afterEach } from '@jest/globals';
|
|
2
|
+
import { StatusFormatter } from './statusFormatter.js';
|
|
3
|
+
describe('StatusFormatter', () => {
|
|
4
|
+
let consoleLogSpy;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
7
|
+
});
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
jest.restoreAllMocks();
|
|
10
|
+
});
|
|
11
|
+
it('prints sections', () => {
|
|
12
|
+
const sections = [
|
|
13
|
+
{
|
|
14
|
+
title: 'Test Section',
|
|
15
|
+
lines: [{ icon: '✓', status: 'ok', name: 'test' }],
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
StatusFormatter.printSections(sections);
|
|
19
|
+
expect(consoleLogSpy).toHaveBeenCalled();
|
|
20
|
+
const calls = consoleLogSpy.mock.calls.map((c) => c[0]);
|
|
21
|
+
expect(calls.some((c) => c?.includes('Test Section'))).toBe(true);
|
|
22
|
+
expect(calls.some((c) => c?.includes('✓ ok'))).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('prints line with details', () => {
|
|
25
|
+
const sections = [
|
|
26
|
+
{
|
|
27
|
+
title: 'Test',
|
|
28
|
+
lines: [{ icon: '✓', status: 'ok', name: 'test', details: 'v1.0.0' }],
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
StatusFormatter.printSections(sections);
|
|
32
|
+
const calls = consoleLogSpy.mock.calls.map((c) => c[0]);
|
|
33
|
+
expect(calls.some((c) => c?.includes('v1.0.0'))).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('prints subtext', () => {
|
|
36
|
+
const sections = [
|
|
37
|
+
{
|
|
38
|
+
title: 'Test',
|
|
39
|
+
lines: [
|
|
40
|
+
{ icon: '✗', status: 'error', name: 'test', subtext: 'Try again' },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
StatusFormatter.printSections(sections);
|
|
45
|
+
const calls = consoleLogSpy.mock.calls.map((c) => c[0]);
|
|
46
|
+
expect(calls.some((c) => c?.includes('Try again'))).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it('adds spacing between sections', () => {
|
|
49
|
+
const sections = [
|
|
50
|
+
{ title: 'First', lines: [] },
|
|
51
|
+
{ title: 'Second', lines: [] },
|
|
52
|
+
];
|
|
53
|
+
StatusFormatter.printSections(sections);
|
|
54
|
+
const calls = consoleLogSpy.mock.calls;
|
|
55
|
+
// Should have blank lines for spacing
|
|
56
|
+
expect(calls.filter((c) => c.length === 0).length).toBeGreaterThan(0);
|
|
57
|
+
});
|
|
58
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agents-at-scale/ark",
|
|
3
|
-
"version": "0.1.35-
|
|
3
|
+
"version": "0.1.35-rc2",
|
|
4
4
|
"description": "ARK CLI - Interactive terminal interface for ARK agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"clean": "rm -rf dist",
|
|
19
19
|
"lint": "eslint src/ --fix && prettier --write src/",
|
|
20
20
|
"lint:check": "eslint src/ && prettier --check src/",
|
|
21
|
-
"test": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage --coverageDirectory=./artifacts/coverage",
|
|
21
|
+
"test": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage --coverageDirectory=./artifacts/coverage --coverageReporters=text --coverageReporters=lcov --coverageReporters=text-summary",
|
|
22
22
|
"postinstall": "echo \"ARK CLI installed! Run 'ark' to try it out.\""
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"openai": "^5.19.1",
|
|
59
59
|
"ora": "^8.2.0",
|
|
60
60
|
"react": "^19.1.0",
|
|
61
|
-
"simple-git": "^3.28.0",
|
|
62
61
|
"yaml": "^2.6.1"
|
|
63
62
|
},
|
|
64
63
|
"devDependencies": {
|
|
65
64
|
"@eslint/js": "^9.17.0",
|
|
65
|
+
"@jest/globals": "^30.1.2",
|
|
66
66
|
"@types/debug": "^4.1.12",
|
|
67
67
|
"@types/inquirer": "^9.0.7",
|
|
68
68
|
"@types/jest": "^30.0.0",
|