rl-rockcli 0.0.2 → 0.0.3

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 (75) hide show
  1. package/README.md +400 -0
  2. package/index.js +51 -21
  3. package/package.json +1 -1
  4. package/commands/log/core/constants.js +0 -237
  5. package/commands/log/core/display.js +0 -370
  6. package/commands/log/core/search.js +0 -330
  7. package/commands/log/core/tail.js +0 -216
  8. package/commands/log/core/utils.js +0 -424
  9. package/commands/log.js +0 -298
  10. package/commands/sandbox/core/log-bridge.js +0 -119
  11. package/commands/sandbox/core/replay/analyzer.js +0 -311
  12. package/commands/sandbox/core/replay/batch-orchestrator.js +0 -536
  13. package/commands/sandbox/core/replay/batch-task.js +0 -369
  14. package/commands/sandbox/core/replay/concurrent-display.js +0 -70
  15. package/commands/sandbox/core/replay/concurrent-orchestrator.js +0 -170
  16. package/commands/sandbox/core/replay/data-source.js +0 -86
  17. package/commands/sandbox/core/replay/display.js +0 -231
  18. package/commands/sandbox/core/replay/executor.js +0 -634
  19. package/commands/sandbox/core/replay/history-fetcher.js +0 -124
  20. package/commands/sandbox/core/replay/index.js +0 -338
  21. package/commands/sandbox/core/replay/loghouse-data-source.js +0 -177
  22. package/commands/sandbox/core/replay/pid-mapping.js +0 -26
  23. package/commands/sandbox/core/replay/request.js +0 -109
  24. package/commands/sandbox/core/replay/worker.js +0 -166
  25. package/commands/sandbox/core/session.js +0 -346
  26. package/commands/sandbox/log-bridge.js +0 -2
  27. package/commands/sandbox/ray.js +0 -2
  28. package/commands/sandbox/replay/analyzer.js +0 -311
  29. package/commands/sandbox/replay/batch-orchestrator.js +0 -536
  30. package/commands/sandbox/replay/batch-task.js +0 -369
  31. package/commands/sandbox/replay/concurrent-display.js +0 -70
  32. package/commands/sandbox/replay/concurrent-orchestrator.js +0 -170
  33. package/commands/sandbox/replay/display.js +0 -231
  34. package/commands/sandbox/replay/executor.js +0 -634
  35. package/commands/sandbox/replay/history-fetcher.js +0 -118
  36. package/commands/sandbox/replay/index.js +0 -338
  37. package/commands/sandbox/replay/pid-mapping.js +0 -26
  38. package/commands/sandbox/replay/request.js +0 -109
  39. package/commands/sandbox/replay/worker.js +0 -166
  40. package/commands/sandbox/replay.js +0 -2
  41. package/commands/sandbox/session.js +0 -2
  42. package/commands/sandbox-original.js +0 -1393
  43. package/commands/sandbox.js +0 -499
  44. package/help/help.json +0 -1071
  45. package/help/middleware.js +0 -71
  46. package/help/renderer.js +0 -800
  47. package/lib/plugin-context.js +0 -40
  48. package/sdks/sandbox/core/client.js +0 -845
  49. package/sdks/sandbox/core/config.js +0 -70
  50. package/sdks/sandbox/core/types.js +0 -74
  51. package/sdks/sandbox/httpLogger.js +0 -251
  52. package/sdks/sandbox/index.js +0 -9
  53. package/utils/asciiArt.js +0 -138
  54. package/utils/bun-compat.js +0 -59
  55. package/utils/ciPipelines.js +0 -138
  56. package/utils/cli.js +0 -17
  57. package/utils/command-router.js +0 -79
  58. package/utils/configManager.js +0 -503
  59. package/utils/dependency-resolver.js +0 -135
  60. package/utils/eagleeye_traceid.js +0 -151
  61. package/utils/envDetector.js +0 -78
  62. package/utils/execution_logger.js +0 -415
  63. package/utils/featureManager.js +0 -68
  64. package/utils/firstTimeTip.js +0 -44
  65. package/utils/hook-manager.js +0 -125
  66. package/utils/http-logger.js +0 -264
  67. package/utils/i18n.js +0 -139
  68. package/utils/image-progress.js +0 -159
  69. package/utils/logger.js +0 -154
  70. package/utils/plugin-loader.js +0 -124
  71. package/utils/plugin-manager.js +0 -348
  72. package/utils/ray_cli_wrapper.js +0 -746
  73. package/utils/sandbox-client.js +0 -419
  74. package/utils/terminal.js +0 -32
  75. package/utils/tips.js +0 -106
