shellx-ai 1.0.12 → 1.1.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +586 -0
  3. package/dist/automation/element-finder.d.ts +189 -0
  4. package/dist/automation/element-finder.js +322 -0
  5. package/dist/automation/element-finder.js.map +1 -0
  6. package/dist/automation/ui-action-handler.d.ts +330 -0
  7. package/dist/automation/ui-action-handler.js +873 -0
  8. package/dist/automation/ui-action-handler.js.map +1 -0
  9. package/dist/cbor-compat.d.ts +27 -0
  10. package/dist/cbor-compat.js +108 -0
  11. package/dist/cbor-compat.js.map +1 -0
  12. package/dist/domain-manager.d.ts +80 -0
  13. package/dist/domain-manager.js +158 -0
  14. package/dist/domain-manager.js.map +1 -0
  15. package/dist/error-handler.d.ts +87 -0
  16. package/dist/error-handler.js +148 -0
  17. package/dist/error-handler.js.map +1 -0
  18. package/dist/errors.d.ts +114 -0
  19. package/dist/errors.js +139 -0
  20. package/dist/errors.js.map +1 -0
  21. package/dist/index.d.ts +163 -54
  22. package/dist/index.js +706 -480
  23. package/dist/index.js.map +1 -0
  24. package/dist/logger.d.ts +81 -0
  25. package/dist/logger.js +128 -0
  26. package/dist/logger.js.map +1 -0
  27. package/dist/protocol.d.ts +147 -31
  28. package/dist/protocol.js +2 -2
  29. package/dist/protocol.js.map +1 -0
  30. package/dist/shell/output-buffer.d.ts +152 -0
  31. package/dist/shell/output-buffer.js +163 -0
  32. package/dist/shell/output-buffer.js.map +1 -0
  33. package/dist/shell/shell-command-executor.d.ts +182 -0
  34. package/dist/shell/shell-command-executor.js +348 -0
  35. package/dist/shell/shell-command-executor.js.map +1 -0
  36. package/dist/shellx.d.ts +681 -178
  37. package/dist/shellx.js +762 -1159
  38. package/dist/shellx.js.map +1 -0
  39. package/dist/types.d.ts +132 -57
  40. package/dist/types.js +4 -4
  41. package/dist/types.js.map +1 -0
  42. package/dist/utils/retry-helper.d.ts +73 -0
  43. package/dist/utils/retry-helper.js +92 -0
  44. package/dist/utils/retry-helper.js.map +1 -0
  45. package/dist/utils.d.ts +3 -3
  46. package/dist/utils.js +17 -23
  47. package/dist/utils.js.map +1 -0
  48. package/package.json +95 -62
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 10cl <notice@toscl.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,586 @@
1
+ # ShellX AI
2
+
3
+ <div align="center">
4
+
5
+ **A powerful TypeScript library for Android device automation and UI control**
6
+
7
+ [![npm version](https://badge.fury.io/js/shellx-ai.svg)](https://www.npmjs.org/package/shellx-ai)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ [![Node.js Version](https://img.shields.io/node/v/shellx-ai.svg)](https://nodejs.org)
10
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.8-blue.svg)](https://www.typescriptlang.org/)
11
+ [![Code Style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io)
12
+
13
+ [Features](#-features) • [Quick Start](#-quick-start) • [API Guide](#-api-guide) • [API Reference](#-api-reference) • [Examples](#-examples) • [Contributing](#-contributing)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## 🎯 Which API Should I Use?
20
+
21
+ ShellX provides two API levels. Choose the one that matches your needs:
22
+
23
+ ### 🟢 ShellX (High-Level API) - **Recommended for 95% of users**
24
+
25
+ Perfect for most automation tasks:
26
+ - ✅ Simple, intuitive methods
27
+ - ✅ Automatic error handling & retry
28
+ - ✅ Type-safe with TypeScript
29
+ - ✅ Less code to write
30
+
31
+ ```typescript
32
+ import { ShellX } from 'shellx-ai';
33
+
34
+ const shellx = new ShellX({ deviceId: 'your-device-id' });
35
+ await shellx.connect();
36
+
37
+ // Easy to use!
38
+ await shellx.click('Submit');
39
+ await shellx.input({ text: 'Hello World' });
40
+ await shellx.swipe({ fromX: 500, fromY: 1000, toX: 500, toY: 500 });
41
+ ```
42
+
43
+ ### 🔵 ConnectionClient (Low-Level API) - Advanced users only
44
+
45
+ For special cases requiring direct WebSocket access:
46
+ - Custom protocol implementations
47
+ - Debugging WebSocket communication
48
+ - Non-standard operations
49
+
50
+ **⚠️ Warning:** Steeper learning curve. Most users don't need this.
51
+
52
+ ```typescript
53
+ import { ConnectionClient } from 'shellx-ai';
54
+
55
+ const client = new ConnectionClient('device-id');
56
+ await client.ensureConnected();
57
+
58
+ // Low-level protocol access
59
+ await client.sendMessage({ click: { elementId: 'element123' } });
60
+ ```
61
+
62
+ **📚 See [API-GUIDE.md](./API-GUIDE.md) for detailed comparison and examples.**
63
+
64
+ ---
65
+
66
+ ## ✨ Features
67
+
68
+ ShellX AI provides a comprehensive suite of tools for Android device automation:
69
+
70
+ - 🎯 **Smart UI Automation** - Advanced element finding with retry logic and multiple selector strategies
71
+ - 🔧 **Shell Command Execution** - Execute shell commands with real-time output monitoring
72
+ - 📸 **Screen Operations** - Screenshots, screen info, and visual element capture
73
+ - 🔄 **Automatic Retry Logic** - Built-in retry mechanism for robust operations
74
+ - 🛠️ **Modular Architecture** - Clean, maintainable code structure with separation of concerns
75
+ - 📝 **Type-Safe API** - Full TypeScript support with comprehensive type definitions
76
+ - 🌍 **Global Optimization** - Automatic domain selection based on user location
77
+ - 🧪 **Well-Tested** - Comprehensive test coverage for reliability
78
+
79
+ ## 📦 Installation
80
+
81
+ ```bash
82
+ npm install shellx-ai
83
+ ```
84
+
85
+ ### Requirements
86
+
87
+ - **Node.js**: >= 14.0.0
88
+ - **TypeScript**: >= 4.0.0 (recommended)
89
+
90
+ ## 🚀 Quick Start
91
+
92
+ ### Basic Usage
93
+
94
+ ```typescript
95
+ import { ShellX } from 'shellx-ai';
96
+
97
+ // Create ShellX instance
98
+ const shellx = new ShellX({
99
+ deviceId: 'your-device-id',
100
+ onOpen: () => console.log('Connected!'),
101
+ onMessage: (message) => console.log('Message:', message)
102
+ });
103
+
104
+ // Wait for connection to be ready
105
+ await shellx.ready();
106
+
107
+ // Execute shell command
108
+ const result = await shellx.command({ cmd: 'getprop ro.build.version.release' });
109
+ console.log('Android version:', result.output);
110
+
111
+ // Click UI element (simplified API)
112
+ await shellx.click('Settings');
113
+
114
+ // Or use full API
115
+ await shellx.click({ text: 'Settings', clickType: 'single' });
116
+
117
+ // Find elements
118
+ const elements = await shellx.find({
119
+ text: 'Submit',
120
+ multiple: true,
121
+ maxResults: 10
122
+ });
123
+
124
+ console.log(`Found ${elements.count} elements`);
125
+ ```
126
+
127
+ ### With Connection Callbacks
128
+
129
+ ```typescript
130
+ import { ShellX } from 'shellx-ai';
131
+
132
+ const shellx = new ShellX({
133
+ deviceId: 'your-device-id',
134
+ timeout: 5000,
135
+ reconnect: true,
136
+ reconnectMaxAttempts: 5,
137
+ onOpen: () => console.log('✅ Connected'),
138
+ onClose: () => console.log('❌ Disconnected'),
139
+ onError: (error) => console.error('⚠️ Error:', error),
140
+ onMessage: (message) => console.log('📨 Message:', message)
141
+ });
142
+
143
+ // Wait for connection
144
+ await shellx.ready();
145
+
146
+ // Ready to use!
147
+ await shellx.command('pm list packages');
148
+ ```
149
+
150
+ ## 🎯 API Reference
151
+
152
+ ### Core Classes
153
+
154
+ #### `ShellX`
155
+
156
+ Main class providing high-level automation utilities.
157
+
158
+ **Constructor:**
159
+ ```typescript
160
+ constructor(options: ShellXOptions)
161
+ ```
162
+
163
+ **ShellXOptions:**
164
+ ```typescript
165
+ interface ShellXOptions {
166
+ deviceId: string; // Required: Device ID
167
+ timeout?: number; // Connection timeout (default: 5000ms)
168
+ reconnect?: boolean; // Enable auto-reconnect (default: true)
169
+ reconnectMaxAttempts?: number; // Max reconnect attempts (default: 5)
170
+ reconnectInterval?: number; // Reconnect interval (default: 1000ms)
171
+ pingInterval?: number; // Ping interval (default: 2000ms)
172
+ onOpen?: () => void; // Connection opened callback
173
+ onClose?: () => void; // Connection closed callback
174
+ onError?: (error?: Event) => void; // Error callback
175
+ onReconnectFailed?: () => void; // Reconnect failed callback
176
+ onMessage?: (message: WsServer) => void; // Message callback
177
+ }
178
+ ```
179
+
180
+ **Methods:**
181
+
182
+ | Method | Description | Return Type |
183
+ |--------|-------------|-------------|
184
+ | `ready()` | Wait for connection to be ready | `Promise<void>` |
185
+ | `click(data)` | Click element by ID, coordinates, or selector | `Promise<ActionResult>` |
186
+ | `input(data)` | Input text into element | `Promise<ActionResult>` |
187
+ | `swipe(data)` | Perform swipe gesture | `Promise<ActionResult>` |
188
+ | `pressKey(data)` | Press hardware key | `Promise<ActionResult>` |
189
+ | `wait(data)` | Wait for element condition | `Promise<ActionResult>` |
190
+ | `find(data)` | Find UI elements | `Promise<FindResult>` |
191
+ | `clipboard(data)` | Clipboard operations (get/set/paste) | `Promise<ActionResult>` |
192
+ | `takeScreenshot(data)` | Capture screenshot | `Promise<ActionResult>` |
193
+ | `getScreenInfo()` | Get screen information | `Promise<ScreenInfoResponse>` |
194
+ | `executeActions(actions)` | Execute multiple actions in sequence | `Promise<ActionResult[]>` |
195
+
196
+ **Element Finder Methods:**
197
+
198
+ | Method | Description | Return Type |
199
+ |--------|-------------|-------------|
200
+ | `findElementWithRetry(selector, maxRetries, retryDelay)` | Find single element with retry | `Promise<UIElement \| null>` |
201
+ | `findElementsWithRetry(selector, maxRetries, retryDelay, options)` | Find multiple elements | `Promise<UIElement[]>` |
202
+ | `waitForAnyElement(selectors, timeout)` | Wait for any element to appear | `Promise<{element, selectorIndex} \| null>` |
203
+ | `scrollToFindElement(selector, maxScrolls, direction)` | Scroll to find element | `Promise<UIElement \| null>` |
204
+
205
+ **Shell Command Methods:**
206
+
207
+ | Method | Description | Return Type |
208
+ |--------|-------------|-------------|
209
+ | `executeShellCommand(command, options)` | Execute shell command with monitoring | `Promise<ShellCommandResult>` |
210
+ | `executeSimpleShellCommand(command, options)` | Execute simple shell command | `Promise<ShellCommandResult>` |
211
+ | `executeShellCommands(commands, options)` | Execute multiple commands | `Promise<ShellCommandResult[]>` |
212
+ | `adbCommand(command, options)` | Execute ADB command | `Promise<ShellCommandResult>` |
213
+ | `executeCode(code, context, timeout)` | Execute code in sandboxed environment | `Promise<any>` |
214
+
215
+ **Device Info Methods:**
216
+
217
+ | Method | Description | Return Type |
218
+ |--------|-------------|-------------|
219
+ | `getDeviceInfo()` | Get comprehensive device information | `Promise<ShellCommandResult[]>` |
220
+ | `getDeviceModel()` | Get device model | `Promise<string \| undefined>` |
221
+ | `getAndroidVersion()` | Get Android version | `Promise<string \| undefined>` |
222
+ | `getScreenSize()` | Get screen size | `Promise<string \| undefined>` |
223
+ | `getBatteryInfo()` | Get battery information | `Promise<BatteryInfo \| undefined>` |
224
+ | `getDeviceInfoSummary()` | Get device information summary | `Promise<DeviceInfo>` |
225
+
226
+ **Navigation Methods:**
227
+
228
+ | Method | Description | Return Type |
229
+ |--------|-------------|-------------|
230
+ | `navigateByPath(textPath)` | Navigate using text path | `Promise<boolean>` |
231
+ | `clickByText(text, exact)` | Click element by text | `Promise<boolean>` |
232
+ | `inputText(selector, text, options)` | Input text into field | `Promise<boolean>` |
233
+
234
+ ### Type Definitions
235
+
236
+ #### `Click`
237
+
238
+ ```typescript
239
+ interface Click {
240
+ targetElementId?: string;
241
+ targetResourceId?: string;
242
+ targetText?: string;
243
+ targetClass?: string;
244
+ targetX?: number;
245
+ targetY?: number;
246
+ clickType?: 'single' | 'double' | 'long';
247
+ wait?: number;
248
+ retry?: number;
249
+ }
250
+ ```
251
+
252
+ #### `Input`
253
+
254
+ ```typescript
255
+ interface Input {
256
+ targetElementId?: string;
257
+ targetResourceId?: string;
258
+ targetText?: string;
259
+ targetClass?: string;
260
+ text: string;
261
+ clear?: boolean;
262
+ hideKeyboard?: boolean;
263
+ wait?: number;
264
+ retry?: number;
265
+ }
266
+ ```
267
+
268
+ #### `Swipe`
269
+
270
+ ```typescript
271
+ interface Swipe {
272
+ fromX: number;
273
+ fromY: number;
274
+ toX: number;
275
+ toY: number;
276
+ duration?: number;
277
+ wait?: number;
278
+ retry?: number;
279
+ }
280
+ ```
281
+
282
+ #### `Command`
283
+
284
+ ```typescript
285
+ interface Command {
286
+ cmd: string;
287
+ timeout?: number;
288
+ wait?: number;
289
+ retry?: number;
290
+ }
291
+ ```
292
+
293
+ #### `ActionResult`
294
+
295
+ ```typescript
296
+ interface ActionResult {
297
+ success: boolean;
298
+ data?: any;
299
+ error?: string;
300
+ duration: number;
301
+ }
302
+ ```
303
+
304
+ ## 📚 Examples
305
+
306
+ ### Example 1: UI Automation Workflow
307
+
308
+ ```typescript
309
+ import { createShellXWithShellMonitoring } from 'shellx-ai';
310
+
311
+ async function automateApp() {
312
+ const shellx = await createShellXWithShellMonitoring({
313
+ deviceId: process.env.SHELLX_DEVICE_ID
314
+ });
315
+
316
+ try {
317
+ // Navigate to settings
318
+ await shellx.clickByText('Settings');
319
+ await shellx.wait({ targetText: 'Accounts', condition: 'visible', timeout: 5000 });
320
+
321
+ // Click on account item
322
+ await shellx.click({ targetText: 'Accounts' });
323
+
324
+ // Input text
325
+ await shellx.input({
326
+ targetResourceId: 'username_field',
327
+ text: 'user@example.com',
328
+ clear: true
329
+ });
330
+
331
+ // Take screenshot
332
+ await shellx.takeScreenshot({
333
+ format: 'png',
334
+ quality: 90,
335
+ saveToFile: true
336
+ });
337
+
338
+ console.log('Automation completed successfully!');
339
+ } catch (error) {
340
+ console.error('Automation failed:', error);
341
+ }
342
+ }
343
+
344
+ automateApp();
345
+ ```
346
+
347
+ ### Example 2: Batch Command Execution
348
+
349
+ ```typescript
350
+ import { createShellX } from 'shellx-ai';
351
+ import ConnectionTaskClient from 'shellx-ai';
352
+
353
+ async function executeDeviceCommands() {
354
+ const client = new ConnectionTaskClient('device-id');
355
+ await client.waitForInitialization();
356
+ const shellx = createShellX(client);
357
+
358
+ // Execute multiple commands
359
+ const commands = [
360
+ { command: 'pm list packages', title: 'List packages' },
361
+ { command: 'dumpsys battery', title: 'Get battery info' },
362
+ { command: 'wm size', title: 'Get screen size' }
363
+ ];
364
+
365
+ const results = await shellx.executeShellCommands(commands, {
366
+ continueOnError: true,
367
+ timeout: 10000
368
+ });
369
+
370
+ results.forEach((result, index) => {
371
+ console.log(`\n${commands[index].title}:`);
372
+ console.log(`Success: ${result.success}`);
373
+ console.log(`Output: ${result.output}`);
374
+ if (result.error) {
375
+ console.error(`Error: ${result.error}`);
376
+ }
377
+ });
378
+ }
379
+
380
+ executeDeviceCommands();
381
+ ```
382
+
383
+ ### Example 3: Advanced Element Finding
384
+
385
+ ```typescript
386
+ async function findAndInteract() {
387
+ const shellx = await createShellXWithShellMonitoring({
388
+ deviceId: 'device-id'
389
+ });
390
+
391
+ // Find element with retry
392
+ const element = await shellx.findElementWithRetry(
393
+ { text: 'Submit Button', visible: true, clickable: true },
394
+ 5, // max retries
395
+ 1000 // retry delay
396
+ );
397
+
398
+ if (element) {
399
+ console.log('Found element:', element.elementId);
400
+ shellx.printElementInfo(element);
401
+ } else {
402
+ console.log('Element not found');
403
+
404
+ // Try scrolling to find it
405
+ const foundElement = await shellx.scrollToFindElement(
406
+ { text: 'Submit Button' },
407
+ 5,
408
+ 'down'
409
+ );
410
+
411
+ if (foundElement) {
412
+ console.log('Found after scrolling!');
413
+ await shellx.click({ targetElementId: foundElement.elementId });
414
+ }
415
+ }
416
+ }
417
+
418
+ findAndInteract();
419
+ ```
420
+
421
+ ### Example 4: Action Sequence
422
+
423
+ ```typescript
424
+ async function executeActionSequence() {
425
+ const shellx = await createShellXWithShellMonitoring({
426
+ deviceId: 'device-id'
427
+ });
428
+
429
+ // Execute multiple actions
430
+ const actions = [
431
+ // Click settings
432
+ { targetText: 'Settings' },
433
+
434
+ // Wait for menu
435
+ { targetText: 'Network', condition: 'visible', timeout: 5000 },
436
+
437
+ // Click network
438
+ { targetText: 'Network' },
439
+
440
+ // Execute command
441
+ { cmd: 'dumpsys wifi' },
442
+
443
+ // Take screenshot
444
+ { format: 'png' }
445
+ ];
446
+
447
+ const results = await shellx.executeActions(actions);
448
+
449
+ results.forEach((result, index) => {
450
+ const status = result.success ? '✅' : '❌';
451
+ console.log(`Action ${index + 1}: ${status}`);
452
+ if (!result.success) {
453
+ console.error(` Error: ${result.error}`);
454
+ }
455
+ });
456
+ }
457
+
458
+ executeActionSequence();
459
+ ```
460
+
461
+ ## 🛠️ Development
462
+
463
+ ### Setup
464
+
465
+ ```bash
466
+ # Clone repository
467
+ git clone https://github.com/10cl/shellx.git
468
+ cd shellx
469
+
470
+ # Install dependencies
471
+ npm install
472
+
473
+ # Build project
474
+ npm run build
475
+
476
+ # Run tests
477
+ npm test
478
+ ```
479
+
480
+ ### Available Scripts
481
+
482
+ | Script | Description |
483
+ |--------|-------------|
484
+ | `npm run build` | Compile TypeScript to JavaScript |
485
+ | `npm run build:watch` | Watch mode for compilation |
486
+ | `npm run type-check` | Type check without emitting files |
487
+ | `npm run lint` | Run ESLint |
488
+ | `npm run lint:fix` | Fix ESLint errors automatically |
489
+ | `npm run format` | Format code with Prettier |
490
+ | `npm run format:check` | Check code formatting |
491
+ | `npm test` | Run tests |
492
+ | `npm run test:coverage` | Run tests with coverage |
493
+ | `npm run clean` | Remove dist directory |
494
+
495
+ ### Project Structure
496
+
497
+ ```
498
+ shellx-ai/
499
+ ├── src/
500
+ │ ├── automation/
501
+ │ │ ├── element-finder.ts # Element finding with retry logic
502
+ │ │ ├── ui-action-handler.ts # UI action execution
503
+ │ │ └── device-info-helper.ts # Device information retrieval
504
+ │ ├── shell/
505
+ │ │ ├── output-buffer.ts # Shell output buffering
506
+ │ │ └── shell-command-executor.ts # Shell command execution
507
+ │ ├── utils/
508
+ │ │ └── retry-helper.ts # Generic retry mechanism
509
+ │ ├── index.ts # Main connection client
510
+ │ ├── shellx.ts # Main ShellX class
511
+ │ ├── protocol.ts # Protocol type definitions
512
+ │ ├── types.ts # Simplified type definitions
513
+ │ ├── domain-manager.ts # Domain management
514
+ │ └── utils.ts # Utility functions
515
+ ├── dist/ # Compiled output
516
+ ├── package.json
517
+ ├── tsconfig.json
518
+ ├── jest.config.js
519
+ ├── .eslintrc.json
520
+ ├── .prettierrc.json
521
+ └── README.md
522
+ ```
523
+
524
+ ## 🧪 Testing
525
+
526
+ ```bash
527
+ # Run all tests
528
+ npm test
529
+
530
+ # Run tests in watch mode
531
+ npm run test:watch
532
+
533
+ # Generate coverage report
534
+ npm run test:coverage
535
+
536
+ # Type checking
537
+ npm run type-check
538
+
539
+ # Linting
540
+ npm run lint
541
+ ```
542
+
543
+ ## 🤝 Contributing
544
+
545
+ We welcome contributions! Please follow these steps:
546
+
547
+ 1. Fork the repository
548
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
549
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
550
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
551
+ 5. Open a Pull Request
552
+
553
+ ### Code Style
554
+
555
+ - Use TypeScript for all new features
556
+ - Follow ESLint rules (`npm run lint`)
557
+ - Format code with Prettier (`npm run format`)
558
+ - Add JSDoc comments for public APIs
559
+ - Write tests for new functionality
560
+ - Ensure all tests pass before submitting
561
+
562
+ ## 📝 License
563
+
564
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
565
+
566
+ ## 🆘 Support
567
+
568
+ - 📚 [Documentation](https://github.com/10cl/shellx/wiki)
569
+ - 🐛 [Issue Tracker](https://github.com/10cl/shellx/issues)
570
+ - 💬 [Discussions](https://github.com/10cl/shellx/discussions)
571
+
572
+ ## 🌟 Acknowledgments
573
+
574
+ - Built with [TypeScript](https://www.typescriptlang.org/)
575
+ - Powered by [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
576
+ - Tested with [Jest](https://jestjs.io/)
577
+
578
+ ---
579
+
580
+ <div align="center">
581
+
582
+ **Built with ❤️ for the automation community**
583
+
584
+ [⬆ Back to Top](#shellx-ai)
585
+
586
+ </div>