Главная / Статьи / Агенты для автоматизации браузера без ограничений с Node.js

Агенты для автоматизации браузера без ограничений с Node.js

Создайте агент для управления браузером с четко определенными границами функций инструментов, механизмами безопасности и возможностью ведения журнала операций.

4302 слов

В этом руководстве воссоздаётся рабочий алгоритм для выполнения задачи: «Как создать ИИ-агента для автоматизации браузера без ограничений с использованием Node.js, Playwright, Bright Data и Gemini». Особое внимание уделяется контрактам, проверкам и коду, который можно просто добавить в репозиторий без необходимости угадывать его назначение. Для обзора сначала определите входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия создаваемым файлам, определите критерии успеха и не допускайте безответственного частичного выполнения задачи.

Введение

Во введении необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее видимость данных предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Строго ограничьте схемы инструментов: широкие параметры в виде свободного текста способствуют внедрению угроз и делают аудиты дорогостоящими.

await page.goto(url)
await page.click(selector)
await page.type(selector, text)

Что мы создаем

Для проектов, над которыми мы работаем, необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Схемы инструментов следует строго ограничивать. Широкие параметры в формате свободного текста способствуют внедрению угроз и затрудняют аудит.

Предварительные условия

В качестве предпосылки необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Строго ограничьте схемы инструментов. Широкие параметры в виде свободного текста способствуют внедрению угроз и затрудняют аудит. В качестве предпосылки необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

Создание проекта Sikki

Для проекта Building Sikki необходимо определить входные данные, ответственного за выполнение этапа и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить этап с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее отслеживание помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. Устанавливайте точку контроля после дорогостоящих вызовов модели, чтобы повторная попытка не влекла за собой повторной оплаты той же работы.

Шаг 1: Создание проекта

Для шага 1: Создайте проект, определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь граф задач. Создавайте точку контроля после дорогостоящих вызовов модели, чтобы повторная попытка не влекла за собой повторной оплаты за одну и ту же работу.

mkdir sikki-agent
cd sikki-agent
npm init -y
npm pkg set type=module
npm install playwright

npm install @google/genai
npm install dotenv
npm install chalk
npm install ora
sikki-agent
 index.js
 .env
 screenshots/
 reports/
 package.json

Шаг 2: Получение ключа API Gemini

Для шага 2: Получение ключа API Gemini — определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Создавайте точки контроля после дорогостоящих вызовов модели, чтобы повторные попытки не приводили к повторной оплате одних и тех же операций. Для шага 2: Получение ключа API Gemini — определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия результатам работы, определите критерии успеха и не допускайте безусловного частичного завершения задачи.

GEMINI_API_KEY = your_gemini_api_key
BRIGHT_WS_ENDPOINT = //i will show you later

Шаг 3: Настройка инфраструктуры браузера Bright Data Cloud

Для шага 3: Настройка инфраструктуры браузера Bright Data Cloud необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее видимость помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. Разделяйте планирование и выполнение задач с помощью инструментов: планер предлагает решения, исполнитель вносит изменения, а проверщик сравнивает результаты с поставленной целью.

BRIGHT_WS_ENDPOINT = "your_endpoint"
chromium.launch()
chromium.connectOverCDP()

Шаг 4: Подключение Playwright к Bright Data

Для шага 4: подключения Playwright к Bright Data необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Необходимо разделить процесс планирования и выполнение с помощью инструментов. Планировщик предлагает действия; исполнитель их реализует; проверщик сравнивает результаты с поставленной целью.

import { chromium }
from "playwright";

const BRIGHT_WS_ENDPOINT = "your_endpoint"

const browser =
await chromium.connectOverCDP(BRIGHT_WS_ENDPOINT
);

const page =
await browser.newPage();
await page.goto(
"https://cnn.com"
);

console.log(
await page.title()
);

Более подробно о SIKKI Agent перед реализацией

Для более глубокого изучения SIKKI Agent перед внедрением необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Необходимо разделить планирование и выполнение с помощью инструментов. Планировщик предлагает варианты; исполнитель вносит изменения; проверщик сравнивает результаты с поставленной целью. Для более глубокого изучения SIKKI Agent перед внедрением необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответных частичных решений.

Завершение.

SIKKI — не скрейпер

В случае SIKKI — не скрейпер необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее видимость помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. Строго ограничьте схемы инструментов. Широкие параметры в виде свободного текста способствуют внедрению угроз и делают аудит дорогостоящим.

ProductPriceAcer Nitro V$899ASUS TUF$949MSI Thin$979

