rl-rockcli 0.0.9 → 0.0.11

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 (90) hide show
  1. package/commands/attach/basic-repl.js +212 -0
  2. package/commands/attach/cleanup-history.js +189 -0
  3. package/commands/attach/cleanup-manager.js +163 -0
  4. package/commands/attach/copy-ui/copyRepl.js +195 -0
  5. package/commands/attach/copy-ui/index.js +7 -0
  6. package/commands/attach/copy-ui/render/outputBlock.js +25 -0
  7. package/commands/attach/copy-ui/viewport/viewport.js +23 -0
  8. package/commands/attach/copy-ui/viewport/wheel.js +14 -0
  9. package/commands/attach/history-manager.js +507 -0
  10. package/commands/attach/history-session.js +48 -0
  11. package/commands/attach/ink-repl/InkREPL.js +1507 -0
  12. package/commands/attach/ink-repl/builtinCommands.js +1253 -0
  13. package/commands/attach/ink-repl/components/ConnectingScreen.js +76 -0
  14. package/commands/attach/ink-repl/components/Console.js +191 -0
  15. package/commands/attach/ink-repl/components/DetailView.js +148 -0
  16. package/commands/attach/ink-repl/components/DropdownMenu.js +86 -0
  17. package/commands/attach/ink-repl/components/InputArea.js +125 -0
  18. package/commands/attach/ink-repl/components/InputLine.js +18 -0
  19. package/commands/attach/ink-repl/components/OutputArea.js +22 -0
  20. package/commands/attach/ink-repl/components/OutputItem.js +96 -0
  21. package/commands/attach/ink-repl/components/ShellLayout.js +61 -0
  22. package/commands/attach/ink-repl/components/Spinner.js +79 -0
  23. package/commands/attach/ink-repl/components/StatusBar.js +106 -0
  24. package/commands/attach/ink-repl/components/WelcomeBanner.js +48 -0
  25. package/commands/attach/ink-repl/contexts/LayoutContext.js +12 -0
  26. package/commands/attach/ink-repl/contexts/ThemeContext.js +43 -0
  27. package/commands/attach/ink-repl/hooks/useFunctionKeys.js +70 -0
  28. package/commands/attach/ink-repl/hooks/useMouse.js +162 -0
  29. package/commands/attach/ink-repl/hooks/useResources.js +132 -0
  30. package/commands/attach/ink-repl/hooks/useSpinner.js +49 -0
  31. package/commands/attach/ink-repl/index.js +112 -0
  32. package/commands/attach/ink-repl/package.json +3 -0
  33. package/commands/attach/ink-repl/replState.js +947 -0
  34. package/commands/attach/ink-repl/shortcuts/defaultKeybindings.js +138 -0
  35. package/commands/attach/ink-repl/shortcuts/index.js +332 -0
  36. package/commands/attach/ink-repl/themes/defaultDark.js +18 -0
  37. package/commands/attach/ink-repl/themes/defaultLight.js +18 -0
  38. package/commands/attach/ink-repl/themes/index.js +4 -0
  39. package/commands/attach/ink-repl/themes/themeManager.js +45 -0
  40. package/commands/attach/ink-repl/themes/themeTokens.js +15 -0
  41. package/commands/attach/ink-repl/utils/atCompletion.js +346 -0
  42. package/commands/attach/ink-repl/utils/clipboard.js +50 -0
  43. package/commands/attach/ink-repl/utils/consoleLogger.js +81 -0
  44. package/commands/attach/ink-repl/utils/exitCodeHandler.js +49 -0
  45. package/commands/attach/ink-repl/utils/exitCodeTips.js +56 -0
  46. package/commands/attach/ink-repl/utils/formatTime.js +12 -0
  47. package/commands/attach/ink-repl/utils/outputSelection.js +120 -0
  48. package/commands/attach/ink-repl/utils/outputViewport.js +77 -0
  49. package/commands/attach/ink-repl/utils/paginatedFileLoading.js +76 -0
  50. package/commands/attach/ink-repl/utils/paramHint.js +60 -0
  51. package/commands/attach/ink-repl/utils/parseError.js +174 -0
  52. package/commands/attach/ink-repl/utils/pathCompletion.js +167 -0
  53. package/commands/attach/ink-repl/utils/remotePathSafety.js +56 -0
  54. package/commands/attach/ink-repl/utils/replSelection.js +205 -0
  55. package/commands/attach/ink-repl/utils/responseFormatter.js +127 -0
  56. package/commands/attach/ink-repl/utils/textWrap.js +117 -0
  57. package/commands/attach/ink-repl/utils/truncate.js +115 -0
  58. package/commands/attach/opentui-repl/App.tsx +891 -0
  59. package/commands/attach/opentui-repl/builtinCommands.ts +80 -0
  60. package/commands/attach/opentui-repl/components/ConfirmDialog.tsx +116 -0
  61. package/commands/attach/opentui-repl/components/ConnectingScreen.tsx +131 -0
  62. package/commands/attach/opentui-repl/components/Console.tsx +73 -0
  63. package/commands/attach/opentui-repl/components/DetailView.tsx +45 -0
  64. package/commands/attach/opentui-repl/components/DropdownMenu.tsx +130 -0
  65. package/commands/attach/opentui-repl/components/ExecutionStatus.tsx +66 -0
  66. package/commands/attach/opentui-repl/components/Header.tsx +24 -0
  67. package/commands/attach/opentui-repl/components/OutputArea.tsx +25 -0
  68. package/commands/attach/opentui-repl/components/OutputBlock.tsx +108 -0
  69. package/commands/attach/opentui-repl/components/PromptInput.tsx +109 -0
  70. package/commands/attach/opentui-repl/components/StatusBar.tsx +63 -0
  71. package/commands/attach/opentui-repl/components/Toast.tsx +65 -0
  72. package/commands/attach/opentui-repl/components/WelcomeBanner.tsx +41 -0
  73. package/commands/attach/opentui-repl/contexts/ReplContext.tsx +137 -0
  74. package/commands/attach/opentui-repl/contexts/SessionContext.tsx +32 -0
  75. package/commands/attach/opentui-repl/contexts/ThemeContext.tsx +70 -0
  76. package/commands/attach/opentui-repl/contexts/ToastContext.tsx +69 -0
  77. package/commands/attach/opentui-repl/contexts/toast-logic.js +71 -0
  78. package/commands/attach/opentui-repl/hooks/useResources.ts +102 -0
  79. package/commands/attach/opentui-repl/hooks/useSpinner.ts +46 -0
  80. package/commands/attach/opentui-repl/index.js +99 -0
  81. package/commands/attach/opentui-repl/keybindings.ts +39 -0
  82. package/commands/attach/opentui-repl/package.json +3 -0
  83. package/commands/attach/opentui-repl/render.tsx +72 -0
  84. package/commands/attach/opentui-repl/tsconfig.json +12 -0
  85. package/commands/attach/repl.js +791 -0
  86. package/commands/attach/sandbox-id-resolver.js +56 -0
  87. package/commands/attach/session-manager.js +307 -0
  88. package/commands/attach/ui-mode.js +146 -0
  89. package/commands/attach.js +186 -0
  90. package/package.json +1 -1
