@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.
Files changed (132) hide show
  1. package/dist/arkServices.d.ts +50 -0
  2. package/dist/arkServices.js +153 -0
  3. package/dist/charts/charts.d.ts +5 -0
  4. package/dist/charts/charts.js +6 -0
  5. package/dist/charts/dependencies.d.ts +6 -0
  6. package/dist/charts/dependencies.js +50 -0
  7. package/dist/charts/types.d.ts +40 -0
  8. package/dist/charts/types.js +1 -0
  9. package/dist/commands/agents/index.d.ts +2 -0
  10. package/dist/commands/agents/index.js +56 -0
  11. package/dist/commands/agents/selector.d.ts +8 -0
  12. package/dist/commands/agents/selector.js +53 -0
  13. package/dist/commands/agents.d.ts +2 -0
  14. package/dist/commands/agents.js +53 -0
  15. package/dist/commands/chat/index.d.ts +2 -0
  16. package/dist/commands/chat/index.js +45 -0
  17. package/dist/commands/chat.d.ts +2 -0
  18. package/dist/commands/chat.js +45 -0
  19. package/dist/commands/cluster/get.d.ts +2 -0
  20. package/dist/commands/cluster/get.js +39 -0
  21. package/dist/commands/cluster/index.js +2 -4
  22. package/dist/commands/completion/index.d.ts +2 -0
  23. package/dist/commands/completion/index.js +268 -0
  24. package/dist/commands/completion.js +159 -2
  25. package/dist/commands/config/index.d.ts +2 -0
  26. package/dist/commands/config/index.js +42 -0
  27. package/dist/commands/config.d.ts +0 -3
  28. package/dist/commands/config.js +38 -321
  29. package/dist/commands/dashboard/index.d.ts +3 -0
  30. package/dist/commands/dashboard/index.js +39 -0
  31. package/dist/commands/dashboard.d.ts +3 -0
  32. package/dist/commands/dashboard.js +39 -0
  33. package/dist/commands/dev/index.d.ts +2 -0
  34. package/dist/commands/dev/index.js +9 -0
  35. package/dist/commands/dev/tool/check.d.ts +2 -0
  36. package/dist/commands/dev/tool/check.js +142 -0
  37. package/dist/commands/dev/tool/clean.d.ts +2 -0
  38. package/dist/commands/dev/tool/clean.js +153 -0
  39. package/dist/commands/dev/tool/generate.d.ts +2 -0
  40. package/dist/commands/dev/tool/generate.js +28 -0
  41. package/dist/commands/dev/tool/index.d.ts +2 -0
  42. package/dist/commands/dev/tool/index.js +14 -0
  43. package/dist/commands/dev/tool/init.d.ts +2 -0
  44. package/dist/commands/dev/tool/init.js +320 -0
  45. package/dist/commands/dev/tool/shared.d.ts +5 -0
  46. package/dist/commands/dev/tool/shared.js +256 -0
  47. package/dist/commands/dev/tool/status.d.ts +2 -0
  48. package/dist/commands/dev/tool/status.js +136 -0
  49. package/dist/commands/dev/tool.d.ts +2 -0
  50. package/dist/commands/dev/tool.js +559 -0
  51. package/dist/commands/generate/config.js +5 -24
  52. package/dist/commands/generate/generators/mcpserver.d.ts +2 -1
  53. package/dist/commands/generate/generators/mcpserver.js +26 -5
  54. package/dist/commands/install/index.d.ts +6 -0
  55. package/dist/commands/install/index.js +165 -0
  56. package/dist/commands/install.d.ts +3 -0
  57. package/dist/commands/install.js +147 -0
  58. package/dist/commands/models/create.d.ts +1 -0
  59. package/dist/commands/models/create.js +213 -0
  60. package/dist/commands/models/index.d.ts +2 -0
  61. package/dist/commands/models/index.js +65 -0
  62. package/dist/commands/models/selector.d.ts +8 -0
  63. package/dist/commands/models/selector.js +53 -0
  64. package/dist/commands/routes/index.d.ts +2 -0
  65. package/dist/commands/routes/index.js +101 -0
  66. package/dist/commands/routes.d.ts +2 -0
  67. package/dist/commands/routes.js +101 -0
  68. package/dist/commands/status/index.d.ts +3 -0
  69. package/dist/commands/status/index.js +33 -0
  70. package/dist/commands/status.d.ts +3 -0
  71. package/dist/commands/status.js +33 -0
  72. package/dist/commands/targets/index.d.ts +2 -0
  73. package/dist/commands/targets/index.js +65 -0
  74. package/dist/commands/targets.d.ts +2 -0
  75. package/dist/commands/targets.js +65 -0
  76. package/dist/commands/teams/index.d.ts +2 -0
  77. package/dist/commands/teams/index.js +54 -0
  78. package/dist/commands/teams/selector.d.ts +8 -0
  79. package/dist/commands/teams/selector.js +55 -0
  80. package/dist/commands/tools/index.d.ts +2 -0
  81. package/dist/commands/tools/index.js +54 -0
  82. package/dist/commands/tools/selector.d.ts +8 -0
  83. package/dist/commands/tools/selector.js +53 -0
  84. package/dist/commands/uninstall/index.d.ts +2 -0
  85. package/dist/commands/uninstall/index.js +84 -0
  86. package/dist/commands/uninstall.d.ts +2 -0
  87. package/dist/commands/uninstall.js +83 -0
  88. package/dist/components/ChatUI.d.ts +16 -0
  89. package/dist/components/ChatUI.js +801 -0
  90. package/dist/components/StatusView.d.ts +10 -0
  91. package/dist/components/StatusView.js +39 -0
  92. package/dist/components/statusChecker.d.ts +10 -13
  93. package/dist/components/statusChecker.js +128 -65
  94. package/dist/config.js +3 -10
  95. package/dist/index.d.ts +1 -1
  96. package/dist/index.js +31 -36
  97. package/dist/lib/arkApiClient.d.ts +53 -0
  98. package/dist/lib/arkApiClient.js +102 -0
  99. package/dist/lib/arkApiProxy.d.ts +9 -0
  100. package/dist/lib/arkApiProxy.js +22 -0
  101. package/dist/lib/arkServiceProxy.d.ts +14 -0
  102. package/dist/lib/arkServiceProxy.js +93 -0
  103. package/dist/lib/arkStatus.d.ts +5 -0
  104. package/dist/lib/arkStatus.js +20 -0
  105. package/dist/lib/chatClient.d.ts +33 -0
  106. package/dist/lib/chatClient.js +101 -0
  107. package/dist/lib/cluster.d.ts +2 -1
  108. package/dist/lib/cluster.js +27 -3
  109. package/dist/lib/commandUtils.d.ts +4 -0
  110. package/dist/lib/commandUtils.js +18 -0
  111. package/dist/lib/commandUtils.test.d.ts +1 -0
  112. package/dist/lib/commandUtils.test.js +44 -0
  113. package/dist/lib/config.d.ts +24 -80
  114. package/dist/lib/config.js +68 -205
  115. package/dist/lib/config.test.d.ts +1 -0
  116. package/dist/lib/config.test.js +93 -0
  117. package/dist/lib/dev/tools/analyzer.d.ts +30 -0
  118. package/dist/lib/dev/tools/analyzer.js +190 -0
  119. package/dist/lib/dev/tools/discover_tools.py +392 -0
  120. package/dist/lib/dev/tools/mcp-types.d.ts +28 -0
  121. package/dist/lib/dev/tools/mcp-types.js +86 -0
  122. package/dist/lib/dev/tools/types.d.ts +50 -0
  123. package/dist/lib/dev/tools/types.js +1 -0
  124. package/dist/lib/output.d.ts +36 -0
  125. package/dist/lib/output.js +89 -0
  126. package/dist/lib/types.d.ts +8 -3
  127. package/dist/types/types.d.ts +40 -0
  128. package/dist/types/types.js +1 -0
  129. package/dist/ui/MainMenu.js +158 -90
  130. package/dist/ui/statusFormatter.d.ts +4 -1
  131. package/dist/ui/statusFormatter.js +91 -19
  132. package/package.json +16 -4