Архитектура SIKKI

Что касается архитектуры SIKKI, необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Схемы инструментов следует строго ограничивать. Широкие параметры в формате свободного текста способствуют внедрению угроз и затрудняют аудит.

SIKKI

Strategic Intelligence Commerce Kernel

┌──────────────────────────────┐
│ Browser Layer                │
│ Playwright + Bright Data     │
└──────────────────────────────┘
                │
                ▼
┌──────────────────────────────┐
│ Extraction Layer             │
│ Product                      │
│ Price                        │
│ Rating                       │
│ Seller                       │
│ Availability                 │
└──────────────────────────────┘
                │
                ▼
┌──────────────────────────────┐
│ AI Layer                     │
│ Gemini                       │
└──────────────────────────────┘
                │
                ▼
┌──────────────────────────────┐
│ Analysis Layer               │
│ Cheapest Products            │
│ Market Average               │
│ Competitor Comparison        │
│ Trend Analysis               │
└──────────────────────────────┘
                │
                ▼
        Markdown / CSV
        Dashboard Export

Создание слоя извлечения

При создании слоя извлечения необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный и аварийный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Строго ограничьте схемы инструментов. Широкие параметры в виде свободного текста способствуют внедрению угроз и затрудняют аудит. При создании слоя извлечения необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия результатам работы, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

const products = await page.evaluate(() => {const items = [];
    document.querySelectorAll('[data-component-type="s-search-result"]')
      .forEach(card => {
        const title =
          card.querySelector('h2 span')?.innerText;
        const price =
          card.querySelector('.a-price .a-offscreen')
          ?.innerText;
        const rating =
          card.querySelector('.a-icon-alt')
          ?.innerText;
        const link =
          card.querySelector('h2 a')
          ?.href;
        if(title && price){
            items.push({
                title,
                price,
                rating,
                link
            });
        }
    });
    return items;
});
console.log(products);
[
 {
   title: "Acer Nitro V Gaming Laptop",
   price: "$899",
   rating: "4.5 out of 5 stars",
   link: "https://..."
 },

{
   title: "ASUS TUF Gaming A15",
   price: "$949",
   rating: "4.4 out of 5 stars",
   link: "https://..."
 }
]

Предоставление «мозга» SIKKI

Чтобы создать для SIKKI «мозг», необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее отображение информации предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Устанавливайте точку контроля после дорогостоящих вызовов модели, чтобы повторная попытка не влекла за собой повторной оплаты той же работы.

const prompt = `You are an ecommerce analyst.
Analyze the following products.
${JSON.stringify(products)}
Return:
1. Cheapest product
2. Average price
3. Best rated product
4. Summary of the market
5. Recommendation
`;

Создание окончательного агента SIKKI

Для создания окончательного агента SIKKI необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Создавайте точки контроля после дорогостоящих вызовов модели, чтобы повторная попытка не влекла за собой повторной оплаты за одну и ту же работу.

Шаг 1: Создание файла агента

Для шага 1: перед изменением кода создайте файл агента, определите входные данные, ответственного за шаг и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Создавайте точку контроля после дорогостоящих вызовов модели, чтобы повторная попытка не приводила к повторной оплате той же работы. Для шага 1: перед изменением кода создайте файл агента, определите входные данные, ответственного за шаг и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успеха и не допускайте безусловного частичного завершения работы.

import "dotenv/config"; //to use environment variables from .env file
import fs from "fs"; //to read and write files

import { chromium } from "playwright";
import { GoogleGenAI } from "@google/genai";


//api keys and endpoints from environment variables
const BRIGHT_WS_ENDPOINT = process.env.BRIGHT_WS_ENDPOINT;
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
//initialize the GoogleGenAI client with the Gemini API key

const ai = new GoogleGenAI({
  apiKey: GEMINI_API_KEY,
});

//the prompt to send to the Gemini API
const prompt = "Write a short introduction to the Gemini API.";

const response = await ai.models.generateContent({
  model: "gemini-2.5-flash",
  contents: prompt,
});

console.log(response.text);

Шаг 2: Настройка Playwright для подключения к WebSocket-сервису Bright Data

Для шага 2: Настройка Playwright для подключения к WebSocket-сервису Bright Data необходимо заранее определить параметры ввода, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее отслеживание позволяет избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. Разделяйте планирование и выполнение с помощью инструментов: планер предлагает варианты, исполнитель вносит изменения, а проверщик сравнивает результаты с поставленной целью.