@@ -0,0 +1,195 @@
1
+ 'use strict';
2
+
3
+ const readline = require('readline');
4
+ const { renderOutputBlock } = require('./render/outputBlock');
5
+
6
+ /**
7
+ * 底层错误消息友好化(简化版)
8
+ * 用于 CommonJS 模块
9
+ */
10
+ function friendlyErrorMessage(message) {
11
+ if (!message || typeof message !== 'string') {
12
+ return '未知错误';
13
+ }
14
+
15
+ // 常见底层错误映射
16
+ const errorMap = {
17
+ 'First argument must be an Error object': '网络连接异常,请检查网络后重试',
18
+ 'ECONNREFUSED': '无法连接到服务器',
19
+ 'ETIMEDOUT': '请求超时,请重试',
20
+ 'ENOTFOUND': '无法解析服务器地址',
21
+ 'ECONNRESET': '网络连接已断开',
22
+ 'socket hang up': '网络连接已断开',
23
+ 'Network Error': '网络异常',
24
+ };
25
+
26
+ // 精确匹配
27
+ if (errorMap[message]) {
28
+ return errorMap[message];
29
+ }
30
+
31
+ // 部分匹配
32
+ for (const [key, friendly] of Object.entries(errorMap)) {
33
+ if (message.includes(key)) {
34
+ return friendly;
35
+ }
36
+ }
37
+
38
+ // 网络相关关键词
39
+ const networkKeywords = ['network', 'socket', 'connection', 'connect', '网络'];
40
+ const lowerMessage = message.toLowerCase();
41
+ if (networkKeywords.some(kw => lowerMessage.includes(kw))) {
42
+ return '网络连接异常,请检查网络后重试';
43
+ }
44
+
45
+ return message;
46
+ }
47
+
48
+ async function startCopyREPL(_options) {
49
+ const options = _options || {};
50
+ const {
51
+ initialPrompt = '$ ',
52
+ sessionManager,
53
+ historyManager,
54
+ onExit,
55
+ _test,
56
+ } = options;
57
+
58
+ if (!sessionManager) {
59
+ throw new Error('startCopyREPL requires sessionManager');
60
+ }
61
+
62
+ // Minimal non-interactive hook for unit tests.
63
+ if (_test && _test.runOnce && typeof _test.runOnce.command === 'string') {
64
+ const command = _test.runOnce.command;
65
+ const result = await sessionManager.execute(command);
66
+ const exitCode = result?.exit_code ?? 0;
67
+ let output = result && typeof result.output === 'string' ? result.output : '';
68
+
69
+ // Handle abnormal exit codes with helpful messages
70
+ if (exitCode === -1) {
71
+ const hint = output ? '' : 'Command terminated abnormally (exit code -1). This may indicate a timeout, signal termination, or internal error.';
72
+ output = output || hint;
73
+ } else if (exitCode === 137) {
74
+ output += output ? '\n' : '';
75
+ output += '[Process killed (exit code 137). Possibly OOM or manually terminated.]';
76
+ } else if (exitCode === 143) {
77
+ output += output ? '\n' : '';
78
+ output += '[Process terminated (exit code 143). Received SIGTERM.]';
79
+ }
80
+
81
+ const block = renderOutputBlock({
82
+ prompt: initialPrompt,
83
+ command,
84
+ output,
85
+ isFirst: true,
86
+ });
87
+ if (block) {
88
+ process.stdout.write(block);
89
+ if (!block.endsWith('\n')) process.stdout.write('\n');
90
+ }
91
+ if (onExit) await onExit();
92
+ return;
93
+ }
94
+
95
+ // Interactive mode: minimal readline loop (will be extended later).
96
+ const rl = readline.createInterface({
97
+ input: process.stdin,
98
+ output: process.stdout,
99
+ terminal: true,
100
+ historySize: 500,
101
+ });
102
+
103
+ if (historyManager && typeof historyManager.getHistory === 'function') {
104
+ try {
105
+ const history = await historyManager.getHistory();
106
+ if (Array.isArray(history) && history.length > 0) {
107
+ rl.history = history.slice().reverse();
108
+ }
109
+ } catch {
110
+ // ignore
111
+ }
112
+ }
113
+
114
+ let isFirst = true;
115
+ let closed = false;
116
+ let pending = Promise.resolve();
117
+
118
+ const cleanup = async () => {
119
+ if (closed) return;
120
+ closed = true;
121
+ try { rl.close(); } catch {}
122
+ if (onExit) await onExit();
123
+ };
124
+
125
+ rl.on('SIGINT', () => {
126
+ process.stdout.write('\n');
127
+ cleanup().catch(() => {});
128
+ });
129
+
130
+ rl.setPrompt(initialPrompt);
131
+ rl.prompt();
132
+
133
+ return new Promise((resolve) => {
134
+ rl.on('line', (rawLine) => {
135
+ const command = String(rawLine || '').replace(/\r?\n/g, '').trim();
136
+ pending = pending.then(async () => {
137
+ if (closed) return;
138
+ if (!command) {
139
+ rl.prompt();
140
+ return;
141
+ }
142
+ try {
143
+ if (historyManager && typeof historyManager.addCommand === 'function') {
144
+ await historyManager.addCommand(command);
145
+ }
146
+ } catch {
147
+ // ignore
148
+ }
149
+
150
+ try {
151
+ const result = await sessionManager.execute(command);
152
+ const exitCode = result?.exit_code ?? 0;
153
+ let output = result && typeof result.output === 'string' ? result.output : '';
154
+
155
+ // Handle abnormal exit codes with helpful messages
156
+ if (exitCode === -1) {
157
+ const hint = output ? '' : 'Command terminated abnormally (exit code -1). This may indicate a timeout, signal termination, or internal error.';
158
+ output = output || hint;
159
+ } else if (exitCode === 137) {
160
+ output += output ? '\n' : '';
161
+ output += '[Process killed (exit code 137). Possibly OOM or manually terminated.]';
162
+ } else if (exitCode === 143) {
163
+ output += output ? '\n' : '';
164
+ output += '[Process terminated (exit code 143). Received SIGTERM.]';
165
+ }
166
+
167
+ const block = renderOutputBlock({
168
+ prompt: initialPrompt,
169
+ command,
170
+ output,
171
+ isFirst,
172
+ });
173
+ isFirst = false;
174
+ if (block) {
175
+ process.stdout.write(block);
176
+ if (!block.endsWith('\n')) process.stdout.write('\n');
177
+ }
178
+ } catch (error) {
179
+ const message = error && error.message ? error.message : String(error);
180
+ process.stderr.write(`Error: ${friendlyErrorMessage(message)}\n`);
181
+ }
182
+
183
+ rl.prompt();
184
+ });
185
+ });
186
+
187
+ rl.on('close', () => {
188
+ pending.finally(() => resolve());
189
+ });
190
+ });
191
+ }
192
+
193
+ module.exports = {
194
+ startCopyREPL,
195
+ };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ const { startCopyREPL } = require('./copyRepl');
4
+
5
+ module.exports = {
6
+ startCopyREPL,
7
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ function normalizeNewlines(s) {
4
+ return String(s || '').replace(/\r\n/g, '\n');
5
+ }
6
+
7
+ function renderOutputBlock({ prompt, command, output, isFirst }) {
8
+ const lines = [];
9
+ if (!isFirst) lines.push('');
10
+
11
+ lines.push(`${String(prompt || '')}${String(command || '')}`);
12
+
13
+ const out = normalizeNewlines(output);
14
+ if (out) {
15
+ out.split('\n').forEach((l) => {
16
+ lines.push(` ${l}`);
17
+ });
18
+ }
19
+
20
+ return lines.join('\n');
21
+ }
22
+
23
+ module.exports = {
24
+ renderOutputBlock,
25
+ };
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ function clampOffset({ linesLength, height, offset }) {
4
+ const safeHeight = Math.max(0, Number(height) || 0);
5
+ const safeLines = Math.max(0, Number(linesLength) || 0);
6
+ const maxOffset = safeHeight > 0 ? Math.max(0, safeLines - safeHeight) : Math.max(0, safeLines);
7
+ const n = Number(offset) || 0;
8
+ if (n < 0) return 0;
9
+ if (n > maxOffset) return maxOffset;
10
+ return n;
11
+ }
12
+
13
+ function computeVisibleLines({ lines, height, offset }) {
14
+ const arr = Array.isArray(lines) ? lines : [];
15
+ const h = Math.max(0, Number(height) || 0);
16
+ const off = clampOffset({ linesLength: arr.length, height: h, offset });
17
+ return arr.slice(off, off + h);
18
+ }
19
+
20
+ module.exports = {
21
+ clampOffset,
22
+ computeVisibleLines,
23
+ };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ const { clampOffset } = require('./viewport');
4
+
5
+ function applyWheel({ offset, deltaY, linesLength, height, linesPerTick }) {
6
+ const step = Math.max(1, Number(linesPerTick) || 3);
7
+ const dir = Number(deltaY) || 0;
8
+ const next = (Number(offset) || 0) + (dir > 0 ? step : dir < 0 ? -step : 0);
9
+ return clampOffset({ linesLength, height, offset: next });
10
+ }
11
+
12
+ module.exports = {
13
+ applyWheel,
14
+ };