@expandai/sdk 0.17.2 → 0.18.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/src/Generated.ts CHANGED
@@ -27,15 +27,6 @@ export class FetchFetchRequest extends S.Class<FetchFetchRequest>('FetchFetchReq
27
27
  ),
28
28
  { nullable: true },
29
29
  ),
30
- summary: S.optionalWith(
31
- S.Union(
32
- S.Boolean,
33
- S.Struct({
34
- prompt: S.optionalWith(S.String.pipe(S.maxLength(5000)), { nullable: true }),
35
- }),
36
- ),
37
- { nullable: true },
38
- ),
39
30
  links: S.optionalWith(
40
31
  S.Union(
41
32
  S.Boolean,
@@ -165,10 +156,24 @@ export class FetchFetch403 extends S.Union(
165
156
 
166
157
  export class PayloadTooLargeTag extends S.Literal('PayloadTooLarge') {}
167
158
 
168
- export class PayloadTooLarge extends S.Class<PayloadTooLarge>('PayloadTooLarge')({
159
+ export class PayloadTooLarge extends S.Struct({
169
160
  _tag: PayloadTooLargeTag,
170
161
  }) {}
171
162
 
163
+ export class FetchPageTooLargeLimitKind extends S.Literal('transfer_bytes', 'domsnapshot_bytes', 'ast_bytes') {}
164
+
165
+ export class FetchPageTooLargeTag extends S.Literal('FetchPageTooLarge') {}
166
+
167
+ export class FetchPageTooLarge extends S.Struct({
168
+ url: S.String,
169
+ limitKind: S.optionalWith(FetchPageTooLargeLimitKind, { nullable: true }),
170
+ limitBytes: S.optionalWith(S.Number, { nullable: true }),
171
+ measuredBytes: S.optionalWith(S.Number, { nullable: true }),
172
+ _tag: FetchPageTooLargeTag,
173
+ }) {}
174
+
175
+ export class FetchFetch413 extends S.Union(PayloadTooLarge, FetchPageTooLarge) {}
176
+
172
177
  export class TooManyRequestsTag extends S.Literal('TooManyRequests') {}
173
178
 
174
179
  export class TooManyRequests extends S.Class<TooManyRequests>('TooManyRequests')({
@@ -184,6 +189,8 @@ export class InternalError extends S.Class<InternalError>('InternalError')({
184
189
  export class ServiceUnavailableTag extends S.Literal('ServiceUnavailable') {}
185
190
 
186
191
  export class ServiceUnavailable extends S.Class<ServiceUnavailable>('ServiceUnavailable')({
192
+ message: S.optionalWith(S.String, { nullable: true }),
193
+ requestId: S.optionalWith(S.String, { nullable: true }),
187
194
  _tag: ServiceUnavailableTag,
188
195
  }) {}
189
196
 
@@ -206,15 +213,6 @@ export class FetchFetchJsonRequest extends S.Class<FetchFetchJsonRequest>('Fetch
206
213
  ),
207
214
  { nullable: true },
208
215
  ),
209
- summary: S.optionalWith(
210
- S.Union(
211
- S.Boolean,
212
- S.Struct({
213
- prompt: S.optionalWith(S.String.pipe(S.maxLength(5000)), { nullable: true }),
214
- }),
215
- ),
216
- { nullable: true },
217
- ),
218
216
  links: S.optionalWith(
219
217
  S.Union(
220
218
  S.Boolean,
@@ -344,33 +342,10 @@ export class FetchAssetReference extends S.Struct({
344
342
  bytes: S.Number,
345
343
  }) {}
346
344
 
347
- export class CaptureTelemetryInfoRequestedStyleMode extends S.Literal('compat_full', 'native_default') {}
348
-
349
- export class CaptureTelemetryInfoSelected extends S.Literal('rust') {}
350
-
351
- export class CaptureTelemetryInfoActual extends S.Literal('rust') {}
352
-
353
- export class CaptureTelemetryInfoActualStyleMode extends S.Literal('compat_full', 'native_default') {}
354
-
355
- export class CaptureTelemetryInfoIconBackendDecision extends S.Literal('cpu', 'remote_gpu') {}
356
-
357
- export class CaptureTelemetryInfo extends S.Struct({
358
- requestedStyleMode: S.optionalWith(CaptureTelemetryInfoRequestedStyleMode, { nullable: true }),
359
- selected: CaptureTelemetryInfoSelected,
360
- actual: CaptureTelemetryInfoActual,
361
- actualStyleMode: S.optionalWith(CaptureTelemetryInfoActualStyleMode, { nullable: true }),
362
- rolloutApplied: S.Boolean,
363
- preparedSessionHit: S.optionalWith(S.Boolean, { nullable: true }),
364
- nativePoolHit: S.optionalWith(S.Boolean, { nullable: true }),
365
- nativePoolCapacity: S.optionalWith(S.Number, { nullable: true }),
366
- nativePoolProfile: S.optionalWith(S.String, { nullable: true }),
367
- poolHit: S.optionalWith(S.Boolean, { nullable: true }),
368
- connectMs: S.optionalWith(S.Number, { nullable: true }),
369
- warmConnectionAgeMs: S.optionalWith(S.Number, { nullable: true }),
370
- iconBackendDecision: S.optionalWith(CaptureTelemetryInfoIconBackendDecision, { nullable: true }),
371
- }) {}
345
+ export class Int extends S.Int {}
372
346
 
373
347
  export class FetchSearchSnippetLocation extends S.Struct({
348
+ evidenceId: S.optionalWith(Int, { nullable: true }),
374
349
  markdownBlockId: S.optionalWith(S.String, { nullable: true }),
375
350
  nodeIds: S.optionalWith(S.Array(S.Number), { nullable: true }),
376
351
  stateJsonSourceId: S.optionalWith(S.Number, { nullable: true }),
@@ -419,7 +394,6 @@ export class FetchObjectModeResult extends S.Class<FetchObjectModeResult>('Fetch
419
394
  data: S.optionalWith(
420
395
  S.Struct({
421
396
  assets: S.optionalWith(S.Array(FetchAssetReference), { nullable: true }),
422
- captureTelemetry: S.optionalWith(CaptureTelemetryInfo, { nullable: true }),
423
397
  search: S.optionalWith(FetchSearchResult, { nullable: true }),
424
398
  screenshot: S.optionalWith(
425
399
  S.Struct({
@@ -444,13 +418,7 @@ export class FetchFetchJson403 extends S.Union(
444
418
  FetchBlocked,
445
419
  ) {}
446
420
 
447
- export class IncludeHtmlConfig extends S.Record({ key: S.String, value: S.Unknown }) {}
448
-
449
- export class IncludeMarkdownConfig extends S.Record({ key: S.String, value: S.Unknown }) {}
450
-
451
- export class IncludeScreenshotConfig extends S.Struct({
452
- fullPage: S.optionalWith(S.Boolean, { nullable: true }),
453
- }) {}
421
+ export class FetchFetchJson413 extends S.Union(PayloadTooLarge, FetchPageTooLarge) {}
454
422
 
455
423
  export class FetchFetchSearchRequest extends S.Class<FetchFetchSearchRequest>('FetchFetchSearchRequest')({
456
424
  snapshotId: S.String.pipe(S.minLength(1)),
@@ -467,18 +435,13 @@ export class FetchFetchSearchRequest extends S.Class<FetchFetchSearchRequest>('F
467
435
  }),
468
436
  include: S.optionalWith(
469
437
  S.Struct({
470
- html: S.optionalWith(S.Union(S.Boolean, IncludeHtmlConfig), { nullable: true }),
471
- markdown: S.optionalWith(S.Union(S.Boolean, IncludeMarkdownConfig), { nullable: true }),
472
- screenshot: S.optionalWith(S.Union(S.Boolean, IncludeScreenshotConfig), { nullable: true }),
473
- summary: S.optionalWith(
438
+ html: S.optionalWith(S.Union(S.Boolean, S.Record({ key: S.String, value: S.Unknown })), { nullable: true }),
439
+ markdown: S.optionalWith(S.Union(S.Boolean, S.Record({ key: S.String, value: S.Unknown })), { nullable: true }),
440
+ screenshot: S.optionalWith(
474
441
  S.Union(
475
442
  S.Boolean,
476
443
  S.Struct({
477
- prompt: S.optionalWith(S.String.pipe(S.maxLength(5000)), {
478
- nullable: true,
479
- default: () =>
480
- '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.' as const,
481
- }),
444
+ fullPage: S.optionalWith(S.Boolean, { nullable: true }),
482
445
  }),
483
446
  ),
484
447
  { nullable: true },
@@ -523,6 +486,7 @@ export class FetchSnapshotSearchResult extends S.Class<FetchSnapshotSearchResult
523
486
  response: ResponseInfo,
524
487
  search: FetchSearchResult,
525
488
  durationMs: S.Number.pipe(S.greaterThanOrEqualTo(0)),
489
+ playground: S.String,
526
490
  }) {}
527
491
 
528
492
  export class FetchFetchSearch400 extends S.Union(HttpApiDecodeError, BadRequest) {}
@@ -544,22 +508,21 @@ export class FetchSnapshotSearchNotFound extends S.Class<FetchSnapshotSearchNotF
544
508
  _tag: FetchSnapshotSearchNotFoundTag,
545
509
  }) {}
546
510
 
511
+ export class FetchBatchedParams extends S.Struct({
512
+ 'x-idempotency-key': S.optionalWith(S.String.pipe(S.minLength(1), S.maxLength(255)), { nullable: true }),
513
+ }) {}
514
+
547
515
  export class FetchBatchedRequest extends S.Class<FetchBatchedRequest>('FetchBatchedRequest')({
548
516
  urls: S.NonEmptyArray(S.String),
549
517
  include: S.optionalWith(
550
518
  S.Struct({
551
- html: S.optionalWith(S.Union(S.Boolean, IncludeHtmlConfig), { nullable: true }),
552
- markdown: S.optionalWith(S.Union(S.Boolean, IncludeMarkdownConfig), { nullable: true }),
553
- screenshot: S.optionalWith(S.Union(S.Boolean, IncludeScreenshotConfig), { nullable: true }),
554
- summary: S.optionalWith(
519
+ html: S.optionalWith(S.Union(S.Boolean, S.Record({ key: S.String, value: S.Unknown })), { nullable: true }),
520
+ markdown: S.optionalWith(S.Union(S.Boolean, S.Record({ key: S.String, value: S.Unknown })), { nullable: true }),
521
+ screenshot: S.optionalWith(
555
522
  S.Union(
556
523
  S.Boolean,
557
524
  S.Struct({
558
- prompt: S.optionalWith(S.String.pipe(S.maxLength(5000)), {
559
- nullable: true,
560
- default: () =>
561
- '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.' as const,
562
- }),
525
+ fullPage: S.optionalWith(S.Boolean, { nullable: true }),
563
526
  }),
564
527
  ),
565
528
  { nullable: true },
@@ -609,15 +572,41 @@ export class FetchBatched403 extends S.Struct({
609
572
  _tag: FetchBatched403Tag,
610
573
  }) {}
611
574
 
575
+ export class BatchedIdempotencyConflictReason extends S.Literal('payload_mismatch') {}
576
+
577
+ export class BatchedIdempotencyConflictTag extends S.Literal('BatchedIdempotencyConflict') {}
578
+
579
+ export class BatchedIdempotencyConflict extends S.Class<BatchedIdempotencyConflict>('BatchedIdempotencyConflict')({
580
+ existingRunId: S.String,
581
+ reason: BatchedIdempotencyConflictReason,
582
+ _tag: BatchedIdempotencyConflictTag,
583
+ }) {}
584
+
612
585
  export class FetchGetBatchedParams extends S.Struct({
613
586
  limit: S.optionalWith(S.String, { nullable: true }),
614
587
  offset: S.optionalWith(S.String, { nullable: true }),
615
588
  include: S.optionalWith(S.String, { nullable: true }),
616
589
  }) {}
617
590
 
618
- export class BatchedStatusStatus extends S.Literal('QUEUED', 'RUNNING', 'COMPLETED', 'FAILED', 'CANCELLED') {}
591
+ export class BatchedStatusStatus extends S.Literal(
592
+ 'QUEUED',
593
+ 'RUNNING',
594
+ 'CANCELLING',
595
+ 'COMPLETED',
596
+ 'FAILED',
597
+ 'CANCELLED',
598
+ ) {}
619
599
 
620
- export class BatchedStatusBatchedStatus extends S.Literal('QUEUED', 'RUNNING', 'COMPLETED', 'FAILED', 'CANCELLED') {}
600
+ export class BatchedStatusBatchedStatus extends S.Literal(
601
+ 'QUEUED',
602
+ 'RUNNING',
603
+ 'CANCELLING',
604
+ 'COMPLETED',
605
+ 'FAILED',
606
+ 'CANCELLED',
607
+ ) {}
608
+
609
+ export class BatchedFetchItemStatus extends S.Literal('QUEUED', 'RUNNING', 'SUCCEEDED', 'FAILED', 'CANCELLED') {}
621
610
 
622
611
  export class IconMeta extends S.Struct({
623
612
  href: S.String.pipe(S.minLength(1)),
@@ -681,6 +670,34 @@ export class RenderEnginesInfo extends S.Struct({
681
670
  tree: S.optionalWith(RenderEnginesInfoTree, { nullable: true }),
682
671
  }) {}
683
672
 
673
+ export class BatchedFetchItem extends S.Struct({
674
+ status: BatchedFetchItemStatus,
675
+ data: S.optionalWith(
676
+ S.Struct({
677
+ response: ResponseInfo,
678
+ meta: S.optionalWith(PageMeta, { nullable: true }),
679
+ json: S.optionalWith(S.Array(S.Struct({})), { nullable: true }),
680
+ snapshotId: S.optionalWith(NonEmptyString, { nullable: true }),
681
+ html: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
682
+ markdown: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
683
+ screenshot: S.optionalWith(
684
+ S.Struct({
685
+ url: S.String,
686
+ fullPage: S.Boolean,
687
+ }),
688
+ { nullable: true },
689
+ ),
690
+ search: S.optionalWith(FetchSearchResult, { nullable: true }),
691
+ links: S.optionalWith(S.Array(FetchLink), { nullable: true }),
692
+ appendix: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
693
+ renderEngines: S.optionalWith(RenderEnginesInfo, { nullable: true }),
694
+ assets: S.optionalWith(S.Array(FetchAssetReference), { nullable: true }),
695
+ }),
696
+ { nullable: true },
697
+ ),
698
+ error: S.optionalWith(S.Union(FetchBlocked, FetchPageTooLarge), { nullable: true }),
699
+ }) {}
700
+
684
701
  export class PaginationMeta extends S.Struct({
685
702
  total: S.Number,
686
703
  limit: S.Number,
@@ -693,38 +710,7 @@ export class BatchedStatus extends S.Class<BatchedStatus>('BatchedStatus')({
693
710
  status: BatchedStatusStatus,
694
711
  batchedStatus: BatchedStatusBatchedStatus,
695
712
  totalUrls: S.Number,
696
- results: S.Array(
697
- S.Struct({
698
- data: S.Struct({
699
- response: ResponseInfo,
700
- meta: S.optionalWith(PageMeta, { nullable: true }),
701
- json: S.optionalWith(S.Array(S.Struct({})), { nullable: true }),
702
- snapshotId: S.optionalWith(NonEmptyString, { nullable: true }),
703
- html: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
704
- markdown: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
705
- screenshot: S.optionalWith(
706
- S.Struct({
707
- url: S.String,
708
- fullPage: S.Boolean,
709
- }),
710
- { nullable: true },
711
- ),
712
- summary: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
713
- search: S.optionalWith(FetchSearchResult, { nullable: true }),
714
- links: S.optionalWith(S.Array(FetchLink), { nullable: true }),
715
- appendix: S.optionalWith(S.String.pipe(S.minLength(1)), { nullable: true }),
716
- renderEngines: S.optionalWith(RenderEnginesInfo, { nullable: true }),
717
- captureTelemetry: S.optionalWith(CaptureTelemetryInfo, { nullable: true }),
718
- assets: S.optionalWith(S.Array(FetchAssetReference), { nullable: true }),
719
- blocked: S.optionalWith(
720
- S.Struct({
721
- blockedType: S.optionalWith(S.String, { nullable: true }),
722
- }),
723
- { nullable: true },
724
- ),
725
- }),
726
- }),
727
- ),
713
+ results: S.Array(BatchedFetchItem),
728
714
  pagination: PaginationMeta,
729
715
  }) {}
730
716
 
@@ -737,6 +723,23 @@ export class BatchedIncludeUnsupported extends S.Struct({
737
723
 
738
724
  export class FetchGetBatched400 extends S.Union(HttpApiDecodeError, BatchedIncludeUnsupported) {}
739
725
 
726
+ export class BatchedCancellationStatus extends S.Literal('CANCELLING', 'CANCELLED') {}
727
+
728
+ export class BatchedCancellation extends S.Class<BatchedCancellation>('BatchedCancellation')({
729
+ id: S.String,
730
+ status: BatchedCancellationStatus,
731
+ }) {}
732
+
733
+ export class BatchedCancellationConflictStatus extends S.Literal('COMPLETED', 'FAILED') {}
734
+
735
+ export class BatchedCancellationConflictTag extends S.Literal('BatchedCancellationConflict') {}
736
+
737
+ export class BatchedCancellationConflict extends S.Class<BatchedCancellationConflict>('BatchedCancellationConflict')({
738
+ id: S.String,
739
+ status: BatchedCancellationConflictStatus,
740
+ _tag: BatchedCancellationConflictTag,
741
+ }) {}
742
+
740
743
  export const make = (
741
744
  httpClient: HttpClient.HttpClient,
742
745
  options: {
@@ -776,7 +779,7 @@ export const make = (
776
779
  '400': (r) => decodeError(r, FetchFetch400),
777
780
  '401': (r) => decodeError(r, AuthFailed),
778
781
  '403': (r) => decodeError(r, FetchFetch403),
779
- '413': (r) => decodeError(r, PayloadTooLarge),
782
+ '413': (r) => decodeError(r, FetchFetch413),
780
783
  '429': (r) => decodeError(r, TooManyRequests),
781
784
  '500': (r) => decodeError(r, InternalError),
782
785
  '503': (r) => decodeError(r, ServiceUnavailable),
@@ -799,7 +802,7 @@ export const make = (
799
802
  '400': (r) => decodeError(r, FetchFetchJson400),
800
803
  '401': (r) => decodeError(r, AuthFailed),
801
804
  '403': (r) => decodeError(r, FetchFetchJson403),
802
- '413': (r) => decodeError(r, PayloadTooLarge),
805
+ '413': (r) => decodeError(r, FetchFetchJson413),
803
806
  '429': (r) => decodeError(r, TooManyRequests),
804
807
  '500': (r) => decodeError(r, InternalError),
805
808
  '503': (r) => decodeError(r, ServiceUnavailable),
@@ -834,7 +837,8 @@ export const make = (
834
837
  ),
835
838
  fetchBatched: (options) =>
836
839
  HttpClientRequest.make('POST')(`/v1/fetch/batched`).pipe(
837
- (req) => Effect.orDie(HttpClientRequest.bodyJson(req, options)),
840
+ HttpClientRequest.setHeaders({ 'x-idempotency-key': options.params['x-idempotency-key'] ?? undefined }),
841
+ (req) => Effect.orDie(HttpClientRequest.bodyJson(req, options.payload)),
838
842
  Effect.flatMap((request) =>
839
843
  Effect.flatMap(applyClientTransform(httpClient), (httpClient) =>
840
844
  Effect.flatMap(
@@ -844,6 +848,7 @@ export const make = (
844
848
  '400': (r) => decodeError(r, FetchBatched400),
845
849
  '401': (r) => decodeError(r, AuthFailed),
846
850
  '403': (r) => decodeError(r, FetchBatched403),
851
+ '409': (r) => decodeError(r, BatchedIdempotencyConflict),
847
852
  '413': (r) => decodeError(r, PayloadTooLarge),
848
853
  '429': (r) => decodeError(r, TooManyRequests),
849
854
  '500': (r) => decodeError(r, InternalError),
@@ -880,6 +885,28 @@ export const make = (
880
885
  ),
881
886
  ),
882
887
  ),
888
+ fetchCancelBatched: (id) =>
889
+ HttpClientRequest.make('POST')(`/v1/fetch/batched/${id}/cancel`).pipe(
890
+ Effect.succeed,
891
+ Effect.flatMap((request) =>
892
+ Effect.flatMap(applyClientTransform(httpClient), (httpClient) =>
893
+ Effect.flatMap(
894
+ httpClient.execute(request),
895
+ HttpClientResponse.matchStatus({
896
+ '200': (r) => HttpClientResponse.schemaBodyJson(BatchedCancellation)(r),
897
+ '400': (r) => decodeError(r, HttpApiDecodeError),
898
+ '401': (r) => decodeError(r, AuthFailed),
899
+ '409': (r) => decodeError(r, BatchedCancellationConflict),
900
+ '413': (r) => decodeError(r, PayloadTooLarge),
901
+ '429': (r) => decodeError(r, TooManyRequests),
902
+ '500': (r) => decodeError(r, InternalError),
903
+ '503': (r) => decodeError(r, ServiceUnavailable),
904
+ orElse: (response) => unexpectedStatus(request, response),
905
+ }),
906
+ ),
907
+ ),
908
+ ),
909
+ ),
883
910
  }
884
911
  }
885
912
 
@@ -894,7 +921,7 @@ export interface Client {
894
921
  | typeof FetchFetch400.Type
895
922
  | typeof AuthFailed.Type
896
923
  | typeof FetchFetch403.Type
897
- | typeof PayloadTooLarge.Type
924
+ | typeof FetchFetch413.Type
898
925
  | typeof TooManyRequests.Type
899
926
  | typeof InternalError.Type
900
927
  | typeof ServiceUnavailable.Type
@@ -909,7 +936,7 @@ export interface Client {
909
936
  | typeof FetchFetchJson400.Type
910
937
  | typeof AuthFailed.Type
911
938
  | typeof FetchFetchJson403.Type
912
- | typeof PayloadTooLarge.Type
939
+ | typeof FetchFetchJson413.Type
913
940
  | typeof TooManyRequests.Type
914
941
  | typeof InternalError.Type
915
942
  | typeof ServiceUnavailable.Type
@@ -929,15 +956,17 @@ export interface Client {
929
956
  | typeof InternalError.Type
930
957
  | typeof ServiceUnavailable.Type
931
958
  >
932
- readonly fetchBatched: (
933
- options: typeof FetchBatchedRequest.Encoded,
934
- ) => Effect.Effect<
959
+ readonly fetchBatched: (options: {
960
+ readonly params: typeof FetchBatchedParams.Encoded
961
+ readonly payload: typeof FetchBatchedRequest.Encoded
962
+ }) => Effect.Effect<
935
963
  typeof BatchedRun.Type,
936
964
  | HttpClientError.HttpClientError
937
965
  | ParseError
938
966
  | typeof FetchBatched400.Type
939
967
  | typeof AuthFailed.Type
940
968
  | typeof FetchBatched403.Type
969
+ | typeof BatchedIdempotencyConflict.Type
941
970
  | typeof PayloadTooLarge.Type
942
971
  | typeof TooManyRequests.Type
943
972
  | typeof InternalError.Type
@@ -957,4 +986,18 @@ export interface Client {
957
986
  | typeof InternalError.Type
958
987
  | typeof ServiceUnavailable.Type
959
988
  >
989
+ readonly fetchCancelBatched: (
990
+ id: string,
991
+ ) => Effect.Effect<
992
+ typeof BatchedCancellation.Type,
993
+ | HttpClientError.HttpClientError
994
+ | ParseError
995
+ | typeof HttpApiDecodeError.Type
996
+ | typeof AuthFailed.Type
997
+ | typeof BatchedCancellationConflict.Type
998
+ | typeof PayloadTooLarge.Type
999
+ | typeof TooManyRequests.Type
1000
+ | typeof InternalError.Type
1001
+ | typeof ServiceUnavailable.Type
1002
+ >
960
1003
  }
package/src/Internal.ts CHANGED
@@ -11,7 +11,9 @@ import {
11
11
  import * as Generated from './Generated.js'
12
12
  import {
13
13
  type BatchedParams,
14
+ type BatchedRequestOptions,
14
15
  type BatchedResponse,
16
+ type CancelBatchedResponse,
15
17
  ExpandService,
16
18
  type ExpandServiceOptions,
17
19
  type FetchJsonParams,
@@ -37,9 +39,15 @@ function hasApiErrorTag(error: unknown, tag: string): error is TaggedApiError {
37
39
 
38
40
  function apiError(status: number, error: unknown): ExpandApiError {
39
41
  const message =
40
- typeof error === 'object' && error !== null && '_tag' in error && typeof error._tag === 'string'
41
- ? error._tag
42
- : `HTTP ${status}`
42
+ typeof error === 'object' &&
43
+ error !== null &&
44
+ 'message' in error &&
45
+ typeof error.message === 'string' &&
46
+ error.message.length > 0
47
+ ? error.message
48
+ : typeof error === 'object' && error !== null && '_tag' in error && typeof error._tag === 'string'
49
+ ? error._tag
50
+ : `HTTP ${status}`
43
51
  return new ExpandApiError({ message, status, body: error, cause: error })
44
52
  }
45
53
 
@@ -80,6 +88,11 @@ export function toExpandError(error: unknown, timeoutMs: number): ExpandError {
80
88
  (error: unknown) => hasApiErrorTag(error, 'AccessBlocked'),
81
89
  (error) => apiError(403, error),
82
90
  ),
91
+ Match.when(
92
+ (error: unknown) =>
93
+ hasApiErrorTag(error, 'BatchedIdempotencyConflict') || hasApiErrorTag(error, 'BatchedCancellationConflict'),
94
+ (error) => apiError(409, error),
95
+ ),
83
96
  Match.when(
84
97
  (error: unknown) => error instanceof Generated.PayloadTooLarge,
85
98
  (error) => new ExpandApiError({ message: 'PayloadTooLarge', status: 413, body: error, cause: error }),
@@ -106,7 +119,7 @@ export function toExpandError(error: unknown, timeoutMs: number): ExpandError {
106
119
  ),
107
120
  Match.when(
108
121
  (error: unknown) => error instanceof Generated.ServiceUnavailable,
109
- (error) => new ExpandApiError({ message: 'ServiceUnavailable', status: 503, body: error, cause: error }),
122
+ (error) => apiError(503, error),
110
123
  ),
111
124
  Match.when(
112
125
  (error: unknown) => hasApiErrorTag(error, 'ServiceUnavailable'),
@@ -142,6 +155,9 @@ export function toExpandError(error: unknown, timeoutMs: number): ExpandError {
142
155
  * retryable; API errors are retryable only for the standard transient status codes (408/409/429/5xx).
143
156
  */
144
157
  export function isRetryable(error: unknown, timeoutMs: number): boolean {
158
+ if (hasApiErrorTag(error, 'BatchedIdempotencyConflict') || hasApiErrorTag(error, 'BatchedCancellationConflict')) {
159
+ return false
160
+ }
145
161
  // An undecodable response (a transient 5xx with an empty/garbled body, a proxy error page, etc.)
146
162
  // surfaces as a bare ParseError with no HTTP status, so the status-based classification below can't
147
163
  // see the 5xx and the request would fail un-retried. Treat decode failures as retryable — the
@@ -170,7 +186,7 @@ export function isRetryable(error: unknown, timeoutMs: number): boolean {
170
186
  /**
171
187
  * Effect-side bridge between {@link ExpandService} and the Promise-based {@link ExpandClient}.
172
188
  *
173
- * Exposes the same fetch/batched/getBatched methods as `ExpandService` but with the typed `ExpandError`
189
+ * Exposes the same fetch/batched/getBatched/cancelBatched methods as `ExpandService` but with the typed `ExpandError`
174
190
  * channel mapped to the `ExpandClientError` hierarchy that async/await consumers expect. Not exported
175
191
  * from the package — Effect consumers depend on `ExpandService` directly and receive the typed
176
192
  * `ExpandError` unions as-is.
@@ -199,7 +215,7 @@ export class InternalClient extends Effect.Service<InternalClient>()('@expandai/
199
215
 
200
216
  const batched = (
201
217
  params: BatchedParams,
202
- options: RequestOptions = {},
218
+ options: BatchedRequestOptions,
203
219
  ): Effect.Effect<BatchedResponse, ExpandClientError> =>
204
220
  service.batched(params, options).pipe(Effect.mapError((error) => error.toPublicError()))
205
221
 
@@ -209,7 +225,13 @@ export class InternalClient extends Effect.Service<InternalClient>()('@expandai/
209
225
  ): Effect.Effect<GetBatchedResponse, ExpandClientError> =>
210
226
  service.getBatched(id, options).pipe(Effect.mapError((error) => error.toPublicError()))
211
227
 
212
- return { fetch, fetchJson, fetchSearch, batched, getBatched } as const
228
+ const cancelBatched = (
229
+ id: string,
230
+ options: RequestOptions = {},
231
+ ): Effect.Effect<CancelBatchedResponse, ExpandClientError> =>
232
+ service.cancelBatched(id, options).pipe(Effect.mapError((error) => error.toPublicError()))
233
+
234
+ return { fetch, fetchJson, fetchSearch, batched, getBatched, cancelBatched } as const
213
235
  }),
214
236
  }) {
215
237
  /**
package/src/Playground.ts CHANGED
@@ -3,12 +3,9 @@
3
3
  // Canonical public snapshot URLs (all public, no auth, no TTL):
4
4
  //
5
5
  // /s/<snapshotId> — whole snapshot
6
- // /s/<snapshotId>/playground#focus=<id> highlight a markdown/appendix block by node id
7
- // /s/<snapshotId>?id=<evidenceId> — open extracted State JSON evidence
6
+ // /s/<snapshotId>?id=<evidenceId> open any public evidence target
8
7
  //
9
- // A citation maps a search snippet (`source` + `location`) to the view that audits it.
10
-
11
- import { Match } from 'effect'
8
+ // A citation maps a search snippet location to the view that audits it.
12
9
 
13
10
  export const DEFAULT_PLAYGROUND_HOST = 'https://expand.land'
14
11
 
@@ -16,7 +13,12 @@ export type CitationSource = 'markdown' | 'appendix' | 'statejson'
16
13
 
17
14
  /** Snippet location subset needed to build a deep link. Tolerates `null` and `undefined`. */
18
15
  export interface CitationLocation {
16
+ readonly evidenceId?: number | null
17
+ /** @deprecated Use evidenceId. */
18
+ readonly markdownBlockId?: string | null
19
+ /** @deprecated Use evidenceId for public citations. */
19
20
  readonly nodeIds?: ReadonlyArray<number> | null
21
+ /** @deprecated Use evidenceId. */
20
22
  readonly stateJsonSourceId?: number | null
21
23
  }
22
24
 
@@ -24,6 +26,18 @@ function normalizeHost(host: string): string {
24
26
  return host.replace(/\/+$/, '')
25
27
  }
26
28
 
29
+ function publicEvidenceId(value: number | null | undefined): number | undefined {
30
+ return value !== null && value !== undefined && Number.isInteger(value) && value > 0 && value <= 2_147_483_647
31
+ ? value
32
+ : undefined
33
+ }
34
+
35
+ function legacyArchiveId(value: number | null | undefined): number | undefined {
36
+ return value !== null && value !== undefined && Number.isInteger(value) && value >= 0 && value <= 0xffffffff
37
+ ? value
38
+ : undefined
39
+ }
40
+
27
41
  /** Whole-snapshot URL: `${host}/s/${snapshotId}`. */
28
42
  export function playgroundBase(snapshotId: string, host: string = DEFAULT_PLAYGROUND_HOST): string {
29
43
  return `${normalizeHost(host)}/s/${encodeURIComponent(snapshotId)}`
@@ -51,26 +65,46 @@ export function resolvePlaygroundHost(metaPlayground: string | null | undefined,
51
65
  }
52
66
 
53
67
  /**
54
- * Deep link auditing a single snippet:
55
- * - `statejson` with a source id → `?id=<stateJsonSourceId>` (opens the JSON evidence object).
56
- * - `markdown`/`appendix` with a node id → `/playground#focus=<nodeIds[0]>` (highlights the block).
57
- * - otherwise → the whole-snapshot base URL.
68
+ * Deep link auditing a single snippet by its canonical public Evidence ID.
58
69
  */
70
+ export function citationUrl(snapshotId: string, location: CitationLocation | null | undefined, host?: string): string
71
+ /** @deprecated Pass the location as the second argument; source is no longer needed. */
59
72
  export function citationUrl(
60
73
  snapshotId: string,
61
74
  source: CitationSource,
62
75
  location: CitationLocation | null | undefined,
63
- host: string = DEFAULT_PLAYGROUND_HOST,
76
+ host?: string,
77
+ ): string
78
+ export function citationUrl(
79
+ snapshotId: string,
80
+ sourceOrLocation: CitationSource | CitationLocation | null | undefined,
81
+ locationOrHost?: CitationLocation | string | null,
82
+ legacyHost: string = DEFAULT_PLAYGROUND_HOST,
64
83
  ): string {
84
+ const legacySignature = typeof sourceOrLocation === 'string'
85
+ const source = legacySignature ? sourceOrLocation : undefined
86
+ const location = legacySignature
87
+ ? typeof locationOrHost === 'string'
88
+ ? undefined
89
+ : locationOrHost
90
+ : sourceOrLocation
91
+ const host = legacySignature
92
+ ? legacyHost
93
+ : typeof locationOrHost === 'string'
94
+ ? locationOrHost
95
+ : DEFAULT_PLAYGROUND_HOST
65
96
  const base = playgroundBase(snapshotId, host)
66
- return Match.value(source).pipe(
67
- Match.when('statejson', () => {
68
- const sourceId = location?.stateJsonSourceId
69
- return sourceId != null ? `${base}?id=${sourceId}` : base
70
- }),
71
- Match.orElse(() => {
72
- const nodeId = location?.nodeIds?.[0]
73
- return nodeId != null ? `${base}/playground#focus=${nodeId}` : base
74
- }),
75
- )
97
+ const evidenceId = publicEvidenceId(location?.evidenceId)
98
+ if (evidenceId !== undefined) {
99
+ return `${base}?id=${evidenceId}`
100
+ }
101
+ if (source === 'statejson') {
102
+ const legacyId = legacyArchiveId(location?.stateJsonSourceId)
103
+ return legacyId === undefined ? base : `${base}?id=${legacyId}`
104
+ }
105
+ if (source === 'markdown' || source === 'appendix') {
106
+ const nodeId = legacyArchiveId(location?.nodeIds?.[0])
107
+ return nodeId === undefined ? base : `${base}/playground#focus=${nodeId}`
108
+ }
109
+ return base
76
110
  }