//setup Playwright to connect to Bright Data's WebSocket endpoint and navigate to Amazon search results for "gaming laptop"
async function main(){
  const browser = await chromium.connectOverCDP(BRIGHT_WS_ENDPOINT);
  const page = await browser.newPage();

  const query = "gaming laptop";
  const searchUrl = `https://www.amazon.com/s?k=${encodeURIComponent(query)}`;

  console.log("Navigating Bright Data Playwright to:", searchUrl);
  await page.goto(searchUrl, { waitUntil: "domcontentloaded" });

  const title = await page.title();
  console.log("Amazon search page title:", title);
  console.log("Bright Data navigation complete for query:", query);

  await browser.close();
}

main();

Шаг 3: Извлечение информации о продукте

Для шага 3: извлечение информации о продукте, необходимо определить входные данные, ответственного за выполнение этого шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Необходимо разделить процесс планирования и выполнение с помощью инструментов. Планировщик предлагает действия; исполнитель их реализует; проверщик сравнивает результаты с поставленной целью.

// Playwright to connect to Bright Data's WebSocket endpoint and navigate to Amazon search results for "gaming laptop"
async function main(){
  const browser = await chromium.connectOverCDP(BRIGHT_WS_ENDPOINT);
  const page = await browser.newPage();

  const query = "gaming laptop";
  const searchUrl = `https://www.amazon.com/s?k=${encodeURIComponent(query)}`;

  console.log("Navigating Bright Data Playwright to:", searchUrl);
  await page.goto(searchUrl, { waitUntil: "domcontentloaded" });

  const products = await page.evaluate(() => {
    const data = [];
    document
      .querySelectorAll('[data-component-type="s-search-result"]')
      .forEach((card) => {
        const title = card.querySelector("h2 span")?.innerText;
        const price = card.querySelector(".a-price .a-offscreen")?.innerText;
        const rating = card.querySelector(".a-icon-alt")?.innerText;
        if (title && price) {
          data.push({
            title,
            price,
            rating,
          });
        }
      });
    return data;
  });

  console.log("Step 3: Extract Product Information");
  console.log(products);

  const title = await page.title();
  console.log("Amazon search page title:", title);
  console.log("Bright Data navigation complete for query:", query);

  await browser.close();
}

main();

Шаг 4: попросить Gemini проанализировать рынок

Для шага 4: «Попросить Gemini проанализировать рынок» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный сценарий выполнения и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Необходимо разделить планирование и выполнение с помощью инструментов. Планировщик предлагает решения; исполнитель вносит изменения; проверщик сравнивает результаты с поставленной целью. Для шага 4: «Попросить Gemini проанализировать рынок» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Укажите названия элементов, определите критерии успеха и не допускайте молчаливого частичного выполнения задачи.

const prompt = `You are an ecommerce analyst.
Analyze these products:
${JSON.stringify(products)}
Return:
1. Cheapest Product
2. Average Market Price
3. Best Rated Product
4. Competitor Comparison
5. Final Recommendation
`;
const result = await model.generateContent(prompt);
const analysis =
result.response.text();
### 3. Best Rated Product
There are three products tied for the highest rating of **5.0 out of 5 stars**:
1.  **HP OMEN 16" Gaming Laptop Computer** (Intel Ultra 9 285H, NVIDIA GeForce RTX 5070 8GB, 16GB DDR5, 1TB PCIe SSD, 144Hz IPS WUXGA Display) at **$1,745.99**
2.  **HP OMEN 16 Slim RTX 5070 Gaming Laptop** (Intel Ultra 9 285H, NVIDIA RTX 5070, 32GB DDR5, 1TB SSD, 16" FHD+ Anti-Glare) at **$1,929.00**
3.  **ASUS ROG Strix G16 Gaming Laptop** (Intel Core i7 14650HX, NVIDIA RTX 5060, 32 GB DDR5 RAM, 1 TB SSD, 16" FHD+ LED Display, & Gaming Accessories) at **$1,999.99**

**Analysis:** It's noteworthy that two HP OMEN laptops achieved perfect ratings, both featuring high-end Ultra 9 CPUs and RTX 5070 GPUs.
This suggests strong customer satisfaction with HP's premium gaming line.
The ASUS ROG Strix G16 also achieved a 5.0 rating,
despite having a slightly lower-tier GPU (RTX 5060) than the
HP OMENs in this bracket, possibly due to the included
"Gaming Accessories" and overall perceived value.
The Alienware product has no rating, so it cannot be considered here.

Шаг 5: Экспорт отчета о рынке Sikki

Для шага 5: Экспорт отчета о рынке Sikki необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность повторно запустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Записывайте время выполнения и затраты рядом с функциональными результатами. Раннее обозрение помогает избежать неожиданных счетов при переходе с демо-среды в общедоступные среды. Схемы инструментов следует строго ограничивать; широкие параметры в виде свободного текста способствуют внедрению угроз и затрудняют аудит.

const report = `
# SIKKI Market Report
## Search Query
${query}

## Products
${JSON.stringify(products, null, 2)}

## Gemini Analysis
${analysis}

Generated: ${new Date().toISOString()}
`;

fs.writeFileSync(reportPath, report, "utf8");
import "dotenv/config"; // use environment variables from .env file
import fs from "fs";

import { chromium } from "playwright";
import { GoogleGenAI } from "@google/genai";

const BRIGHT_WS_ENDPOINT = process.env.BRIGHT_WS_ENDPOINT;
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;

if (!BRIGHT_WS_ENDPOINT) {
  throw new Error("Missing BRIGHT_WS_ENDPOINT environment variable.");
}

if (!GEMINI_API_KEY) {
  throw new Error("Missing GEMINI_API_KEY environment variable.");
}

const ai = new GoogleGenAI({
  apiKey: GEMINI_API_KEY,
});

async function retryWithBackoff(fn, maxRetries = 5, initialDelayMs = 2000) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const errorMsg = error?.message || error?.status || JSON.stringify(error);
      if (attempt === maxRetries) {
        console.error(`Final attempt failed. Error: ${errorMsg}`);
        throw error;
      }
      const delayMs = initialDelayMs * Math.pow(2, attempt - 1);
      console.log(`Attempt ${attempt} failed: ${errorMsg}`);
      console.log(`Retrying in ${delayMs}ms... (${attempt}/${maxRetries})`);
      await new Promise((resolve) => setTimeout(resolve, delayMs));
    }
  }
}

