rackmind-cli 0.1.2

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 (183) hide show
  1. package/README.md +179 -0
  2. package/bin/rackmind.js +6 -0
  3. package/dist/ai/client.d.ts +71 -0
  4. package/dist/ai/client.d.ts.map +1 -0
  5. package/dist/ai/client.js +198 -0
  6. package/dist/ai/client.js.map +1 -0
  7. package/dist/ai/system-prompt.d.ts +20 -0
  8. package/dist/ai/system-prompt.d.ts.map +1 -0
  9. package/dist/ai/system-prompt.js +169 -0
  10. package/dist/ai/system-prompt.js.map +1 -0
  11. package/dist/ai/tool-executor.d.ts +27 -0
  12. package/dist/ai/tool-executor.d.ts.map +1 -0
  13. package/dist/ai/tool-executor.js +184 -0
  14. package/dist/ai/tool-executor.js.map +1 -0
  15. package/dist/ai/tools.d.ts +7 -0
  16. package/dist/ai/tools.d.ts.map +1 -0
  17. package/dist/ai/tools.js +203 -0
  18. package/dist/ai/tools.js.map +1 -0
  19. package/dist/commands/config.d.ts +21 -0
  20. package/dist/commands/config.d.ts.map +1 -0
  21. package/dist/commands/config.js +169 -0
  22. package/dist/commands/config.js.map +1 -0
  23. package/dist/commands/connect.d.ts +7 -0
  24. package/dist/commands/connect.d.ts.map +1 -0
  25. package/dist/commands/connect.js +117 -0
  26. package/dist/commands/connect.js.map +1 -0
  27. package/dist/commands/containers.d.ts +5 -0
  28. package/dist/commands/containers.d.ts.map +1 -0
  29. package/dist/commands/containers.js +83 -0
  30. package/dist/commands/containers.js.map +1 -0
  31. package/dist/commands/exec.d.ts +5 -0
  32. package/dist/commands/exec.d.ts.map +1 -0
  33. package/dist/commands/exec.js +133 -0
  34. package/dist/commands/exec.js.map +1 -0
  35. package/dist/commands/lifecycle.d.ts +7 -0
  36. package/dist/commands/lifecycle.d.ts.map +1 -0
  37. package/dist/commands/lifecycle.js +213 -0
  38. package/dist/commands/lifecycle.js.map +1 -0
  39. package/dist/commands/logs.d.ts +5 -0
  40. package/dist/commands/logs.d.ts.map +1 -0
  41. package/dist/commands/logs.js +117 -0
  42. package/dist/commands/logs.js.map +1 -0
  43. package/dist/commands/report.d.ts +6 -0
  44. package/dist/commands/report.d.ts.map +1 -0
  45. package/dist/commands/report.js +203 -0
  46. package/dist/commands/report.js.map +1 -0
  47. package/dist/commands/servers.d.ts +17 -0
  48. package/dist/commands/servers.d.ts.map +1 -0
  49. package/dist/commands/servers.js +116 -0
  50. package/dist/commands/servers.js.map +1 -0
  51. package/dist/commands/status.d.ts +5 -0
  52. package/dist/commands/status.d.ts.map +1 -0
  53. package/dist/commands/status.js +174 -0
  54. package/dist/commands/status.js.map +1 -0
  55. package/dist/commands/vms.d.ts +5 -0
  56. package/dist/commands/vms.d.ts.map +1 -0
  57. package/dist/commands/vms.js +83 -0
  58. package/dist/commands/vms.js.map +1 -0
  59. package/dist/config/crypto.d.ts +20 -0
  60. package/dist/config/crypto.d.ts.map +1 -0
  61. package/dist/config/crypto.js +78 -0
  62. package/dist/config/crypto.js.map +1 -0
  63. package/dist/config/index.d.ts +21 -0
  64. package/dist/config/index.d.ts.map +1 -0
  65. package/dist/config/index.js +158 -0
  66. package/dist/config/index.js.map +1 -0
  67. package/dist/config/types.d.ts +263 -0
  68. package/dist/config/types.d.ts.map +1 -0
  69. package/dist/config/types.js +83 -0
  70. package/dist/config/types.js.map +1 -0
  71. package/dist/globals.d.ts +22 -0
  72. package/dist/globals.d.ts.map +1 -0
  73. package/dist/globals.js +43 -0
  74. package/dist/globals.js.map +1 -0
  75. package/dist/index.d.ts +2 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +399 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/interactive/App.d.ts +3 -0
  80. package/dist/interactive/App.d.ts.map +1 -0
  81. package/dist/interactive/App.js +103 -0
  82. package/dist/interactive/App.js.map +1 -0
  83. package/dist/interactive/components/Header.d.ts +8 -0
  84. package/dist/interactive/components/Header.d.ts.map +1 -0
  85. package/dist/interactive/components/Header.js +20 -0
  86. package/dist/interactive/components/Header.js.map +1 -0
  87. package/dist/interactive/components/InputBar.d.ts +9 -0
  88. package/dist/interactive/components/InputBar.d.ts.map +1 -0
  89. package/dist/interactive/components/InputBar.js +89 -0
  90. package/dist/interactive/components/InputBar.js.map +1 -0
  91. package/dist/interactive/components/MessageList.d.ts +9 -0
  92. package/dist/interactive/components/MessageList.d.ts.map +1 -0
  93. package/dist/interactive/components/MessageList.js +28 -0
  94. package/dist/interactive/components/MessageList.js.map +1 -0
  95. package/dist/interactive/components/Spinner.d.ts +7 -0
  96. package/dist/interactive/components/Spinner.d.ts.map +1 -0
  97. package/dist/interactive/components/Spinner.js +19 -0
  98. package/dist/interactive/components/Spinner.js.map +1 -0
  99. package/dist/interactive/components/StatusBar.d.ts +10 -0
  100. package/dist/interactive/components/StatusBar.d.ts.map +1 -0
  101. package/dist/interactive/components/StatusBar.js +7 -0
  102. package/dist/interactive/components/StatusBar.js.map +1 -0
  103. package/dist/interactive/components/StreamingMessage.d.ts +7 -0
  104. package/dist/interactive/components/StreamingMessage.d.ts.map +1 -0
  105. package/dist/interactive/components/StreamingMessage.js +9 -0
  106. package/dist/interactive/components/StreamingMessage.js.map +1 -0
  107. package/dist/interactive/components/ToolIndicator.d.ts +7 -0
  108. package/dist/interactive/components/ToolIndicator.d.ts.map +1 -0
  109. package/dist/interactive/components/ToolIndicator.js +10 -0
  110. package/dist/interactive/components/ToolIndicator.js.map +1 -0
  111. package/dist/interactive/components/ToolOutput.d.ts +8 -0
  112. package/dist/interactive/components/ToolOutput.d.ts.map +1 -0
  113. package/dist/interactive/components/ToolOutput.js +9 -0
  114. package/dist/interactive/components/ToolOutput.js.map +1 -0
  115. package/dist/interactive/components/WelcomeScreen.d.ts +9 -0
  116. package/dist/interactive/components/WelcomeScreen.d.ts.map +1 -0
  117. package/dist/interactive/components/WelcomeScreen.js +8 -0
  118. package/dist/interactive/components/WelcomeScreen.js.map +1 -0
  119. package/dist/interactive/launch.d.ts +6 -0
  120. package/dist/interactive/launch.d.ts.map +1 -0
  121. package/dist/interactive/launch.js +30 -0
  122. package/dist/interactive/launch.js.map +1 -0
  123. package/dist/interactive/slashCommands.d.ts +13 -0
  124. package/dist/interactive/slashCommands.d.ts.map +1 -0
  125. package/dist/interactive/slashCommands.js +102 -0
  126. package/dist/interactive/slashCommands.js.map +1 -0
  127. package/dist/interactive/useRackMind.d.ts +30 -0
  128. package/dist/interactive/useRackMind.d.ts.map +1 -0
  129. package/dist/interactive/useRackMind.js +241 -0
  130. package/dist/interactive/useRackMind.js.map +1 -0
  131. package/dist/oneshot/run.d.ts +2 -0
  132. package/dist/oneshot/run.d.ts.map +1 -0
  133. package/dist/oneshot/run.js +195 -0
  134. package/dist/oneshot/run.js.map +1 -0
  135. package/dist/server/client.d.ts +89 -0
  136. package/dist/server/client.d.ts.map +1 -0
  137. package/dist/server/client.js +239 -0
  138. package/dist/server/client.js.map +1 -0
  139. package/dist/server/proxmox.d.ts +160 -0
  140. package/dist/server/proxmox.d.ts.map +1 -0
  141. package/dist/server/proxmox.js +219 -0
  142. package/dist/server/proxmox.js.map +1 -0
  143. package/dist/server/ssh.d.ts +80 -0
  144. package/dist/server/ssh.d.ts.map +1 -0
  145. package/dist/server/ssh.js +262 -0
  146. package/dist/server/ssh.js.map +1 -0
  147. package/dist/utils/ascii.d.ts +3 -0
  148. package/dist/utils/ascii.d.ts.map +1 -0
  149. package/dist/utils/ascii.js +16 -0
  150. package/dist/utils/ascii.js.map +1 -0
  151. package/dist/utils/format.d.ts +7 -0
  152. package/dist/utils/format.d.ts.map +1 -0
  153. package/dist/utils/format.js +20 -0
  154. package/dist/utils/format.js.map +1 -0
  155. package/dist/utils/history.d.ts +23 -0
  156. package/dist/utils/history.d.ts.map +1 -0
  157. package/dist/utils/history.js +107 -0
  158. package/dist/utils/history.js.map +1 -0
  159. package/dist/utils/logger.d.ts +9 -0
  160. package/dist/utils/logger.d.ts.map +1 -0
  161. package/dist/utils/logger.js +51 -0
  162. package/dist/utils/logger.js.map +1 -0
  163. package/dist/utils/markdown.d.ts +12 -0
  164. package/dist/utils/markdown.d.ts.map +1 -0
  165. package/dist/utils/markdown.js +76 -0
  166. package/dist/utils/markdown.js.map +1 -0
  167. package/dist/utils/prompt.d.ts +25 -0
  168. package/dist/utils/prompt.d.ts.map +1 -0
  169. package/dist/utils/prompt.js +133 -0
  170. package/dist/utils/prompt.js.map +1 -0
  171. package/dist/utils/retry.d.ts +37 -0
  172. package/dist/utils/retry.d.ts.map +1 -0
  173. package/dist/utils/retry.js +122 -0
  174. package/dist/utils/retry.js.map +1 -0
  175. package/dist/utils/shutdown.d.ts +22 -0
  176. package/dist/utils/shutdown.d.ts.map +1 -0
  177. package/dist/utils/shutdown.js +94 -0
  178. package/dist/utils/shutdown.js.map +1 -0
  179. package/dist/utils/table.d.ts +38 -0
  180. package/dist/utils/table.d.ts.map +1 -0
  181. package/dist/utils/table.js +150 -0
  182. package/dist/utils/table.js.map +1 -0
  183. package/package.json +71 -0
