npm package: @horuzhenko/input-sequencer
Description: Планировщик ввода для последовательного выполнения команд ввода с задержками
Latest version: 6.0.14

# @horuzhenko/input-sequencer

Планировщик ввода для последовательного выполнения команд ввода с задержками. Предотвращает гонку состояний при отправке команд от LLM и делает взаимодействие с удаленным рабочим столом более стабильным и похожим на человеческое.

## Установка

```bash
pnpm add @horuzhenko/input-sequencer
```

## Основные возможности

- **Последовательное выполнение**: Гарантирует выполнение операций ввода в правильном порядке
- **Автоматические задержки**: Добавляет реалистичные задержки между операциями
- **Сложная логика click**: Разбивает клик на move → delay → mousedown → delay → mouseup
- **Очереди по сессиям**: Отдельная очередь для каждой сессии
- **Обработка ошибок**: Продолжает работу даже при ошибках в отдельных операциях

## Использование

### Базовый пример

```typescript
import { InputSequencer } from '@horuzhenko/input-sequencer';
import { GuacAdapter } from '@horuzhenko/guac-adapter';

// Создание адаптера и планировщика
const guacAdapter = new GuacAdapter();
const sequencer = new InputSequencer(guacAdapter);

// Подключение к сессии
const sessionInfo = await guacAdapter.connect({
  auth: { baseUrl: 'https://guacamole.example.com', token: 'your-token' }
});

// Добавление операций в очередь
await sequencer.enqueue(sessionInfo.id, {
  kind: 'move',
  data: { x: 100, y: 100 }
});

await sequencer.enqueue(sessionInfo.id, {
  kind: 'click',
  data: { x: 100, y: 100, button: 'left' }
});

await sequencer.enqueue(sessionInfo.id, {
  kind: 'typeText',
  data: { text: 'Hello, World!' }
});

// Ожидание завершения всех операций
await sequencer.flush(sessionInfo.id);
```

### Сложные операции

```typescript
// Двойной клик
await sequencer.enqueue(sessionInfo.id, {
  kind: 'click',
  data: { x: 200, y: 150, button: 'left', count: 2 }
});

// Комбинация клавиш
await sequencer.enqueue(sessionInfo.id, {
  kind: 'keyCombo',
  data: { keys: ['Ctrl', 'c'] }
});

// Прокрутка
await sequencer.enqueue(sessionInfo.id, {
  kind: 'scroll',
  data: { x: 300, y: 300, deltaY: -100 }
});
```

### Управление очередью

```typescript
// Очистка очереди
sequencer.clear(sessionInfo.id);

// Принудительное выполнение всех операций
await sequencer.flush(sessionInfo.id);
```

## API

### InputSequencer

#### `enqueue(sessionId: SessionId, operation: InputOperation): Promise<void>`

Добавляет операцию в очередь для указанной сессии. Если очередь пуста, немедленно начинает обработку.

**Параметры:**
- `sessionId` - Идентификатор сессии
- `operation` - Операция ввода

**Поддерживаемые операции:**
- `{ kind: "move", data: MouseMove }`
- `{ kind: "click", data: MouseClick }`
- `{ kind: "scroll", data: Scroll }`
- `{ kind: "keyCombo", data: KeyCombo }`
- `{ kind: "typeText", data: TypeText }`

#### `flush(sessionId: SessionId): Promise<void>`

Ожидает завершения всех операций в очереди для указанной сессии.

#### `clear(sessionId: SessionId): void`

Очищает очередь операций для указанной сессии.

## Внутренняя логика

### Задержки

- **Между операциями**: 20ms
- **Click операция**: move → 20ms → mousedown → 50ms → mouseup
- **Двойной клик**: дополнительная задержка 100ms между кликами

### Обработка click

Операция click автоматически разбивается на последовательность:

1. `move` к координатам клика
2. Задержка 20ms
3. `mousedown` с указанной кнопкой
4. Задержка 50ms  
5. `mouseup`

Для двойного клика (count: 2) последовательность повторяется с дополнительной задержкой.

## Тестирование

```bash
# Запуск тестов
pnpm test

# Запуск тестов в режиме наблюдения
pnpm test --watch
```

## Разработка

```bash
# Сборка
pnpm build

# Разработка с автоматической пересборкой
pnpm dev

# Проверка типов
pnpm lint
```

## Примеры использования

### Автоматизация GUI

```typescript
// Открытие приложения и ввод текста
await sequencer.enqueue(sessionId, { kind: 'keyCombo', data: { keys: ['Ctrl', 'Alt', 't'] } });
await sequencer.enqueue(sessionId, { kind: 'typeText', data: { text: 'notepad' } });
await sequencer.enqueue(sessionId, { kind: 'keyCombo', data: { keys: ['Enter'] } });
await sequencer.enqueue(sessionId, { kind: 'typeText', data: { text: 'Hello from InputSequencer!' } });

await sequencer.flush(sessionId);
```

### Работа с формами

```typescript
// Заполнение формы
await sequencer.enqueue(sessionId, { kind: 'click', data: { x: 100, y: 50, button: 'left' } });
await sequencer.enqueue(sessionId, { kind: 'typeText', data: { text: 'username' } });
await sequencer.enqueue(sessionId, { kind: 'keyCombo', data: { keys: ['Tab'] } });
await sequencer.enqueue(sessionId, { kind: 'typeText', data: { text: 'password' } });
await sequencer.enqueue(sessionId, { kind: 'keyCombo', data: { keys: ['Enter'] } });

await sequencer.flush(sessionId);
```