@expandai/mcp-server 0.1.4 → 0.2.1

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/dist/main.cjs CHANGED
@@ -39,7 +39,7 @@ var S__namespace = /*#__PURE__*/_interopNamespace(S);
39
39
 
40
40
  // package.json
41
41
  var package_default = {
42
- version: "0.1.4"};
42
+ version: "0.2.1"};
43
43
  var ExpandDocs = ai.McpServer.resource({
44
44
  uri: "expand://about",
45
45
  name: "About expand.ai",
@@ -103,10 +103,14 @@ var HttpApiDecodeError = class extends S__namespace.Class("HttpApiDecodeError")(
103
103
  _tag: HttpApiDecodeErrorTag
104
104
  }) {
105
105
  };
106
- var UnauthorizedAccessTag = class extends S__namespace.Literal("UnauthorizedAccess") {
106
+ var AuthFailedReason = class extends S__namespace.Literal("InvalidApiKey", "InvalidToken", "InvalidSession", "InvalidTenant") {
107
107
  };
108
- var UnauthorizedAccess = class extends S__namespace.Class("UnauthorizedAccess")({
109
- _tag: UnauthorizedAccessTag
108
+ var AuthFailedTag = class extends S__namespace.Literal("AuthFailed") {
109
+ };
110
+ var AuthFailed = class extends S__namespace.Class("AuthFailed")({
111
+ reason: AuthFailedReason,
112
+ description: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
113
+ _tag: AuthFailedTag
110
114
  }) {
111
115
  };
112
116
  var AssetNotFoundTag = class extends S__namespace.Literal("AssetNotFound") {
@@ -149,7 +153,13 @@ var AssetRetrievalError = class extends S__namespace.Class("AssetRetrievalError"
149
153
  _tag: AssetRetrievalErrorTag
150
154
  }) {
151
155
  };
152
- var AssetsGetByUrl500 = class extends S__namespace.Union(AssetReadError, InvalidWaczFormat, AssetRetrievalError) {
156
+ var InternalErrorTag = class extends S__namespace.Literal("InternalError") {
157
+ };
158
+ var InternalError = class extends S__namespace.Class("InternalError")({
159
+ _tag: InternalErrorTag
160
+ }) {
161
+ };
162
+ var AssetsGetByUrl500 = class extends S__namespace.Union(InternalError, AssetReadError, InvalidWaczFormat, AssetRetrievalError) {
153
163
  };
154
164
  var CurlErrorInputMethod = class extends S__namespace.Literal(
155
165
  "GET",
@@ -163,6 +173,8 @@ var CurlErrorInputMethod = class extends S__namespace.Literal(
163
173
  "PATCH"
164
174
  ) {
165
175
  };
176
+ var URL = class extends S__namespace.String {
177
+ };
166
178
  var CurlErrorTag = class extends S__namespace.Literal("CurlError") {
167
179
  };
168
180
  var CurlError = class extends S__namespace.Class("CurlError")({
@@ -173,11 +185,14 @@ var CurlError = class extends S__namespace.Class("CurlError")({
173
185
  body: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
174
186
  headers: S__namespace.optionalWith(S__namespace.Struct({}), { nullable: true }),
175
187
  proxy: S__namespace.optionalWith(
176
- S__namespace.Struct({
177
- server: S__namespace.String,
178
- username: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
179
- password: S__namespace.optionalWith(S__namespace.String, { nullable: true })
180
- }),
188
+ S__namespace.Union(
189
+ S__namespace.Struct({
190
+ server: S__namespace.String,
191
+ username: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
192
+ password: S__namespace.optionalWith(S__namespace.String, { nullable: true })
193
+ }),
194
+ URL
195
+ ),
181
196
  { nullable: true }
182
197
  ),
183
198
  timeout: S__namespace.optionalWith(S__namespace.Number, { nullable: true }),
@@ -197,9 +212,20 @@ var AssetListResponse = class extends S__namespace.Class("AssetListResponse")({
197
212
  assets: S__namespace.Array(AssetListItem)
198
213
  }) {
199
214
  };
200
- var AssetsList500 = class extends S__namespace.Union(AssetReadError, InvalidWaczFormat) {
215
+ var AssetsList500 = class extends S__namespace.Union(InternalError, AssetReadError, InvalidWaczFormat) {
201
216
  };
202
- var URL = class extends S__namespace.String {
217
+ var AssetsGetWacz500 = class extends S__namespace.Union(InternalError, AssetReadError) {
218
+ };
219
+ var DatasetNotFoundTag = class extends S__namespace.Literal("DatasetNotFound") {
220
+ };
221
+ var DatasetNotFound = class extends S__namespace.Class("DatasetNotFound")({
222
+ path: S__namespace.String,
223
+ _tag: DatasetNotFoundTag
224
+ }) {
225
+ };
226
+ var DatasetsGetDataset500 = class extends S__namespace.Union(InternalError, DatasetNotFound) {
227
+ };
228
+ var DatasetsGetFinetuneDataset500 = class extends S__namespace.Union(InternalError, DatasetNotFound) {
203
229
  };
204
230
  var SelectHtmlConfig = class extends S__namespace.Record({ key: S__namespace.String, value: S__namespace.Unknown }) {
205
231
  };
@@ -292,6 +318,29 @@ var Int2 = class extends S__namespace.Int {
292
318
  }),
293
319
  { nullable: true }
294
320
  ),
321
+ links: S__namespace.optionalWith(
322
+ S__namespace.Union(
323
+ S__namespace.Boolean,
324
+ /**
325
+ * Options for customizing link extraction from the page
326
+ */
327
+ S__namespace.Struct({
328
+ /**
329
+ * Only include links from the same domain as the fetched URL
330
+ */
331
+ sameDomainOnly: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => true }),
332
+ /**
333
+ * Regex patterns - only include links matching at least one pattern
334
+ */
335
+ includePatterns: S__namespace.optionalWith(S__namespace.Array(S__namespace.String), { nullable: true }),
336
+ /**
337
+ * Regex patterns - exclude links matching any pattern
338
+ */
339
+ excludePatterns: S__namespace.optionalWith(S__namespace.Array(S__namespace.String), { nullable: true })
340
+ })
341
+ ),
342
+ { nullable: true }
343
+ ),
295
344
  /**
296
345
  * Include page metadata in the response
297
346
  */
@@ -307,7 +356,15 @@ var Int2 = class extends S__namespace.Int {
307
356
  includeHeaders: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
308
357
  }),
309
358
  { nullable: true }
310
- )
359
+ ),
360
+ /**
361
+ * Include pruned JSON in the response (opt-in)
362
+ */
363
+ json: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false }),
364
+ /**
365
+ * Set to true to include extracted links and sidebar content
366
+ */
367
+ appendix: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true })
311
368
  }),