@@ -0,0 +1,241 @@
1
+ // ---------------------------------------------------------------------------
2
+ // useRackMind hook — core state management for the interactive REPL
3
+ // ---------------------------------------------------------------------------
4
+ // Manages conversation history, streaming state, server connection,
5
+ // and tool execution tracking. Provides a `sendMessage` function
6
+ // that components call when the user submits a query.
7
+ // ---------------------------------------------------------------------------
8
+ import { useState, useCallback, useRef, useEffect } from 'react';
9
+ import { AIClient } from '../ai/client.js';
10
+ import { ServerClient } from '../server/client.js';
11
+ import { getAnthropicApiKey, getActiveProfile, readConfig } from '../config/index.js';
12
+ import { logger } from '../utils/logger.js';
13
+ import { onShutdown, removeShutdownHandler } from '../utils/shutdown.js';
14
+ // ---------------------------------------------------------------------------
15
+ // ID generation
16
+ // ---------------------------------------------------------------------------
17
+ let messageCounter = 0;
18
+ function nextMessageId() {
19
+ messageCounter += 1;
20
+ return `msg-${Date.now()}-${messageCounter}`;
21
+ }
22
+ // ---------------------------------------------------------------------------
23
+ // Hook
24
+ // ---------------------------------------------------------------------------
25
+ export function useRackMind() {
26
+ const [messages, setMessages] = useState([]);
27
+ const [connection, setConnection] = useState({
28
+ status: 'disconnected',
29
+ serverAlias: null,
30
+ error: null,
31
+ });
32
+ const [isThinking, setIsThinking] = useState(false);
33
+ const [streamingText, setStreamingText] = useState('');
34
+ const [activeTools, setActiveTools] = useState([]);
35
+ const [error, setError] = useState(null);
36
+ const config = readConfig();
37
+ const model = config.preferences.model;
38
+ // Refs for mutable state that callbacks need
39
+ const serverClientRef = useRef(null);
40
+ const aiClientRef = useRef(null);
41
+ const historyRef = useRef([]);
42
+ const toolExecutionsRef = useRef([]);
43
+ // -----------------------------------------------------------------------
44
+ // Connect to server
45
+ // -----------------------------------------------------------------------
46
+ const connect = useCallback(async () => {
47
+ setConnection({
48
+ status: 'connecting',
49
+ serverAlias: null,
50
+ error: null,
51
+ });
52
+ try {
53
+ const apiKey = getAnthropicApiKey();
54
+ if (!apiKey) {
55
+ setConnection({
56
+ status: 'error',
57
+ serverAlias: null,
58
+ error: 'No API key configured. Run: rackmind config set-api-key',
59
+ });
60
+ return;
61
+ }
62
+ const profile = getActiveProfile();
63
+ if (!profile) {
64
+ setConnection({
65
+ status: 'error',
66
+ serverAlias: null,
67
+ error: 'No active server. Run: rackmind connect <alias>',
68
+ });
69
+ return;
70
+ }
71
+ // Create server client and connect SSH
72
+ const client = new ServerClient(profile);
73
+ await client.connectSSH();
74
+ serverClientRef.current = client;
75
+ // Create AI client
76
+ aiClientRef.current = new AIClient({
77
+ apiKey,
78
+ model: config.preferences.model,
79
+ });
80
+ setConnection({
81
+ status: 'connected',
82
+ serverAlias: profile.alias,
83
+ error: null,
84
+ });
85
+ logger.info('Interactive mode connected', { alias: profile.alias });
86
+ }
87
+ catch (err) {
88
+ const message = err instanceof Error ? err.message : String(err);
89
+ logger.error('Interactive mode connection failed', { error: message });
90
+ setConnection({
91
+ status: 'error',
92
+ serverAlias: null,
93
+ error: message,
94
+ });
95
+ }
96
+ }, [config.preferences.model]);
97
+ // -----------------------------------------------------------------------
98
+ // Disconnect
99
+ // -----------------------------------------------------------------------
100
+ const disconnect = useCallback(() => {
101
+ if (serverClientRef.current) {
102
+ serverClientRef.current.dispose();
103
+ serverClientRef.current = null;
104
+ }
105
+ aiClientRef.current = null;
106
+ historyRef.current = [];
107
+ setConnection({
108
+ status: 'disconnected',
109
+ serverAlias: null,
110
+ error: null,
111
+ });
112
+ }, []);
113
+ // Clean up on unmount + register signal handler cleanup
114
+ useEffect(() => {
115
+ const cleanupFn = () => {
116
+ if (serverClientRef.current) {
117
+ serverClientRef.current.dispose();
118
+ serverClientRef.current = null;
119
+ }
120
+ };
121
+ onShutdown(cleanupFn);
122
+ return () => {
123
+ cleanupFn();
124
+ removeShutdownHandler(cleanupFn);
125
+ };
126
+ }, []);
127
+ // -----------------------------------------------------------------------
128
+ // Send message
129
+ // -----------------------------------------------------------------------
130
+ const sendMessage = useCallback(async (text) => {
131
+ if (!aiClientRef.current || !serverClientRef.current || !connection.serverAlias) {
132
+ setError('Not connected to a server.');
133
+ return;
134
+ }
135
+ const trimmed = text.trim();
136
+ if (!trimmed)
137
+ return;
138
+ // Add user message
139
+ const userMessage = {
140
+ id: nextMessageId(),
141
+ role: 'user',
142
+ content: trimmed,
143
+ timestamp: Date.now(),
144
+ };
145
+ setMessages((prev) => [...prev, userMessage]);
146
+ setIsThinking(true);
147
+ setStreamingText('');
148
+ setError(null);
149
+ toolExecutionsRef.current = [];
150
+ let accumulatedText = '';
151
+ const callbacks = {
152
+ onText: (chunk) => {
153
+ accumulatedText += chunk;
154
+ setStreamingText(accumulatedText);
155
+ },
156
+ onToolStart: (toolName) => {
157
+ setActiveTools((prev) => [...prev, toolName]);
158
+ },
159
+ onToolEnd: (toolName) => {
160
+ setActiveTools((prev) => prev.filter((t) => t !== toolName));
161
+ },
162
+ onToolResult: (execution) => {
163
+ toolExecutionsRef.current.push(execution);
164
+ },
165
+ onError: (errorMsg) => {
166
+ setError(errorMsg);
167
+ },
168
+ };
169
+ try {
170
+ const updatedHistory = await aiClientRef.current.chatMultiTurn(trimmed, historyRef.current, serverClientRef.current, connection.serverAlias, callbacks);
171
+ historyRef.current = updatedHistory;
172
+ // Add assistant message with final text
173
+ const assistantMessage = {
174
+ id: nextMessageId(),
175
+ role: 'assistant',
176
+ content: accumulatedText,
177
+ timestamp: Date.now(),
178
+ toolExecutions: toolExecutionsRef.current.length > 0
179
+ ? [...toolExecutionsRef.current]
180
+ : undefined,
181
+ };
182
+ setMessages((prev) => [...prev, assistantMessage]);
183
+ }
184
+ catch (err) {
185
+ const message = err instanceof Error ? err.message : String(err);
186
+ logger.error('Interactive chat failed', { error: message });
187
+ // Provide human-readable errors
188
+ let userError = message;
189
+ if (message.includes('401') || message.includes('authentication_error')) {
190
+ userError = 'Anthropic API authentication failed. Check your API key.';
191
+ }
192
+ else if (message.includes('429') || message.includes('rate_limit')) {
193
+ userError = 'Rate limit hit. Please wait and try again.';
194
+ }
195
+ else if (message.includes('overloaded')) {
196
+ userError = 'Anthropic API is overloaded. Try again in a moment.';
197
+ }
198
+ else if (message.includes('ECONNREFUSED') || message.includes('ETIMEDOUT')) {
199
+ userError = 'Cannot connect to server. Check your configuration.';
200
+ }
201
+ const errorMessage = {
202
+ id: nextMessageId(),
203
+ role: 'system',
204
+ content: userError,
205
+ timestamp: Date.now(),
206
+ };
207
+ setMessages((prev) => [...prev, errorMessage]);
208
+ }
209
+ finally {
210
+ setIsThinking(false);
211
+ setStreamingText('');
212
+ setActiveTools([]);
213
+ }
214
+ }, [connection.serverAlias]);
215
+ // -----------------------------------------------------------------------
216
+ // Clear messages
217
+ // -----------------------------------------------------------------------
218
+ const clearMessages = useCallback(() => {
219
+ setMessages([]);
220
+ historyRef.current = [];
221
+ setStreamingText('');
222
+ setError(null);
223
+ }, []);
224
+ // -----------------------------------------------------------------------
225
+ // Return
226
+ // -----------------------------------------------------------------------
227
+ return {
228
+ messages,
229
+ connection,
230
+ isThinking,
231
+ streamingText,
232
+ activeTools,
233
+ model,
234
+ error,
235
+ sendMessage,
236
+ clearMessages,
237
+ connect,
238
+ disconnect,
239
+ };
240
+ }
241
+ //# sourceMappingURL=useRackMind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRackMind.js","sourceRoot":"","sources":["../../src/interactive/useRackMind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runOneshot(prompt: string): Promise<void>;
2
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/oneshot/run.ts"],"names":[],"mappings":"AAgGA,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8I9D"}
@@ -0,0 +1,195 @@
1
+ // ---------------------------------------------------------------------------
2
+ // One-shot command execution — rackmind "query" or rackmind ask "query"
3
+ // ---------------------------------------------------------------------------
4
+ // Loads config, connects to the active server, sends the query to Claude
5
+ // with full server context and tools, streams the response to stdout, and
6
+ // exits with 0 (success) or 1 (error).
7
+ // ---------------------------------------------------------------------------
8
+ import chalk from 'chalk';
9
+ import ora from 'ora';
10
+ import { getAnthropicApiKey, getActiveProfile, readConfig, setAnthropicApiKey, } from '../config/index.js';
11
+ import { ServerClient } from '../server/client.js';
12
+ import { AIClient } from '../ai/client.js';
13
+ import { formatError } from '../utils/format.js';
14
+ import { logger } from '../utils/logger.js';
15
+ import { promptSecret } from '../utils/prompt.js';
16
+ import { renderMarkdown } from '../utils/markdown.js';
17
+ import { registerSignalHandlers, onShutdown } from '../utils/shutdown.js';
18
+ import { isQuietMode, isJsonMode } from '../globals.js';
19
+ // ---------------------------------------------------------------------------
20
+ // API key setup
21
+ // ---------------------------------------------------------------------------
22
+ /**
23
+ * Ensure an Anthropic API key is available.
24
+ * If not configured, prompt the user to enter one (only in TTY mode).
25
+ * Returns the API key or null if unavailable.
26
+ */
27
+ async function ensureApiKey() {
28
+ let apiKey = getAnthropicApiKey();
29
+ if (apiKey)
30
+ return apiKey;
31
+ // Check if we're in an interactive terminal
32
+ if (!process.stdin.isTTY) {
33
+ process.stderr.write(formatError('No Anthropic API key configured. Run `rackmind` interactively to set one up, ' +
34
+ 'or set it with: rackmind config set-api-key') + '\n');
35
+ return null;
36
+ }
37
+ // Prompt the user
38
+ process.stderr.write(chalk.yellow('\nNo Anthropic API key configured.\n') +
39
+ chalk.dim('Get one at https://console.anthropic.com/settings/keys\n\n'));
40
+ apiKey = await promptSecret('Enter your Anthropic API key');
41
+ if (!apiKey) {
42
+ process.stderr.write(formatError('API key is required.') + '\n');
43
+ return null;
44
+ }
45
+ // Validate format
46
+ if (!apiKey.startsWith('sk-ant-')) {
47
+ process.stderr.write(chalk.yellow('Warning: API key does not start with "sk-ant-". Saving anyway.\n'));
48
+ }
49
+ // Save encrypted
50
+ setAnthropicApiKey(apiKey);
51
+ process.stderr.write(chalk.green('API key saved.\n\n'));
52
+ return apiKey;
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Active server check
56
+ // ---------------------------------------------------------------------------
57
+ function ensureActiveServer() {
58
+ const profile = getActiveProfile();
59
+ if (profile)
60
+ return { alias: profile.alias };
61
+ process.stderr.write(formatError('No active server configured. Run `rackmind connect <alias>` to set one up.') +
62
+ '\n');
63
+ return null;
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Oneshot runner
67
+ // ---------------------------------------------------------------------------
68
+ export async function runOneshot(prompt) {
69
+ let serverClient = null;
70
+ // Register signal handlers for graceful shutdown
71
+ registerSignalHandlers();
72
+ try {
73
+ // 1. Ensure API key
74
+ const apiKey = await ensureApiKey();
75
+ if (!apiKey) {
76
+ process.exit(1);
77
+ }
78
+ // 2. Ensure active server
79
+ const server = ensureActiveServer();
80
+ if (!server) {
81
+ process.exit(1);
82
+ }
83
+ // 3. Create server client and connect SSH
84
+ const quiet = isQuietMode();
85
+ const spinner = quiet
86
+ ? null
87
+ : ora({
88
+ text: 'Connecting to server...',
89
+ stream: process.stderr,
90
+ }).start();
91
+ serverClient = ServerClient.fromActiveProfile();
92
+ // Register cleanup handler for SSH
93
+ onShutdown(() => {
94
+ serverClient?.dispose();
95
+ });
96
+ await serverClient.connectSSH();
97
+ if (spinner)
98
+ spinner.text = 'Fetching server context...';
99
+ // 4. Create AI client
100
+ const config = readConfig();
101
+ const aiClient = new AIClient({
102
+ apiKey,
103
+ model: config.preferences.model,
104
+ });
105
+ if (spinner)
106
+ spinner.succeed('Connected');
107
+ // 5. Set up stream callbacks — collect full response for markdown rendering
108
+ let fullText = '';
109
+ const isTTY = Boolean(process.stdout.isTTY);
110
+ const jsonMode = isJsonMode();
111
+ const callbacks = {
112
+ onText: (text) => {
113
+ fullText += text;
114
+ // Stream raw text to non-TTY (piped) output for scriptability
115
+ // Also stream raw text in JSON mode (we wrap it after)
116
+ if (!isTTY && !jsonMode) {
117
+ process.stdout.write(text);
118
+ }
119
+ },
120
+ onToolStart: (_toolName, label) => {
121
+ if (!quiet) {
122
+ process.stderr.write(chalk.cyan(` ⚡ Executing: ${label}\n`));
123
+ }
124
+ },
125
+ onToolEnd: (_toolName, label, isError) => {
126
+ if (!quiet) {
127
+ if (isError) {
128
+ process.stderr.write(chalk.red(` ✗ ${label}\n`));
129
+ }
130
+ else {
131
+ process.stderr.write(chalk.green(` ✓ ${label}\n`));
132
+ }
133
+ }
134
+ },
135
+ onError: (error) => {
136
+ process.stderr.write(formatError(error) + '\n');
137
+ },
138
+ };
139
+ // 6. Run the AI query
140
+ if (!quiet) {
141
+ process.stderr.write(chalk.dim(`\nQuerying: "${prompt}"\n\n`));
142
+ }
143
+ await aiClient.chat(prompt, serverClient, server.alias, callbacks);
144
+ // Output the response
145
+ if (fullText) {
146
+ if (jsonMode) {
147
+ // JSON mode: wrap the response in a structured object
148
+ const output = {
149
+ model: aiClient.getModel(),
150
+ prompt,
151
+ response: fullText,
152
+ };
153
+ process.stdout.write(JSON.stringify(output, null, 2) + '\n');
154
+ }
155
+ else if (isTTY) {
156
+ // TTY: render with markdown formatting
157
+ const rendered = renderMarkdown(fullText);
158
+ process.stdout.write(rendered + '\n');
159
+ }
160
+ else {
161
+ // Piped: raw text was already streamed, add a trailing newline
162
+ process.stdout.write('\n');
163
+ }
164
+ }
165
+ // Clean up and exit
166
+ serverClient.dispose();
167
+ process.exit(0);
168
+ }
169
+ catch (err) {
170
+ // Clean up on error
171
+ if (serverClient) {
172
+ serverClient.dispose();
173
+ }
174
+ const message = err instanceof Error ? err.message : String(err);
175
+ logger.error('Oneshot execution failed', { error: message });
176
+ // Provide human-readable error messages
177
+ if (message.includes('401') || message.includes('authentication_error')) {
178
+ process.stderr.write(formatError('Anthropic API authentication failed. Check your API key.') + '\n');
179
+ }
180
+ else if (message.includes('429') || message.includes('rate_limit')) {
181
+ process.stderr.write(formatError('Anthropic API rate limit hit. Please wait and try again.') + '\n');
182
+ }
183
+ else if (message.includes('ECONNREFUSED') || message.includes('ETIMEDOUT')) {
184
+ process.stderr.write(formatError('Cannot connect to server. Check your server configuration.') + '\n');
185
+ }
186
+ else if (message.includes('overloaded')) {
187
+ process.stderr.write(formatError('Anthropic API is overloaded. Please try again in a moment.') + '\n');
188
+ }
189
+ else {
190
+ process.stderr.write(formatError(message) + '\n');
191
+ }
192
+ process.exit(1);
193
+ }
194
+ }
195
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/oneshot/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { type ProxmoxNode, type ProxmoxContainer, type ProxmoxVM, type ProxmoxGuestStatus, type ProxmoxGuestConfig, type ProxmoxVersion, type ProxmoxResource } from './proxmox.js';
2
+ import { type SSHExecResult, type StreamCallback } from './ssh.js';
3
+ import type { ServerProfile } from '../config/types.js';
4
+ export interface ServerStatus {
5
+ /** Whether the Proxmox API is reachable */
6
+ apiConnected: boolean;
7
+ /** Whether SSH is connected */
8
+ sshConnected: boolean;
9
+ /** Proxmox version info (null if API unreachable) */
10
+ proxmoxVersion: ProxmoxVersion | null;
11
+ /** SSH hostname (null if SSH unreachable) */
12
+ sshHostname: string | null;
13
+ /** Active server profile alias */
14
+ serverAlias: string;
15
+ /** Base URL for the Proxmox API */
16
+ apiUrl: string;
17
+ /** Resolved node name */
18
+ node: string | null;
19
+ /** Error messages for failed connections */
20
+ errors: string[];
21
+ }
22
+ export declare class ServerClient {
23
+ private readonly profile;
24
+ private readonly proxmox;
25
+ private readonly ssh;
26
+ private resolvedNode;
27
+ constructor(profile: ServerProfile);
28
+ /**
29
+ * Create a ServerClient from the active server profile in config.
30
+ * Throws if no active server is configured.
31
+ */
32
+ static fromActiveProfile(): ServerClient;
33
+ /** Connect SSH (Proxmox API is stateless, no connect needed) */
34
+ connectSSH(): Promise<void>;
35
+ /** Disconnect SSH */
36
+ disconnectSSH(): void;
37
+ /** Test all connections and return status */
38
+ getStatus(): Promise<ServerStatus>;
39
+ /**
40
+ * Get the node name to use for API calls.
41
+ * Uses the profile's configured node, or auto-detects from the API.
42
+ */
43
+ getNodeName(): Promise<string>;
44
+ /** List all nodes in the cluster */
45
+ listNodes(): Promise<ProxmoxNode[]>;
46
+ /** Get status of a specific node */
47
+ getNodeStatus(node?: string): Promise<ProxmoxNode>;
48
+ /** List all LXC containers on the active node */
49
+ listContainers(node?: string): Promise<ProxmoxContainer[]>;
50
+ /** Get status of an LXC container */
51
+ getContainerStatus(vmid: number, node?: string): Promise<ProxmoxGuestStatus>;
52
+ /** Get configuration of an LXC container */
53
+ getContainerConfig(vmid: number, node?: string): Promise<ProxmoxGuestConfig>;
54
+ /** Start an LXC container */
55
+ startContainer(vmid: number, node?: string): Promise<string>;
56
+ /** Stop an LXC container */
57
+ stopContainer(vmid: number, node?: string): Promise<string>;
58
+ /** Restart an LXC container */
59
+ restartContainer(vmid: number, node?: string): Promise<string>;
60
+ /** List all QEMU VMs on the active node */
61
+ listVMs(node?: string): Promise<ProxmoxVM[]>;
62
+ /** Get status of a QEMU VM */
63
+ getVMStatus(vmid: number, node?: string): Promise<ProxmoxGuestStatus>;
64
+ /** Get configuration of a QEMU VM */
65
+ getVMConfig(vmid: number, node?: string): Promise<ProxmoxGuestConfig>;
66
+ /** Start a QEMU VM */
67
+ startVM(vmid: number, node?: string): Promise<string>;
68
+ /** Stop a QEMU VM */
69
+ stopVM(vmid: number, node?: string): Promise<string>;
70
+ /** Restart a QEMU VM */
71
+ restartVM(vmid: number, node?: string): Promise<string>;
72
+ /** Get all resources across the cluster */
73
+ listResources(type?: string): Promise<ProxmoxResource[]>;
74
+ /** Execute a command on the Proxmox host via SSH (auto-reconnects) */
75
+ execOnHost(command: string): Promise<SSHExecResult>;
76
+ /** Execute a command on the Proxmox host with streaming output (auto-reconnects) */
77
+ execOnHostStream(command: string, onData: StreamCallback): Promise<number | null>;
78
+ /** Execute a command inside an LXC container via SSH + pct exec (auto-reconnects) */
79
+ execInContainer(vmid: number, command: string): Promise<SSHExecResult>;
80
+ /** Execute a command inside an LXC container with streaming output (auto-reconnects) */
81
+ execInContainerStream(vmid: number, command: string, onData: StreamCallback): Promise<number | null>;
82
+ /** Clean up all connections */
83
+ dispose(): void;
84
+ }
85
+ export { ProxmoxClient, ProxmoxApiError } from './proxmox.js';
86
+ export { SSHConnection, SSHConnectionError } from './ssh.js';
87
+ export type { ProxmoxNode, ProxmoxContainer, ProxmoxVM, ProxmoxGuestStatus, ProxmoxGuestConfig, ProxmoxVersion, ProxmoxResource, ProxmoxClientOptions, } from './proxmox.js';
88
+ export type { SSHClientOptions, SSHExecResult, StreamCallback } from './ssh.js';
89
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/server/client.ts"],"names":[],"mappings":"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"}