@productcraft/trawl 0.2.3 → 0.2.4

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
@@ -20,7 +20,7 @@ import: `npm install productcraft`.
20
20
 
21
21
  ## Usage
22
22
 
23
- ```ts
23
+ ```ts before
24
24
  import { Trawl } from "@productcraft/trawl";
25
25
 
26
26
  // Reads PRODUCTCRAFT_API_KEY from the environment
package/dist/index.d.cts CHANGED
@@ -487,6 +487,64 @@ interface components {
487
487
  */
488
488
  reason: string;
489
489
  };
490
+ /**
491
+ * CreditsLowEvent
492
+ * @description Your Trawl balance dropped below 10% of your last top-up (at least 100 steps). Sent once; it comes again after your next top-up. New jobs are refused when the balance reaches zero. Job events also carry the keys of the previous webhook body (`event`, `occurred_at`, `job`) until its sunset; read `type`, `created_at` and `data` instead.
493
+ * @example {
494
+ * "created_at": "2026-11-05T09:00:00.000Z",
495
+ * "data": {
496
+ * "balance_steps": 840,
497
+ * "last_top_up_steps": 10000,
498
+ * "threshold_steps": 1000
499
+ * },
500
+ * "id": "evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f",
501
+ * "type": "credits.low",
502
+ * "workspace_id": "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
503
+ * }
504
+ */
505
+ CreditsLowEvent: {
506
+ /**
507
+ * Format: date-time
508
+ * @description When the event happened (the same on every retry).
509
+ * @example 2026-11-05T09:00:00.000Z
510
+ */
511
+ created_at: string;
512
+ data: components["schemas"]["CreditsLowEventDataDto"];
513
+ /**
514
+ * @description The event id, also sent as `webhook-id`; the same on every retry and replay.
515
+ * @example evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f
516
+ */
517
+ id: string;
518
+ /** @description Present and true only on a delivery made by "Send test"; its `data` is the catalogue example. */
519
+ test?: boolean;
520
+ /**
521
+ * @description The event type. Switch on it to narrow the event.
522
+ * @enum {string}
523
+ */
524
+ type: "credits.low";
525
+ /**
526
+ * Format: uuid
527
+ * @description The workspace the event belongs to, so you can route without opening `data`. Absent on "Send test" deliveries.
528
+ */
529
+ workspace_id?: string;
530
+ };
531
+ CreditsLowEventDataDto: {
532
+ /**
533
+ * @description The balance, in steps, when the event was sent.
534
+ * @example 840
535
+ */
536
+ balance_steps: number;
537
+ /**
538
+ * @description Steps added by the last top-up.
539
+ * @example 10000
540
+ */
541
+ last_top_up_steps: number;
542
+ /**
543
+ * @description The threshold it dropped below: 10% of the last top-up, at least 100 steps.
544
+ * @example 1000
545
+ */
546
+ threshold_steps: number;
547
+ };
490
548
  CreditsResponseDto: {
491
549
  /**
492
550
  * @description Remaining steps. One agent step uses one credit; new jobs are refused (402) at zero. Can dip slightly below zero, because a running job is always allowed to finish.
@@ -563,6 +621,54 @@ interface components {
563
621
  */
564
622
  status_code: number;
565
623
  };
