heyvm 1.0.0

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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +621 -0
  3. package/bin/file-browser +0 -0
  4. package/bin/heyvm +0 -0
  5. package/bin/heyvm-core +0 -0
  6. package/bin/heyvm.js +61 -0
  7. package/core/README.md +51 -0
  8. package/core/cmd/heyvm-core/main.go +73 -0
  9. package/core/go.mod +25 -0
  10. package/core/go.sum +47 -0
  11. package/core/internal/auth/errors.go +29 -0
  12. package/core/internal/auth/password.go +187 -0
  13. package/core/internal/auth/provider.go +33 -0
  14. package/core/internal/auth/ssh_key.go +142 -0
  15. package/core/internal/config/config.go +111 -0
  16. package/core/internal/ipc/actions.go +738 -0
  17. package/core/internal/ipc/handler.go +281 -0
  18. package/core/internal/ipc/protocol.go +126 -0
  19. package/core/internal/sftp/errors.go +29 -0
  20. package/core/internal/sftp/manager.go +303 -0
  21. package/core/internal/sftp/types.go +30 -0
  22. package/core/internal/ssh/errors.go +23 -0
  23. package/core/internal/ssh/manager.go +226 -0
  24. package/core/internal/ssh/session.go +105 -0
  25. package/core/internal/vm/errors.go +35 -0
  26. package/core/internal/vm/models.go +84 -0
  27. package/core/internal/vm/registry.go +240 -0
  28. package/package.json +59 -0
  29. package/scripts/install.js +100 -0
  30. package/ui/README.md +43 -0
  31. package/ui/dist/App.d.ts +3 -0
  32. package/ui/dist/App.d.ts.map +1 -0
  33. package/ui/dist/App.js +142 -0
  34. package/ui/dist/App.js.map +1 -0
  35. package/ui/dist/components/ConfirmDialog.d.ts +9 -0
  36. package/ui/dist/components/ConfirmDialog.d.ts.map +1 -0
  37. package/ui/dist/components/ConfirmDialog.js +22 -0
  38. package/ui/dist/components/ConfirmDialog.js.map +1 -0
  39. package/ui/dist/components/ErrorMessage.d.ts +8 -0
  40. package/ui/dist/components/ErrorMessage.d.ts.map +1 -0
  41. package/ui/dist/components/ErrorMessage.js +10 -0
  42. package/ui/dist/components/ErrorMessage.js.map +1 -0
  43. package/ui/dist/components/Header.d.ts +8 -0
  44. package/ui/dist/components/Header.d.ts.map +1 -0
  45. package/ui/dist/components/Header.js +10 -0
  46. package/ui/dist/components/Header.js.map +1 -0
  47. package/ui/dist/components/LoadingSpinner.d.ts +7 -0
  48. package/ui/dist/components/LoadingSpinner.d.ts.map +1 -0
  49. package/ui/dist/components/LoadingSpinner.js +7 -0
  50. package/ui/dist/components/LoadingSpinner.js.map +1 -0
  51. package/ui/dist/components/StatusBar.d.ts +11 -0
  52. package/ui/dist/components/StatusBar.d.ts.map +1 -0
  53. package/ui/dist/components/StatusBar.js +11 -0
  54. package/ui/dist/components/StatusBar.js.map +1 -0
  55. package/ui/dist/core/ipc.d.ts +96 -0
  56. package/ui/dist/core/ipc.d.ts.map +1 -0
  57. package/ui/dist/core/ipc.js +310 -0
  58. package/ui/dist/core/ipc.js.map +1 -0
  59. package/ui/dist/core/types.d.ts +45 -0
  60. package/ui/dist/core/types.d.ts.map +1 -0
  61. package/ui/dist/core/types.js +3 -0
  62. package/ui/dist/core/types.js.map +1 -0
  63. package/ui/dist/hooks/useFiles.d.ts +14 -0
  64. package/ui/dist/hooks/useFiles.d.ts.map +1 -0
  65. package/ui/dist/hooks/useFiles.js +102 -0
  66. package/ui/dist/hooks/useFiles.js.map +1 -0
  67. package/ui/dist/hooks/useVM.d.ts +10 -0
  68. package/ui/dist/hooks/useVM.d.ts.map +1 -0
  69. package/ui/dist/hooks/useVM.js +54 -0
  70. package/ui/dist/hooks/useVM.js.map +1 -0
  71. package/ui/dist/hooks/useVMList.d.ts +10 -0
  72. package/ui/dist/hooks/useVMList.d.ts.map +1 -0
  73. package/ui/dist/hooks/useVMList.js +56 -0
  74. package/ui/dist/hooks/useVMList.js.map +1 -0
  75. package/ui/dist/index.d.ts +3 -0
  76. package/ui/dist/index.d.ts.map +1 -0
  77. package/ui/dist/index.js +7488 -0
  78. package/ui/dist/index.js.map +1 -0
  79. package/ui/dist/keybindings.d.ts +146 -0
  80. package/ui/dist/keybindings.d.ts.map +1 -0
  81. package/ui/dist/keybindings.js +96 -0
  82. package/ui/dist/keybindings.js.map +1 -0
  83. package/ui/dist/screens/AddVMScreen.d.ts +9 -0
  84. package/ui/dist/screens/AddVMScreen.d.ts.map +1 -0
  85. package/ui/dist/screens/AddVMScreen.js +163 -0
  86. package/ui/dist/screens/AddVMScreen.js.map +1 -0
  87. package/ui/dist/screens/VMDetailScreen.d.ts +12 -0
  88. package/ui/dist/screens/VMDetailScreen.d.ts.map +1 -0
  89. package/ui/dist/screens/VMDetailScreen.js +96 -0
  90. package/ui/dist/screens/VMDetailScreen.js.map +1 -0
  91. package/ui/dist/screens/VMListScreen.d.ts +12 -0
  92. package/ui/dist/screens/VMListScreen.d.ts.map +1 -0
  93. package/ui/dist/screens/VMListScreen.js +158 -0
  94. package/ui/dist/screens/VMListScreen.js.map +1 -0
  95. package/ui/dist/screens/tabs/FilesTab.d.ts +9 -0
  96. package/ui/dist/screens/tabs/FilesTab.d.ts.map +1 -0
  97. package/ui/dist/screens/tabs/FilesTab.js +374 -0
  98. package/ui/dist/screens/tabs/FilesTab.js.map +1 -0
  99. package/ui/dist/screens/tabs/OverviewTab.d.ts +10 -0
  100. package/ui/dist/screens/tabs/OverviewTab.d.ts.map +1 -0
  101. package/ui/dist/screens/tabs/OverviewTab.js +110 -0
  102. package/ui/dist/screens/tabs/OverviewTab.js.map +1 -0
  103. package/ui/dist/screens/tabs/TerminalTab.d.ts +9 -0
  104. package/ui/dist/screens/tabs/TerminalTab.d.ts.map +1 -0
  105. package/ui/dist/screens/tabs/TerminalTab.js +270 -0
  106. package/ui/dist/screens/tabs/TerminalTab.js.map +1 -0
  107. package/ui/dist/utils/terminalEmulator.d.ts +49 -0
  108. package/ui/dist/utils/terminalEmulator.d.ts.map +1 -0
  109. package/ui/dist/utils/terminalEmulator.js +88 -0
  110. package/ui/dist/utils/terminalEmulator.js.map +1 -0
  111. package/ui/package.json +34 -0
  112. package/ui/scripts/start-with-core.js +81 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,iBAAiB;AACjB,MAAM,CAAC,oBAAC,GAAG,OAAG,CAAC,CAAC"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Centralized key bindings configuration for heyvm
