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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/dist/commands/cluster/index.d.ts +1 -2
  2. package/dist/commands/cluster/index.js +5 -3
  3. package/dist/commands/completion.js +2 -159
  4. package/dist/commands/config.d.ts +3 -0
  5. package/dist/commands/config.js +321 -38
  6. package/dist/commands/generate/config.js +24 -5
  7. package/dist/commands/generate/generators/agent.js +2 -2
  8. package/dist/commands/generate/generators/mcpserver.d.ts +1 -2
  9. package/dist/commands/generate/generators/mcpserver.js +5 -26
  10. package/dist/commands/generate/generators/project.js +41 -22
  11. package/dist/commands/generate/generators/team.js +2 -2
  12. package/dist/commands/generate/index.d.ts +1 -2
  13. package/dist/commands/generate/index.js +1 -1
  14. package/dist/components/statusChecker.d.ts +23 -13
  15. package/dist/components/statusChecker.js +129 -275
  16. package/dist/config.d.ts +22 -3
  17. package/dist/config.js +161 -10
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +42 -40
  20. package/dist/lib/cluster.d.ts +1 -2
  21. package/dist/lib/cluster.js +16 -37
  22. package/dist/lib/config.d.ts +80 -26
  23. package/dist/lib/config.js +205 -70
  24. package/dist/lib/consts.d.ts +1 -0
  25. package/dist/lib/consts.js +2 -0
  26. package/dist/lib/errors.js +1 -1
  27. package/dist/lib/exec.d.ts +4 -0
  28. package/dist/lib/exec.js +11 -0
  29. package/dist/lib/types.d.ts +3 -10
  30. package/dist/ui/MainMenu.d.ts +1 -5
  31. package/dist/ui/MainMenu.js +91 -222
  32. package/dist/ui/statusFormatter.d.ts +7 -22
  33. package/dist/ui/statusFormatter.js +39 -39
  34. package/package.json +5 -17
  35. package/dist/arkServices.d.ts +0 -42
  36. package/dist/arkServices.js +0 -138
  37. package/dist/arkServices.spec.d.ts +0 -1
  38. package/dist/arkServices.spec.js +0 -24
  39. package/dist/charts/charts.d.ts +0 -5
  40. package/dist/charts/charts.js +0 -6
  41. package/dist/charts/dependencies.d.ts +0 -6
  42. package/dist/charts/dependencies.js +0 -50
  43. package/dist/charts/types.d.ts +0 -40
  44. package/dist/charts/types.js +0 -1
  45. package/dist/commands/agents/index.d.ts +0 -3
  46. package/dist/commands/agents/index.js +0 -51
  47. package/dist/commands/agents/index.spec.d.ts +0 -1
  48. package/dist/commands/agents/index.spec.js +0 -67
  49. package/dist/commands/agents/selector.d.ts +0 -8
  50. package/dist/commands/agents/selector.js +0 -53
  51. package/dist/commands/agents.d.ts +0 -2
  52. package/dist/commands/agents.js +0 -53
  53. package/dist/commands/chat/index.d.ts +0 -3
  54. package/dist/commands/chat/index.js +0 -29
  55. package/dist/commands/chat.d.ts +0 -2
  56. package/dist/commands/chat.js +0 -45
  57. package/dist/commands/cluster/get.d.ts +0 -2
  58. package/dist/commands/cluster/get.js +0 -39
  59. package/dist/commands/cluster/get.spec.d.ts +0 -1
  60. package/dist/commands/cluster/get.spec.js +0 -92
  61. package/dist/commands/cluster/index.spec.d.ts +0 -1
  62. package/dist/commands/cluster/index.spec.js +0 -24
  63. package/dist/commands/completion/index.d.ts +0 -3
  64. package/dist/commands/completion/index.js +0 -268
  65. package/dist/commands/completion/index.spec.d.ts +0 -1
  66. package/dist/commands/completion/index.spec.js +0 -34
  67. package/dist/commands/config/index.d.ts +0 -3
  68. package/dist/commands/config/index.js +0 -42
  69. package/dist/commands/config/index.spec.d.ts +0 -1
  70. package/dist/commands/config/index.spec.js +0 -78
  71. package/dist/commands/dashboard/index.d.ts +0 -4
  72. package/dist/commands/dashboard/index.js +0 -39
  73. package/dist/commands/dashboard.d.ts +0 -3
  74. package/dist/commands/dashboard.js +0 -39
  75. package/dist/commands/dev/index.d.ts +0 -3
  76. package/dist/commands/dev/index.js +0 -9
  77. package/dist/commands/dev/tool/check.d.ts +0 -2
  78. package/dist/commands/dev/tool/check.js +0 -142
  79. package/dist/commands/dev/tool/clean.d.ts +0 -2
  80. package/dist/commands/dev/tool/clean.js +0 -153
  81. package/dist/commands/dev/tool/generate.d.ts +0 -2
  82. package/dist/commands/dev/tool/generate.js +0 -28
  83. package/dist/commands/dev/tool/index.d.ts +0 -2
  84. package/dist/commands/dev/tool/index.js +0 -14
  85. package/dist/commands/dev/tool/init.d.ts +0 -2
  86. package/dist/commands/dev/tool/init.js +0 -320
  87. package/dist/commands/dev/tool/shared.d.ts +0 -5
  88. package/dist/commands/dev/tool/shared.js +0 -256
  89. package/dist/commands/dev/tool/status.d.ts +0 -2
  90. package/dist/commands/dev/tool/status.js +0 -136
  91. package/dist/commands/dev/tool-generate.spec.d.ts +0 -1
  92. package/dist/commands/dev/tool-generate.spec.js +0 -163
  93. package/dist/commands/dev/tool.d.ts +0 -2
  94. package/dist/commands/dev/tool.js +0 -559
  95. package/dist/commands/dev/tool.spec.d.ts +0 -1
  96. package/dist/commands/dev/tool.spec.js +0 -48
  97. package/dist/commands/install/index.d.ts +0 -8
  98. package/dist/commands/install/index.js +0 -302
  99. package/dist/commands/install/index.spec.d.ts +0 -1
  100. package/dist/commands/install/index.spec.js +0 -135
  101. package/dist/commands/install.d.ts +0 -3
  102. package/dist/commands/install.js +0 -147
  103. package/dist/commands/models/create.d.ts +0 -1
  104. package/dist/commands/models/create.js +0 -213
  105. package/dist/commands/models/create.spec.d.ts +0 -1
  106. package/dist/commands/models/create.spec.js +0 -125
  107. package/dist/commands/models/index.d.ts +0 -3
  108. package/dist/commands/models/index.js +0 -60
  109. package/dist/commands/models/index.spec.d.ts +0 -1
  110. package/dist/commands/models/index.spec.js +0 -76
  111. package/dist/commands/models/selector.d.ts +0 -8
  112. package/dist/commands/models/selector.js +0 -53
  113. package/dist/commands/routes/index.d.ts +0 -3
  114. package/dist/commands/routes/index.js +0 -93
  115. package/dist/commands/routes.d.ts +0 -2
  116. package/dist/commands/routes.js +0 -101
  117. package/dist/commands/status/index.d.ts +0 -4
  118. package/dist/commands/status/index.js +0 -232
  119. package/dist/commands/status.d.ts +0 -3
  120. package/dist/commands/status.js +0 -33
  121. package/dist/commands/targets/index.d.ts +0 -3
  122. package/dist/commands/targets/index.js +0 -65
  123. package/dist/commands/targets/index.spec.d.ts +0 -1
  124. package/dist/commands/targets/index.spec.js +0 -105
  125. package/dist/commands/targets.d.ts +0 -2
  126. package/dist/commands/targets.js +0 -65
  127. package/dist/commands/teams/index.d.ts +0 -3
  128. package/dist/commands/teams/index.js +0 -49
  129. package/dist/commands/teams/index.spec.d.ts +0 -1
  130. package/dist/commands/teams/index.spec.js +0 -70
  131. package/dist/commands/teams/selector.d.ts +0 -8
  132. package/dist/commands/teams/selector.js +0 -55
  133. package/dist/commands/tools/index.d.ts +0 -3
  134. package/dist/commands/tools/index.js +0 -49
  135. package/dist/commands/tools/index.spec.d.ts +0 -1
  136. package/dist/commands/tools/index.spec.js +0 -70
  137. package/dist/commands/tools/selector.d.ts +0 -8
  138. package/dist/commands/tools/selector.js +0 -53
  139. package/dist/commands/uninstall/index.d.ts +0 -3
  140. package/dist/commands/uninstall/index.js +0 -107
  141. package/dist/commands/uninstall/index.spec.d.ts +0 -1
  142. package/dist/commands/uninstall/index.spec.js +0 -117
  143. package/dist/commands/uninstall.d.ts +0 -2
  144. package/dist/commands/uninstall.js +0 -83
  145. package/dist/components/ChatUI.d.ts +0 -16
  146. package/dist/components/ChatUI.js +0 -801
  147. package/dist/components/StatusView.d.ts +0 -10
  148. package/dist/components/StatusView.js +0 -39
  149. package/dist/lib/arkApiClient.d.ts +0 -53
  150. package/dist/lib/arkApiClient.js +0 -102
  151. package/dist/lib/arkApiProxy.d.ts +0 -9
  152. package/dist/lib/arkApiProxy.js +0 -22
  153. package/dist/lib/arkServiceProxy.d.ts +0 -14
  154. package/dist/lib/arkServiceProxy.js +0 -95
  155. package/dist/lib/arkStatus.d.ts +0 -10
  156. package/dist/lib/arkStatus.js +0 -79
  157. package/dist/lib/arkStatus.spec.d.ts +0 -1
  158. package/dist/lib/arkStatus.spec.js +0 -49
  159. package/dist/lib/chatClient.d.ts +0 -33
  160. package/dist/lib/chatClient.js +0 -99
  161. package/dist/lib/cluster.spec.d.ts +0 -1
  162. package/dist/lib/cluster.spec.js +0 -338
  163. package/dist/lib/commandUtils.d.ts +0 -4
  164. package/dist/lib/commandUtils.js +0 -18
  165. package/dist/lib/commandUtils.test.d.ts +0 -1
  166. package/dist/lib/commandUtils.test.js +0 -44
  167. package/dist/lib/commands.d.ts +0 -16
  168. package/dist/lib/commands.js +0 -29
  169. package/dist/lib/commands.spec.d.ts +0 -1
  170. package/dist/lib/commands.spec.js +0 -146
  171. package/dist/lib/config.spec.d.ts +0 -1
  172. package/dist/lib/config.spec.js +0 -99
  173. package/dist/lib/config.test.d.ts +0 -1
  174. package/dist/lib/config.test.js +0 -93
  175. package/dist/lib/consts.spec.d.ts +0 -1
  176. package/dist/lib/consts.spec.js +0 -15
  177. package/dist/lib/dev/tools/analyzer.d.ts +0 -30
  178. package/dist/lib/dev/tools/analyzer.js +0 -190
  179. package/dist/lib/dev/tools/discover_tools.py +0 -392
  180. package/dist/lib/dev/tools/mcp-types.d.ts +0 -28
  181. package/dist/lib/dev/tools/mcp-types.js +0 -86
  182. package/dist/lib/dev/tools/types.d.ts +0 -50
  183. package/dist/lib/dev/tools/types.js +0 -1
  184. package/dist/lib/errors.spec.d.ts +0 -1
  185. package/dist/lib/errors.spec.js +0 -221
  186. package/dist/lib/output.d.ts +0 -36
  187. package/dist/lib/output.js +0 -89
  188. package/dist/lib/output.spec.d.ts +0 -1
  189. package/dist/lib/output.spec.js +0 -123
  190. package/dist/lib/portUtils.d.ts +0 -8
  191. package/dist/lib/portUtils.js +0 -39
  192. package/dist/lib/startup.d.ts +0 -5
  193. package/dist/lib/startup.js +0 -73
  194. package/dist/lib/startup.spec.d.ts +0 -1
  195. package/dist/lib/startup.spec.js +0 -168
  196. package/dist/types/types.d.ts +0 -40
  197. package/dist/types/types.js +0 -1
  198. package/dist/ui/AgentSelector.d.ts +0 -8
  199. package/dist/ui/AgentSelector.js +0 -53
  200. package/dist/ui/ModelSelector.d.ts +0 -8
  201. package/dist/ui/ModelSelector.js +0 -53
  202. package/dist/ui/TeamSelector.d.ts +0 -8
  203. package/dist/ui/TeamSelector.js +0 -55
  204. package/dist/ui/ToolSelector.d.ts +0 -8
  205. package/dist/ui/ToolSelector.js +0 -53
  206. package/dist/ui/statusFormatter.spec.d.ts +0 -1
  207. package/dist/ui/statusFormatter.spec.js +0 -58