624
+ JobEventDataDto: {
625
+ /** @description The job that finished. */
626
+ job: components["schemas"]["JobOutcomeDto"];
627
+ };
628
+ /**
629
+ * JobFailedEvent
630
+ * @description An extraction job stopped without a result: the page did not load, the agent ran out of steps or time, or the result did not match your schema. The reason is in data.job.error. Job events also carry the keys of the previous webhook body (`event`, `occurred_at`, `job`) until its sunset; read `type`, `created_at` and `data` instead.
631
+ * @example {
632
+ * "created_at": "2026-11-05T09:00:00.000Z",
633
+ * "data": {
634
+ * "job": {
635
+ * "error": "The job ran out of steps before it found the data.",
636
+ * "id": "7c1e2a4b-5d3f-4e8a-9b6c-0d1e2f3a4b5c",
637
+ * "result": null,
638
+ * "status": "failed"
639
+ * }
640
+ * },
641
+ * "id": "evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f",
642
+ * "type": "job.failed",
643
+ * "workspace_id": "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
644
+ * }
645
+ */
646
+ JobFailedEvent: {
647
+ /**
648
+ * Format: date-time
649
+ * @description When the event happened (the same on every retry).
650
+ * @example 2026-11-05T09:00:00.000Z
651
+ */
652
+ created_at: string;
653
+ data: components["schemas"]["JobEventDataDto"];
654
+ /**
655
+ * @description The event id, also sent as `webhook-id`; the same on every retry and replay.
656
+ * @example evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f
657
+ */
658
+ id: string;
659
+ /** @description Present and true only on a delivery made by "Send test"; its `data` is the catalogue example. */
660
+ test?: boolean;
661
+ /**
662
+ * @description The event type. Switch on it to narrow the event.
663
+ * @enum {string}
664
+ */
665
+ type: "job.failed";
666
+ /**
667
+ * Format: uuid
668
+ * @description The workspace the event belongs to, so you can route without opening `data`. Absent on "Send test" deliveries.
669
+ */
670
+ workspace_id?: string;
671
+ };
566
672
  JobListPaginationDto: {
567
673
  /** @description Whether another page follows. */
568
674
  has_more: boolean;
@@ -575,6 +681,36 @@ interface components {
575
681
  /** @description The cursor for the next page. */
576
682
  pagination: components["schemas"]["JobListPaginationDto"];
577
683
  };
684
+ JobOutcomeDto: {
685
+ /**
686
+ * @description Why the job stopped without a result; null when it succeeded.
687
+ * @example null
688
+ */
689
+ error: string | null;
690
+ /**
691
+ * Format: uuid
692
+ * @description The job id.
693
+ * @example 7c1e2a4b-5d3f-4e8a-9b6c-0d1e2f3a4b5c
694
+ */
695
+ id: string;
696
+ /**
697
+ * @description The extracted JSON, matching the JSON Schema the job was created with; null when the job failed.
698
+ * @example {
699
+ * "price": null,
700
+ * "title": "Example Domain"
701
+ * }
702
+ */
703
+ result: {
704
+ [key: string]: unknown;
705
+ } | null;
706
+ /**
707
+ * @description `succeeded` on `job.succeeded`, `failed` on `job.failed`.
708
+ * @example succeeded
709
+ */
710
+ status: components["schemas"]["JobOutcomeStatus"];
711
+ };
712
+ /** @enum {string} */
713
+ JobOutcomeStatus: "succeeded" | "failed";
578
714
  JobResponseDto: {
579
715
  /** @description How many times a worker has picked the job up. */
580
716
  attempts: number;
@@ -638,6 +774,53 @@ interface components {
638
774
  };
639
775
  /** @enum {string} */
640
776
  JobStatus: "queued" | "running" | "succeeded" | "failed" | "cancelled";
777
+ /**
778
+ * JobSucceededEvent
779
+ * @description An extraction job finished and its result matches your JSON Schema. The result is in data.job.result. Job events also carry the keys of the previous webhook body (`event`, `occurred_at`, `job`) until its sunset; read `type`, `created_at` and `data` instead.
780
+ * @example {
781
+ * "created_at": "2026-11-05T09:00:00.000Z",
782
+ * "data": {
783
+ * "job": {
784
+ * "error": null,
785
+ * "id": "7c1e2a4b-5d3f-4e8a-9b6c-0d1e2f3a4b5c",
786
+ * "result": {
787
+ * "price": null,
788
+ * "title": "Example Domain"
789
+ * },
790
+ * "status": "succeeded"
791
+ * }
792
+ * },
793
+ * "id": "evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f",
794
+ * "type": "job.succeeded",
795
+ * "workspace_id": "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
796
+ * }
797
+ */
798
+ JobSucceededEvent: {
799
+ /**
800
+ * Format: date-time
801
+ * @description When the event happened (the same on every retry).
802
+ * @example 2026-11-05T09:00:00.000Z
803
+ */
804
+ created_at: string;
805
+ data: components["schemas"]["JobEventDataDto"];
806
+ /**
807
+ * @description The event id, also sent as `webhook-id`; the same on every retry and replay.
808
+ * @example evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f
809
+ */
810
+ id: string;
811
+ /** @description Present and true only on a delivery made by "Send test"; its `data` is the catalogue example. */
812
+ test?: boolean;
813
+ /**
814
+ * @description The event type. Switch on it to narrow the event.
815
+ * @enum {string}
816
+ */
817
+ type: "job.succeeded";
818
+ /**
819
+ * Format: uuid
820
+ * @description The workspace the event belongs to, so you can route without opening `data`. Absent on "Send test" deliveries.
821
+ */
822
+ workspace_id?: string;
823
+ };
641
824
  ListWebhookEndpointsResponseDto: {
642
825
  /** @description The endpoints, newest first. */
643
826
  data: components["schemas"]["WebhookEndpointDto"][];
@@ -1130,7 +1313,10 @@ interface components {
1130
1313
  };
1131
1314
  /** @enum {string} */
1132
1315
  WebhookEventStatus: "pending" | "delivered" | "failed" | "not_sent";
1133
- /** @enum {string} */
1316
+ /**
1317
+ * @description Every event type this product sends; `x-webhooks` maps each to its payload schema. New types can be added, so treat it as open.
1318
+ * @enum {string}
1319
+ */
1134
1320
  WebhookEventType: "job.succeeded" | "job.failed" | "credits.low";
1135
1321
  WebhookEventTypeDto: {
1136
1322
  /**
package/dist/index.d.ts CHANGED
@@ -487,6 +487,64 @@ interface components {
487
487
  */
488
488
  reason: string;
489
489
  };
490
+ /**
491
+ * CreditsLowEvent
492
+ * @description Your Trawl balance dropped below 10% of your last top-up (at least 100 steps). Sent once; it comes again after your next top-up. New jobs are refused when the balance reaches zero. Job events also carry the keys of the previous webhook body (`event`, `occurred_at`, `job`) until its sunset; read `type`, `created_at` and `data` instead.
493
+ * @example {
494
+ * "created_at": "2026-11-05T09:00:00.000Z",
495
+ * "data": {
496
+ * "balance_steps": 840,
497
+ * "last_top_up_steps": 10000,
498
+ * "threshold_steps": 1000
499
+ * },
500
+ * "id": "evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f",
501
+ * "type": "credits.low",
502
+ * "workspace_id": "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
503
+ * }
504
+ */
505
+ CreditsLowEvent: {
506
+ /**
507
+ * Format: date-time
508
+ * @description When the event happened (the same on every retry).
509
+ * @example 2026-11-05T09:00:00.000Z
510
+ */
511
+ created_at: string;
512
+ data: components["schemas"]["CreditsLowEventDataDto"];
513
+ /**
514
+ * @description The event id, also sent as `webhook-id`; the same on every retry and replay.
515
+ * @example evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f
516
+ */
517
+ id: string;
518
+ /** @description Present and true only on a delivery made by "Send test"; its `data` is the catalogue example. */
519
+ test?: boolean;
520
+ /**
521
+ * @description The event type. Switch on it to narrow the event.
522
+ * @enum {string}
523
+ */
524
+ type: "credits.low";
525
+ /**
526
+ * Format: uuid
527
+ * @description The workspace the event belongs to, so you can route without opening `data`. Absent on "Send test" deliveries.
528
+ */
529
+ workspace_id?: string;
530
+ };
531
+ CreditsLowEventDataDto: {
532
+ /**
533
+ * @description The balance, in steps, when the event was sent.
534
+ * @example 840
535
+ */
536
+ balance_steps: number;
537
+ /**
538
+ * @description Steps added by the last top-up.
539
+ * @example 10000
540
+ */
541
+ last_top_up_steps: number;
542
+ /**
543
+ * @description The threshold it dropped below: 10% of the last top-up, at least 100 steps.
544
+ * @example 1000
545
+ */
546
+ threshold_steps: number;
547
+ };
490
548
  CreditsResponseDto: {
491
549
  /**
492
550
  * @description Remaining steps. One agent step uses one credit; new jobs are refused (402) at zero. Can dip slightly below zero, because a running job is always allowed to finish.
@@ -563,6 +621,54 @@ interface components {
563
621
  */
564
622
  status_code: number;
565
623
  };
624
+ JobEventDataDto: {
625
+ /** @description The job that finished. */
626
+ job: components["schemas"]["JobOutcomeDto"];
627
+ };
628
+ /**
629
+ * JobFailedEvent
630
+ * @description An extraction job stopped without a result: the page did not load, the agent ran out of steps or time, or the result did not match your schema. The reason is in data.job.error. Job events also carry the keys of the previous webhook body (`event`, `occurred_at`, `job`) until its sunset; read `type`, `created_at` and `data` instead.
631
+ * @example {
632
+ * "created_at": "2026-11-05T09:00:00.000Z",
633
+ * "data": {
634
+ * "job": {
635
+ * "error": "The job ran out of steps before it found the data.",
636
+ * "id": "7c1e2a4b-5d3f-4e8a-9b6c-0d1e2f3a4b5c",
637
+ * "result": null,
638
+ * "status": "failed"
639
+ * }
640
+ * },
641
+ * "id": "evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f",
642
+ * "type": "job.failed",
643
+ * "workspace_id": "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
644
+ * }
645
+ */
646
+ JobFailedEvent: {
647
+ /**
648
+ * Format: date-time
649
+ * @description When the event happened (the same on every retry).
650
+ * @example 2026-11-05T09:00:00.000Z
651
+ */
652
+ created_at: string;
653
+ data: components["schemas"]["JobEventDataDto"];
654
+ /**
655
+ * @description The event id, also sent as `webhook-id`; the same on every retry and replay.
656
+ * @example evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f
657
+ */
658
+ id: string;
659
+ /** @description Present and true only on a delivery made by "Send test"; its `data` is the catalogue example. */
660
+ test?: boolean;
661
+ /**
662
+ * @description The event type. Switch on it to narrow the event.
663
+ * @enum {string}
664
+ */
665
+ type: "job.failed";
666
+ /**
667
+ * Format: uuid
668
+ * @description The workspace the event belongs to, so you can route without opening `data`. Absent on "Send test" deliveries.
669
+ */
670
+ workspace_id?: string;
671
+ };
566
672
  JobListPaginationDto: {
567
673
  /** @description Whether another page follows. */
568
674
  has_more: boolean;
@@ -575,6 +681,36 @@ interface components {
575
681
  /** @description The cursor for the next page. */
576
682
  pagination: components["schemas"]["JobListPaginationDto"];
577
683
  };
684
+ JobOutcomeDto: {
685
+ /**
686
+ * @description Why the job stopped without a result; null when it succeeded.
687
+ * @example null
688
+ */
689
+ error: string | null;
690
+ /**
691
+ * Format: uuid
692
+ * @description The job id.
693
+ * @example 7c1e2a4b-5d3f-4e8a-9b6c-0d1e2f3a4b5c
694
+ */
695
+ id: string;
696
+ /**
697
+ * @description The extracted JSON, matching the JSON Schema the job was created with; null when the job failed.
698
+ * @example {
699
+ * "price": null,
700
+ * "title": "Example Domain"
701
+ * }
702
+ */
703
+ result: {
704
+ [key: string]: unknown;
705
+ } | null;
706
+ /**
707
+ * @description `succeeded` on `job.succeeded`, `failed` on `job.failed`.
708
+ * @example succeeded
709
+ */
710
+ status: components["schemas"]["JobOutcomeStatus"];
711
+ };
712
+ /** @enum {string} */
713
+ JobOutcomeStatus: "succeeded" | "failed";
578
714
  JobResponseDto: {
579
715
  /** @description How many times a worker has picked the job up. */
580
716
  attempts: number;
@@ -638,6 +774,53 @@ interface components {
638
774
  };
639
775
  /** @enum {string} */
640
776
  JobStatus: "queued" | "running" | "succeeded" | "failed" | "cancelled";
777
+ /**
778
+ * JobSucceededEvent
779
+ * @description An extraction job finished and its result matches your JSON Schema. The result is in data.job.result. Job events also carry the keys of the previous webhook body (`event`, `occurred_at`, `job`) until its sunset; read `type`, `created_at` and `data` instead.
780
+ * @example {
781
+ * "created_at": "2026-11-05T09:00:00.000Z",
782
+ * "data": {
783
+ * "job": {
784
+ * "error": null,
785
+ * "id": "7c1e2a4b-5d3f-4e8a-9b6c-0d1e2f3a4b5c",
786
+ * "result": {
787
+ * "price": null,
788
+ * "title": "Example Domain"
789
+ * },
790
+ * "status": "succeeded"
791
+ * }
792
+ * },
793
+ * "id": "evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f",
794
+ * "type": "job.succeeded",
795
+ * "workspace_id": "9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b"
796
+ * }
797
+ */
798
+ JobSucceededEvent: {
799
+ /**
800
+ * Format: date-time
801
+ * @description When the event happened (the same on every retry).
802
+ * @example 2026-11-05T09:00:00.000Z
803
+ */
804
+ created_at: string;
805
+ data: components["schemas"]["JobEventDataDto"];
806
+ /**
807
+ * @description The event id, also sent as `webhook-id`; the same on every retry and replay.
808
+ * @example evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f
809
+ */
810
+ id: string;
811
+ /** @description Present and true only on a delivery made by "Send test"; its `data` is the catalogue example. */
812
+ test?: boolean;
813
+ /**
814
+ * @description The event type. Switch on it to narrow the event.
815
+ * @enum {string}
816
+ */
817
+ type: "job.succeeded";
818
+ /**
819
+ * Format: uuid
820
+ * @description The workspace the event belongs to, so you can route without opening `data`. Absent on "Send test" deliveries.
821
+ */
822
+ workspace_id?: string;
823
+ };
641
824
  ListWebhookEndpointsResponseDto: {
642
825
  /** @description The endpoints, newest first. */
643
826
  data: components["schemas"]["WebhookEndpointDto"][];
@@ -1130,7 +1313,10 @@ interface components {
1130
1313
  };
1131
1314
  /** @enum {string} */
1132
1315
  WebhookEventStatus: "pending" | "delivered" | "failed" | "not_sent";
1133
- /** @enum {string} */
1316
+ /**
1317
+ * @description Every event type this product sends; `x-webhooks` maps each to its payload schema. New types can be added, so treat it as open.
1318
+ * @enum {string}
1319
+ */
1134
1320
  WebhookEventType: "job.succeeded" | "job.failed" | "credits.low";
1135
1321
  WebhookEventTypeDto: {
1136
1322
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productcraft/trawl",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "AI web-extraction — submit a JSON Schema + natural-language description, get schema-conforming data extracted from the live web and delivered to an HMAC-signed webhook via ProductCraft Trawl. Generated from the production OpenAPI spec.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",