@@ -1,419 +0,0 @@
1
- /**
2
- * Sandbox Client Adapter
3
- *
4
- * 适配 rl-rock 的 Sandbox 类,提供与原 sdks/sandbox 兼容的 API
5
- */
6
-
7
- const { Sandbox: RlRockSandbox } = require('rl-rock');
8
- const logger = require('./logger');
9
-
10
- /**
11
- * SandboxConfig 配置类(兼容旧 API)
12
- */
13
- class SandboxConfig {
14
- constructor(options = {}) {
15
- this.image = options.image || 'python:3.11';
16
- this.autoClearSeconds = options.autoClearSeconds || 300;
17
- this.startupTimeout = options.startupTimeout || 120;
18
- this.memory = options.memory || '8g';
19
- this.cpus = options.cpus !== undefined ? options.cpus : 2.0;
20
- this.baseUrl = options.baseUrl;
21
- this.xrlAuthorization = options.xrlAuthorization;
22
- this.extraHeaders = options.extraHeaders || {};
23
- this.cluster = options.cluster || 'zb';
24
- this.namespace = options.namespace || null;
25
- this.userId = options.userId || null;
26
- this.experimentId = options.experimentId || null;
27
- this.waitForAlive = options.waitForAlive !== undefined ? options.waitForAlive : false;
28
- }
29
-
30
- validate() {
31
- if (!this.baseUrl) {
32
- throw new Error('baseUrl is required');
33
- }
34
- if (!this.image) {
35
- throw new Error('image is required');
36
- }
37
- }
38
- }
39
-
40
- /**
41
- * SandboxClient - 适配 rl-rock 的 Sandbox 类
42
- *
43
- * 提供与原 sdks/sandbox/client.js 兼容的 API
44
- */
45
- class SandboxClient {
46
- constructor(config, options = {}) {
47
- // 支持 SandboxConfig 实例或普通对象
48
- if (config instanceof SandboxConfig) {
49
- this._config = config;
50
- } else {
51
- this._config = new SandboxConfig(config);
52
- }
53
- this._config.validate();
54
-
55
- // 创建 rl-rock Sandbox 实例(只传递非 null 的参数)
56
- // 注意:rl-rock 不自动处理 xrlAuthorization,需要通过 extraHeaders 传递
57
- const extraHeaders = {
58
- ...this._config.extraHeaders,
59
- };
60
-
61
- // 将 xrlAuthorization 添加到 extraHeaders(rl-rock 要求通过 headers 传递)
62
- if (this._config.xrlAuthorization) {
63
- extraHeaders['XRL-Authorization'] = `Bearer ${this._config.xrlAuthorization}`;
64
- }
65
-
66
- const sandboxConfig = {
67
- baseUrl: this._config.baseUrl,
68
- image: this._config.image,
69
- autoClearSeconds: this._config.autoClearSeconds,
70
- startupTimeout: this._config.startupTimeout,
71
- memory: this._config.memory,
72
- cpus: this._config.cpus,
73
- cluster: this._config.cluster,
74
- extraHeaders,
75
- };
76
-
77
- // 只添加非 null 的可选参数(rl-rock 会自动添加到 headers)
78
- if (this._config.userId) {
79
- sandboxConfig.userId = this._config.userId;
80
- }
81
- if (this._config.experimentId) {
82
- sandboxConfig.experimentId = this._config.experimentId;
83
- }
84
- if (this._config.namespace) {
85
- sandboxConfig.namespace = this._config.namespace;
86
- }
87
-
88
- this._sandbox = new RlRockSandbox(sandboxConfig);
89
-
90
- // 兼容旧 API:允许直接设置 sandboxId
91
- this._sandboxId = null;
92
- this._onLog = options.onLog || null;
93
- }
94
-
95
- /**
96
- * 兼容旧 API:直接设置 sandboxId
97
- */
98
- set _sandboxId(value) {
99
- this._sandbox.sandboxId = value;
100
- }
101
-
102
- get _sandboxId() {
103
- return this._sandbox.sandboxId;
104
- }
105
-
106
- get sandboxId() {
107
- return this._sandbox.getSandboxId();
108
- }
109
-
110
- get hostName() {
111
- return this._sandbox.getHostName();
112
- }
113
-
114
- get hostIp() {
115
- return this._sandbox.getHostIp();
116
- }
117
-
118
- /**
119
- * 公开的 config getter(用于测试和外部访问)
120
- */
121
- get config() {
122
- return this._config;
123
- }
124
-
125
- /**
126
- * Log a message
127
- */
128
- _log(level, message) {
129
- if (this._onLog) {
130
- this._onLog(level, message);
131
- } else {
132
- logger[level](message);
133
- }
134
- }
135
-
136
- /**
137
- * Start a new sandbox instance
138
- */
139
- async start() {
140
- await this._sandbox.start();
141
-
142
- const sandboxId = this._sandbox.getSandboxId();
143
- const hostName = this._sandbox.getHostName();
144
- const hostIp = this._sandbox.getHostIp();
145
-
146
- let isAlive = false;
147
- if (this._config.waitForAlive) {
148
- // Wait for sandbox to be alive
149
- await this._waitForAlive();
150
- isAlive = true;
151
- }
152
-
153
- return {
154
- sandboxId,
155
- hostName,
156
- hostIp,
157
- isAlive,
158
- };
159
- }
160
-
161
- /**
162
- * Wait for sandbox to be alive
163
- */
164
- async _waitForAlive() {
165
- const startTime = Date.now();
166
- const timeout = this._config.startupTimeout * 1000;
167
- const loadingChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
168
- let loadingIndex = 0;
169
- let lastLogTime = 0;
170
-
171
- this._log('info', 'Waiting for sandbox to be ready...');
172
-
173
- while (Date.now() - startTime < timeout) {
174
- const status = await this._sandbox.getStatus();
175
-
176
- if (status.isAlive) {
177
- this._log('info', `Sandbox is ready (ID: ${this._sandbox.getSandboxId()})`);
178
- return;
179
- }
180
-
181
- const now = Date.now();
182
- if (now - lastLogTime > 3000) {
183
- loadingIndex = (loadingIndex + 1) % loadingChars.length;
184
- const elapsed = Math.floor((now - startTime) / 1000);
185
- this._log('info', `${loadingChars[loadingIndex]} Starting sandbox... (${elapsed}s elapsed)`);
186
- lastLogTime = now;
187
- }
188
-
189
- await new Promise(resolve => setTimeout(resolve, 3000));
190
- }
191
-
192
- throw new Error(`Sandbox did not become alive within ${this._config.startupTimeout}s`);
193
- }
194
-
195
- /**
196
- * Get sandbox status
197
- */
198
- async getStatus() {
199
- return this._sandbox.getStatus();
200
- }
201
-
202
- /**
203
- * Check if sandbox is alive
204
- */
205
- async isAlive() {
206
- try {
207
- const status = await this.getStatus();
208
- return {
209
- isAlive: status.isAlive,
210
- message: status.hostName || '',
211
- };
212
- } catch (error) {
213
- logger.warn(`Failed to check isAlive: ${error.message}`);
214
- throw new Error(`Failed to check isAlive: ${error.message}`);
215
- }
216
- }
217
-
218
- /**
219
- * Execute a command in the sandbox
220
- */
221
- async execute(command) {
222
- let commandArray;
223
- if (Array.isArray(command)) {
224
- commandArray = command;
225
- } else {
226
- commandArray = ['sh', '-c', command];
227
- }
228
-
229
- const result = await this._sandbox.execute({ command: commandArray });
230
-
231
- return {
232
- stdout: result.stdout,
233
- stderr: result.stderr,
234
- exit_code: result.exitCode,
235
- };
236
- }
237
-
238
- /**
239
- * Stop the sandbox
240
- */
241
- async stop() {
242
- if (!this._sandbox.sandboxId) {
243
- logger.warn('No sandbox ID to stop');
244
- return;
245
- }
246
- await this._sandbox.stop();
247
- logger.info(`Sandbox ${this._sandbox.sandboxId} stopped successfully`);
248
- }
249
-
250
- /**
251
- * Create a bash session
252
- */
253
- async createSession(options = {}) {
254
- return this._sandbox.createSession({
255
- session: options.session || 'default',
256
- startupSource: options.startupSource || [],
257
- envEnable: options.envEnable || false,
258
- env: options.env,
259
- remoteUser: options.remoteUser,
260
- });
261
- }
262
-
263
- /**
264
- * Run a command in a session
265
- */
266
- async runInSession(action) {
267
- const result = await this._sandbox.arun(action.command, {
268
- session: action.session || 'default',
269
- mode: 'normal',
270
- timeout: action.timeout,
271
- });
272
-
273
- return {
274
- output: result.output || '',
275
- exit_code: result.exitCode,
276
- };
277
- }
278
-
279
- /**
280
- * Run a command asynchronously in a session using nohup
281
- */
282
- async runInSessionAsync(action) {
283
- const result = await this._sandbox.arun(action.command, {
284
- session: action.session || 'default',
285
- mode: 'nohup',
286
- waitTimeout: (action.timeout || 3600000) / 1000,
287
- waitInterval: (action.pollInterval || 5000) / 1000,
288
- });
289
-
290
- return {
291
- output: result.output || '',
292
- exit_code: result.exitCode || 0,
293
- timeout: result.failureReason?.includes('timeout') || false,
294
- warning: result.failureReason || null,
295
- };
296
- }
297
-
298
- /**
299
- * Write content to a file
300
- */
301
- async writeFile(content, path) {
302
- const result = await this._sandbox.write_file({ content, path });
303
- return {
304
- success: result.success,
305
- message: result.message,
306
- };
307
- }
308
-
309
- /**
310
- * Read a file (with optional line range)
311
- */
312
- async readFile(filePath, startLine, endLine) {
313
- if (startLine && endLine) {
314
- if (startLine < 1 || endLine < startLine) {
315
- throw new Error(`Invalid line range: startLine=${startLine}, endLine=${endLine}`);
316
- }
317
- if (endLine - startLine > 1000) {
318
- throw new Error(`Line range too large: ${endLine - startLine} lines (max 1000)`);
319
- }
320
-
321
- const command = `sed -n ${startLine},${endLine}p ${filePath}`;
322
- const result = await this.execute(command);
323
-
324
- if (result.exit_code !== 0) {
325
- throw new Error(`Failed to read file ${filePath}: ${result.stderr}`);
326
- }
327
-
328
- return { content: result.stdout };
329
- }
330
-
331
- // No line range, use read_file directly
332
- const result = await this._sandbox.read_file({ path: filePath });
333
- return { content: result.content };
334
- }
335
-
336
- /**
337
- * Upload a file to the sandbox
338
- */
339
- async uploadFile(localPath, targetPath) {
340
- const result = await this._sandbox.uploadByPath(localPath, targetPath);
341
- return result;
342
- }
343
-
344
- /**
345
- * Download a file from the sandbox
346
- */
347
- async downloadFile(filePath) {
348
- const result = await this._sandbox.read_file({ path: filePath });
349
- return result;
350
- }
351
-
352
- /**
353
- * Close a session
354
- */
355
- async closeSession(session = 'default') {
356
- return this._sandbox.closeSession({ session });
357
- }
358
-
359
- /**
360
- * Close the sandbox
361
- */
362
- async close() {
363
- await this.stop();
364
- }
365
-
366
- /**
367
- * Make a generic HTTP request to the sandbox API
368
- */
369
- async makeRequest(request) {
370
- const { method, uri, requestBody, headers } = request;
371
- const url = `${this._config.baseUrl}${uri}`;
372
-
373
- const axios = require('axios');
374
- const requestHeaders = {
375
- 'X-Cluster': this._config.cluster,
376
- 'Content-Type': 'application/json',
377
- };
378
-
379
- if (this._config.xrlAuthorization) {
380
- requestHeaders['XRL-Authorization'] = `Bearer ${this._config.xrlAuthorization}`;
381
- }
382
-
383
- if (this._config.userId) {
384
- requestHeaders['X-User-Id'] = this._config.userId;
385
- }
386
-
387
- if (this._config.experimentId) {
388
- requestHeaders['X-Experiment-Id'] = this._config.experimentId;
389
- }
390
-
391
- if (this._config.extraHeaders) {
392
- Object.assign(requestHeaders, this._config.extraHeaders);
393
- }
394
-
395
- if (headers) {
396
- Object.assign(requestHeaders, headers);
397
- }
398
-
399
- const axiosConfig = {
400
- method: method.toLowerCase(),
401
- url,
402
- headers: requestHeaders,
403
- };
404
-
405
- if (requestBody) {
406
- axiosConfig.data = requestBody;
407
- }
408
-
409
- const response = await axios(axiosConfig);
410
-
411
- return {
412
- data: response.data,
413
- headers: response.headers,
414
- status: response.status,
415
- };
416
- }
417
- }
418
-
419
- module.exports = { SandboxClient, SandboxConfig };
package/utils/terminal.js DELETED
@@ -1,32 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * 终端工具函数
5
- *
6
- * 提供统一的终端宽度获取和分隔线创建功能
7
- */
8
-
9
- /**
10
- * 获取终端宽度
11
- * @param {number} [defaultWidth=80] - 默认宽度(当无法获取终端宽度时使用)
12
- * @returns {number} 终端宽度
13
- */
14
- function getTerminalWidth(defaultWidth = 80) {
15
- return process.stdout.columns || defaultWidth;
16
- }
17
-
18
- /**
19
- * 创建分隔线
20
- * @param {string} [char='─'] - 分隔线字符
21
- * @param {number} [width] - 分隔线宽度(默认使用终端宽度)
22
- * @returns {string} 分隔线字符串
23
- */
24
- function createSeparator(char = '─', width = null) {
25
- const w = width || getTerminalWidth();
26
- return char.repeat(Math.max(1, w));
27
- }
28
-
29
- module.exports = {
30
- getTerminalWidth,
31
- createSeparator,
32
- };
package/utils/tips.js DELETED
@@ -1,106 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Tips module - Display helpful tips after command output
5
- */
6
-
7
- const chalk = require('chalk');
8
- const { CLI_NAME } = require('./cli');
9
-
10
- /**
11
- * Format a tip with consistent styling
12
- * @param {string} message - The tip message
13
- * @param {string} command - Optional command to highlight
14
- * @returns {string} Formatted tip string
15
- */
16
- function formatTip(message, command = null) {
17
- const prefix = chalk.dim('💡 Tip:');
18
- if (command) {
19
- return `${prefix} ${message}\n ${chalk.cyan(command)}`;
20
- }
21
- return `${prefix} ${message}`;
22
- }
23
-
24
- /**
25
- * Format a "next step" suggestion
26
- * @param {string} message - The suggestion message
27
- * @param {string} command - The command to run
28
- * @returns {string} Formatted next step string
29
- */
30
- function formatNextStep(message, command) {
31
- const prefix = chalk.dim('→');
32
- return `${prefix} ${message}\n ${chalk.cyan(command)}`;
33
- }
34
-
35
- /**
36
- * Print a tip to console
37
- * @param {string} message - The tip message
38
- * @param {string} command - Optional command to highlight
39
- */
40
- function printTip(message, command = null) {
41
- console.log('');
42
- console.log(formatTip(message, command));
43
- }
44
-
45
- /**
46
- * Print a "next step" suggestion to console
47
- * @param {string} message - The suggestion message
48
- * @param {string} command - The command to run
49
- */
50
- function printNextStep(message, command) {
51
- console.log('');
52
- console.log(formatNextStep(message, command));
53
- }
54
-
55
- /**
56
- * Print multiple tips in a box
57
- * @param {Array<{message: string, command?: string}>} tips - Array of tips
58
- */
59
- function printTipsBox(tips) {
60
- console.log('');
61
- console.log(chalk.dim('─'.repeat(60)));
62
- for (const tip of tips) {
63
- if (tip.command) {
64
- console.log(` ${tip.message}`);
65
- console.log(` ${chalk.cyan(tip.command)}`);
66
- } else {
67
- console.log(` ${tip.message}`);
68
- }
69
- console.log('');
70
- }
71
- console.log(chalk.dim('─'.repeat(60)));
72
- }
73
-
74
- /**
75
- * Common tips for various commands
76
- */
77
- const TIPS = {
78
- afterStart: (sandboxId) => ({
79
- message: 'To connect to this sandbox:',
80
- command: `${CLI_NAME} sandbox ${sandboxId} attach`,
81
- }),
82
-
83
- afterStop: () => ({
84
- message: 'To start a new sandbox:',
85
- command: `${CLI_NAME} start`,
86
- }),
87
-
88
- afterStatus: (sandboxId) => ({
89
- message: 'To connect to this sandbox:',
90
- command: `${CLI_NAME} sandbox ${sandboxId} attach`,
91
- }),
92
-
93
- afterList: () => ({
94
- message: 'To connect to a sandbox:',
95
- command: `${CLI_NAME} sandbox <sandbox-id> attach`,
96
- }),
97
- };
98
-
99
- module.exports = {
100
- formatTip,
101
- formatNextStep,
102
- printTip,
103
- printNextStep,
104
- printTipsBox,
105
- TIPS,
106
- };