npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andy-toolforge/core

v1.2.1

Published

Toolforge foundation: browser manager, LLM client, logger, job queue

Readme

@andy-toolforge/core

npm License

Toolforge foundation package. Cung cấp 4 dịch vụ nền tảng: LLM client (multi-provider với adapter chain & fallback), browser automation, structured logger, và job queue. Tất cả domain packages (footage-generation, ba-support, book-writing, ...) đều dựa trên package này.

⚠️ Quan trọng: Core KHÔNG chứa domain-specific logic (không có analyzeScript, generateXxx). Những method đó nằm trong domain package's LLMClient subclass.

Installation

npm install @andy-toolforge/core

API Reference


LLMClient

Generic LLM client với multi-provider routing & fallback. Supports Gemini, Groq, OpenAI qua unified API.

Constructor

Cách 1 (backward-compatible): Provider + API key đơn

| Param | Type | Default | Mô tả | |-------|------|---------|-------| | provider | string | 'gemini' | 'gemini' | 'groq' | 'openai' | | apiKey | string | (required) | API key từ provider | | model | string | Provider default | Tên model | | maxRetries | number | 3 | Số lần retry tối đa | | baseDelay | number | 2000 | Base delay cho exponential backoff (ms) |

Cách 2 (khuyên dùng): Priority-ordered adapter chain — tự động fallback khi adapter đầu fail

| Param | Type | Default | Mô tả | |-------|------|---------|-------| | adapters | ProviderAdapter[] | (required) | Array adapter theo thứ tự ưu tiên | | maxRetries | number | 3 | Số lần retry tối đa | | baseDelay | number | 2000 | Base delay cho exponential backoff (ms) |

Phương thức:

| Method | Params | Returns | Mô tả | |--------|--------|---------|-------| | chat() | systemPrompt, userPrompt, jsonMode?, fetchFn? | Promise<string> | Gửi chat completion với adapter chain. Tự động fallback nếu adapter đầu fail |

Providers hỗ trợ:

| Provider | Adapter | API Key Env | Model mặc định | |----------|---------|-------------|---------------| | Gemini | OpenAIAdapter | GEMINI_API_KEY | gemini-2.0-flash | | Gemini (SDK) | GenAIAdapter | GEMINI_API_KEY | gemini-2.5-flash | | Groq | OpenAIAdapter | GROQ_API_KEY | llama-3.3-70b-versatile | | OpenAI | OpenAIAdapter | OPENAI_API_KEY | Provider default |

Ví dụ — backward-compatible (cách 1):

const { LLMClient } = require('@andy-toolforge/core');

const llm = new LLMClient({
    provider: 'gemini',
    apiKey: process.env.GEMINI_API_KEY,
});

const reply = await llm.chat('Bạn là trợ lý tiếng Việt', 'Xin chào!');
console.log(reply);

Ví dụ — adapter chain với fallback (cách 2, khuyên dùng):

const { LLMClient, OpenAIAdapter } = require('@andy-toolforge/core');
const { GenAIAdapter } = require('@andy-toolforge/genai-tools');

const llm = new LLMClient({
    adapters: [
        new GenAIAdapter(process.env.GEMINI_API_KEY),     // 1st: Gemini SDK
        new OpenAIAdapter('groq', process.env.GROQ_API_KEY), // 2nd: Groq fallback
    ],
});

// Nếu Gemini fail → tự động fallback sang Groq
const reply = await llm.chat('System prompt', 'User message');

Ví dụ với error handling:

try {
    const reply = await llm.chat('System prompt', 'User message');
} catch (err) {
    if (err.message.includes('All adapters failed')) {
        // Tất cả providers trong chain đều fail
        console.error('All providers unavailable:', err.message);
    } else if (err.message.includes('429')) {
        console.error('Rate limited after retries');
    } else if (err.message.includes('401')) {
        console.error('Invalid API key');
    } else {
        console.error('LLM call failed:', err.message);
    }
}

ProviderAdapter (base class)

Abstract base cho tất cả provider adapters. Triển khai chat() contract để LLMClient sử dụng trong adapter chain.

Methods:

| Method | Params | Returns | Mô tả | |--------|--------|---------|-------| | chat() | { systemPrompt, messages, jsonMode, fetchFn } | Promise<{ content, toolCalls, usage }> | Gọi LLM, trả về normalized response |

Các adapter có sẵn:

| Adapter | Package | Mô tả | |---------|---------|-------| | OpenAIAdapter | @andy-toolforge/core | Fetch-based, cho Gemini/Groq/OpenAI endpoints | | GenAIAdapter | @andy-toolforge/genai-tools | Dùng @google/genai SDK |

