webcrawlerapi-js 2.2.2 → 2.2.6

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.
@@ -1,4 +1,4 @@
1
- import { CrawlRequest, Job, JobId, ScrapeRequest, ScrapeResponse, ScrapeResponseError, ScrapeId, JobMarkdownResponse, AgentRunRequest, AgentRun } from "./model";
1
+ import { CrawlRequest, Job, JobId, ScrapeRequest, ScrapeResponse, ScrapeResponseError, ScrapeId, JobMarkdownResponse, MarkdownRequest, MarkdownResponse, AgentRunRequest, AgentRun } from "./model";
2
2
  import { JobStatus, ErrorCode } from "./constants";
3
3
  import { WebcrawlerApiError } from "./errors";
4
4
  export { WebcrawlerApiError, JobStatus, ErrorCode };
@@ -20,5 +20,6 @@ export declare class WebcrawlerClient {
20
20
  getJob(jobID: string): Promise<Job>;
21
21
  getJobMarkdown(jobID: string): Promise<JobMarkdownResponse>;
22
22
  getJobMarkdownContent(jobID: string): Promise<string>;
23
+ markdown(request: MarkdownRequest): Promise<MarkdownResponse>;
23
24
  private sendRequest;
24
25
  }
@@ -29,6 +29,8 @@ export interface ScrapeResponse {
29
29
  page_title?: string;
30
30
  structured_data?: any;
31
31
  links?: string[];
32
+ /** Server-recommended delay before the next status poll, if provided */
33
+ recommended_pull_delay_ms?: number;
32
34
  }
33
35
  export interface ScrapeResponseError {
34
36
  success: boolean;
@@ -120,6 +122,15 @@ export interface UploadS3Action extends Action {
120
122
  export interface JobMarkdownResponse {
121
123
  content_url: string;
122
124
  }
125
+ export interface MarkdownRequest {
126
+ /** The URL of the webpage to extract the article markdown from. */
127
+ url: string;
128
+ }
129
+ export interface MarkdownResponse {
130
+ success: boolean;
131
+ /** Cleaned article markdown (main content only). */
132
+ markdown?: string;
133
+ }
123
134
  export interface AgentRunRequest {
124
135
  /** Natural-language task for the agent to complete. */
125
136
  prompt: string;
package/dist/api.js CHANGED
@@ -24,6 +24,9 @@ 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 SCRAPE_MAX_WAIT_MS = 400 * 1000;
28
+ // Effectively unbounded by count at the 2s default; elapsed time is the real limit
29
+ const SCRAPE_MAX_POLLS = 1000;
27
30
  const AgentTerminalStatuses = ["done", "error", "canceled"];
28
31
  __exportStar(require("./model"), exports);
29
32
  const SCRAPE_VERSION = "v2";
@@ -183,17 +186,21 @@ class WebcrawlerClient {
183
186
  return {
184
187
  success: false,
185
188
  status: status,
186
- page_status_code: 0
189
+ page_status_code: 0,
190
+ recommended_pull_delay_ms: responseData.recommended_pull_delay_ms
187
191
  };
188
192
  }
189
193
  }
190
- async scrape(request, maxPolls = 100) {
194
+ async scrape(request, maxPolls = SCRAPE_MAX_POLLS) {
191
195
  // Start the scraping job
192
196
  const scrapeIdResponse = await this.scrapeAsync(request);
193
197
  const scrapeId = scrapeIdResponse.id;
198
+ const startedAt = Date.now();
194
199
  let polls = 0;
200
+ let delayMs = DEFAULT_POLL_DELAY_SECONDS * 1000;
195
201
  let result;
196
- while (polls < maxPolls) {
202
+ // Bounded by both elapsed time (SCRAPE_MAX_WAIT_MS) and maxPolls
203
+ while (polls < maxPolls && Date.now() - startedAt < SCRAPE_MAX_WAIT_MS) {
197
204
  result = await this.getScrape(scrapeId);
198
205
  // Return immediately if scrape is done
199
206
  if ('status' in result && result.status === "done") {
@@ -203,12 +210,17 @@ class WebcrawlerClient {
203
210
  if ('error_code' in result) {
204
211
  return result;
205
212
  }
206
- // Continue polling if status is in_progress or any other non-terminal status
207
- // Wait before next poll
208
- await new Promise(resolve => setTimeout(resolve, DEFAULT_POLL_DELAY_SECONDS * 1000));
213
+ // Use server-recommended delay when present, otherwise keep the default
214
+ const recommended = result.recommended_pull_delay_ms;
215
+ delayMs = recommended && recommended > 0 ? recommended : DEFAULT_POLL_DELAY_SECONDS * 1000;
216
+ // Don't sleep past the overall deadline
217
+ const remainingMs = SCRAPE_MAX_WAIT_MS - (Date.now() - startedAt);
218
+ if (remainingMs <= 0)
219
+ break;
220
+ await new Promise(resolve => setTimeout(resolve, Math.min(delayMs, remainingMs)));
209
221
  polls++;
210
222
  }
211
- // Return the last known state if maxPolls is reached
223
+ // Return the last known state on timeout
212
224
  return result;
213
225
  }
214
226
  async crawl(crawlRequest, maxPolls = MaxPullRetries) {
@@ -328,6 +340,15 @@ class WebcrawlerClient {
328
340
  }
329
341
  return response.text();
330
342
  }
343
+ async markdown(request) {
344
+ const url = `${this.basePath}/markdown`;
345
+ const requestOptions = {
346
+ 'method': 'POST',
347
+ 'headers': this.getDefaultHeaders(),
348
+ 'body': JSON.stringify(request),
349
+ };
350
+ return this.sendRequest(url, requestOptions);
351
+ }
331
352
  async sendRequest(url, requestOptions) {
332
353
  let response;
333
354
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcrawlerapi-js",
3
- "version": "2.2.2",
3
+ "version": "2.2.6",
4
4
  "description": "JS client for WebcrawlerAPI",
5
5
  "main": "./dist/api.js",
6
6
  "types": "./dist/@types/api.d.ts",