3
+ * This defines all keyboard shortcuts used throughout the application
4
+ */
5
+ export declare const KEYBINDINGS: {
6
+ readonly global: {
7
+ readonly quit: {
8
+ readonly keys: readonly ["q"];
9
+ readonly description: "quit";
10
+ };
11
+ readonly back: {
12
+ readonly keys: readonly ["escape"];
13
+ readonly description: "back";
14
+ };
15
+ };
16
+ readonly vmList: {
17
+ readonly up: {
18
+ readonly keys: readonly ["k", "up"];
19
+ readonly description: "move up";
20
+ };
21
+ readonly down: {
22
+ readonly keys: readonly ["j", "down"];
23
+ readonly description: "move down";
24
+ };
25
+ readonly select: {
26
+ readonly keys: readonly ["return"];
27
+ readonly description: "select";
28
+ };
29
+ readonly add: {
30
+ readonly keys: readonly ["a"];
31
+ readonly description: "add VM";
32
+ };
33
+ readonly delete: {
34
+ readonly keys: readonly ["d"];
35
+ readonly description: "delete";
36
+ };
37
+ readonly refresh: {
38
+ readonly keys: readonly ["r"];
39
+ readonly description: "refresh";
40
+ };
41
+ };
42
+ readonly addVM: {
43
+ readonly nextField: {
44
+ readonly keys: readonly ["return"];
45
+ readonly description: "next field";
46
+ };
47
+ readonly prevField: {
48
+ readonly keys: readonly ["shift+tab"];
49
+ readonly description: "previous field";
50
+ };
51
+ readonly navigate: {
52
+ readonly keys: readonly ["up", "down"];
53
+ readonly description: "navigate fields";
54
+ };
55
+ readonly cancel: {
56
+ readonly keys: readonly ["escape"];
57
+ readonly description: "cancel";
58
+ };
59
+ };
60
+ readonly vmDetail: {
61
+ readonly tab1: {
62
+ readonly keys: readonly ["1"];
63
+ readonly description: "overview";
64
+ };
65
+ readonly tab2: {
66
+ readonly keys: readonly ["2"];
67
+ readonly description: "terminal";
68
+ };
69
+ readonly tab3: {
70
+ readonly keys: readonly ["3"];
71
+ readonly description: "files";
72
+ };
73
+ readonly back: {
74
+ readonly keys: readonly ["escape"];
75
+ readonly description: "back to list";
76
+ };
77
+ };
78
+ readonly overview: {
79
+ readonly connect: {
80
+ readonly keys: readonly ["c"];
81
+ readonly description: "connect";
82
+ };
83
+ readonly disconnect: {
84
+ readonly keys: readonly ["d"];
85
+ readonly description: "disconnect";
86
+ };
87
+ };
88
+ readonly terminal: {};
89
+ readonly files: {
90
+ readonly switchPane: {
91
+ readonly keys: readonly ["tab"];
92
+ readonly description: "switch pane";
93
+ };
94
+ readonly up: {
95
+ readonly keys: readonly ["k", "up"];
96
+ readonly description: "move up";
97
+ };
98
+ readonly down: {
99
+ readonly keys: readonly ["j", "down"];
100
+ readonly description: "move down";
101
+ };
102
+ readonly enter: {
103
+ readonly keys: readonly ["return"];
104
+ readonly description: "open directory";
105
+ };
106
+ readonly push: {
107
+ readonly keys: readonly ["p"];
108
+ readonly description: "push (local→remote)";
109
+ };
110
+ readonly get: {
111
+ readonly keys: readonly ["g"];
112
+ readonly description: "get (remote→local)";
113
+ };
114
+ readonly delete: {
115
+ readonly keys: readonly ["d"];
116
+ readonly description: "delete file";
117
+ };
118
+ };
119
+ readonly confirm: {
120
+ readonly yes: {
121
+ readonly keys: readonly ["y", "Y"];
122
+ readonly description: "confirm";
123
+ };
124
+ readonly no: {
125
+ readonly keys: readonly ["n", "N", "escape"];
126
+ readonly description: "cancel";
127
+ };
128
+ };
129
+ };
130
+ /**
131
+ * Helper function to check if a key matches a binding
132
+ */
133
+ export declare function matchesKey(input: string, key: any, binding: {
134
+ keys: readonly string[];
135
+ }): boolean;
136
+ /**
137
+ * Format key bindings for status bar display
138
+ */
139
+ export declare function formatKeybindings(bindings: Array<{
140
+ keys: readonly string[];
141
+ description: string;
142
+ }>): Array<{
143
+ key: string;
144
+ description: string;
145
+ }>;
146
+ //# sourceMappingURL=keybindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkEd,CAAC;AAEX;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE;IAAE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAWjG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAKhJ"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Centralized key bindings configuration for heyvm
3
+ * This defines all keyboard shortcuts used throughout the application
4
+ */
5
+ export const KEYBINDINGS = {
6
+ // Global navigation
7
+ global: {
8
+ quit: { keys: ['q'], description: 'quit' },
9
+ back: { keys: ['escape'], description: 'back' },
10
+ },
11
+ // VM List Screen
12
+ vmList: {
13
+ up: { keys: ['k', 'up'], description: 'move up' },
14
+ down: { keys: ['j', 'down'], description: 'move down' },
15
+ select: { keys: ['return'], description: 'select' },
16
+ add: { keys: ['a'], description: 'add VM' },
17
+ delete: { keys: ['d'], description: 'delete' },
18
+ refresh: { keys: ['r'], description: 'refresh' },
19
+ },
20
+ // Add VM Form
21
+ addVM: {
22
+ nextField: { keys: ['return'], description: 'next field' },
23
+ prevField: { keys: ['shift+tab'], description: 'previous field' },
24
+ navigate: { keys: ['up', 'down'], description: 'navigate fields' },
25
+ cancel: { keys: ['escape'], description: 'cancel' },
26
+ },
27
+ // VM Detail Tabs
28
+ vmDetail: {
29
+ tab1: { keys: ['1'], description: 'overview' },
30
+ tab2: { keys: ['2'], description: 'terminal' },
31
+ tab3: { keys: ['3'], description: 'files' },
32
+ back: { keys: ['escape'], description: 'back to list' },
33
+ },
34
+ // Overview Tab
35
+ overview: {
36
+ connect: { keys: ['c'], description: 'connect' },
37
+ disconnect: { keys: ['d'], description: 'disconnect' },
38
+ },
39
+ // Terminal Tab
40
+ terminal: {
41
+ // All input is passed directly to the PTY session
42
+ // Special keys:
43
+ // - Ctrl+C: Send interrupt signal
44
+ // - Ctrl+D: Send EOF/exit signal
45
+ // - Ctrl+Z: Send suspend signal
46
+ // - Arrow keys: Navigate command history and cursor
47
+ // - Tab: Auto-complete (if supported by shell)
48
+ },
49
+ // Files Tab
50
+ files: {
51
+ switchPane: { keys: ['tab'], description: 'switch pane' },
52
+ up: { keys: ['k', 'up'], description: 'move up' },
53
+ down: { keys: ['j', 'down'], description: 'move down' },
54
+ enter: { keys: ['return'], description: 'open directory' },
55
+ push: { keys: ['p'], description: 'push (local→remote)' },
56
+ get: { keys: ['g'], description: 'get (remote→local)' },
57
+ delete: { keys: ['d'], description: 'delete file' },
58
+ },
59
+ // Confirmation Dialog
60
+ confirm: {
61
+ yes: { keys: ['y', 'Y'], description: 'confirm' },
62
+ no: { keys: ['n', 'N', 'escape'], description: 'cancel' },
63
+ },
64
+ };
65
+ /**
66
+ * Helper function to check if a key matches a binding
67
+ */
68
+ export function matchesKey(input, key, binding) {
69
+ return binding.keys.some(k => {
70
+ if (k === 'return')
71
+ return key.return;
72
+ if (k === 'escape')
73
+ return key.escape;
74
+ if (k === 'tab')
75
+ return key.tab;
76
+ if (k === 'up')
77
+ return key.upArrow;
78
+ if (k === 'down')
79
+ return key.downArrow;
80
+ if (k === 'left')
81
+ return key.leftArrow;
82
+ if (k === 'right')
83
+ return key.rightArrow;
84
+ return input === k;
85
+ });
86
+ }
87
+ /**
88
+ * Format key bindings for status bar display
89
+ */
90
+ export function formatKeybindings(bindings) {
91
+ return bindings.map(binding => ({
92
+ key: binding.keys[0], // Use first key as display
93
+ description: binding.description,
94
+ }));
95
+ }
96
+ //# sourceMappingURL=keybindings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../src/keybindings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { VM } from '../core/types.js';
3
+ interface AddVMScreenProps {
4
+ onCancel: () => void;
5
+ onSubmit: (vm: Partial<VM>, password?: string) => void;
6
+ }
7
+ export default function AddVMScreen({ onCancel, onSubmit }: AddVMScreenProps): React.JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=AddVMScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddVMScreen.d.ts","sourceRoot":"","sources":["../../src/screens/AddVMScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,OAAO,KAAK,EAAE,EAAE,EAAY,MAAM,kBAAkB,CAAC;AAGrD,UAAU,gBAAgB;IACzB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAKD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,gBAAgB,qBAqN3E"}
@@ -0,0 +1,163 @@
1
+ import React, { useState } from 'react';
2
+ import { Box, Text, useInput } from 'ink';
3
+ import TextInput from 'ink-text-input';
4
+ import SelectInput from 'ink-select-input';
5
+ import { ipcClient } from '../core/ipc.js';
6
+ export default function AddVMScreen({ onCancel, onSubmit }) {
7
+ const [step, setStep] = useState('auth-type');
8
+ const [authType, setAuthType] = useState('key');
9
+ const [currentField, setCurrentField] = useState('name');
10
+ const [error, setError] = useState(null);
11
+ const [testing, setTesting] = useState(false);
12
+ // Form data
13
+ const [formData, setFormData] = useState({
14
+ name: '',
15
+ host: '',
16
+ port: '22',
17
+ username: '',
18
+ keyPath: '~/.ssh/id_rsa',
19
+ password: ''
20
+ });
21
+ // Handle auth type selection
22
+ const handleAuthTypeSelect = (item) => {
23
+ setAuthType(item.value);
24
+ setStep('details');
25
+ };
26
+ // Field definitions
27
+ const fields = authType === 'key'
28
+ ? ['name', 'host', 'port', 'username', 'keyPath']
29
+ : ['name', 'host', 'port', 'username', 'password'];
30
+ const fieldLabels = {
31
+ name: 'VM Name',
32
+ host: 'Host (IP or hostname)',
33
+ port: 'Port',
34
+ username: 'Username',
35
+ keyPath: 'SSH Key Path',
36
+ password: 'Password'
37
+ };
38
+ const currentFieldIndex = fields.indexOf(currentField);
39
+ // Handle field input
40
+ const handleFieldChange = (value) => {
41
+ setFormData(prev => ({ ...prev, [currentField]: value }));
42
+ };
43
+ // Move to next field
44
+ const handleFieldSubmit = () => {
45
+ if (currentFieldIndex < fields.length - 1) {
46
+ setCurrentField(fields[currentFieldIndex + 1]);
47
+ }
48
+ else {
49
+ handleFormSubmit();
50
+ }
51
+ };
52
+ // Test connection and submit
53
+ const handleFormSubmit = async () => {
54
+ try {
55
+ setError(null);
56
+ setTesting(true);
57
+ // Validate required fields
58
+ const requiredFields = fields;
59
+ const missingFields = requiredFields.filter(field => !formData[field]);
60
+ if (missingFields.length > 0) {
61
+ setError(`Missing required fields: ${missingFields.map(f => fieldLabels[f]).join(', ')}`);
62
+ setTesting(false);
63
+ return;
64
+ }
65
+ // Build VM object
66
+ const vm = {
67
+ name: formData.name,
68
+ host: formData.host,
69
+ port: parseInt(formData.port, 10),
70
+ username: formData.username,
71
+ auth: {
72
+ type: authType,
73
+ keyPath: authType === 'key' ? formData.keyPath : undefined,
74
+ rememberPassword: authType === 'password'
75
+ }
76
+ };
77
+ // Test connection (pass password for testing, don't store yet)
78
+ await ipcClient.testConnection(vm, authType === 'password' ? formData.password : undefined);
79
+ // Submit - pass password to parent for storage after VM is added
80
+ onSubmit(vm, authType === 'password' ? formData.password : undefined);
81
+ }
82
+ catch (err) {
83
+ setError(err instanceof Error ? err.message : 'Failed to add VM');
84
+ }
85
+ finally {
86
+ setTesting(false);
87
+ }
88
+ };
89
+ // Key handlers for navigation
90
+ useInput((input, key) => {
91
+ if (key.escape) {
92
+ onCancel();
93
+ }
94
+ // Navigate between fields with arrow keys (when not editing)
95
+ if (step === 'details' && !testing) {
96
+ if (key.upArrow && currentFieldIndex > 0) {
97
+ setCurrentField(fields[currentFieldIndex - 1]);
98
+ }
99
+ if (key.downArrow && currentFieldIndex < fields.length - 1) {
100
+ setCurrentField(fields[currentFieldIndex + 1]);
101
+ }
102
+ }
103
+ });
104
+ // Auth type selection step
105
+ if (step === 'auth-type') {
106
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
107
+ React.createElement(Box, { marginBottom: 1 },
108
+ React.createElement(Text, { bold: true, color: "magenta" }, "Add New VM")),
109
+ React.createElement(Box, { marginBottom: 1 },
110
+ React.createElement(Text, null, "Select authentication method:")),
111
+ React.createElement(SelectInput, { items: [
112
+ { label: 'SSH Key (recommended)', value: 'key' },
113
+ { label: 'Password', value: 'password' }
114
+ ], onSelect: handleAuthTypeSelect }),
115
+ React.createElement(Box, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 },
116
+ React.createElement(Text, { dimColor: true },
117
+ React.createElement(Text, { bold: true }, "\u2191/\u2193"),
118
+ " navigate \u2022 ",
119
+ React.createElement(Text, { bold: true }, "Enter"),
120
+ " select \u2022 ",
121
+ React.createElement(Text, { bold: true }, "Esc"),
122
+ " cancel"))));
123
+ }
124
+ // Details form step
125
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
126
+ React.createElement(Box, { marginBottom: 1 },
127
+ React.createElement(Text, { bold: true, color: "magenta" }, "Add New VM")),
128
+ React.createElement(Box, { marginBottom: 1 },
129
+ React.createElement(Text, { dimColor: true },
130
+ "Auth: ",
131
+ authType === 'key' ? 'SSH Key' : 'Password')),
132
+ error && (React.createElement(Box, { marginBottom: 1 },
133
+ React.createElement(Text, { color: "red" },
134
+ "Error: ",
135
+ error))),
136
+ testing && (React.createElement(Box, { marginBottom: 1 },
137
+ React.createElement(Text, { color: "yellow" }, "Testing connection..."))),
138
+ !testing && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, fields.map((field, index) => {
139
+ const isActive = field === currentField;
140
+ const value = formData[field];
141
+ const label = fieldLabels[field];
142
+ return (React.createElement(Box, { key: field, marginBottom: 1, flexDirection: "column" },
143
+ React.createElement(Text, { bold: isActive },
144
+ isActive ? '>' : ' ',
145
+ " ",
146
+ label,
147
+ ":"),
148
+ isActive ? (React.createElement(Box, { marginLeft: 2 },
149
+ React.createElement(TextInput, { value: value, onChange: handleFieldChange, onSubmit: handleFieldSubmit, placeholder: label, mask: field === 'password' ? '*' : undefined }))) : (React.createElement(Box, { marginLeft: 2 },
150
+ React.createElement(Text, { dimColor: true }, value || React.createElement(Text, { italic: true }, "(empty)"))))));
151
+ }))),
152
+ React.createElement(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1 },
153
+ React.createElement(Text, { dimColor: true },
154
+ React.createElement(Text, { bold: true }, "Enter"),
155
+ " next field \u2022 ",
156
+ ' ',
157
+ React.createElement(Text, { bold: true }, "\u2191/\u2193"),
158
+ " navigate \u2022 ",
159
+ ' ',
160
+ React.createElement(Text, { bold: true }, "Esc"),
161
+ " cancel"))));
162
+ }
163
+ //# sourceMappingURL=AddVMScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddVMScreen.js","sourceRoot":"","sources":["../../src/screens/AddVMScreen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { VM, Tab } from '../core/types.js';
3
+ interface VMDetailScreenProps {
4
+ vm: VM;
5
+ activeTab: Tab;
6
+ onTabChange: (tab: Tab) => void;
7
+ isActive: boolean;
8
+ onVMUpdated?: () => Promise<void>;
9
+ }
10
+ declare const _default: React.NamedExoticComponent<VMDetailScreenProps>;
11
+ export default _default;
12
+ //# sourceMappingURL=VMDetailScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VMDetailScreen.d.ts","sourceRoot":"","sources":["../../src/screens/VMDetailScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAKhD,UAAU,mBAAmB;IAC5B,EAAE,EAAE,EAAE,CAAC;IACP,SAAS,EAAE,GAAG,CAAC;IACf,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;;AAED,wBAiGG"}
@@ -0,0 +1,96 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ import OverviewTab from './tabs/OverviewTab.js';
4
+ import TerminalTab from './tabs/TerminalTab.js';
5
+ import FilesTab from './tabs/FilesTab.js';
6
+ export default React.memo(function VMDetailScreen({ vm, activeTab, onTabChange, isActive, onVMUpdated }) {
7
+ // Tab state is now controlled by parent (no local state or key handlers)
8
+ const getStatusColor = () => {
9
+ if (vm.status === 'connected')
10
+ return 'green';
11
+ if (vm.status === 'connecting')
12
+ return 'yellow';
13
+ return 'gray';
14
+ };
15
+ const getStatusText = () => {
16
+ if (vm.status === 'connected')
17
+ return 'CONNECTED';
18
+ if (vm.status === 'connecting')
19
+ return 'CONNECTING';
20
+ return 'DISCONNECTED';
21
+ };
22
+ const getContextHelp = () => {
23
+ switch (activeTab) {
24
+ case 'overview':
25
+ return (React.createElement(Text, { dimColor: true },
26
+ React.createElement(Text, { bold: true }, "c"),
27
+ " connect \u2022 ",
28
+ React.createElement(Text, { bold: true }, "d"),
29
+ " disconnect \u2022 ",
30
+ React.createElement(Text, { bold: true }, "1/2/3"),
31
+ " tabs \u2022 ",
32
+ React.createElement(Text, { bold: true }, "Esc"),
33
+ " back"));
34
+ case 'terminal':
35
+ return (React.createElement(Text, { dimColor: true },
36
+ React.createElement(Text, { bold: true }, "PgUp/PgDn"),
37
+ " or ",
38
+ React.createElement(Text, { bold: true }, "Shift+\u2191\u2193"),
39
+ " scroll \u2022 ",
40
+ React.createElement(Text, { bold: true }, "Ctrl+O"),
41
+ " overview \u2022 ",
42
+ React.createElement(Text, { bold: true }, "Esc"),
43
+ " back"));
44
+ case 'files':
45
+ return (React.createElement(Text, { dimColor: true },
46
+ React.createElement(Text, { bold: true }, "j/k"),
47
+ " navigate \u2022 ",
48
+ React.createElement(Text, { bold: true }, "Tab"),
49
+ " pane \u2022 ",
50
+ React.createElement(Text, { bold: true }, "p"),
51
+ " push \u2022 ",
52
+ React.createElement(Text, { bold: true }, "g"),
53
+ " get \u2022 ",
54
+ React.createElement(Text, { bold: true }, "/"),
55
+ " search \u2022 ",
56
+ React.createElement(Text, { bold: true }, "Esc"),
57
+ " back"));
58
+ default:
59
+ return null;
60
+ }
61
+ };
62
+ return (React.createElement(Box, { flexDirection: "column", padding: 1, height: "100%" },
63
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
64
+ React.createElement(Box, null,
65
+ React.createElement(Text, { bold: true, color: "cyan" }, vm.status === 'connected' ? '● ' : vm.status === 'connecting' ? '◐ ' : '○ '),
66
+ React.createElement(Text, { bold: true }, vm.name),
67
+ React.createElement(Text, null, ' '),
68
+ React.createElement(Text, { bold: true, color: getStatusColor() }, getStatusText())),
69
+ React.createElement(Box, null,
70
+ React.createElement(Text, { dimColor: true },
71
+ " ",
72
+ vm.username,
73
+ "@",
74
+ vm.host)),
75
+ React.createElement(Box, { marginTop: 1 },
76
+ React.createElement(Text, { dimColor: true }, '─'.repeat(60)))),
77
+ React.createElement(Box, { marginBottom: 1 },
78
+ React.createElement(Text, null,
79
+ React.createElement(Text, { bold: activeTab === 'overview', color: activeTab === 'overview' ? 'cyan' : 'gray' }, "Overview"),
80
+ React.createElement(Text, { dimColor: true },
81
+ " ",
82
+ activeTab === 'overview' ? '▶' : '|',
83
+ " "),
84
+ React.createElement(Text, { bold: activeTab === 'terminal', color: activeTab === 'terminal' ? 'cyan' : 'gray' }, "Terminal"),
85
+ React.createElement(Text, { dimColor: true },
86
+ " ",
87
+ activeTab === 'terminal' ? '▶' : '|',
88
+ " "),
89
+ React.createElement(Text, { bold: activeTab === 'files', color: activeTab === 'files' ? 'cyan' : 'gray' }, "Files"))),
90
+ React.createElement(Box, { flexGrow: 1, flexDirection: "column" },
91
+ activeTab === 'overview' && React.createElement(OverviewTab, { vm: vm, isActive: isActive, onVMUpdated: onVMUpdated }),
92
+ activeTab === 'terminal' && React.createElement(TerminalTab, { vm: vm, isActive: isActive }),
93
+ activeTab === 'files' && React.createElement(FilesTab, { vm: vm, isActive: isActive })),
94
+ React.createElement(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, getContextHelp())));
95
+ });
96
+ //# sourceMappingURL=VMDetailScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VMDetailScreen.js","sourceRoot":"","sources":["../../src/screens/VMDetailScreen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { VM } from '../core/types.js';
3
+ interface VMListScreenProps {
4
+ selectedVM: VM | null;
5
+ onSelectVM: (vm: VM) => void;
6
+ isActive: boolean;
7
+ onVMDeleted?: () => void;
8
+ vmListVersion?: number;
9
+ }
10
+ export default function VMListScreen({ selectedVM, onSelectVM, isActive, onVMDeleted, vmListVersion }: VMListScreenProps): React.JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=VMListScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VMListScreen.d.ts","sourceRoot":"","sources":["../../src/screens/VMListScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAG3C,UAAU,iBAAiB;IAC1B,UAAU,EAAE,EAAE,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,iBAAiB,qBAsLvH"}