Агенти автоматизації браузера без обмежень з Node.js
Створіть агента для керування браузером із чіткими межами функцій інструменту, захисними механізмами та можливістю журналізації дій.
У цьому посібнику створюється функціональний підхід до того, як побудувати агента для автоматизації браузера без обмежень за допомогою 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 перед реалізацією
Щоб глибше дослідити 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”);
Куди далі?
Щодо подальших кроків, необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Необхідно документувати як шлях успішного виконання, так і шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Створюйте точки контролю після дорогих викликів моделей, щоб повторні спроби не призводили до подвійного оплати однакової роботи. Щодо подальших кроків, необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цю стадію як контракт між вхідними даними та перевіреними результатами. Називайте результати роботи, визначайте критерії успіху та не допускайте безповідомного часткового завершення.
Висновок
На завершення необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан.
Чек-лист для експлуатації
Для чек-листу експлуатації також потрібно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори мають можливість повторно виконувати крок з відомої точки контролю без необхідності вгадування прихованих даних.
Віддавайте перевагу невеликим, тестованим одиницям коду перед складними скриптами. Якщо крок зазнає невдачі, причина має бути чітко визначена та стосуватися лише однієї функції, а не всього складного процесу.
Пункт перевірки після дорогих викликів моделей, щоб повторна спроба не стягувала плату за ту саму роботу.
Зрозумійте межі циклу подій: що блокує потік та що чекає на ядро.
Напишіть короткий посібник: як змінювати ключі, як спорожнювати чергу, як скасовувати останні зміни.
Зберігайте конфігурацію поза кодом додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф.
Перед підвищенням версії стека заморозьте версії, збережіть ідеальний запис для критичного шляху та підтвердьте кроки скасування. У спільних середовищах потрібні обмеження швидкості, перевірки приватності та чіткий власник для зміни секретів. Віддавайте перевагу надійності перед креативними одноразовими демонстраціями.