async function main() {
  let browser;
  try {
    browser = await chromium.connectOverCDP(BRIGHT_WS_ENDPOINT);
    const page = await browser.newPage();

    const query = "gaming laptop";
    const searchUrl = `https://www.amazon.com/s?k=${encodeURIComponent(query)}`;

    console.log("Connecting Playwright to Bright Data...");
    console.log("Navigating to:", searchUrl);

    await page.goto(searchUrl, { waitUntil: "domcontentloaded" });

    const products = await page.evaluate(() => {
      const data = [];
      document
        .querySelectorAll('[data-component-type="s-search-result"]')
        .forEach((card) => {
          const title = card.querySelector("h2 span")?.innerText;
          const price = card.querySelector(".a-price .a-offscreen")?.innerText;
          const rating = card.querySelector(".a-icon-alt")?.innerText;
          if (title && price) {
            data.push({
              title,
              price,
              rating,
            });
          }
        });
      return data;
    });

    console.log(`Extracted ${products.length} products.`);

    const analysisPrompt = `You are an ecommerce analyst.
Analyze these products:
${JSON.stringify(products)}
Return:
1. Cheapest Product
2. Average Market Price
3. Best Rated Product
4. Competitor Comparison
5. Final Recommendation
`;

    console.log("Sending products to Gemini for analysis (with retry logic)...");
    const analysisResult = await retryWithBackoff(async () => {
      return await ai.models.generateContent({
        model: "gemini-2.5-flash",
        contents: analysisPrompt,
      });
    }, 5, 2000);

    const analysis = analysisResult.text || "No analysis text returned.";

    const report = `# SIKKI Market Report

## Search Query
${query}

## Products
${JSON.stringify(products, null, 2)}

## Gemini Analysis
${analysis}

Generated: ${new Date().toISOString()}
`;

    fs.writeFileSync("sikki-report.md", report, "utf8");

    console.log("Step 5: Export the Results");
    console.log("Report generated: sikki-report.md");
    console.log("Final analysis saved. Open sikki-report.md to review the result.");

    await browser.close();
  } catch (error) {
    console.error("Error:", error.message || error);
    if (browser) {
      await browser.close().catch(() => {});
    }
    process.exit(1);
  }
}

main();

Шаг 6: Обучение SIKKI сбору доказательств

Для шага 6 «Обучение SIKKI сбору доказательств» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Схемы инструментов следует строго ограничивать. Широкие параметры в формате свободного текста способствуют внедрению угроз и затрудняют аудит.

const searchScreenshot = path.join(screenshotDir, "search-results.png");
await page.screenshot({ path: searchScreenshot, fullPage: true });
const summaryPath = path.join(screenshotDir, "top-product-summary.png");
await cards[0].screenshot({ path: summaryPath });

Шаг 7: Сохранение копий каждой страницы продукта

