webcrawlerapi-js 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,6 +46,31 @@ for (const item of job.job_items) {
46
46
  }
47
47
  ```
48
48
 
49
+ ## Run an agent
50
+
51
+ ```javascript
52
+ import webcrawlerapi from "webcrawlerapi-js"
53
+
54
+ const client = new webcrawlerapi.WebcrawlerClient("YOUR_API_KEY")
55
+
56
+ const result = await client.runAgent({
57
+ prompt: "Visit the provided website and return the page title as JSON.",
58
+ urls: ["https://books.toscrape.com/"],
59
+ seed_urls_only: true,
60
+ output_schema: {
61
+ type: "object",
62
+ properties: {
63
+ title: { type: "string" },
64
+ },
65
+ required: ["title"],
66
+ additionalProperties: false,
67
+ },
68
+ max_spend_usd: 0.02,
69
+ })
70
+
71
+ console.log(result.status, result.data)
72
+ ```
73
+
49
74
  ## Documentation
50
75
 
51
76
  - [Scraping](docs/scraping.md) — single page, async mode, AI extraction, parameters, response fields
@@ -1,4 +1,4 @@
1
- import { CrawlRequest, Job, JobId, ScrapeRequest, ScrapeResponse, ScrapeResponseError, ScrapeId, Action, JobMarkdownResponse } from "./model";
1
+ import { CrawlRequest, Job, JobId, ScrapeRequest, ScrapeResponse, ScrapeResponseError, ScrapeId, Action, JobMarkdownResponse, AgentRunRequest, AgentRun } from "./model";
2
2
  import { JobStatus, ErrorCode } from "./constants";
3
3
  import { WebcrawlerApiError } from "./errors";
4
4
  export { WebcrawlerApiError, JobStatus, ErrorCode };
@@ -8,7 +8,11 @@ export declare class WebcrawlerClient {
8
8
  protected apiKey: string;
9
9
  protected basePath: string;
10
10
  constructor(apiKey: string, basePath?: string, apiVersion?: string);
11
+ private getDefaultHeaders;
11
12
  scrapeAsync(request: ScrapeRequest): Promise<ScrapeId>;
13
+ runAgentAsync(request: AgentRunRequest): Promise<AgentRun>;
14
+ getAgentJob(jobID: string): Promise<AgentRun>;
15
+ runAgent(request: AgentRunRequest, maxPolls?: number): Promise<AgentRun>;
12
16
  getScrape(scrapeId: string): Promise<ScrapeResponse | ScrapeResponseError>;
13
17
  scrape(request: ScrapeRequest, maxPolls?: number): Promise<ScrapeResponse | ScrapeResponseError>;
14
18
  crawl(crawlRequest: CrawlRequest, actions?: Action | Action[]): Promise<Job>;
@@ -119,3 +119,35 @@ export interface UploadS3Action extends Action {
119
119
  export interface JobMarkdownResponse {
120
120
  content_url: string;
121
121
  }
122
+ export interface AgentRunRequest {
123
+ /** Natural-language task for the agent to complete. */
124
+ prompt: string;
125
+ /** Optional seed URLs the agent can use while running the task. */
126
+ urls?: string[];
127
+ /** If true, the agent only uses the provided seed URLs. */
128
+ seed_urls_only?: boolean;
129
+ /** Optional JSON schema for structured agent output. */
130
+ output_schema?: Record<string, any>;
131
+ /** Model to use for the run. Omit to use the API default. */
132
+ model?: string;
133
+ /** Maximum spend for this run in USD. Required by the API. */
134
+ max_spend_usd: number;
135
+ }
136
+ export interface AgentRun {
137
+ id: string;
138
+ status: string;
139
+ prompt: string;
140
+ model: string;
141
+ data?: any;
142
+ error_reason?: string;
143
+ balance_used_usd: number;
144
+ max_spend_usd?: number;
145
+ urls?: string[];
146
+ created_at: string;
147
+ updated_at: string;
148
+ success: boolean;
149
+ }
150
+ export interface AgentRunList {
151
+ items: AgentRun[];
152
+ total: number;
153
+ }
package/dist/api.js CHANGED
@@ -24,6 +24,7 @@ const BASE_PATH = "https://api.webcrawlerapi.com";
24
24
  const initialPullDelayMs = 2000;
25
25
  const MaxPullRetries = 100;
26
26
  const DEFAULT_POLL_DELAY_SECONDS = 2;
27
+ const AgentTerminalStatuses = ["done", "error", "canceled"];
27
28
  __exportStar(require("./model"), exports);
28
29
  const SCRAPE_VERSION = "v2";
29
30
  function resolveContentUrl(job, item) {
@@ -94,6 +95,19 @@ class WebcrawlerClient {
94
95
  this.basePath = basePath;
95
96
  this.apiVersion = apiVersion;
96
97
  }
98
+ getDefaultHeaders(cacheControl = false) {
99
+ const headers = {
100
+ 'Content-Type': 'application/json',
101
+ 'Authorization': `Bearer ${this.apiKey}`,
102
+ "User-Agent": "WebcrawlerAPI-NodeJS-Client"
103
+ };
104
+ if (cacheControl) {
105
+ headers['Cache-Control'] = 'no-cache, no-store, must-revalidate';
106
+ headers['Pragma'] = 'no-cache';
107
+ headers['Expires'] = '0';
108
+ }
109
+ return headers;
110
+ }
97
111
  async scrapeAsync(request) {
98
112
  const apiUrl = `${this.basePath}/${SCRAPE_VERSION}/scrape?async=true`;
99
113
  const requestOptions = {
@@ -108,6 +122,41 @@ class WebcrawlerClient {
108
122
  const response = await this.sendRequest(apiUrl, requestOptions);
109
123
  return { id: response.id };
110
124
  }
125
+ async runAgentAsync(request) {
126
+ const url = `${this.basePath}/${this.apiVersion}/agent`;
127
+ const requestOptions = {
128
+ 'method': 'POST',
129
+ 'headers': this.getDefaultHeaders(),
130
+ 'body': JSON.stringify(request),
131
+ };
132
+ return await this.sendRequest(url, requestOptions);
133
+ }
134
+ async getAgentJob(jobID) {
135
+ const url = `${this.basePath}/${this.apiVersion}/agent/job/${jobID}`;
136
+ const requestOptions = {
137
+ 'method': 'GET',
138
+ 'headers': this.getDefaultHeaders(true)
139
+ };
140
+ return await this.sendRequest(url, requestOptions);
141
+ }
142
+ async runAgent(request, maxPolls = MaxPullRetries) {
143
+ const run = await this.runAgentAsync(request);
144
+ if (!run.id) {
145
+ throw new errors_1.WebcrawlerApiError('invalid_response', 'Failed to fetch agent job status', 0);
146
+ }
147
+ if (AgentTerminalStatuses.includes(run.status)) {
148
+ return run;
149
+ }
150
+ for (let i = 0; i < maxPolls; i++) {
151
+ await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_DELAY_SECONDS * 1000));
152
+ const timestamp = new Date().getTime();
153
+ const agentJob = await this.getAgentJob(`${run.id}?t=${timestamp}`);
154
+ if (AgentTerminalStatuses.includes(agentJob.status)) {
155
+ return agentJob;
156
+ }
157
+ }
158
+ throw new errors_1.WebcrawlerApiError('timeout', 'Agent run took too long, please retry or increase the number of polling retries', 0);
159
+ }
111
160
  async getScrape(scrapeId) {
112
161
  const url = `${this.basePath}/${SCRAPE_VERSION}/scrape/${scrapeId}`;
113
162
  const requestOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcrawlerapi-js",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "JS client for WebcrawlerAPI",
5
5
  "main": "./dist/api.js",
6
6
  "types": "./dist/@types/api.d.ts",