@@ -13,13 +13,16 @@ export interface KubernetesConfig {
13
13
  namespace?: string;
14
14
  inCluster: boolean;
15
15
  }
16
- export interface ServiceStatus {
16
+ export type DeploymentStatus = 'available' | 'progressing' | 'replicafailure' | 'failed' | 'not found' | 'unknown';
17
+ export type ServiceStatus = {
17
18
  name: string;
18
- status: 'healthy' | 'unhealthy' | 'not installed';
19
+ status: 'healthy' | 'warning' | 'unhealthy' | 'not installed' | 'not ready';
20
+ deploymentStatus?: DeploymentStatus;
19
21
  url?: string;
20
22
  version?: string;
23
+ revision?: string;
21
24
  details?: string;
22
- }
25
+ };
23
26
  export interface DependencyStatus {
24
27
  name: string;
25
28
  installed: boolean;
@@ -29,6 +32,8 @@ export interface DependencyStatus {
29
32
  export interface StatusData {
30
33
  services: ServiceStatus[];
31
34
  dependencies: DependencyStatus[];
35
+ arkReady?: boolean;
36
+ defaultModelExists?: boolean;
32
37
  }
33
38
  export interface CommandVersionConfig {
34
39
  command: string;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Represents a Helm chart configuration for ARK components
3
+ */
4
+ export interface ArkChart {
5
+ /** Name of the chart (used as release name) */
6
+ name: string;
7
+ /** Full chart path (OCI registry or local path) */
8
+ chartPath: string;
9
+ /** Kubernetes namespace to install into */
10
+ namespace: string;
11
+ /** Additional arguments to pass to helm (e.g., --create-namespace, --wait, --timeout 300s, --set key=value) */
12
+ args?: string[];
13
+ /** Description of what this chart provides */
14
+ description?: string;
15
+ }
16
+ /**
17
+ * Collection of ARK charts
18
+ */
19
+ export interface ChartCollection {
20
+ [key: string]: ArkChart;
21
+ }
22
+ /**
23
+ * Represents a dependency that needs to be installed
24
+ */
25
+ export interface Dependency {
26
+ /** Name of the dependency */
27
+ name: string;
28
+ /** Command to execute (helm, kubectl, etc.) */
29
+ command: string;
30
+ /** Arguments to pass to the command */
31
+ args: string[];
32
+ /** Description of what this dependency provides */
33
+ description?: string;
34
+ }
35
+ /**
36
+ * Collection of dependencies
37
+ */
38
+ export interface DependencyCollection {
39
+ [key: string]: Dependency;
40
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,70 +1,169 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Text, Box, useInput } from 'ink';
3
- import SelectInput from 'ink-select-input';
2
+ import { Text, Box, render, useInput } from 'ink';
4
3
  import * as React from 'react';
5
- import DashboardCLI from '../components/DashboardCLI.js';
6
- import GeneratorUI from '../components/GeneratorUI.js';
7
- import { StatusChecker } from '../components/statusChecker.js';
8
- import { ConfigManager } from '../config.js';
9
- import { ArkClient } from '../lib/arkClient.js';
10
- const EXIT_TIMEOUT_MS = 1000;
4
+ // Helper function to unmount the main ink app - used when we move from a
5
+ // React TUI app to basic input/output.
6
+ async function unmountInkApp() {
7
+ const app = globalThis.inkApp;
8
+ if (app) {
9
+ app.unmount();
10
+ // Remove all existing signal listeners that might interfere with inquirer
11
+ process.removeAllListeners('SIGINT');
12
+ process.removeAllListeners('SIGTERM');
13
+ process.removeAllListeners('SIGQUIT');
14
+ process.removeAllListeners('exit');
15
+ // Reset stdin completely
16
+ if (process.stdin.isTTY) {
17
+ process.stdin.setRawMode(false);
18
+ process.stdin.pause();
19
+ process.stdin.removeAllListeners();
20
+ process.stdin.resume();
21
+ }
22
+ // Reset stdout/stderr
23
+ process.stdout.removeAllListeners();
24
+ process.stderr.removeAllListeners();
25
+ console.clear();
26
+ // Give terminal more time to fully reset
27
+ await new Promise((resolve) => setTimeout(resolve, 200));
28
+ }
29
+ }
11
30
  const MainMenu = () => {
12
- const [selectedChoice, setSelectedChoice] = React.useState(null);
13
- const [statusData, setStatusData] = React.useState(null);
14
- const [isLoading, setIsLoading] = React.useState(false);
15
- const [error, setError] = React.useState(null);
31
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
16
32
  const choices = [
17
- { label: '🏷️ Dashboard', value: 'dashboard' },
18
- { label: '🔍 Status Check', value: 'status' },
19
- { label: '🎯 Generate', value: 'generate' },
20
- { label: '👋 Exit', value: 'exit' },
33
+ {
34
+ label: 'Chat',
35
+ description: 'Interactive chat with ARK agents',
36
+ value: 'chat',
37
+ command: 'ark chat',
38
+ },
39
+ {
40
+ label: 'Install',
41
+ description: 'Install Ark',
42
+ value: 'install',
43
+ command: 'ark install',
44
+ },
45
+ {
46
+ label: 'Dashboard',
47
+ description: 'Open ARK dashboard in browser',
48
+ value: 'dashboard',
49
+ command: 'ark dashboard',
50
+ },
51
+ {
52
+ label: 'Status Check',
53
+ description: 'Check ARK services status',
54
+ value: 'status',
55
+ command: 'ark status',
56
+ },
57
+ {
58
+ label: 'Generate',
59
+ description: 'Generate new ARK components',
60
+ value: 'generate',
61
+ command: 'ark generate',
62
+ },
63
+ { label: 'Exit', description: 'Exit ARK CLI', value: 'exit' },
21
64
  ];
22
- React.useEffect(() => {
23
- if (selectedChoice === 'exit') {
24
- const timer = setTimeout(() => {
25
- process.exit(0);
26
- }, EXIT_TIMEOUT_MS);
27
- return () => clearTimeout(timer);
28
- }
29
- }, [selectedChoice]);
30
- React.useEffect(() => {
31
- if (selectedChoice === 'status' && !statusData && !isLoading) {
32
- checkStatus();
65
+ useInput((input, key) => {
66
+ if (key.upArrow || input === 'k') {
67
+ setSelectedIndex((prev) => (prev > 0 ? prev - 1 : choices.length - 1));
33
68
  }
34
- }, [selectedChoice, statusData, isLoading]);
35
- const checkStatus = async () => {
36
- setIsLoading(true);
37
- setError(null);
38
- try {
39
- const configManager = new ConfigManager();
40
- const apiBaseUrl = await configManager.getApiBaseUrl();
41
- const serviceUrls = await configManager.getServiceUrls();
42
- const arkClient = new ArkClient(apiBaseUrl);
43
- const statusChecker = new StatusChecker(arkClient);
44
- const status = await statusChecker.checkAll(serviceUrls, apiBaseUrl);
45
- setStatusData(status);
69
+ else if (key.downArrow || input === 'j') {
70
+ setSelectedIndex((prev) => (prev < choices.length - 1 ? prev + 1 : 0));
46
71
  }
47
- catch (err) {
48
- setError(err instanceof Error ? err.message : 'Unknown error occurred');
72
+ else if (key.return) {
73
+ handleSelect(choices[selectedIndex]);
49
74
  }
50
- finally {
51
- setIsLoading(false);
75
+ else {
76
+ // Handle number keys for quick selection
77
+ const num = parseInt(input, 10);
78
+ if (!isNaN(num) && num >= 1 && num <= choices.length) {
79
+ handleSelect(choices[num - 1]);
80
+ }
52
81
  }
53
- };
54
- useInput((input, key) => {
55
- if (selectedChoice && selectedChoice !== 'exit') {
56
- if (key.escape || input === 'q' || key.return) {
57
- // For generate, only reset on specific key combinations to avoid conflicts
58
- if (selectedChoice === 'generate' && !(key.escape || input === 'q')) {
59
- return;
82
+ });
83
+ const handleSelect = async (item) => {
84
+ switch (item.value) {
85
+ case 'exit':
86
+ process.exit(0);
87
+ break;
88
+ case 'chat': {
89
+ // Unmount fullscreen app and clear screen.
90
+ await unmountInkApp();
91
+ // Import and start ChatUI in the same process
92
+ const { render } = await import('ink');
93
+ const { ArkApiProxy } = await import('../lib/arkApiProxy.js');
94
+ const ChatUI = (await import('../components/ChatUI.js')).default;
95
+ try {
96
+ const proxy = new ArkApiProxy();
97
+ const arkApiClient = await proxy.start();
98
+ // Render ChatUI as a new Ink app
99
+ render(_jsx(ChatUI, { arkApiClient: arkApiClient, arkApiProxy: proxy }));
60
100
  }
61
- setSelectedChoice(null);
62
- setStatusData(null);
63
- setError(null);
101
+ catch (error) {
102
+ const output = (await import('../lib/output.js')).default;
103
+ output.error(error instanceof Error
104
+ ? error.message
105
+ : 'Failed to connect to ARK API');
106
+ process.exit(1);
107
+ }
108
+ break;
109
+ }
110
+ case 'install': {
111
+ // Unmount fullscreen app and clear screen.
112
+ await unmountInkApp();
113
+ // NOTE: We spawn the install command as a separate process to avoid
114
+ // signal handling conflicts between Ink's useInput and inquirer's prompts.
115
+ // The signal-exit library used by inquirer conflicts with Ink's signal handlers,
116
+ // causing ExitPromptError even after proper cleanup. Spawning ensures
117
+ // a clean process environment for inquirer to work correctly.
118
+ const { spawn } = await import('child_process');
119
+ const child = spawn(process.execPath, [process.argv[1], 'install'], {
120
+ stdio: 'inherit',
121
+ });
122
+ await new Promise((resolve, reject) => {
123
+ child.on('close', (code) => {
124
+ if (code === 0) {
125
+ resolve();
126
+ }
127
+ else if (code === 130) {
128
+ // 130 is the exit code for SIGINT (Ctrl+C)
129
+ process.exit(130);
130
+ }
131
+ else {
132
+ reject(new Error(`Install command failed with code ${code}`));
133
+ }
134
+ });
135
+ child.on('error', reject);
136
+ // Forward SIGINT to child and exit
137
+ process.on('SIGINT', () => {
138
+ child.kill('SIGINT');
139
+ process.exit(130);
140
+ });
141
+ });
142
+ break;
143
+ }
144
+ case 'dashboard': {
145
+ // Unmount fullscreen app and clear screen.
146
+ await unmountInkApp();
147
+ const { openDashboard } = await import('../commands/dashboard/index.js');
148
+ await openDashboard();
149
+ break;
150
+ }
151
+ case 'status': {
152
+ // Unmount fullscreen app and clear screen.
153
+ await unmountInkApp();
154
+ const { checkStatus } = await import('../commands/status/index.js');
155
+ await checkStatus();
156
+ break;
157
+ }
158
+ case 'generate': {
159
+ const GeneratorUI = (await import('../components/GeneratorUI.js'))
160
+ .default;
161
+ render(_jsx(GeneratorUI, {}));
162
+ break;
64
163
  }
65
164
  }
66
- });
67
- const renderBanner = () => (_jsxs(Box, { flexDirection: "column", alignItems: "center", marginBottom: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: `
165
+ };
166
+ return (_jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: "column", alignItems: "center", marginBottom: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: `
68
167
  ╔═══════════════════════════════════════╗
69
168
  ║ ║
70
169
  ║ █████╗ ██████╗ ██╗ ██╗ ║
@@ -77,40 +176,9 @@ const MainMenu = () => {
77
176
  ║ Agents at Scale Platform ║
78
177
  ║ ║
79
178
  ╚═══════════════════════════════════════╝
80
- ` }), _jsx(Text, { color: "green", bold: true, children: "Welcome to ARK! \uD83D\uDE80" }), _jsx(Text, { color: "gray", children: "Interactive terminal interface for ARK agents" })] }));
81
- const renderServiceStatus = (service) => {
82
- const statusColor = service.status === 'healthy'
83
- ? 'green'
84
- : service.status === 'unhealthy'
85
- ? 'red'
86
- : 'yellow';
87
- const statusIcon = service.status === 'healthy'
88
- ? '✓'
89
- : service.status === 'unhealthy'
90
- ? '✗'
91
- : '?';
92
- return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [statusIcon, " "] }), _jsxs(Text, { bold: true, children: [service.name, ": "] }), _jsx(Text, { color: statusColor, children: service.status })] }), service.url && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: "gray", children: ["URL: ", service.url] }) })), service.details && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "gray", children: service.details }) }))] }, service.name));
93
- };
94
- const renderDependencyStatus = (dep) => {
95
- const statusColor = dep.installed ? 'green' : 'red';
96
- const statusIcon = dep.installed ? '✓' : '✗';
97
- const statusText = dep.installed ? 'installed' : 'missing';
98
- return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [statusIcon, " "] }), _jsxs(Text, { bold: true, children: [dep.name, ": "] }), _jsx(Text, { color: statusColor, children: statusText })] }), dep.version && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: "gray", children: ["Version: ", dep.version] }) })), dep.details && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "gray", children: dep.details }) }))] }, dep.name));
99
- };
100
- const renderStatus = () => {
101
- if (isLoading) {
102
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "\uD83D\uDD0D Checking ARK system status..." }), _jsx(Text, { color: "gray", children: "Please wait while we verify services and dependencies." })] }));
103
- }
104
- if (error) {
105
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: "\u274C Error checking status:" }), _jsx(Text, { color: "red", children: error }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press ESC, 'q', or Enter to return to menu..." }) })] }));
106
- }
107
- if (!statusData) {
108
- return null;
109
- }
110
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDD0D ARK System Status" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDCE1 ARK Services:" }) }), statusData.services.map(renderServiceStatus), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDEE0\uFE0F System Dependencies:" }) }), statusData.dependencies.map(renderDependencyStatus), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press ESC, 'q', or Enter to return to menu..." }) })] }));
111
- };
112
- return (_jsxs(_Fragment, { children: [renderBanner(), !selectedChoice && (_jsx(SelectInput, { items: choices, onSelect: (choice) => {
113
- setSelectedChoice(choice.value);
114
- } })), selectedChoice === 'status' && renderStatus(), selectedChoice === 'dashboard' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "green", children: "\uD83C\uDFF7\uFE0F Dashboard feature selected" }), _jsx(DashboardCLI, {})] })), selectedChoice === 'generate' && _jsx(GeneratorUI, {}), selectedChoice === 'exit' && _jsx(Text, { color: "yellow", children: "\uD83D\uDC4B Goodbye!" })] }));
179
+ ` }), _jsx(Text, { color: "green", bold: true, children: "Welcome to ARK! \uD83D\uDE80" }), _jsx(Text, { color: "gray", children: "Interactive terminal interface for ARK agents" })] }), _jsx(Box, { flexDirection: "column", paddingX: 4, marginTop: 1, children: choices.map((choice, index) => {
180
+ const isSelected = index === selectedIndex;
181
+ return (_jsxs(Box, { flexDirection: "row", paddingY: 0, children: [_jsx(Text, { color: "gray", dimColor: true, children: isSelected ? '❯ ' : ' ' }), _jsxs(Text, { color: "gray", dimColor: true, children: [index + 1, "."] }), _jsx(Box, { marginLeft: 1, width: 20, children: _jsx(Text, { color: isSelected ? 'green' : 'white', bold: isSelected, children: choice.label }) }), _jsx(Text, { color: "gray", children: choice.description })] }, choice.value));
182
+ }) })] }));
115
183
  };
116
184
  export default MainMenu;
@@ -3,7 +3,10 @@ export declare class StatusFormatter {
3
3
  /**
4
4
  * Print status check results to console
5
5
  */
6
- static printStatus(statusData: StatusData): void;
6
+ static printStatus(statusData: StatusData & {
7
+ clusterAccess?: boolean;
8
+ clusterInfo?: any;
9
+ }): void;
7
10
  private static printService;
8
11
  private static printDependency;
9
12
  }
@@ -4,18 +4,78 @@ export class StatusFormatter {
4
4
  * Print status check results to console
5
5
  */
6
6
  static printStatus(statusData) {
7
- console.log(chalk.cyan.bold('\n🔍 ARK System Status Check'));
8
- console.log(chalk.gray('Checking ARK services and dependencies...\n'));
9
- // Print services status
10
- console.log(chalk.cyan.bold('📡 ARK Services:'));
11
- for (const service of statusData.services) {
12
- StatusFormatter.printService(service);
13
- }
14
- // Print dependencies status
15
- console.log(chalk.cyan.bold('\n🛠️ System Dependencies:'));
7
+ console.log();
8
+ // Print dependencies status first
9
+ console.log(chalk.cyan.bold('system dependencies:'));
16
10
  for (const dep of statusData.dependencies) {
17
11
  StatusFormatter.printDependency(dep);
18
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')}`);
77
+ }
78
+ }
19
79
  console.log();
20
80
  }
21
81
  static printService(service) {
@@ -23,24 +83,36 @@ export class StatusFormatter {
23
83
  ? chalk.green('✓ healthy')
24
84
  : service.status === 'unhealthy'
25
85
  ? chalk.red('✗ unhealthy')
26
- : chalk.yellow('? not installed');
27
- console.log(` • ${chalk.bold(service.name)}: ${statusColor}`);
28
- if (service.url) {
29
- console.log(` ${chalk.gray(`URL: ${service.url}`)}`);
86
+ : service.status === 'warning'
87
+ ? chalk.yellow('⚠ warning')
88
+ : service.status === 'not ready'
89
+ ? chalk.yellow('○ not ready')
90
+ : chalk.yellow('? not installed');
91
+ // Show version and revision in grey after the name for healthy services
92
+ let versionInfo = '';
93
+ if (service.status === 'healthy' && (service.version || service.revision)) {
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(', ')}`);
30
100
  }
101
+ // Show details inline in grey for all statuses
102
+ let inlineDetails = '';
31
103
  if (service.details) {
32
- console.log(` ${chalk.gray(service.details)}`);
104
+ inlineDetails = chalk.gray(` ${service.details}`);
33
105
  }
106
+ console.log(` ${statusColor} ${chalk.bold(service.name)}${versionInfo}${inlineDetails}`);
34
107
  }
35
108
  static printDependency(dep) {
36
109
  const statusColor = dep.installed
37
110
  ? chalk.green('✓ installed')
38
111
  : chalk.red('✗ missing');
39
- console.log(` ${chalk.bold(dep.name)}: ${statusColor}`);
40
- if (dep.version) {
41
- console.log(` ${chalk.gray(`Version: ${dep.version}`)}`);
42
- }
43
- if (dep.details) {
112
+ const versionText = dep.version ? chalk.gray(` ${dep.version}`) : '';
113
+ console.log(` ${statusColor} ${chalk.bold(dep.name)}${versionText}`);
114
+ if (dep.details && !dep.installed) {
115
+ // Only show details if there's an issue
44
116
  console.log(` ${chalk.gray(dep.details)}`);
45
117
  }
46
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-at-scale/ark",
3
- "version": "0.1.33",
3
+ "version": "0.1.35-rc.1",
4
4
  "description": "ARK CLI - Interactive terminal interface for ARK agents",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -12,11 +12,13 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "build": "tsc && chmod +x dist/index.js",
15
- "dev": "node --loader ts-node/esm src/index.tsx",
16
- "start": "node dist/index.js",
15
+ "postbuild": "mkdir -p dist/lib/dev/tools && cp src/lib/dev/tools/*.py dist/lib/dev/tools/ 2>/dev/null || true",
16
+ "dev": "tsc --watch",
17
+ "start": "NODE_NO_WARNINGS=1 node dist/index.js",
17
18
  "clean": "rm -rf dist",
18
19
  "lint": "eslint src/ --fix && prettier --write src/",
19
20
  "lint:check": "eslint src/ && prettier --check src/",
21
+ "test": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage --coverageDirectory=./artifacts/coverage",
20
22
  "postinstall": "echo \"ARK CLI installed! Run 'ark' to try it out.\""
21
23
  },
22
24
  "keywords": [
@@ -39,7 +41,7 @@
39
41
  },
40
42
  "dependencies": {
41
43
  "@kubernetes/client-node": "^1.3.0",
42
- "@types/react": "^19.1.8",
44
+ "@modelcontextprotocol/sdk": "^1.18.0",
43
45
  "axios": "^1.7.7",
44
46
  "chalk": "^4.1.2",
45
47
  "commander": "^12.1.0",
@@ -47,9 +49,14 @@
47
49
  "execa": "^9.6.0",
48
50
  "ink": "^6.0.1",
49
51
  "ink-select-input": "^6.2.0",
52
+ "ink-spinner": "^5.0.0",
50
53
  "ink-text-input": "^6.0.0",
51
54
  "inquirer": "^12.1.0",
55
+ "marked": "^15.0.12",
56
+ "marked-terminal": "^7.3.0",
52
57
  "open": "^10.2.0",
58
+ "openai": "^5.19.1",
59
+ "ora": "^8.2.0",
53
60
  "react": "^19.1.0",
54
61
  "simple-git": "^3.28.0",
55
62
  "yaml": "^2.6.1"
@@ -58,12 +65,17 @@
58
65
  "@eslint/js": "^9.17.0",
59
66
  "@types/debug": "^4.1.12",
60
67
  "@types/inquirer": "^9.0.7",
68
+ "@types/jest": "^30.0.0",
61
69
  "@types/node": "^22.10.2",
70
+ "@types/react": "^19.1.13",
62
71
  "@typescript-eslint/eslint-plugin": "^8.20.0",
63
72
  "@typescript-eslint/parser": "^8.20.0",
64
73
  "eslint": "^9.17.0",
74
+ "jest": "^30.1.3",
65
75
  "prettier": "^3.6.2",
76
+ "ts-jest": "^29.4.1",
66
77
  "ts-node": "^10.9.2",
78
+ "tsx": "^4.20.5",
67
79
  "typescript": "^5.7.2"
68
80
  },
69
81
  "engines": {