All skills

Этот скилл MUST быть вызван для управления 1С:Предприятие в веб-клиенте через Playwright MCP: запуск/перезапуск/завершение сеанса, навигация, создание и редактирование справочников и документов. SHOULD также вызывать для генерации тестовых данных через UI и сценарного тестирования в браузере. Do NOT использовать для scaffold автотестов — используй playwright-test.

Use this Skill: https://skilld.dev/gh/arman-kudaibergenov/1c-ai-development-kit/1c-web-session

This session only. Nothing lands on disk.

SKILL.md

≈160 tokens always: the name and description. ≈3k when used: this file. ≈1.4k more on demand in 2 files.

/1c-web-session — Управление 1С в веб-клиенте

Скилл для работы с 1С:Предприятие через Playwright MCP (браузер).

Источник: адаптировано из RooLee10/1c-web-session (MIT)

Запуск базы

  1. Прочитать CLAUDE.md проекта — найти URL базы (формат: http://<сервер>/<публикация>/ru_RU/)
  2. browser_navigate на URL
  3. Обработать лицензию/вход если появятся (см. ниже)

Завершение и перезапуск

Сервис и настройки → Файл → Выход → Завершить работу

Перезапуск: завершить → browser_navigate на URL.


КРИТИЧЕСКИЕ ПРАВИЛА 1С веб-клиента

1. Clipboard paste — ЕДИНСТВЕННЫЙ способ ввода

Стандартные fill(), type(), pressSequentially() НЕ работают в 1С. Всегда:

await page.evaluate((v) => navigator.clipboard.writeText(v), 'Значение');
await page.keyboard.press('Control+A');  // очистить поле
await page.keyboard.press('Control+V');

2. Суффиксные селекторы — ЕДИНСТВЕННЫЙ надёжный метод

Формы 1С получают инкрементальные ID (form26, form40). Никогда не хардкодить номер формы.

// ПРАВИЛЬНО
await page.locator('[id$="_ВидНоменклатуры_DLB"]').click();
// НЕПРАВИЛЬНО — сломается после первой формы
await page.locator('[id="form40_ВидНоменклатуры_DLB"]').click();

3. DLB-кнопки — универсальный паттерн выбора

Все кнопки выбора имеют суффикс _DLB — и перечисления, и справочники:

await page.locator('[id$="_ВидАттракциона_DLB"]').click();
await page.waitForTimeout(100);

if (await page.locator('#editDropDown').count() > 0) {
  // Dropdown — перечисление или небольшой справочник
  await page.locator('#editDropDown').getByText('Экстремальный').click();
} else {
  // Picker — большой справочник
  await page.getByTitle('Выбрать значение (Ctrl+Enter)').waitFor();
  await page.getByText('Экстремальный').click();
  await page.getByTitle('Выбрать значение (Ctrl+Enter)').click();
}

4. Навигационный кеш

ID разделов (#themesCell_theme_N) и пунктов меню (#cmd_0_3_txt) уникальны для каждой базы.

При первом запуске — выполнить references/scan-nav.js через browser_run_code, результат сохранить в .claude/1c-nav.json (Write tool).

Навигация — только через кешированные ID:

await page.locator('#themesCell_theme_1').click();  // из 1c-nav.json
await page.locator('#cmd_0_3_txt').waitFor({ state: 'visible', timeout: 2000 });
await page.locator('#cmd_0_3_txt').click();

НЕ использовать getByText('Справочники') — strict mode violation.


Обработка диалогов

Диалог лицензии

"Не обнаружено свободной лицензии!" — установить checkbox через JS, нажать "Выполнить запуск":

async (page) => {
  const rows = await page.locator('text=сеанс:').all();
  for (const row of rows) {
    const parent = row.locator('xpath=..');
    await parent.locator('input, [class*="check"], [class*="box"]').first().click();
  }
  return { clicked: rows.length };
}

Форма входа

Если появляется — сразу browser_navigate с тем же URL. Не нажимать "Войти".

Модальные диалоги

Диалог Действие
beforeunload browser_handle_dialog с accept: true
"Данные были изменены" locator('a').filter({ hasText: 'Нет' }).click()
Подтверждение (Пометить на удаление?) page.keyboard.press('Enter')

Клавиатурные сочетания

Сочетание Действие
Ctrl+Enter Записать и закрыть / Провести и закрыть
Ctrl+S Записать (без проведения)
Escape Закрыть диалог ошибки
Tab Следующее поле
F4 Показать список для выбора
Ins Добавить строку в табличную часть
Ctrl+Shift+Z Закрыть панель ошибок валидации
Delete Пометить на удаление

Проведение: Ctrl+Enter проводит и формирует движения. Ctrl+S только записывает.


Поле "Наименование" при создании

Поле "Наименование" уже в фокусе при открытии формы нового элемента. Не искать по ID:

await page.keyboard.press('Control+A');
await page.evaluate((v) => navigator.clipboard.writeText(v), name);
await page.keyboard.press('Control+V');

Табличные части

Добавить строку (Ins), заполнить clipboard paste + Tab между полями.

Справочник в ячейке:

await page.keyboard.press('F4');
await page.waitForTimeout(300);
await page.getByTitle('Выбрать значение (Ctrl+Enter)').waitFor();
const pickerSearch = page.getByRole('textbox', { name: 'Поиск (Ctrl+F)' }).last();
await pickerSearch.click();
await page.evaluate((v) => navigator.clipboard.writeText(v), 'Текст поиска');
await page.keyboard.press('Control+V');
await page.waitForTimeout(600);
await page.locator('.gridBoxText').filter({ hasText: /Текст поиска/ }).first().click({ force: true });
await page.getByTitle('Выбрать значение (Ctrl+Enter)').click();

При нескольких таблицах на форме — скоупить к нужной командной панели:

await page.locator('[id$="_ТоварыКоманднаяПанель"]').last()
  .getByTitle('Добавить новый элемент (Ins)').click();

Создание объекта из dropdown

Если нужного элемента нет в справочнике:

await page.locator('[id$="_Филиал_DLB"]').click();
await page.waitForTimeout(200);
await page.getByTitle('Создать (F8)').click();
await page.waitForTimeout(500);
// Форма нового объекта — после Ctrl+Enter подставится автоматически

Группы в иерархических справочниках

Развернуть/свернуть — двойной клик. При создании внутри развёрнутой группы поле "Группа" заполняется автоматически.


JS-верификация (вместо screenshot)

После Ctrl+Enter проверить результат прямо в browser_run_code:

await page.waitForTimeout(800);
const hasModal = await page.locator('.modalSurface').count() > 0;
const formOpen = await page.getByRole('textbox', { name: 'Наименование:' }).count() > 0;
const hasValidationPanel = await page.locator('[title="Закрыть (Ctrl+Shift+Z)"]')
  .filter({ visible: true }).count() > 0;

if (hasModal) return { status: 'error', reason: 'модальная ошибка' };
if (formOpen && hasValidationPanel) return { status: 'error', reason: 'ошибка валидации' };
if (formOpen) return { status: 'error', reason: 'форма не закрылась' };
return { status: 'ok' };

Запуск JS-сценариев

Команда запусти сценарий <путь>.js — выполнить файл через browser_run_code.

Способ A (по умолчанию): clipboard loader

Get-Content -LiteralPath <путь> -Raw | Set-Clipboard

Затем loader в browser_run_code:

async (page) => {
  let src;
  try { src = await page.evaluate(() => navigator.clipboard.readText()); }
  catch (e) { return { ok: false, stage: 'clipboard', message: String(e) }; }

  if (!src || !src.includes('async (page)'))
    return { ok: false, stage: 'clipboard', message: 'Нет сценария в буфере' };

  let scenario;
  try { scenario = (0, eval)(`(\n${src}\n)`); }
  catch (e) { return { ok: false, stage: 'compile', message: e.message }; }

  try { return { ok: true, result: await scenario(page) }; }
  catch (e) { return { ok: false, stage: 'runtime', message: e.message, stack: e.stack }; }
}

Способ B (fallback): прямой запуск

Если clipboard недоступен — прочитать файл, передать код напрямую в browser_run_code.



Скрипты утилиты

Готовые скрипты в .claude/skills/1c-web-session/scripts/ — включать в browser_run_code через ${read(...)}.

1c-screenshot.js

Скриншоты + кеш селекторов (.claude/1c-web-cache.json):

  • screenshot1C(page, name, opts) — скриншот в playwright-screenshots/, автоочистка > 7 дней
  • loadCache(baseUrl) / saveSelector(baseUrl, key, value) — чтение/запись кеша (точечная нотация)
  • locatorWithCache(page, baseUrl, cacheKey, fallbacks[]) — пробует кеш → fallbacks → сохраняет найденный

1c-login.js (требует 1c-screenshot.js)

login1C(page, baseUrl, user, password) — логин через clipboard paste, пропускает если уже залогинен.

1c-open-object.js

  • openObject1C(page, baseUrl, metadataPath, guid) — открыть объект по GUID
  • openList1C(page, baseUrl, metadataPath) — открыть список

1c-snapshot.js (требует 1c-screenshot.js)

snapshot1C(page, navigateTo?) — собирает visibleFields (label+value без скриншота) + заголовок формы.

1c-fill-form.js

fillForm1C(page, fields, options) — заполняет поля формы через clipboard paste.

Пример: открыть объект по GUID и прочитать поля

async (page) => {
  // paste content of 1c-open-object.js
  // paste content of 1c-screenshot.js
  // paste content of 1c-snapshot.js
  return await snapshot1C(page,
    'http://YOUR_EDT_SERVER/KAF/e1cib/data/Справочник.Номенклатура?ref=<guid>'
  );
}

Оптимизация

Подробные рекомендации — в references/optimization.md. Ключевое:

  • Один browser_run_code на всё задание — не пошаговые вызовы
  • Tab перед DLB-кликом — снимает фокус с поля ввода
  • waitForTimeout(50) для dropdown — waitFor избыточен
  • JS-верификация внутри — без screenshot
  • browser_snapshot только при первом типе элемента или при ошибке
  • При сбое цепочки → переключиться на пошаговые инструменты + browser_snapshot

Source: SKILL.md on GitHub

2 alerts6mo4 checks · Risk MEDIUM
  • Gen Agent Trust Hub6mo

    This skill facilitates 1C:Enterprise web client automation using Playwright. It employs a dynamic loader that executes JavaScript directly from the system clipboard using eval and handles login credentials in plain text, which introduces risks related to arbitrary code execution and credential safety.

  • Socket6mo

    1 alert: obfuscatedFile

  • Snyk6mo

    Risk: CRITICAL · No issues

  • Runlayer6mo

    9/9 files flagged

Signed by skilld at 94ad6ec. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 7 months ago
What it can do
Reads files Edits files Runs commands
MCP servers
playwright
argument-hint
[action]
All 16 allowed tools
ReadWriteGlobBashmcp__playwright__browser_navigatemcp__playwright__browser_snapshotmcp__playwright__browser_clickmcp__playwright__browser_typemcp__playwright__browser_press_keymcp__playwright__browser_run_codemcp__playwright__browser_handle_dialogmcp__playwright__browser_take_screenshotmcp__playwright__browser_evaluatemcp__playwright__browser_console_messagesmcp__playwright__browser_wait_formcp__playwright__browser_tabs

README badge

README badge for arman-kudaibergenov/1c-ai-development-kit/1c-web-session