const { ProviderAdapter } = require('@andy-toolforge/core');

class MyCustomAdapter extends ProviderAdapter {
    async chat({ systemPrompt, messages, jsonMode, fetchFn }) {
        // Triển khai provider-specific logic
    }
}

OpenAIAdapter

Fetch-based adapter — hỗ trợ Gemini, Groq, OpenAI qua OpenAI-compatible REST API.

Constructor: new OpenAIAdapter(provider, apiKey, model?)

| Param | Type | Mô tả | |-------|------|-------| | provider | string | 'gemini' | 'groq' | 'openai' | | apiKey | string | API key | | model | string | (optional) Override model default |

Tự động retry: Network errors + 429 (exponential backoff, max 3 lần).


BrowserManager

Puppeteer browser lifecycle management. Singleton-safe: chỉ launch một browser duy nhất.

Constructor params:

| Param | Type | Default | Mô tả | |-------|------|---------|-------| | headless | boolean | true | Chạy headless (không UI) |

Phương thức:

| Method | Returns | Mô tả | |--------|---------|-------| | launch() | Promise<Browser> | Khởi động Puppeteer browser | | close() | Promise<void> | Đóng browser | | newPage() | Promise<Page> | Tạo page mới (tự động launch nếu chưa có) |

Ví dụ — crawl một trang web:

const { BrowserManager } = require('@andy-toolforge/core');

const browser = new BrowserManager({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });

const title = await page.title();
const content = await page.content();

console.log('Title:', title);
await browser.close();

Lưu ý:

  • Puppeteer là optional dependency — nếu không cần browser automation, có thể bỏ qua (không gây lỗi install)
  • Trên macOS/Linux, Puppeteer tự động download Chromium
  • Gọi close() sau khi dùng xong để giải phóng tài nguyên

Logger

Structured logging với 4 levels. Output ra console với timestamp + context.

Constructor params:

| Param | Type | Default | Mô tả | |-------|------|---------|-------| | level | string | 'info' | 'debug' | 'info' | 'warn' | 'error' | | (name) | string | optional | Tên logger (hiển thị trong log) |

Phương thức:

| Method | Params | Mô tả | |--------|--------|-------| | debug() | message, context? | Chỉ hiển thị khi level = debug | | info() | message, context? | Thông tin thông thường | | warn() | message, context? | Cảnh báo | | error() | message, error? | Lỗi |

Ví dụ:

const { Logger } = require('@andy-toolforge/core');

const log = new Logger('MyApp', 'debug');
// Hoặc: new Logger({ level: 'info' });

log.debug('Connecting to DB', { host: 'localhost', port: 5432 });
log.info('Server started', { port: 3000 });
log.warn('Rate limit approaching', { requestsLeft: 10 });
log.error('Failed to connect', err);
// Output: [2026-07-05T10:30:00.000Z] [INFO] MyApp: Server started {"port":3000}

JobQueue

In-memory async FIFO job queue. Tạo, theo dõi, và quản lý jobs.

Phương thức:

| Method | Params | Returns | Mô tả | |--------|--------|---------|-------| | create() | params | Job | Tạo job mới, trả về job object | | get() | id | Job \| undefined | Lấy job theo ID | | update() | id, updates | void | Cập nhật job state | | list() | filter? | Job[] | Liệt kê jobs, có thể filter | | remove() | id | void | Xoá job |

Job object:

{
    id: 'uuid',
    state: 'pending' | 'running' | 'done' | 'failed',
    currentStep: null,
    completedSteps: [],
    params: { ... },
    error: null,
    startTime: 'ISO date',
}

Ví dụ:

const { JobQueue } = require('@andy-toolforge/core');

const queue = new JobQueue();

// Tạo jobs
const job1 = queue.create({ type: 'scrape', url: 'https://example.com' });
const job2 = queue.create({ type: 'process', file: 'data.csv' });

// List jobs đang pending
const pending = queue.list({ state: 'pending' });

// Cập nhật job progress
queue.update(job1.id, { state: 'running' });
queue.update(job1.id, { state: 'done', completedSteps: ['scrape'] });

Error Handling Checklist

| Triệu chứng | Nguyên nhân | Cách xử lý | |-------------|-------------|-------------| | LLM không response | API key sai | Kiểm tra GEMINI_API_KEY / GROQ_API_KEY env | | LLM trả về 429 | Rate limit | LLMClient tự retry, tăng baseDelay nếu cần | | LLM trả về error | Network error | maxRetries: 5 + kiểm tra network | | Browser không launch | Puppeteer chưa cài | npm install puppeteer | | Browser page crash | Memory | Gọi browser.close() giữa các lần crawl |

Related