@hira-core/sdk
v1.0.24
Published
SDK for building Hira automation flows with TypeScript
Downloads
1,299
Maintainers
Readme
@hira-core/sdk
SDK for building Hira automation flows with TypeScript. Provides type-safe base classes, browser utilities, and logger for running flows inside the Hira Agent sandbox.
📖 Full Documentation — Guides, API reference, and examples.
Installation
npm install @hira-core/sdk
# or
pnpm add @hira-core/sdkPeer dependency: Requires
puppeteer-coreto be available at runtime (provided by the Hira Agent).
Quick Start
1. Define your Flow Config
import {
AntidetectBaseFlow,
AntidetectProvider,
defineFlowConfig,
IScriptContext,
BrowserUtils,
FlowLogger,
} from "@hira-core/sdk";
const config = defineFlowConfig({
globalInput: [
{
key: "targetUrl",
label: "Target URL",
type: "text" as const,
required: true,
},
{
key: "delay",
label: "Delay (ms)",
type: "number" as const,
defaultValue: 2000,
},
],
profileInput: [
{ key: "username", label: "Username", type: "text" as const },
{ key: "password", label: "Password", type: "text" as const },
],
output: [
{ index: 0, key: "isLoggedIn", label: "Login Status" },
{ index: 1, key: "pageTitle", label: "Page Title" },
],
});
type MyConfig = typeof config;
defineFlowConfig()validates for duplicate keys, labels, and output indices at compile time — providing instant TS errors if any field is duplicated.
2. Implement your Flow class
export class MyFlow extends AntidetectBaseFlow<MyConfig> {
constructor() {
super(AntidetectProvider.GPM, new FlowLogger(MyFlow.name), config);
}
async script(context: IScriptContext<MyConfig>): Promise<void> {
const { page, logger, globalInput, profileInput, output } = context;
const utils = new BrowserUtils(context);
await utils.goto(globalInput.targetUrl);
logger.info(`Logging in as: ${profileInput.username}`);
await utils.type("#username", profileInput.username);
await utils.type("#password", profileInput.password);
await utils.click("#login-btn");
const title = await page.title();
// Write typed output (validated against config.output keys)
await utils.writeOutput("isLoggedIn", true);
await utils.writeOutput("pageTitle", title);
logger.success(`✅ Done — page: ${title}`);
}
}
export default MyFlow;3. Run locally (for development)
import MyFlow from "./index";
const flow = new MyFlow();
await flow.run(
flow.createRunParams({
antidetect: {
profileSettings: [
flow.createProfileSetting("ProfileA", {
username: "user1",
password: "pass1",
}),
],
},
execution: { concurrency: 2, maxRetries: 1 },
globalInput: { targetUrl: "https://example.com", delay: 2000 },
window: { width: 1280, height: 720, scale: 1 },
}),
);API Reference
AntidetectBaseFlow<TConfig>
Abstract base class for browser automation flows.
| Method / Property | Description |
| ----------------------------------- | ------------------------------------------------ |
| abstract script(context) | Your automation logic — implement this |
| run(params) | Start the flow (called by Hira Agent) |
| createRunParams(params) | Type-safe helper to build run params |
| createProfileSetting(name, data?) | Type-safe helper to build profile settings |
| flowConfig | The declared config schema (embedded in .hira) |
AntidetectProvider
enum AntidetectProvider {
GPM = "gpm", // GPM Login antidetect browser
HIDEMIUM = "hidemium", // Hidemium antidetect browser
GENLOGIN = "genlogin", // coming soon
}IScriptContext<TConfig>
Injected into script() by the runtime:
| Field | Type | Description |
| -------------- | ---------------------------- | ---------------------------------------------------- |
| browser | Browser | Puppeteer browser instance |
| page | Page | Active page |
| profile | IAntidetectProfile | Current profile info (unified across providers) |
| index | number | Profile index in the batch |
| globalInput | InferGlobalInput<TConfig> | Typed global inputs |
| profileInput | InferProfileInput<TConfig> | Typed per-profile inputs |
| output | InferOutput<TConfig> | Current output values (pre-populated from last run) |
| logger | ILogger | Bound logger (auto-tagged with profile name) |
IAntidetectProfile
Unified profile interface — works across all providers (GPM, Hidemium, etc.):
interface IAntidetectProfile {
id: string; // Unique ID
name: string; // Human-readable name
provider: "gpm" | "hidemium" | "genlogin";
raw_proxy?: string; // Proxy string
browser_type: "chromium" | "firefox";
browser_version: string;
group_id?: string;
profile_path: string;
note: string;
created_at: string; // ISO 8601
}Note:
IGpmProfileis deprecated — useIAntidetectProfileinstead.
BrowserUtils
Helper class for common browser actions. All methods auto-log and respect the abort signal.
const utils = new BrowserUtils(context);Navigation & Interaction
| Method | Description |
| ------------------------------------------ | -------------------------------------- |
| utils.goto(url) | Navigate to URL |
| utils.click(selector) | Wait + scroll + click |
| utils.click({ x, y }) | Click at specific coordinates |
| utils.type(selector, text) | Wait + clear + type |
| utils.select(selector, value) | Select dropdown option (native <select>) |
| utils.getText(selector) | Get text content |
| utils.getPosition(selector) | Get element center coordinates |
| utils.exists(selector, timeout?) | Check element exists |
| utils.waitForElement(selector, timeout?) | Wait for element |
| utils.waitForNavigation() | Wait for page navigation |
| utils.screenshot(path?) | Take screenshot |
| utils.sleep(ms) | Delay (respects abort signal) |
| utils.scroll({ deltaY }) | Smooth 60fps scroll (ease-in-out) |
| utils.scroll({ deltaY, container }) | Smooth scroll inside overflow container|
Tab Management
| Method | Description |
| --------------------------------- | ------------------------ |
| utils.activeNewTab(options?) | Switch to new tab, returns true on success / false on timeout |
| utils.activePopup(options?) | Switch to popup, returns true on success / false on timeout |
| utils.switchToPopup(matcher) | Legacy alias for popup switching |
| utils.switchToTabIndex(index) | Switch to tab by index |
| utils.closeCurrentTab() | Close current tab |
| utils.closeOtherTabs() | Close all other tabs |
Output & Data
| Method | Description |
| ------------------------------------ | ------------------------------------------------ |
| utils.writeOutput(key, value) | Write output value (type-safe against config) |
| utils.writeProfileInput(key, val) | Update profile input value for next run |
| utils.logGlobalInput() | Log all global inputs |
| utils.logProfileInput() | Log all profile inputs |
Production Stability Notes
activeNewTab()andactivePopup()now use soft-fail semantics: returnfalsewhen the tab/popup is not found instead of throwing. Always check the boolean before interacting with the new page.- Browser activation internally catches non-critical CDP focus/stealth failures so a closed or unstable tab does not crash the whole flow.
BaseFlow.processProfile()performs final logger cleanup and promise-reference cleanup to prevent ghost logs and memory leaks in long-running agents.- GPM/Hidemium profile startup errors preserve the provider's original error message, making production failures easier to diagnose.
FlowLogger
Logger that works both in standalone mode (console) and inside Hira Agent worker (postMessage).
const logger = new FlowLogger("MyFlow");
logger.info("message");
logger.success("done");
logger.warn("warning");
logger.error("error");
logger.debug("debug");IFlowConfig
Schema declaration for your flow's inputs and outputs:
interface IFlowConfig {
globalInput: readonly IInputField[]; // shared across all profiles
profileInput: readonly IInputField[]; // per-profile data
output?: readonly IOutputField[]; // output fields per profile
}
interface IInputField {
key: string;
label: string;
type: "text" | "number" | "boolean" | "select" | "textarea";
required?: boolean;
defaultValue?: string | number | boolean;
placeholder?: string;
options?: { label: string; value: string | number }[];
}
interface IOutputField {
index: number; // display order
key: string; // unique key for writeOutput()
label: string; // human-readable label
}defineFlowConfig()
Helper function that validates your config at compile time — catches duplicate keys, labels, indices, and option values:
// ✅ OK
const config = defineFlowConfig({
globalInput: [
{ key: "url", label: "URL", type: "text" },
],
profileInput: [
{ key: "user", label: "User", type: "text" },
],
output: [
{ index: 0, key: "status", label: "Status" },
{ index: 1, key: "title", label: "Title" },
],
});
// ❌ TS Error — duplicate key "url" in globalInput
const bad = defineFlowConfig({
globalInput: [
{ key: "url", label: "URL 1", type: "text" },
{ key: "url", label: "URL 2", type: "text" }, // Error!
],
profileInput: [],
});ExcelStorage
Read profile data from Excel files and write output back:
import { ExcelStorage } from "@hira-core/sdk";
const storage = new ExcelStorage("data.xlsx");
// Read rows from a sheet
const rows = await storage.readRows("Sheet1");
// Write output rows
await storage.writeRows("Output", outputData);Type Inference
The SDK automatically infers TypeScript types from your config at compile time:
const config = defineFlowConfig({
globalInput: [
{ key: "url", type: "text" as const, label: "URL" },
{ key: "count", type: "number" as const, label: "Count" },
],
profileInput: [
{ key: "username", type: "text" as const, label: "Username" },
],
output: [
{ index: 0, key: "isLoggedIn", label: "Logged In" },
],
});
// Inside script():
// globalInput.url → string ✅
// globalInput.count → number ✅
// profileInput.username → string ✅
// output.isLoggedIn → ProfileOutputValue | null ✅Building & Publishing a Flow
Use @hira-core/cli to package your flow:
npx @hira-core/cli buildVirtual Cursor
The SDK includes a virtual cursor — a visible SVG cursor overlay that shows mouse movement, clicks, and scrolling in real-time. This is enabled by default and can be toggled via IExecutionConfig.virtualCursor:
// In flow runner params
execution: {
virtualCursor: true, // default — show cursor overlay
// virtualCursor: false, // disable cursor overlay
}When enabled, BrowserUtils.click(), scroll(), and other interaction methods will show realistic Bézier curve mouse movement with human-like timing.
License
ISC