Для шага 7: Запись каждой страницы продукта. Перед изменением кода необходимо определить входные данные, ответственного за выполнение шага и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Строго ограничьте схемы инструментов. Широкие параметры в виде свободного текста способствуют внедрению угроз и затрудняют аудит. Для шага 7: Запись каждой страницы продукта. Перед изменением кода необходимо определить входные данные, ответственного за выполнение шага и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия результатам работы, определите критерии успеха и не допускайте молчаливого частичного завершения задачи.

const normalized = normalizeAmazonUrl(p.url, p.title);
await retryWithBackoff(async () =>
 await page.goto(normalized, { waitUntil: "domcontentloaded", timeout: 120000 }),
 3,
 1500
);
await page.waitForTimeout(800);
await page.screenshot({ path: outPath, fullPage: true });

Шаг 8: Создание экспорта в формате CSV

Для шага 8: Создание экспорта в формате CSV — необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрируйте время выполнения и затраты рядом с функциональными результатами. Раннее отображение информации предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды. Устанавливайте точку контроля после дорогостоящих вызовов модели, чтобы повторная попытка не влекла за собой повторной оплаты той же работы.

const csvLines = ["TITLE,PRICE,RATING,URL"];
enriched.forEach((p) => {
 const safe = (s) => `"${String(s || "").replace(/"/g, '""')}"`;
 csvLines.push([safe(p.title), safe(p.price), safe(p.rating || ""), safe(p.url || "")].join(","));
});
fs.writeFileSync(csvPath, csvLines.join("\n"), "utf8");

Шаг 9: Сгенерировать краткое описание на панели управления

Для шага 9: «Сгенерировать краткое описание панели управления», определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь код. Создавайте точку контроля после дорогостоящих вызовов модели, чтобы повторная попытка не приводила к повторной оплате за одну и ту же работу.

const priced = enriched.filter((p) => !isNaN(p.priceValue));
const cheapestObj = priced.length ? priced.reduce((a, b) => (a.priceValue <= b.priceValue ? a : b)) : null;
const avgPriceVal = priced.length ? (priced.reduce((s, p) => s + p.priceValue, 0) / priced.length).toFixed(2) : “N/A”;
const bestRatedObj = enriched.slice().sort((a, b) => {
 const ra = parseFloat((a.rating || “”).split(“ “)[0]) || 0;
 const rb = parseFloat((b.rating || “”).split(“ “)[0]) || 0;
 return rb — ra;
})[0] || null;
const dashboard = [];
dashboard.push(“==================================”);
dashboard.push(“SIKKI MARKET DASHBOARD”);
dashboard.push(“==================================”);
dashboard.push(`Query: ${query}`);
dashboard.push(`Products Extracted: ${enriched.length}`);
dashboard.push(`Cheapest Product: ${cheapestObj ? `${cheapestObj.title} | ${cheapestObj.price}` : “N/A”}`);
dashboard.push(`Average Price: ${avgPriceVal === “N/A” ? “N/A” : `${avgPriceVal}`}`);
dashboard.push(`Best Rated: ${bestRatedObj ? `${bestRatedObj.title} | ${bestRatedObj.rating || “N/A”}` : “N/A”}`);
dashboard.push(“\nTop 5 Products:”);
enriched.slice(0, 5).forEach((p, i) => {
 dashboard.push(`${i + 1}. ${p.title} | ${p.price} | ${p.rating || “N/A”} | ${p.url || “N/A”}`);
});
fs.writeFileSync(dashboardPath, dashboard.join(“\n”), “utf8”);

Куда дальше?

Чтобы определить дальнейшие шаги, необходимо заранее указать входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и аварийный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Создавайте точки контроля после дорогостоящих вызовов модели, чтобы повторные попытки не приводили к повторной оплате одних и тех же операций. Чтобы определить дальнейшие шаги, необходимо заранее указать входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия результатам работы, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

Заключение

В заключение необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Регистрируйте время выполнения и затраты рядом с функциональными результатами. Раннее видимость проблем предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Разделяйте планирование и выполнение с помощью инструментов: планер предлагает решения, исполнитель вносит изменения, а проверщик сравнивает результаты с поставленной целью.

Чек-лист операционной деятельности

Для чек-листа операционной деятельности необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии.

Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага он должен указывать на конкретную проблему, а не на запутанную структуру обработки данных.

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

Понимайте границы цикла событий: что блокирует поток, а что ожидает обработки в ядре.

Напишите краткое руководство: как обновлять ключи, как опустошать очередь, как откатывать последние изменения.

Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф.

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