@@ -1,49 +0,0 @@
1
- import { Command } from 'commander';
2
- import { execa } from 'execa';
3
- import output from '../../lib/output.js';
4
- async function listTeams(options) {
5
- try {
6
- // Use kubectl to get teams
7
- const result = await execa('kubectl', ['get', 'teams', '-o', 'json'], {
8
- stdio: 'pipe',
9
- });
10
- const data = JSON.parse(result.stdout);
11
- const teams = data.items || [];
12
- if (options.output === 'json') {
13
- // Output the raw items for JSON format
14
- console.log(JSON.stringify(teams, null, 2));
15
- }
16
- else {
17
- if (teams.length === 0) {
18
- output.info('No teams found');
19
- return;
20
- }
21
- teams.forEach((team) => {
22
- console.log(team.metadata.name);
23
- });
24
- }
25
- }
26
- catch (error) {
27
- output.error('fetching teams:', error instanceof Error ? error.message : error);
28
- process.exit(1);
29
- }
30
- }
31
- export function createTeamsCommand(_) {
32
- const teamsCommand = new Command('teams');
33
- teamsCommand
34
- .description('List available teams')
35
- .option('-o, --output <format>', 'Output format (json)', 'text')
36
- .action(async (options) => {
37
- await listTeams(options);
38
- });
39
- const listCommand = new Command('list');
40
- listCommand
41
- .alias('ls')
42
- .description('List available teams')
43
- .option('-o, --output <format>', 'Output format (json)', 'text')
44
- .action(async (options) => {
45
- await listTeams(options);
46
- });
47
- teamsCommand.addCommand(listCommand);
48
- return teamsCommand;
49
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,70 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { Command } from 'commander';
3
- const mockExeca = jest.fn();
4
- jest.unstable_mockModule('execa', () => ({
5
- execa: mockExeca,
6
- }));
7
- const mockOutput = {
8
- info: jest.fn(),
9
- error: jest.fn(),
10
- };
11
- jest.unstable_mockModule('../../lib/output.js', () => ({
12
- default: mockOutput,
13
- }));
14
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
15
- throw new Error('process.exit called');
16
- }));
17
- const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
18
- const { createTeamsCommand } = await import('./index.js');
19
- describe('teams command', () => {
20
- beforeEach(() => {
21
- jest.clearAllMocks();
22
- });
23
- it('creates command with correct structure', () => {
24
- const command = createTeamsCommand({});
25
- expect(command).toBeInstanceOf(Command);
26
- expect(command.name()).toBe('teams');
27
- });
28
- it('lists teams in text format', async () => {
29
- const mockTeams = {
30
- items: [
31
- { metadata: { name: 'engineering' } },
32
- { metadata: { name: 'data-science' } },
33
- ],
34
- };
35
- mockExeca.mockResolvedValue({ stdout: JSON.stringify(mockTeams) });
36
- const command = createTeamsCommand({});
37
- await command.parseAsync(['node', 'test']);
38
- expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'teams', '-o', 'json'], { stdio: 'pipe' });
39
- expect(mockConsoleLog).toHaveBeenCalledWith('engineering');
40
- expect(mockConsoleLog).toHaveBeenCalledWith('data-science');
41
- });
42
- it('lists teams in json format', async () => {
43
- const mockTeams = {
44
- items: [{ metadata: { name: 'engineering' } }],
45
- };
46
- mockExeca.mockResolvedValue({ stdout: JSON.stringify(mockTeams) });
47
- const command = createTeamsCommand({});
48
- await command.parseAsync(['node', 'test', '-o', 'json']);
49
- expect(mockConsoleLog).toHaveBeenCalledWith(JSON.stringify(mockTeams.items, null, 2));
50
- });
51
- it('shows info when no teams', async () => {
52
- mockExeca.mockResolvedValue({ stdout: JSON.stringify({ items: [] }) });
53
- const command = createTeamsCommand({});
54
- await command.parseAsync(['node', 'test']);
55
- expect(mockOutput.info).toHaveBeenCalledWith('No teams found');
56
- });
57
- it('handles errors', async () => {
58
- mockExeca.mockRejectedValue(new Error('kubectl failed'));
59
- const command = createTeamsCommand({});
60
- await expect(command.parseAsync(['node', 'test'])).rejects.toThrow('process.exit called');
61
- expect(mockOutput.error).toHaveBeenCalledWith('fetching teams:', 'kubectl failed');
62
- expect(mockExit).toHaveBeenCalledWith(1);
63
- });
64
- it('list subcommand works', async () => {
65
- mockExeca.mockResolvedValue({ stdout: JSON.stringify({ items: [] }) });
66
- const command = createTeamsCommand({});
67
- await command.parseAsync(['node', 'test', 'list']);
68
- expect(mockExeca).toHaveBeenCalled();
69
- });
70
- });
@@ -1,8 +0,0 @@
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 {};
@@ -1,55 +0,0 @@
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
- }
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- import type { ArkConfig } from '../../lib/config.js';
3
- export declare function createToolsCommand(_: ArkConfig): Command;
@@ -1,49 +0,0 @@
1
- import { Command } from 'commander';
2
- import { execa } from 'execa';
3
- import output from '../../lib/output.js';
4
- async function listTools(options) {
5
- try {
6
- // Use kubectl to get tools (MCPServers)
7
- const result = await execa('kubectl', ['get', 'mcpservers', '-o', 'json'], {
8
- stdio: 'pipe',
9
- });
10
- const data = JSON.parse(result.stdout);
11
- const tools = data.items || [];
12
- if (options.output === 'json') {
13
- // Output the raw items for JSON format
14
- console.log(JSON.stringify(tools, null, 2));
15
- }
16
- else {
17
- if (tools.length === 0) {
18
- output.info('No tools found');
19
- return;
20
- }
21
- tools.forEach((tool) => {
22
- console.log(tool.metadata.name);
23
- });
24
- }
25
- }
26
- catch (error) {
27
- output.error('fetching tools:', error instanceof Error ? error.message : error);
28
- process.exit(1);
29
- }
30
- }
31
- export function createToolsCommand(_) {
32
- const toolsCommand = new Command('tools');
33
- toolsCommand
34
- .description('List available tools')
35
- .option('-o, --output <format>', 'Output format (json)', 'text')
36
- .action(async (options) => {
37
- await listTools(options);
38
- });
39
- const listCommand = new Command('list');
40
- listCommand
41
- .alias('ls')
42
- .description('List available tools')
43
- .option('-o, --output <format>', 'Output format (json)', 'text')
44
- .action(async (options) => {
45
- await listTools(options);
46
- });
47
- toolsCommand.addCommand(listCommand);
48
- return toolsCommand;
49
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,70 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { Command } from 'commander';
3
- const mockExeca = jest.fn();
4
- jest.unstable_mockModule('execa', () => ({
5
- execa: mockExeca,
6
- }));
7
- const mockOutput = {
8
- info: jest.fn(),
9
- error: jest.fn(),
10
- };
11
- jest.unstable_mockModule('../../lib/output.js', () => ({
12
- default: mockOutput,
13
- }));
14
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
15
- throw new Error('process.exit called');
16
- }));
17
- const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
18
- const { createToolsCommand } = await import('./index.js');
19
- describe('tools command', () => {
20
- beforeEach(() => {
21
- jest.clearAllMocks();
22
- });
23
- it('creates command with correct structure', () => {
24
- const command = createToolsCommand({});
25
- expect(command).toBeInstanceOf(Command);
26
- expect(command.name()).toBe('tools');
27
- });
28
- it('lists tools in text format', async () => {
29
- const mockTools = {
30
- items: [
31
- { metadata: { name: 'github-mcp' } },
32
- { metadata: { name: 'slack-mcp' } },
33
- ],
34
- };
35
- mockExeca.mockResolvedValue({ stdout: JSON.stringify(mockTools) });
36
- const command = createToolsCommand({});
37
- await command.parseAsync(['node', 'test']);
38
- expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'mcpservers', '-o', 'json'], { stdio: 'pipe' });
39
- expect(mockConsoleLog).toHaveBeenCalledWith('github-mcp');
40
- expect(mockConsoleLog).toHaveBeenCalledWith('slack-mcp');
41
- });
42
- it('lists tools in json format', async () => {
43
- const mockTools = {
44
- items: [{ metadata: { name: 'github-mcp' } }],
45
- };
46
- mockExeca.mockResolvedValue({ stdout: JSON.stringify(mockTools) });
47
- const command = createToolsCommand({});
48
- await command.parseAsync(['node', 'test', '-o', 'json']);
49
- expect(mockConsoleLog).toHaveBeenCalledWith(JSON.stringify(mockTools.items, null, 2));
50
- });
51
- it('shows info when no tools', async () => {
52
- mockExeca.mockResolvedValue({ stdout: JSON.stringify({ items: [] }) });
53
- const command = createToolsCommand({});
54
- await command.parseAsync(['node', 'test']);
55
- expect(mockOutput.info).toHaveBeenCalledWith('No tools found');
56
- });
57
- it('handles errors', async () => {
58
- mockExeca.mockRejectedValue(new Error('kubectl failed'));
59
- const command = createToolsCommand({});
60
- await expect(command.parseAsync(['node', 'test'])).rejects.toThrow('process.exit called');
61
- expect(mockOutput.error).toHaveBeenCalledWith('fetching tools:', 'kubectl failed');
62
- expect(mockExit).toHaveBeenCalledWith(1);
63
- });
64
- it('list subcommand works', async () => {
65
- mockExeca.mockResolvedValue({ stdout: JSON.stringify({ items: [] }) });
66
- const command = createToolsCommand({});
67
- await command.parseAsync(['node', 'test', 'list']);
68
- expect(mockExeca).toHaveBeenCalled();
69
- });
70
- });
@@ -1,8 +0,0 @@
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 {};
@@ -1,53 +0,0 @@
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,3 +0,0 @@
1
- import { Command } from 'commander';
2
- import type { ArkConfig } from '../../lib/config.js';
3
- export declare function createUninstallCommand(_: ArkConfig): Command;
@@ -1,107 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import { execute } from '../../lib/commands.js';
4
- import inquirer from 'inquirer';
5
- import { getClusterInfo } from '../../lib/cluster.js';
6
- import output from '../../lib/output.js';
7
- import { getInstallableServices } from '../../arkServices.js';
8
- async function uninstallService(service, verbose = false) {
9
- const helmArgs = ['uninstall', service.helmReleaseName, '--ignore-not-found'];
10
- // Only add namespace flag if service has explicit namespace
11
- if (service.namespace) {
12
- helmArgs.push('--namespace', service.namespace);
13
- }
14
- await execute('helm', helmArgs, { stdio: 'inherit' }, { verbose });
15
- }
16
- async function uninstallArk(serviceName, options = {}) {
17
- // Check cluster connectivity
18
- const clusterInfo = await getClusterInfo();
19
- if (clusterInfo.error) {
20
- output.error('no kubernetes cluster detected');
21
- output.info('please ensure you have a running cluster and kubectl is configured.');
22
- process.exit(1);
23
- }
24
- // Show cluster info
25
- output.success(`connected to cluster: ${chalk.bold(clusterInfo.context)}`);
26
- output.info(`type: ${clusterInfo.type}`);
27
- output.info(`namespace: ${clusterInfo.namespace}`);
28
- if (clusterInfo.ip) {
29
- output.info(`ip: ${clusterInfo.ip}`);
30
- }
31
- console.log(); // Add blank line after cluster info
32
- // If a specific service is requested, uninstall only that service
33
- if (serviceName) {
34
- const services = getInstallableServices();
35
- const service = Object.values(services).find((s) => s.name === serviceName);
36
- if (!service) {
37
- output.error(`service '${serviceName}' not found`);
38
- output.info('available services:');
39
- for (const s of Object.values(services)) {
40
- output.info(` ${s.name}`);
41
- }
42
- process.exit(1);
43
- }
44
- output.info(`uninstalling ${service.name}...`);
45
- try {
46
- await uninstallService(service, options.verbose);
47
- output.success(`${service.name} uninstalled successfully`);
48
- }
49
- catch (error) {
50
- output.error(`failed to uninstall ${service.name}`);
51
- console.error(error);
52
- process.exit(1);
53
- }
54
- return;
55
- }
56
- // Get installable services and iterate through them in reverse order for clean uninstall
57
- const services = getInstallableServices();
58
- const serviceEntries = Object.entries(services).reverse();
59
- for (const [, service] of serviceEntries) {
60
- let shouldUninstall = false;
61
- try {
62
- // Ask for confirmation
63
- shouldUninstall =
64
- options.yes ||
65
- (await inquirer.prompt([
66
- {
67
- type: 'confirm',
68
- name: 'shouldUninstall',
69
- message: `uninstall ${chalk.bold(service.name)}? ${service.description ? chalk.gray(`(${service.description.toLowerCase()})`) : ''}`,
70
- default: true,
71
- },
72
- ])).shouldUninstall;
73
- }
74
- catch (error) {
75
- // Handle Ctrl-C gracefully
76
- if (error && error.name === 'ExitPromptError') {
77
- console.log('\nUninstallation cancelled');
78
- process.exit(130); // Standard exit code for SIGINT
79
- }
80
- throw error;
81
- }
82
- if (!shouldUninstall) {
83
- output.warning(`skipping ${service.name}`);
84
- continue;
85
- }
86
- try {
87
- await uninstallService(service, options.verbose);
88
- console.log(); // Add blank line after command output
89
- }
90
- catch {
91
- // Continue with remaining charts on error
92
- console.log(); // Add blank line after error output
93
- }
94
- }
95
- }
96
- export function createUninstallCommand(_) {
97
- const command = new Command('uninstall');
98
- command
99
- .description('Uninstall ARK components using Helm')
100
- .argument('[service]', 'specific service to uninstall, or all if omitted')
101
- .option('-y, --yes', 'automatically confirm all uninstallations')
102
- .option('-v, --verbose', 'show commands being executed')
103
- .action(async (service, options) => {
104
- await uninstallArk(service, options);
105
- });
106
- return command;
107
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,117 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { Command } from 'commander';
3
- const mockExeca = jest.fn(() => Promise.resolve());
4
- jest.unstable_mockModule('execa', () => ({
5
- execa: mockExeca,
6
- }));
7
- const mockGetClusterInfo = jest.fn();
8
- jest.unstable_mockModule('../../lib/cluster.js', () => ({
9
- getClusterInfo: mockGetClusterInfo,
10
- }));
11
- const mockGetInstallableServices = jest.fn();
12
- jest.unstable_mockModule('../../arkServices.js', () => ({
13
- getInstallableServices: mockGetInstallableServices,
14
- }));
15
- const mockOutput = {
16
- error: jest.fn(),
17
- info: jest.fn(),
18
- success: jest.fn(),
19
- warning: jest.fn(),
20
- };
21
- jest.unstable_mockModule('../../lib/output.js', () => ({
22
- default: mockOutput,
23
- }));
24
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
25
- throw new Error('process.exit called');
26
- }));
27
- jest.spyOn(console, 'log').mockImplementation(() => { });
28
- jest.spyOn(console, 'error').mockImplementation(() => { });
29
- const { createUninstallCommand } = await import('./index.js');
30
- describe('uninstall command', () => {
31
- beforeEach(() => {
32
- jest.clearAllMocks();
33
- mockGetClusterInfo.mockResolvedValue({
34
- context: 'test-cluster',
35
- type: 'minikube',
36
- namespace: 'default',
37
- });
38
- });
39
- it('creates command with correct structure', () => {
40
- const command = createUninstallCommand({});
41
- expect(command).toBeInstanceOf(Command);
42
- expect(command.name()).toBe('uninstall');
43
- });
44
- it('uninstalls single service with correct helm parameters', async () => {
45
- const mockService = {
46
- name: 'ark-api',
47
- helmReleaseName: 'ark-api',
48
- namespace: 'ark-system',
49
- };
50
- mockGetInstallableServices.mockReturnValue({
51
- 'ark-api': mockService,
52
- });
53
- const command = createUninstallCommand({});
54
- await command.parseAsync(['node', 'test', 'ark-api']);
55
- expect(mockExeca).toHaveBeenCalledWith('helm', [
56
- 'uninstall',
57
- 'ark-api',
58
- '--ignore-not-found',
59
- '--namespace',
60
- 'ark-system',
61
- ], {
62
- stdio: 'inherit',
63
- });
64
- expect(mockOutput.success).toHaveBeenCalledWith('ark-api uninstalled successfully');
65
- });
66
- it('shows error when service not found', async () => {
67
- mockGetInstallableServices.mockReturnValue({
68
- 'ark-api': { name: 'ark-api' },
69
- 'ark-controller': { name: 'ark-controller' },
70
- });
71
- const command = createUninstallCommand({});
72
- await expect(command.parseAsync(['node', 'test', 'invalid-service'])).rejects.toThrow('process.exit called');
73
- expect(mockOutput.error).toHaveBeenCalledWith("service 'invalid-service' not found");
74
- expect(mockOutput.info).toHaveBeenCalledWith('available services:');
75
- expect(mockOutput.info).toHaveBeenCalledWith(' ark-api');
76
- expect(mockOutput.info).toHaveBeenCalledWith(' ark-controller');
77
- expect(mockExit).toHaveBeenCalledWith(1);
78
- });
79
- it('handles service without namespace (uses current context)', async () => {
80
- const mockService = {
81
- name: 'ark-dashboard',
82
- helmReleaseName: 'ark-dashboard',
83
- // namespace is undefined - should use current context
84
- };
85
- mockGetInstallableServices.mockReturnValue({
86
- 'ark-dashboard': mockService,
87
- });
88
- const command = createUninstallCommand({});
89
- await command.parseAsync(['node', 'test', 'ark-dashboard']);
90
- // Should NOT include --namespace flag
91
- expect(mockExeca).toHaveBeenCalledWith('helm', ['uninstall', 'ark-dashboard', '--ignore-not-found'], {
92
- stdio: 'inherit',
93
- });
94
- });
95
- it('handles helm uninstall error gracefully', async () => {
96
- const mockService = {
97
- name: 'ark-api',
98
- helmReleaseName: 'ark-api',
99
- namespace: 'ark-system',
100
- };
101
- mockGetInstallableServices.mockReturnValue({
102
- 'ark-api': mockService,
103
- });
104
- mockExeca.mockRejectedValue(new Error('helm failed'));
105
- const command = createUninstallCommand({});
106
- await expect(command.parseAsync(['node', 'test', 'ark-api'])).rejects.toThrow('process.exit called');
107
- expect(mockOutput.error).toHaveBeenCalledWith('failed to uninstall ark-api');
108
- expect(mockExit).toHaveBeenCalledWith(1);
109
- });
110
- it('exits when cluster not connected', async () => {
111
- mockGetClusterInfo.mockResolvedValue({ error: true });
112
- const command = createUninstallCommand({});
113
- await expect(command.parseAsync(['node', 'test', 'ark-api'])).rejects.toThrow('process.exit called');
114
- expect(mockOutput.error).toHaveBeenCalledWith('no kubernetes cluster detected');
115
- expect(mockExit).toHaveBeenCalledWith(1);
116
- });
117
- });
@@ -1,2 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createUninstallCommand(): Command;