312
369
  { nullable: true }
313
370
  ),
@@ -475,58 +532,75 @@ var PageMeta = class extends S__namespace.Class("PageMeta")({
475
532
  twitter: S__namespace.optionalWith(TwitterCardMeta, { nullable: true })
476
533
  }) {
477
534
  };
478
- var FetchData = class extends S__namespace.Class("FetchData")({
479
- response: ResponseInfo,
480
- /**
481
- * Page metadata extracted from HTML head (title, description, Open Graph, Twitter Card, icons)
482
- */
483
- meta: S__namespace.optionalWith(PageMeta, { nullable: true }),
535
+ var FetchLink = class extends S__namespace.Class("FetchLink")({
484
536
  /**
485
- * The HTML content of the fetched page
537
+ * The URL of the link
486
538
  */
487
- html: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
488
- /**
489
- * The markdown-formatted content extracted from the page
490
- */
491
- markdown: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
492
- /**
493
- * Base64-encoded data URI of the screenshot image
494
- */
495
- screenshot: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
496
- /**
497
- * AI-generated summary of the page content
498
- */
499
- summary: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
539
+ url: S__namespace.String,
500
540
  /**
501
- * Relevant snippets extracted from the page based on the search query
541
+ * The anchor text of the link
502
542
  */
503
- snippets: S__namespace.optionalWith(
504
- S__namespace.Array(
505
- S__namespace.Struct({
506
- /**
507
- * Type identifier for TextPart compatibility
508
- */
509
- type: S__namespace.optionalWith(S__namespace.Literal("text"), { nullable: true, default: () => "text" }),
510
- /**
511
- * The text content of the snippet
512
- */
513
- text: S__namespace.String,
514
- /**
515
- * Relevance score from the reranker (0-1)
516
- */
517
- score: S__namespace.Number,
518
- /**
519
- * Original chunk index
520
- */
521
- index: S__namespace.Number
522
- })
523
- ),
524
- { nullable: true }
525
- )
543
+ text: S__namespace.optionalWith(S__namespace.String, { nullable: true })
526
544
  }) {
527
545
  };
528
546
  var FetchResult = class extends S__namespace.Class("FetchResult")({
529
- data: FetchData
547
+ /**
548
+ * Contains the extracted content in the formats specified by the select configuration
549
+ */
550
+ data: S__namespace.Struct({
551
+ response: ResponseInfo,
552
+ meta: S__namespace.optionalWith(PageMeta, { nullable: true }),
553
+ /**
554
+ * The HTML content of the fetched page
555
+ */
556
+ html: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
557
+ /**
558
+ * The markdown-formatted content extracted from the page
559
+ */
560
+ markdown: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
561
+ /**
562
+ * Base64-encoded data URI of the screenshot image
563
+ */
564
+ screenshot: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
565
+ /**
566
+ * AI-generated summary of the page content
567
+ */
568
+ summary: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
569
+ /**
570
+ * Relevant snippets extracted from the page based on the search query
571
+ */
572
+ snippets: S__namespace.optionalWith(
573
+ S__namespace.Array(
574
+ S__namespace.Struct({
575
+ /**
576
+ * Type identifier for TextPart compatibility
577
+ */
578
+ type: S__namespace.optionalWith(S__namespace.Literal("text"), { nullable: true, default: () => "text" }),
579
+ /**
580
+ * The text content of the snippet
581
+ */
582
+ text: S__namespace.String,
583
+ /**
584
+ * Relevance score from the reranker (0-1)
585
+ */
586
+ score: S__namespace.Number,
587
+ /**
588
+ * Original chunk index
589
+ */
590
+ index: S__namespace.Number
591
+ })
592
+ ),
593
+ { nullable: true }
594
+ ),
595
+ /**
596
+ * Links extracted from the page
597
+ */
598
+ links: S__namespace.optionalWith(S__namespace.Array(FetchLink), { nullable: true }),
599
+ /**
600
+ * Extracted links and sidebar content
601
+ */
602
+ appendix: S__namespace.optionalWith(S__namespace.String, { nullable: true })
603
+ })
530
604
  }) {
531
605
  };
532
606
  var FetchErrorTag = class extends S__namespace.Literal("FetchError") {
@@ -535,25 +609,8 @@ var FetchError = class extends S__namespace.Class("FetchError")({
535
609
  _tag: FetchErrorTag
536
610
  }) {
537
611
  };
538
- (class extends S__namespace.Class("MarkdownRequest")({
539
- /**
540
- * The URL to fetch markdown content from
541
- */
542
- url: S__namespace.String,
543
- /**
544
- * Configuration options for browser behavior during the fetch
545
- */
546
- browserConfig: S__namespace.optionalWith(
547
- S__namespace.Struct({
548
- /**
549
- * Whether to scroll the entire page to capture lazy-loaded content
550
- */
551
- scrollFullPage: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
552
- }),
553
- { nullable: true }
554
- )
555
- }) {
556
- });
612
+ var Fetch500 = class extends S__namespace.Union(InternalError, FetchError) {
613
+ };
557
614
  var InvalidAssetHashTag = class extends S__namespace.Literal("InvalidAssetHash") {
558
615
  };
559
616
  var InvalidAssetHash = class extends S__namespace.Class("InvalidAssetHash")({
@@ -585,12 +642,223 @@ var AssetFetchError = class extends S__namespace.Class("AssetFetchError")({
585
642
  }) {
586
643
  };
587
644
  var LocalAssetsGetAsset500 = class extends S__namespace.Union(
645
+ InternalError,
588
646
  InvalidAssetHash,
589
647
  AssetNotFoundInHar,
590
648
  HarNotFound,
591
649
  AssetFetchError
592
650
  ) {
593
651
  };
652
+ (class extends S__namespace.Class("PlaygroundFetchRequest")({
653
+ url: URL,
654
+ /**
655
+ * Specifies which content formats to include in the response
656
+ */
657
+ select: S__namespace.optionalWith(
658
+ S__namespace.Struct({
659
+ html: S__namespace.optionalWith(
660
+ S__namespace.Union(
661
+ S__namespace.Boolean,
662
+ SelectHtmlConfig
663
+ ),
664
+ { nullable: true }
665
+ ),
666
+ /**
667
+ * Include markdown-formatted content in the response
668
+ */
669
+ markdown: S__namespace.optionalWith(
670
+ S__namespace.Union(
671
+ S__namespace.Boolean,
672
+ SelectMarkdownConfig
673
+ ),
674
+ { nullable: true }
675
+ ),
676
+ screenshot: S__namespace.optionalWith(
677
+ S__namespace.Union(
678
+ S__namespace.Boolean,
679
+ SelectScreenshotConfig
680
+ ),
681
+ { nullable: true }
682
+ ),
683
+ summary: S__namespace.optionalWith(
684
+ S__namespace.Union(
685
+ S__namespace.Boolean,
686
+ /**
687
+ * Options for AI-powered page summarization
688
+ */
689
+ S__namespace.Struct({
690
+ /**
691
+ * Custom prompt for AI summarization (max 5000 characters)
692
+ */
693
+ prompt: S__namespace.optionalWith(S__namespace.String.pipe(S__namespace.maxLength(5e3)), {
694
+ nullable: true,
695
+ default: () => "You are a helpful assistant that summarizes web page content.\nGiven the markdown content of a web page, provide a clear and concise summary.\nFocus on the main points and key information.\nKeep the summary informative but brief."
696
+ })
697
+ })
698
+ ),
699
+ { nullable: true }
700
+ ),
701
+ /**
702
+ * Options for extracting relevant snippets from page content using semantic search
703
+ */
704
+ snippets: S__namespace.optionalWith(
705
+ S__namespace.Struct({
706
+ /**
707
+ * Query to find relevant content snippets from the page (required, non-empty)
708
+ */
709
+ query: Trimmed,
710
+ /**
711
+ * Maximum number of snippets to return (1-50)
712
+ */
713
+ maxSnippets: S__namespace.optionalWith(Int2, { nullable: true, default: () => 5 }),
714
+ /**
715
+ * Minimum relevance score threshold (0-1). Snippets below this score are filtered out.
716
+ */
717
+ minScore: S__namespace.optionalWith(S__namespace.Number.pipe(S__namespace.greaterThanOrEqualTo(0), S__namespace.lessThanOrEqualTo(1)), {
718
+ nullable: true,
719
+ default: () => 0.5
720
+ }),
721
+ /**
722
+ * Target snippet size in characters (100-2000)
723
+ */
724
+ targetSnippetSize: S__namespace.optionalWith(Int2, { nullable: true, default: () => 384 })
725
+ }),
726
+ { nullable: true }
727
+ ),
728
+ links: S__namespace.optionalWith(
729
+ S__namespace.Union(
730
+ S__namespace.Boolean,
731
+ /**
732
+ * Options for customizing link extraction from the page
733
+ */
734
+ S__namespace.Struct({
735
+ /**
736
+ * Only include links from the same domain as the fetched URL
737
+ */
738
+ sameDomainOnly: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => true }),
739
+ /**
740
+ * Regex patterns - only include links matching at least one pattern
741
+ */
742
+ includePatterns: S__namespace.optionalWith(S__namespace.Array(S__namespace.String), { nullable: true }),
743
+ /**
744
+ * Regex patterns - exclude links matching any pattern
745
+ */
746
+ excludePatterns: S__namespace.optionalWith(S__namespace.Array(S__namespace.String), { nullable: true })
747
+ })
748
+ ),
749
+ { nullable: true }
750
+ ),
751
+ /**
752
+ * Include page metadata in the response
753
+ */
754
+ meta: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => true }),
755
+ /**
756
+ * Configure response info options (headers inclusion)
757
+ */
758
+ response: S__namespace.optionalWith(
759
+ S__namespace.Struct({
760
+ /**
761
+ * Whether to include HTTP response headers
762
+ */
763
+ includeHeaders: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
764
+ }),
765
+ { nullable: true }
766
+ ),
767
+ /**
768
+ * Include pruned JSON in the response (opt-in)
769
+ */
770
+ json: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false }),
771
+ /**
772
+ * Set to true to include extracted links and sidebar content
773
+ */
774
+ appendix: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true })
775
+ }),
776
+ { nullable: true }
777
+ ),
778
+ /**
779
+ * Configuration options for browser behavior during the fetch
780
+ */
781
+ browserConfig: S__namespace.optionalWith(
782
+ S__namespace.Struct({
783
+ /**
784
+ * Whether to scroll the entire page to capture lazy-loaded content
785
+ */
786
+ scrollFullPage: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
787
+ }),
788
+ { nullable: true }
789
+ )
790
+ }) {
791
+ });
792
+ var PlaygroundData = class extends S__namespace.Class("PlaygroundData")({
793
+ response: ResponseInfo,
794
+ /**
795
+ * HTML with expand-id attributes on elements
796
+ */
797
+ html: S__namespace.String,
798
+ browserSessionId: S__namespace.String
799
+ }) {
800
+ };
801
+ var PlaygroundResult = class extends S__namespace.Class("PlaygroundResult")({
802
+ data: PlaygroundData
803
+ }) {
804
+ };
805
+ var PlaygroundFetch500 = class extends S__namespace.Union(InternalError, FetchError) {
806
+ };
807
+ var PlaygroundGet500 = class extends S__namespace.Union(InternalError, FetchError) {
808
+ };
809
+ var PlaygroundGetBySession500 = class extends S__namespace.Union(InternalError, FetchError) {
810
+ };
811
+ (class extends S__namespace.Class("PlaygroundSearchRequest")({
812
+ /**
813
+ * Search query to find relevant content chunks
814
+ */
815
+ query: Trimmed,
816
+ /**
817
+ * Browser session ID from the playground fetch result
818
+ */
819
+ browserSessionId: S__namespace.String,
820
+ /**
821
+ * Maximum number of results to return
822
+ */
823
+ maxResults: S__namespace.optionalWith(S__namespace.Number, { nullable: true }),
824
+ /**
825
+ * Minimum relevance score threshold (0-1). A value of 0 disables filtering.
826
+ */
827
+ minScore: S__namespace.optionalWith(S__namespace.Number, { nullable: true })
828
+ }) {
829
+ });
830
+ var PlaygroundSearchChunk = class extends S__namespace.Class("PlaygroundSearchChunk")({
831
+ /**
832
+ * The chunk text content
833
+ */
834
+ text: S__namespace.String,
835
+ /**
836
+ * Relevance score from 0-1
837
+ */
838
+ score: S__namespace.Number,
839
+ /**
840
+ * Original chunk index
841
+ */
842
+ index: S__namespace.Number,
843
+ /**
844
+ * MDAST originalNodeIds for highlighting in HTML/markdown views
845
+ */
846
+ nodeIds: S__namespace.Array(S__namespace.Number)
847
+ }) {
848
+ };
849
+ var PlaygroundSearch200 = class extends S__namespace.Struct({
850
+ /**
851
+ * Scored and ranked content chunks
852
+ */
853
+ chunks: S__namespace.Array(PlaygroundSearchChunk),
854
+ /**
855
+ * Duration of the search operation in milliseconds
856
+ */
857
+ durationMs: S__namespace.optionalWith(S__namespace.Number, { nullable: true })
858
+ }) {
859
+ };
860
+ var PlaygroundSearch500 = class extends S__namespace.Union(InternalError, FetchError) {
861
+ };
594
862
  var make = (httpClient, options = {}) => {
595
863
  const unexpectedStatus = (response) => Effect2__namespace.flatMap(
596
864
  Effect2__namespace.orElseSucceed(response.json, () => "Unexpected status code"),
@@ -619,49 +887,79 @@ var make = (httpClient, options = {}) => {
619
887
  withResponse(
620
888
  HttpClientResponse__namespace.matchStatus({
621
889
  "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
622
- "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
890
+ "401": decodeError("AuthFailed", AuthFailed),
623
891
  "404": decodeError("AssetsGetByUrl404", AssetsGetByUrl404),
624
892
  "500": decodeError("AssetsGetByUrl500", AssetsGetByUrl500),
625
893
  "502": decodeError("CurlError", CurlError),
626
894
  "429": () => Effect2__namespace.void,
895
+ "503": () => Effect2__namespace.void,
627
896
  orElse: unexpectedStatus
628
897
  })
629
898
  )
630
899
  ),
631
- assetsList: (browserSessionId) => HttpClientRequest__namespace.get(`/v1/assets/${browserSessionId}`).pipe(
900
+ assetsList: (browserSessionId) => HttpClientRequest__namespace.get(`/v1/assets/${browserSessionId}/list`).pipe(
632
901
  withResponse(
633
902
  HttpClientResponse__namespace.matchStatus({
634
903
  "2xx": decodeSuccess(AssetListResponse),
635
904
  "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
636
- "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
905
+ "401": decodeError("AuthFailed", AuthFailed),
637
906
  "404": decodeError("AssetNotFound", AssetNotFound),
638
907
  "500": decodeError("AssetsList500", AssetsList500),
639
908
  "429": () => Effect2__namespace.void,
909
+ "503": () => Effect2__namespace.void,
640
910
  orElse: unexpectedStatus
641
911
  })
642
912
  )
643
913
  ),
644
- fetch: (options2) => HttpClientRequest__namespace.post(`/v1/fetch`).pipe(
645
- HttpClientRequest__namespace.bodyUnsafeJson(options2),
914
+ assetsGetWacz: (browserSessionId) => HttpClientRequest__namespace.get(`/v1/assets/${browserSessionId}`).pipe(
915
+ withResponse(
916
+ HttpClientResponse__namespace.matchStatus({
917
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
918
+ "401": decodeError("AuthFailed", AuthFailed),
919
+ "404": decodeError("AssetNotFound", AssetNotFound),
920
+ "500": decodeError("AssetsGetWacz500", AssetsGetWacz500),
921
+ "429": () => Effect2__namespace.void,
922
+ "503": () => Effect2__namespace.void,
923
+ orElse: unexpectedStatus
924
+ })
925
+ )
926
+ ),
927
+ datasetsGetDataset: () => HttpClientRequest__namespace.get(`/datasets/page-analysis`).pipe(
928
+ withResponse(
929
+ HttpClientResponse__namespace.matchStatus({
930
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
931
+ "401": decodeError("AuthFailed", AuthFailed),
932
+ "500": decodeError("DatasetsGetDataset500", DatasetsGetDataset500),
933
+ "204": () => Effect2__namespace.void,
934
+ "429": () => Effect2__namespace.void,
935
+ "503": () => Effect2__namespace.void,
936
+ orElse: unexpectedStatus
937
+ })
938
+ )
939
+ ),
940
+ datasetsGetFinetuneDataset: () => HttpClientRequest__namespace.get(`/datasets/finetune`).pipe(
646
941
  withResponse(
647
942
  HttpClientResponse__namespace.matchStatus({
648
- "2xx": decodeSuccess(FetchResult),
649
943
  "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
650
- "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
651
- "500": decodeError("FetchError", FetchError),
944
+ "401": decodeError("AuthFailed", AuthFailed),
945
+ "500": decodeError("DatasetsGetFinetuneDataset500", DatasetsGetFinetuneDataset500),
946
+ "204": () => Effect2__namespace.void,
652
947
  "429": () => Effect2__namespace.void,
948
+ "503": () => Effect2__namespace.void,
653
949
  orElse: unexpectedStatus
654
950
  })
655
951
  )
656
952
  ),
657
- markdown: (options2) => HttpClientRequest__namespace.post(`/v1/fetch/markdown`).pipe(
953
+ fetch: (options2) => HttpClientRequest__namespace.post(`/v1/fetch`).pipe(
658
954
  HttpClientRequest__namespace.bodyUnsafeJson(options2),
659
955
  withResponse(
660
956
  HttpClientResponse__namespace.matchStatus({
957
+ "2xx": decodeSuccess(FetchResult),
661
958
  "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
662
- "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
663
- "500": decodeError("FetchError", FetchError),
959
+ "401": decodeError("AuthFailed", AuthFailed),
960
+ "500": decodeError("Fetch500", Fetch500),
664
961
  "429": () => Effect2__namespace.void,
962
+ "503": () => Effect2__namespace.void,
665
963
  orElse: unexpectedStatus
666
964
  })
667
965
  )
@@ -670,9 +968,65 @@ var make = (httpClient, options = {}) => {
670
968
  withResponse(
671
969
  HttpClientResponse__namespace.matchStatus({
672
970
  "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
971
+ "401": decodeError("AuthFailed", AuthFailed),
673
972
  "500": decodeError("LocalAssetsGetAsset500", LocalAssetsGetAsset500),
674
973
  "204": () => Effect2__namespace.void,
675
974
  "429": () => Effect2__namespace.void,
975
+ "503": () => Effect2__namespace.void,
976
+ orElse: unexpectedStatus
977
+ })
978
+ )
979
+ ),
980
+ playgroundFetch: (options2) => HttpClientRequest__namespace.post(`/v1/playground/fetch`).pipe(
981
+ HttpClientRequest__namespace.bodyUnsafeJson(options2),
982
+ withResponse(
983
+ HttpClientResponse__namespace.matchStatus({
984
+ "2xx": decodeSuccess(PlaygroundResult),
985
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
986
+ "401": decodeError("AuthFailed", AuthFailed),
987
+ "500": decodeError("PlaygroundFetch500", PlaygroundFetch500),
988
+ "429": () => Effect2__namespace.void,
989
+ "503": () => Effect2__namespace.void,
990
+ orElse: unexpectedStatus
991
+ })
992
+ )
993
+ ),
994
+ playgroundGet: (fetchRequestId) => HttpClientRequest__namespace.get(`/v1/playground/get/${fetchRequestId}`).pipe(
995
+ withResponse(
996
+ HttpClientResponse__namespace.matchStatus({
997
+ "2xx": decodeSuccess(PlaygroundResult),
998
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
999
+ "401": decodeError("AuthFailed", AuthFailed),
1000
+ "500": decodeError("PlaygroundGet500", PlaygroundGet500),
1001
+ "429": () => Effect2__namespace.void,
1002
+ "503": () => Effect2__namespace.void,
1003
+ orElse: unexpectedStatus
1004
+ })
1005
+ )
1006
+ ),
1007
+ playgroundGetBySession: (browserSessionId) => HttpClientRequest__namespace.get(`/v1/playground/session/${browserSessionId}`).pipe(
1008
+ withResponse(
1009
+ HttpClientResponse__namespace.matchStatus({
1010
+ "2xx": decodeSuccess(PlaygroundResult),
1011
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
1012
+ "401": decodeError("AuthFailed", AuthFailed),
1013
+ "500": decodeError("PlaygroundGetBySession500", PlaygroundGetBySession500),
1014
+ "429": () => Effect2__namespace.void,
1015
+ "503": () => Effect2__namespace.void,
1016
+ orElse: unexpectedStatus
1017
+ })
1018
+ )
1019
+ ),
1020
+ playgroundSearch: (options2) => HttpClientRequest__namespace.post(`/v1/playground/search`).pipe(
1021
+ HttpClientRequest__namespace.bodyUnsafeJson(options2),
1022
+ withResponse(
1023
+ HttpClientResponse__namespace.matchStatus({
1024
+ "2xx": decodeSuccess(PlaygroundSearch200),
1025
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
1026
+ "401": decodeError("AuthFailed", AuthFailed),
1027
+ "500": decodeError("PlaygroundSearch500", PlaygroundSearch500),
1028
+ "429": () => Effect2__namespace.void,
1029
+ "503": () => Effect2__namespace.void,
676
1030
  orElse: unexpectedStatus
677
1031
  })
678
1032
  )
@@ -722,81 +1076,82 @@ var ExpandClient = class extends effect.Effect.Service()("ExpandClient", {
722
1076
  })
723
1077
  }) {
724
1078
  };
725
- var SnippetsFormat = class extends effect.Schema.Class("SnippetsFormat")({
1079
+ var SearchParams = class extends effect.Schema.Class("SearchParams")({
726
1080
  query: effect.Schema.String.annotations({
727
- description: "Query to find relevant content snippets from the page"
1081
+ description: "Query to find relevant content snippets"
728
1082
  }),
729
- maxSnippets: effect.Schema.optional(
730
- effect.Schema.Int.pipe(effect.Schema.greaterThanOrEqualTo(1), effect.Schema.lessThanOrEqualTo(50))
731
- ).annotations({
732
- description: "Maximum number of snippets to return (1-50, default: 5)"
1083
+ minScore: effect.Schema.optionalWith(effect.Schema.Number.pipe(effect.Schema.greaterThanOrEqualTo(0), effect.Schema.lessThanOrEqualTo(1)), {
1084
+ default: () => 0.6
1085
+ }).annotations({
1086
+ description: "Minimum relevance score (0-1)",
1087
+ default: 0.6
733
1088
  }),
734
- targetSnippetSize: effect.Schema.optional(
735
- effect.Schema.Int.pipe(effect.Schema.greaterThanOrEqualTo(100), effect.Schema.lessThanOrEqualTo(2e3))
736
- ).annotations({
737
- description: "Target snippet size in characters (100-2000, default: 384)"
1089
+ maxResults: effect.Schema.optionalWith(effect.Schema.Int.pipe(effect.Schema.greaterThanOrEqualTo(1), effect.Schema.lessThanOrEqualTo(50)), {
1090
+ default: () => 5
1091
+ }).annotations({
1092
+ description: "Maximum snippets to return",
1093
+ default: 5
738
1094
  })
739
1095
  }) {
740
1096
  };
741
- var Format = effect.Schema.Union(
742
- effect.Schema.Literal("markdown").annotations({
743
- description: "Return as cleaned markdown content"
744
- }),
745
- effect.Schema.Literal("html").annotations({
746
- description: "Return as raw HTML content"
747
- }),
748
- effect.Schema.Literal("summary").annotations({
749
- description: "Return AI-generated summary of the page content"
750
- }),
751
- SnippetsFormat
752
- ).annotations({
753
- description: "Output format for the fetched content"
754
- });
755
1097
  var FetchParams = class extends effect.Schema.Class("FetchParams")({
756
1098
  url: effect.Schema.String.annotations({
757
1099
  description: "The URL to fetch content from"
758
1100
  }),
759
- format: Format,
760
- includeMeta: effect.Schema.Boolean.annotations({
761
- description: "Whether to include page meta tags in the response"
1101
+ includeMeta: effect.Schema.optionalWith(effect.Schema.Boolean, { default: () => false }).annotations({
1102
+ description: "Include page meta tags (title, description, Open Graph)",
1103
+ default: false
1104
+ }),
1105
+ includeAppendix: effect.Schema.optionalWith(effect.Schema.Boolean, { default: () => false }).annotations({
1106
+ description: "Include extracted links and sidebar content",
1107
+ default: false
1108
+ }),
1109
+ includeJson: effect.Schema.optionalWith(effect.Schema.Boolean, { default: () => false }).annotations({
1110
+ description: "Include JSON extracted from network responses and DOM",
1111
+ default: false
1112
+ }),
1113
+ search: effect.Schema.optional(SearchParams).annotations({
1114
+ description: "Semantic search. When provided, returns snippets instead of markdown."
762
1115
  })
763
1116
  }) {
764
1117
  };
765
- var FetchResult2 = class extends effect.Schema.Class("FetchResult")({
766
- content: effect.Schema.String,
767
- url: effect.Schema.String,
768
- meta: effect.Schema.optional(PageMeta)
769
- }) {
770
- };
771
1118
  var FetchTool = ai.Tool.make("fetch", {
772
- description: "Fetch and extract content from any URL.",
773
- parameters: FetchParams.fields,
774
- success: FetchResult2
1119
+ description: `Fetch and extract content from any URL.
1120
+
1121
+ Returns markdown by default. When \`search\` is provided, returns semantically relevant snippets instead.`,
1122
+ parameters: FetchParams.fields
775
1123
  }).annotate(ai.Tool.Readonly, true).annotate(ai.Tool.Destructive, false);
776
1124
  var Fetch = class extends effect.Effect.Service()("Fetch", {
777
1125
  dependencies: [ExpandClient.Default],
778
1126
  scoped: effect.Effect.gen(function* () {
779
1127
  const client = yield* ExpandClient;
780
- const fetch = effect.Effect.fn("Fetch.fetch")(function* ({ url, format, includeMeta }) {
781
- const formatLabel = format instanceof SnippetsFormat ? "snippets" : format;
782
- yield* effect.Effect.logDebug(`Fetching: ${url}`).pipe(effect.Effect.annotateLogs({ format: formatLabel, includeMeta }));
1128
+ const fetch = effect.Effect.fn("Fetch.fetch")(function* ({
1129
+ url,
1130
+ includeMeta,
1131
+ includeAppendix,
1132
+ includeJson,
1133
+ search
1134
+ }) {
1135
+ const hasSearch = search !== void 0;
1136
+ yield* effect.Effect.logDebug(`Fetching: ${url}`).pipe(
1137
+ effect.Effect.annotateLogs({ hasSearch, includeMeta, includeAppendix, includeJson })
1138
+ );
783
1139
  const result = yield* client.fetch({
784
1140
  url,
785
1141
  select: {
786
- markdown: format === "markdown",
787
- html: format === "html",
788
- summary: format === "summary",
789
- snippets: format instanceof SnippetsFormat ? { ...format } : void 0,
790
- meta: includeMeta
1142
+ markdown: !hasSearch,
1143
+ snippets: hasSearch ? {
1144
+ query: search.query,
1145
+ maxSnippets: search.maxResults,
1146
+ minScore: search.minScore
1147
+ } : void 0,
1148
+ meta: includeMeta,
1149
+ json: includeJson,
1150
+ appendix: includeAppendix
791
1151
  }
792
1152
  });
793
- const content = result.data.markdown ?? result.data.html ?? result.data.summary ?? result.data.snippets?.map((snippet) => `${snippet.text} (Score: ${snippet.score})`).join("\n") ?? "";
794
- yield* effect.Effect.logDebug(`\u{1F4E4} Fetched successfully: ${result.data.response.url}`);
795
- return new FetchResult2({
796
- content,
797
- url: result.data.response.url,
798
- meta: result.data.meta
799
- });
1153
+ yield* effect.Effect.logDebug(`Fetched successfully: ${result.data.response.url}`);
1154
+ return result.data;
800
1155
  }, effect.Effect.orDie);
801
1156
  return { fetch };
802
1157
  })