@syfthub/sdk 0.2.0 → 0.3.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/index.d.ts CHANGED
@@ -792,7 +792,15 @@ interface Document {
792
792
  /**
793
793
  * Status of a data source query.
794
794
  */
795
- type SourceStatus = 'success' | 'error' | 'timeout';
795
+ type SourceStatus = 'success' | 'error' | 'timeout' | 'payment_failed' | 'access_denied' | 'policy_violation' | 'rate_limited';
796
+ /**
797
+ * Machine-readable rejection reason on a {@link BillingEntry}.
798
+ *
799
+ * The known set the producer emits today. `BillingEntry.reasonCode` stays open
800
+ * (`ReasonCode | (string & {})`) so a future code never breaks typing, while
801
+ * still offering autocomplete on the known values.
802
+ */
803
+ type ReasonCode = 'NO_PRICING_TIER' | 'INSUFFICIENT_BALANCE' | 'PAYMENT_REQUIRED' | 'ACCESS_DENIED' | 'RATE_LIMITED';
796
804
  /**
797
805
  * Information about a data source retrieval (metadata).
798
806
  */
@@ -838,6 +846,101 @@ interface TokenUsage {
838
846
  /** Total tokens used */
839
847
  totalTokens: number;
840
848
  }
849
+ /**
850
+ * The "to whom" of a billing entry — the endpoint owner / publisher.
851
+ *
852
+ * All fields are optional; `walletAddress` is a public MPP address only and
853
+ * never a private key.
854
+ */
855
+ interface Recipient {
856
+ /** Endpoint owner / publisher username */
857
+ username?: string;
858
+ /** Recipient email */
859
+ email?: string;
860
+ /** Public MPP wallet address (never a private key) */
861
+ walletAddress?: string;
862
+ }
863
+ /**
864
+ * A rail-native transaction reference for a billing entry.
865
+ *
866
+ * `id` is the rail-native identifier (Tempo tx hash for `mpp`; the ledger
867
+ * transaction id for `xendit` / `stripe`); `rail` is the discriminator.
868
+ */
869
+ interface Transaction {
870
+ /** Payment rail discriminator (mpp, xendit, stripe, ...) */
871
+ rail: string;
872
+ /** Rail-native transaction id */
873
+ id: string;
874
+ /** Secondary reference (e.g. MPP external_id) */
875
+ reference?: string;
876
+ }
877
+ /**
878
+ * A single policy-metadata entry from a queried source.
879
+ *
880
+ * Emitted by both payment and non-payment policies. When surfaced via the
881
+ * aggregated {@link Billing} block, `source` carries the `owner/slug` of the
882
+ * source that produced the entry; on the direct path it is absent.
883
+ */
884
+ interface BillingEntry {
885
+ /** Source endpoint path (owner/slug); absent if direct */
886
+ source?: string;
887
+ /** Policy type (e.g. mpp_per_request, rate_limit, pii_filter) */
888
+ policyType: string;
889
+ /** Policy kind (payment, access, transform, rate_limit) */
890
+ kind: string;
891
+ /** Outcome status (charged, refunded, free, rejected, applied, skipped) */
892
+ status: string;
893
+ /** Charged amount, if any */
894
+ amount?: number;
895
+ /** Currency code, if any */
896
+ currency?: string;
897
+ /** Who the payment is owed to, if any */
898
+ recipient?: Recipient;
899
+ /** Rail-native transaction reference, if any */
900
+ transaction?: Transaction;
901
+ /** Machine-readable rejection code; see {@link ReasonCode} for the known set */
902
+ reasonCode?: ReasonCode | (string & {});
903
+ /** Human-readable reason message */
904
+ reason?: string;
905
+ /** Extra structured details (e.g. { documents: 3 }) */
906
+ details: Record<string, unknown>;
907
+ }
908
+ /**
909
+ * Aggregated billing block surfaced on chat and search responses.
910
+ *
911
+ * `totalCost` is the sum of entries with `status === "charged"` (null if none
912
+ * charged); `currency` is the common currency or null if mixed. No FX
913
+ * conversion is performed — each entry keeps its own currency.
914
+ */
915
+ interface Billing {
916
+ /**
917
+ * Sum of charged entries; null if nothing charged.
918
+ *
919
+ * Note: can be > 0 on a *rejected* query — an earlier policy may have
920
+ * committed a charge before a later policy blocked the request (the
921
+ * rejection carries both the `charged` and the `rejected` entry). Inspect
922
+ * per-entry `status` rather than assuming a positive `totalCost` means success.
923
+ */
924
+ totalCost: number | null;
925
+ /** Common currency, or null if mixed */
926
+ currency: string | null;
927
+ /** Per-source policy-metadata entries */
928
+ entries: BillingEntry[];
929
+ }
930
+ /**
931
+ * Raw policy-metadata block returned on the direct syft-space path.
932
+ *
933
+ * Unlike the aggregated {@link Billing} block, this is the per-source object
934
+ * exactly as the syft-space `/query` response carries it: an `outcome` string
935
+ * plus the list of {@link BillingEntry} items (whose `source` key is absent on
936
+ * the direct path). No aggregation or total is applied.
937
+ */
938
+ interface PolicyMetadata {
939
+ /** Query outcome (e.g. success, payment_required) */
940
+ outcome: string;
941
+ /** Per-policy metadata entries */
942
+ entries: BillingEntry[];
943
+ }
841
944
  /**
842
945
  * Response from a chat completion request.
843
946
  */
@@ -854,6 +957,8 @@ interface ChatResponse {
854
957
  usage?: TokenUsage;
855
958
  /** Normalized contribution scores per source (owner/slug to fraction 0-1) */
856
959
  profitShare?: Record<string, number>;
960
+ /** Aggregated payment-policy metadata across queried sources */
961
+ billing?: Billing;
857
962
  }
858
963
  /**
859
964
  * A chat message for model queries.
@@ -895,6 +1000,73 @@ interface ChatOptions {
895
1000
  /** Conversation history (prior turns) for multi-turn context */
896
1001
  messages?: Message[];
897
1002
  }
1003
+ /**
1004
+ * A single document returned by a retrieval-only search.
1005
+ *
1006
+ * Unlike {@link Document} (the low-level direct-query shape), this carries the
1007
+ * document title and the source endpoint path, matching the aggregated
1008
+ * `sources` map returned by the aggregator's retrieval-only path.
1009
+ */
1010
+ interface SearchDocument {
1011
+ /** Document title (key in the sources map) */
1012
+ title: string;
1013
+ /** Source endpoint path (owner/slug) the document came from */
1014
+ slug: string;
1015
+ /** The document content */
1016
+ content: string;
1017
+ }
1018
+ /**
1019
+ * Options for a retrieval-only search via the Aggregator.
1020
+ *
1021
+ * Symmetric to {@link ChatOptions} minus the model: data sources are queried
1022
+ * for relevant documents, but no model is invoked.
1023
+ */
1024
+ interface SearchQueryOptions {
1025
+ /** The search query */
1026
+ prompt: string;
1027
+ /** Data source endpoints (paths, EndpointRefs, or `collective/<slug>` paths) */
1028
+ dataSources?: (string | EndpointRef)[];
1029
+ /** Number of documents to retrieve per source (default: 5) */
1030
+ topK?: number;
1031
+ /** Minimum similarity for retrieved docs (default: 0.5) */
1032
+ similarityThreshold?: number;
1033
+ /** Custom aggregator URL to use instead of the default */
1034
+ aggregatorUrl?: string;
1035
+ /** Use guest mode for unauthenticated access to policy-free endpoints */
1036
+ guestMode?: boolean;
1037
+ /** AbortSignal for request cancellation */
1038
+ signal?: AbortSignal;
1039
+ }
1040
+ /**
1041
+ * Response from a retrieval-only search via the Aggregator.
1042
+ *
1043
+ * Mirrors {@link ChatResponse} minus the generated text: retrieval runs across
1044
+ * the data sources (with satellite-token auth and MPP payment handled by the
1045
+ * aggregator), but no model is invoked.
1046
+ */
1047
+ interface SearchResponse {
1048
+ /** Retrieved documents across all data sources */
1049
+ documents: SearchDocument[];
1050
+ /** Metadata about each data source retrieval (status, count, errors) */
1051
+ retrievalInfo: SourceInfo[];
1052
+ /** Timing metadata */
1053
+ metadata: ChatMetadata;
1054
+ /** Aggregated payment-policy metadata across queried sources */
1055
+ billing?: Billing;
1056
+ }
1057
+ /**
1058
+ * Result of a direct data-source query (`client.syftai.queryDataSource`).
1059
+ *
1060
+ * Carries the retrieved documents plus the raw `policyMetadata` block from the
1061
+ * syft-space `/query` response (Boundary A), so direct-query callers get the
1062
+ * same authoritative payment/policy metadata the aggregator surfaces.
1063
+ */
1064
+ interface DataSourceQueryResult {
1065
+ /** Retrieved documents */
1066
+ documents: Document[];
1067
+ /** Raw policy metadata from the syft-space response, if present */
1068
+ policyMetadata?: PolicyMetadata;
1069
+ }
898
1070
  /**
899
1071
  * Options for querying a data source directly.
900
1072
  */
@@ -909,6 +1081,22 @@ interface QueryDataSourceOptions {
909
1081
  topK?: number;
910
1082
  /** Minimum similarity score (default: 0.5) */
911
1083
  similarityThreshold?: number;
1084
+ /**
1085
+ * Pre-minted satellite token to send as `Authorization: Bearer`. If omitted,
1086
+ * one is minted automatically when an owner is known (see `ownerUsername` /
1087
+ * `endpoint.ownerUsername`).
1088
+ */
1089
+ authorizationToken?: string;
1090
+ /**
1091
+ * Endpoint owner username used as the satellite-token audience. Falls back to
1092
+ * `endpoint.ownerUsername`.
1093
+ */
1094
+ ownerUsername?: string;
1095
+ /**
1096
+ * If true, settle an MPP `402 Payment Required` challenge via the Hub wallet
1097
+ * and retry. If false (default), a `402` throws a `RetrievalError`.
1098
+ */
1099
+ pay?: boolean;
912
1100
  }
913
1101
  /**
914
1102
  * Options for querying a model directly.
@@ -1003,6 +1191,8 @@ interface DoneEvent {
1003
1191
  usage?: TokenUsage;
1004
1192
  /** Normalized contribution scores per source (owner/slug to fraction 0-1) */
1005
1193
  profitShare?: Record<string, number>;
1194
+ /** Aggregated payment-policy metadata across queried sources */
1195
+ billing?: Billing;
1006
1196
  /**
1007
1197
  * Clean response text with attribution markers stripped.
1008
1198
  * Present when attribution ran (data sources were used). Frontends should
@@ -1016,6 +1206,11 @@ interface DoneEvent {
1016
1206
  interface ErrorEvent {
1017
1207
  type: 'error';
1018
1208
  message: string;
1209
+ /**
1210
+ * Billing surfaced on the error path: a paid query may be REJECTED yet still
1211
+ * carry policy/billing metadata (e.g. a charge that must be refunded).
1212
+ */
1213
+ billing?: Billing;
1019
1214
  }
1020
1215
  /**
1021
1216
  * Discriminated union of all streaming event types.
@@ -1039,6 +1234,131 @@ interface ErrorEvent {
1039
1234
  */
1040
1235
  type ChatStreamEvent = RetrievalStartEvent | SourceCompleteEvent | RetrievalCompleteEvent | RerankingStartEvent | RerankingCompleteEvent | GenerationStartEvent | GenerationHeartbeatEvent | TokenEvent$1 | DoneEvent | ErrorEvent;
1041
1236
 
1237
+ /**
1238
+ * Resource for managing user's aggregator configurations.
1239
+ *
1240
+ * Aggregators are custom RAG orchestration service endpoints that users can
1241
+ * configure to use for chat operations. Each user can have multiple aggregator
1242
+ * configurations, with one set as the default.
1243
+ *
1244
+ * The first aggregator created is automatically set as the default. Only one
1245
+ * aggregator can be the default at a time; setting a new default automatically
1246
+ * unsets the previous one.
1247
+ *
1248
+ * @example
1249
+ * // List all aggregators
1250
+ * const aggregators = await client.users.aggregators.list();
1251
+ * for (const agg of aggregators) {
1252
+ * console.log(`${agg.name}: ${agg.url}`);
1253
+ * }
1254
+ *
1255
+ * @example
1256
+ * // Create a new aggregator
1257
+ * const agg = await client.users.aggregators.create({
1258
+ * name: 'My Custom Aggregator',
1259
+ * url: 'https://my-aggregator.example.com'
1260
+ * });
1261
+ *
1262
+ * @example
1263
+ * // Set as default
1264
+ * const defaultAgg = await client.users.aggregators.setDefault(agg.id);
1265
+ */
1266
+ declare class AggregatorsResource {
1267
+ private readonly http;
1268
+ constructor(http: HTTPClient);
1269
+ /**
1270
+ * List all aggregator configurations for the current user.
1271
+ *
1272
+ * @returns Array of UserAggregator objects
1273
+ * @throws {AuthenticationError} If not authenticated
1274
+ *
1275
+ * @example
1276
+ * const aggregators = await client.users.aggregators.list();
1277
+ * for (const agg of aggregators) {
1278
+ * if (agg.isDefault) {
1279
+ * console.log(`Default: ${agg.name}`);
1280
+ * }
1281
+ * }
1282
+ */
1283
+ list(): Promise<UserAggregator[]>;
1284
+ /**
1285
+ * Get a specific aggregator configuration by ID.
1286
+ *
1287
+ * @param aggregatorId - The aggregator ID
1288
+ * @returns The UserAggregator object
1289
+ * @throws {AuthenticationError} If not authenticated
1290
+ * @throws {NotFoundError} If aggregator not found
1291
+ *
1292
+ * @example
1293
+ * const agg = await client.users.aggregators.get(1);
1294
+ * console.log(`${agg.name}: ${agg.url}`);
1295
+ */
1296
+ get(aggregatorId: number): Promise<UserAggregator>;
1297
+ /**
1298
+ * Create a new aggregator configuration.
1299
+ *
1300
+ * The first aggregator created is automatically set as the default.
1301
+ *
1302
+ * @param input - Aggregator creation input
1303
+ * @returns The created UserAggregator object
1304
+ * @throws {AuthenticationError} If not authenticated
1305
+ * @throws {ValidationError} If input is invalid
1306
+ *
1307
+ * @example
1308
+ * const agg = await client.users.aggregators.create({
1309
+ * name: 'My Custom Aggregator',
1310
+ * url: 'https://my-aggregator.example.com'
1311
+ * });
1312
+ * console.log(`Created: ${agg.id}`);
1313
+ */
1314
+ create(input: UserAggregatorCreateInput): Promise<UserAggregator>;
1315
+ /**
1316
+ * Update an aggregator configuration.
1317
+ *
1318
+ * Only provided fields will be updated.
1319
+ *
1320
+ * @param aggregatorId - The aggregator ID to update
1321
+ * @param input - Fields to update
1322
+ * @returns The updated UserAggregator object
1323
+ * @throws {AuthenticationError} If not authenticated
1324
+ * @throws {NotFoundError} If aggregator not found
1325
+ * @throws {ValidationError} If input is invalid
1326
+ *
1327
+ * @example
1328
+ * const agg = await client.users.aggregators.update(1, {
1329
+ * name: 'Updated Name'
1330
+ * });
1331
+ */
1332
+ update(aggregatorId: number, input: UserAggregatorUpdateInput): Promise<UserAggregator>;
1333
+ /**
1334
+ * Delete an aggregator configuration.
1335
+ *
1336
+ * @param aggregatorId - The aggregator ID to delete
1337
+ * @throws {AuthenticationError} If not authenticated
1338
+ * @throws {NotFoundError} If aggregator not found
1339
+ *
1340
+ * @example
1341
+ * await client.users.aggregators.delete(1);
1342
+ */
1343
+ delete(aggregatorId: number): Promise<void>;
1344
+ /**
1345
+ * Set an aggregator as the default.
1346
+ *
1347
+ * Only one aggregator can be the default at a time. Setting a new default
1348
+ * automatically unsets the previous one.
1349
+ *
1350
+ * @param aggregatorId - The aggregator ID to set as default
1351
+ * @returns The updated UserAggregator object with isDefault=true
1352
+ * @throws {AuthenticationError} If not authenticated
1353
+ * @throws {NotFoundError} If aggregator not found
1354
+ *
1355
+ * @example
1356
+ * const agg = await client.users.aggregators.setDefault(2);
1357
+ * console.log(`${agg.name} is now the default`);
1358
+ */
1359
+ setDefault(aggregatorId: number): Promise<UserAggregator>;
1360
+ }
1361
+
1042
1362
  /**
1043
1363
  * Authentication resource for login, register, and session management.
1044
1364
  *
@@ -1345,131 +1665,6 @@ interface SatelliteTokenResponse {
1345
1665
  expiresIn: number;
1346
1666
  }
1347
1667
 
1348
- /**
1349
- * Resource for managing user's aggregator configurations.
1350
- *
1351
- * Aggregators are custom RAG orchestration service endpoints that users can
1352
- * configure to use for chat operations. Each user can have multiple aggregator
1353
- * configurations, with one set as the default.
1354
- *
1355
- * The first aggregator created is automatically set as the default. Only one
1356
- * aggregator can be the default at a time; setting a new default automatically
1357
- * unsets the previous one.
1358
- *
1359
- * @example
1360
- * // List all aggregators
1361
- * const aggregators = await client.users.aggregators.list();
1362
- * for (const agg of aggregators) {
1363
- * console.log(`${agg.name}: ${agg.url}`);
1364
- * }
1365
- *
1366
- * @example
1367
- * // Create a new aggregator
1368
- * const agg = await client.users.aggregators.create({
1369
- * name: 'My Custom Aggregator',
1370
- * url: 'https://my-aggregator.example.com'
1371
- * });
1372
- *
1373
- * @example
1374
- * // Set as default
1375
- * const defaultAgg = await client.users.aggregators.setDefault(agg.id);
1376
- */
1377
- declare class AggregatorsResource {
1378
- private readonly http;
1379
- constructor(http: HTTPClient);
1380
- /**
1381
- * List all aggregator configurations for the current user.
1382
- *
1383
- * @returns Array of UserAggregator objects
1384
- * @throws {AuthenticationError} If not authenticated
1385
- *
1386
- * @example
1387
- * const aggregators = await client.users.aggregators.list();
1388
- * for (const agg of aggregators) {
1389
- * if (agg.isDefault) {
1390
- * console.log(`Default: ${agg.name}`);
1391
- * }
1392
- * }
1393
- */
1394
- list(): Promise<UserAggregator[]>;
1395
- /**
1396
- * Get a specific aggregator configuration by ID.
1397
- *
1398
- * @param aggregatorId - The aggregator ID
1399
- * @returns The UserAggregator object
1400
- * @throws {AuthenticationError} If not authenticated
1401
- * @throws {NotFoundError} If aggregator not found
1402
- *
1403
- * @example
1404
- * const agg = await client.users.aggregators.get(1);
1405
- * console.log(`${agg.name}: ${agg.url}`);
1406
- */
1407
- get(aggregatorId: number): Promise<UserAggregator>;
1408
- /**
1409
- * Create a new aggregator configuration.
1410
- *
1411
- * The first aggregator created is automatically set as the default.
1412
- *
1413
- * @param input - Aggregator creation input
1414
- * @returns The created UserAggregator object
1415
- * @throws {AuthenticationError} If not authenticated
1416
- * @throws {ValidationError} If input is invalid
1417
- *
1418
- * @example
1419
- * const agg = await client.users.aggregators.create({
1420
- * name: 'My Custom Aggregator',
1421
- * url: 'https://my-aggregator.example.com'
1422
- * });
1423
- * console.log(`Created: ${agg.id}`);
1424
- */
1425
- create(input: UserAggregatorCreateInput): Promise<UserAggregator>;
1426
- /**
1427
- * Update an aggregator configuration.
1428
- *
1429
- * Only provided fields will be updated.
1430
- *
1431
- * @param aggregatorId - The aggregator ID to update
1432
- * @param input - Fields to update
1433
- * @returns The updated UserAggregator object
1434
- * @throws {AuthenticationError} If not authenticated
1435
- * @throws {NotFoundError} If aggregator not found
1436
- * @throws {ValidationError} If input is invalid
1437
- *
1438
- * @example
1439
- * const agg = await client.users.aggregators.update(1, {
1440
- * name: 'Updated Name'
1441
- * });
1442
- */
1443
- update(aggregatorId: number, input: UserAggregatorUpdateInput): Promise<UserAggregator>;
1444
- /**
1445
- * Delete an aggregator configuration.
1446
- *
1447
- * @param aggregatorId - The aggregator ID to delete
1448
- * @throws {AuthenticationError} If not authenticated
1449
- * @throws {NotFoundError} If aggregator not found
1450
- *
1451
- * @example
1452
- * await client.users.aggregators.delete(1);
1453
- */
1454
- delete(aggregatorId: number): Promise<void>;
1455
- /**
1456
- * Set an aggregator as the default.
1457
- *
1458
- * Only one aggregator can be the default at a time. Setting a new default
1459
- * automatically unsets the previous one.
1460
- *
1461
- * @param aggregatorId - The aggregator ID to set as default
1462
- * @returns The updated UserAggregator object with isDefault=true
1463
- * @throws {AuthenticationError} If not authenticated
1464
- * @throws {NotFoundError} If aggregator not found
1465
- *
1466
- * @example
1467
- * const agg = await client.users.aggregators.setDefault(2);
1468
- * console.log(`${agg.name} is now the default`);
1469
- */
1470
- setDefault(aggregatorId: number): Promise<UserAggregator>;
1471
- }
1472
-
1473
1668
  /**
1474
1669
  * Users resource for profile management and availability checks.
1475
1670
  *
@@ -2565,7 +2760,19 @@ declare class AgentSessionClient {
2565
2760
  declare class AggregatorError extends SyftHubError {
2566
2761
  readonly status?: number | undefined;
2567
2762
  readonly detail?: unknown | undefined;
2568
- constructor(message: string, status?: number | undefined, detail?: unknown | undefined);
2763
+ /**
2764
+ * Billing/policy metadata the aggregator may attach even on an error
2765
+ * response — a paid query can be REJECTED yet still carry a charge that
2766
+ * must be surfaced (and possibly refunded).
2767
+ */
2768
+ readonly billing?: Billing | undefined;
2769
+ constructor(message: string, status?: number | undefined, detail?: unknown | undefined,
2770
+ /**
2771
+ * Billing/policy metadata the aggregator may attach even on an error
2772
+ * response — a paid query can be REJECTED yet still carry a charge that
2773
+ * must be surfaced (and possibly refunded).
2774
+ */
2775
+ billing?: Billing | undefined);
2569
2776
  }
2570
2777
  /**
2571
2778
  * Error thrown when an endpoint cannot be resolved.
@@ -2674,6 +2881,20 @@ declare class ChatResource {
2674
2881
  * Parse TokenUsage from raw data.
2675
2882
  */
2676
2883
  private parseUsage;
2884
+ /**
2885
+ * Parse a single billing/policy-metadata entry from a raw (snake_case) dict.
2886
+ *
2887
+ * Shared by {@link parseBilling} (aggregated, carries `source`) and the
2888
+ * direct-path `policy_metadata` parsing in {@link SyftAIResource}.
2889
+ */
2890
+ static parseBillingEntry(raw: Record<string, unknown>): BillingEntry;
2891
+ /**
2892
+ * Parse the aggregated `billing` block from a raw aggregator response.
2893
+ *
2894
+ * Returns undefined when no `billing` object is present (e.g. an error body
2895
+ * with no policy metadata). The wire keys are snake_case.
2896
+ */
2897
+ private parseBilling;
2677
2898
  /**
2678
2899
  * Parse document sources from raw data.
2679
2900
  * The new format is a dict mapping document title to {slug, content}.
@@ -2698,6 +2919,28 @@ declare class ChatResource {
2698
2919
  * @throws {AggregatorError} If aggregator service fails
2699
2920
  */
2700
2921
  complete(options: ChatOptions): Promise<ChatResponse>;
2922
+ /**
2923
+ * Placeholder model for retrieval-only requests. The aggregator requires a
2924
+ * `model` field on every request, but short-circuits before dereferencing it
2925
+ * when `retrieval_only` is set, so an empty ref is never contacted.
2926
+ */
2927
+ private static readonly RETRIEVAL_ONLY_MODEL;
2928
+ /**
2929
+ * Retrieve documents from data sources without model generation.
2930
+ *
2931
+ * Drives the aggregator's retrieval-only path: data sources are queried in
2932
+ * parallel (with satellite-token auth and MPP payment handled server-side,
2933
+ * exactly like {@link complete}), but no model is invoked.
2934
+ *
2935
+ * Prefer the symmetric `client.search.query(...)` facade; this is the
2936
+ * underlying primitive.
2937
+ *
2938
+ * @param options - Search options
2939
+ * @returns SearchResponse with retrieved documents and per-source metadata
2940
+ * @throws {EndpointResolutionError} If a data source cannot be resolved
2941
+ * @throws {AggregatorError} If the aggregator service fails
2942
+ */
2943
+ retrieve(options: SearchQueryOptions): Promise<SearchResponse>;
2701
2944
  /**
2702
2945
  * Send a chat request and stream response events.
2703
2946
  *
@@ -2732,6 +2975,58 @@ declare class ChatResource {
2732
2975
  getAvailableDataSources(limit?: number): Promise<EndpointPublic[]>;
2733
2976
  }
2734
2977
 
2978
+ /**
2979
+ * Search resource for retrieval-only queries via the Aggregator service.
2980
+ *
2981
+ * Symmetric counterpart to {@link ChatResource}: where `client.chat.complete()`
2982
+ * retrieves context *and* generates a model response, `client.search.query()`
2983
+ * retrieves documents from data sources without invoking any model.
2984
+ *
2985
+ * @example
2986
+ * // Symmetric to client.chat.complete(...)
2987
+ * const result = await client.search.query({
2988
+ * prompt: 'What happened at EPFL this week?',
2989
+ * dataSources: ['epfl-news/epfl-news'],
2990
+ * });
2991
+ * for (const doc of result.documents) {
2992
+ * console.log(doc.title, '->', doc.content.slice(0, 80));
2993
+ * }
2994
+ *
2995
+ * Authentication and billing are handled by the aggregator exactly as for chat:
2996
+ * satellite tokens are minted per data source owner, and metered endpoints that
2997
+ * respond with `402 Payment Required` are settled via the user's Hub wallet.
2998
+ */
2999
+
3000
+ /**
3001
+ * Retrieval-only search via the Aggregator.
3002
+ *
3003
+ * Thin facade over {@link ChatResource.retrieve}, exposed as `client.search` to
3004
+ * mirror the shape of `client.chat`.
3005
+ */
3006
+ declare class SearchResource {
3007
+ private readonly chat;
3008
+ /**
3009
+ * @param chat - The chat resource that owns aggregator communication and
3010
+ * request preparation (satellite tokens, MPP, collective expansion). Search
3011
+ * reuses it rather than duplicating that logic.
3012
+ */
3013
+ constructor(chat: ChatResource);
3014
+ /**
3015
+ * Retrieve documents from data sources without model generation.
3016
+ *
3017
+ * @param options - Search options (prompt, data sources, top-k, etc.)
3018
+ * @returns SearchResponse with retrieved documents and per-source metadata
3019
+ *
3020
+ * @example
3021
+ * const result = await client.search.query({
3022
+ * prompt: 'Hello, world!',
3023
+ * dataSources: ['epfl-news/epfl-news'],
3024
+ * });
3025
+ * console.log(result.documents.length, 'documents');
3026
+ */
3027
+ query(options: SearchQueryOptions): Promise<SearchResponse>;
3028
+ }
3029
+
2735
3030
  /**
2736
3031
  * SyftAI-Space resource for direct endpoint queries.
2737
3032
  *
@@ -2785,18 +3080,66 @@ declare class GenerationError extends SyftHubError {
2785
3080
  * For most use cases, prefer the higher-level `client.chat` API instead.
2786
3081
  */
2787
3082
  declare class SyftAIResource {
3083
+ private readonly http;
3084
+ /**
3085
+ * @param http - Hub HTTP client, used to mint satellite tokens and settle
3086
+ * MPP payments. Endpoint queries themselves use direct `fetch`, since the
3087
+ * SyftAI-Space URL is arbitrary and not the Hub base URL.
3088
+ */
3089
+ constructor(http: HTTPClient);
3090
+ /**
3091
+ * Mint a satellite token for `audience` (the endpoint owner's username).
3092
+ *
3093
+ * Mirrors the aggregator's token coordination layer: try an authenticated
3094
+ * token first, then fall back to a guest token. Returns `undefined` if both
3095
+ * fail, so the caller can still attempt an unauthenticated request.
3096
+ */
3097
+ private mintSatelliteToken;
3098
+ /**
3099
+ * Pay an MPP `402` challenge via the Hub wallet, returning an X-Payment credential.
3100
+ *
3101
+ * Mirrors the aggregator's `handleMppPayment`: the `WWW-Authenticate`
3102
+ * challenge is forwarded verbatim to the Hub's `/api/v1/wallet/pay`, which
3103
+ * parses it and returns an `x_payment` string to attach to a retry.
3104
+ */
3105
+ private payMpp;
2788
3106
  /**
2789
3107
  * Build headers for SyftAI-Space request.
2790
3108
  */
2791
3109
  private buildHeaders;
3110
+ /**
3111
+ * Parse documents from a SyftAI-Space query response.
3112
+ *
3113
+ * Mirrors the aggregator's `DataSourceClient._parse_syftai_response`: the
3114
+ * canonical shape nests documents under `references.documents` and names the
3115
+ * score `similarity_score`. A legacy top-level `documents` list (with
3116
+ * `score`) is still honoured for backward compatibility.
3117
+ */
3118
+ private parseDocuments;
3119
+ /**
3120
+ * Parse the raw `policy_metadata` block from a syft-space response.
3121
+ *
3122
+ * The direct path (Boundary A) carries a top-level `policy_metadata` object
3123
+ * shaped `{ outcome, entries: [...] }`. Entries reuse the {@link BillingEntry}
3124
+ * shape (with `source` absent), so this delegates entry parsing to
3125
+ * {@link ChatResource.parseBillingEntry}. The wire keys are snake_case.
3126
+ */
3127
+ private parsePolicyMetadata;
2792
3128
  /**
2793
3129
  * Query a data source endpoint directly.
2794
3130
  *
3131
+ * Authentication mirrors the aggregator: SyftAI-Space endpoints expect a
3132
+ * satellite bearer token whose audience is the endpoint owner's username. If
3133
+ * `authorizationToken` is not supplied, one is minted automatically when an
3134
+ * owner is known (`ownerUsername` option or `endpoint.ownerUsername`).
3135
+ *
2795
3136
  * @param options - Query options
2796
- * @returns Array of Document objects
3137
+ * @returns DataSourceQueryResult the retrieved documents plus the raw
3138
+ * `policyMetadata` block from the syft-space response (price, recipient,
3139
+ * transaction, status).
2797
3140
  * @throws {RetrievalError} If the query fails
2798
3141
  */
2799
- queryDataSource(options: QueryDataSourceOptions): Promise<Document[]>;
3142
+ queryDataSource(options: QueryDataSourceOptions): Promise<DataSourceQueryResult>;
2800
3143
  /**
2801
3144
  * Query a model endpoint directly.
2802
3145
  *
@@ -2895,8 +3238,10 @@ declare class SyftHubClient {
2895
3238
  private _myEndpoints?;
2896
3239
  private _hub?;
2897
3240
  private _accounting?;
3241
+ private _aggregators?;
2898
3242
  private _agent?;
2899
3243
  private _chat?;
3244
+ private _search?;
2900
3245
  private _syftai?;
2901
3246
  private _apiTokens?;
2902
3247
  /**
@@ -2976,22 +3321,8 @@ declare class SyftHubClient {
2976
3321
  */
2977
3322
  get accounting(): AccountingResource;
2978
3323
  /**
2979
- * Initialize the accounting (wallet) resource.
2980
- *
2981
- * The wallet API uses the same SyftHub authentication as other resources.
2982
- * This method simply verifies authentication and creates the resource.
2983
- *
2984
- * @returns The initialized AccountingResource
2985
- * @throws {AuthenticationError} If not authenticated
2986
- *
2987
- * @example
2988
- * // Login first, then initialize accounting
2989
- * await client.auth.login('alice', 'password');
2990
- * await client.initAccounting();
2991
- *
2992
- * // Now accounting is available
2993
- * const wallet = await client.accounting.getWallet();
2994
- * const balance = await client.accounting.getBalance();
3324
+ * @deprecated Accounting is now initialized automatically on first access.
3325
+ * This method is kept for backward compatibility and is a no-op.
2995
3326
  */
2996
3327
  initAccounting(): Promise<AccountingResource>;
2997
3328
  /**
@@ -3021,6 +3352,23 @@ declare class SyftHubClient {
3021
3352
  * const sources = await client.chat.getAvailableDataSources();
3022
3353
  */
3023
3354
  get chat(): ChatResource;
3355
+ /**
3356
+ * Retrieval-only search via the Aggregator (no model generation).
3357
+ *
3358
+ * Symmetric counterpart to {@link chat}: queries data sources for relevant
3359
+ * documents without invoking a model. Satellite-token auth and MPP payment
3360
+ * are handled by the aggregator exactly as for chat.
3361
+ *
3362
+ * @example
3363
+ * const result = await client.search.query({
3364
+ * prompt: 'Hello, world!',
3365
+ * dataSources: ['epfl-news/epfl-news'],
3366
+ * });
3367
+ * for (const doc of result.documents) {
3368
+ * console.log(doc.title, doc.content.slice(0, 80));
3369
+ * }
3370
+ */
3371
+ get search(): SearchResource;
3024
3372
  /**
3025
3373
  * SyftAI-Space resource for direct endpoint queries (low-level API).
3026
3374
  *
@@ -3066,6 +3414,7 @@ declare class SyftHubClient {
3066
3414
  * // Revoke a token
3067
3415
  * await client.apiTokens.revoke(tokenId);
3068
3416
  */
3417
+ get aggregators(): AggregatorsResource;
3069
3418
  get apiTokens(): APITokensResource;
3070
3419
  /**
3071
3420
  * Check if the client is using API token authentication.
@@ -3129,4 +3478,4 @@ declare class SyftHubClient {
3129
3478
  close(): void;
3130
3479
  }
3131
3480
 
3132
- export { APIError, type APIToken, type APITokenCreateResponse, type APITokenListResponse, type APITokenScope, APITokensResource, AccountingAccountExistsError, type AccountingCredentials, AccountingResource, type AccountingResourceOptions, AccountingServiceUnavailableError, type AgentConfig, type AgentErrorEvent, type AgentEvent, type AgentHistoryMessage, type AgentMessageEvent, type RequestInputEvent as AgentRequestInputEvent, AgentResource, AgentSessionClient, type SessionCompletedEvent as AgentSessionCompletedEvent, type SessionCreatedEvent as AgentSessionCreatedEvent, AgentSessionError, type SessionFailedEvent as AgentSessionFailedEvent, type AgentSessionOptions, type AgentSessionState, type StatusEvent as AgentStatusEvent, type ThinkingEvent as AgentThinkingEvent, type TokenEvent as AgentTokenEvent, type ToolCallEvent as AgentToolCallEvent, type ToolResultEvent as AgentToolResultEvent, AggregatorError, AggregatorsResource, type AuthConfig, type AuthTokens, AuthenticationError, AuthorizationError, type BrowseOptions, type ChatMetadata, type ChatOptions, ChatResource, type ChatResponse, type ChatStreamEvent, ConfigurationError, type Connection, type CreateAPITokenInput, type Document, type DocumentSource, type DoneEvent, type Endpoint, type EndpointCreateInput, type EndpointPublic, type EndpointRef, EndpointResolutionError, EndpointType, type EndpointUpdateInput, type ErrorEvent, GenerationError, type GenerationStartEvent, type HeartbeatInput, type HeartbeatResponse, InvalidAccountingPasswordError, type ListEndpointsOptions, type Message, NetworkError, NotFoundError, type PageFetcher, PageIterator, type PasswordChangeInput, type PasswordResetConfirmInput, type PasswordResetRequestInput, type Policy, type QueryDataSourceOptions, type QueryModelOptions, type RegisterResult, type RetrievalCompleteEvent, RetrievalError, type RetrievalStartEvent, type SourceCompleteEvent, type SourceInfo, type SourceStatus, SyftAIResource, SyftHubClient, type SyftHubClientOptions, SyftHubError, type SyncEndpointsResponse, type TokenEvent$1 as TokenEvent, type TransactionTokensResponse, type TransactionsOptions, type TrendingOptions, type UpdateAPITokenInput, type User, type UserAggregator, type UserAggregatorCreateInput, type UserAggregatorUpdateInput, UserAlreadyExistsError, type UserRegisterInput, UserRole, type UserUpdateInput, ValidationError, type VerifyOTPInput, Visibility, type WalletBalance, type WalletInfo, type WalletTransaction, createAccountingResource, getEndpointPublicPath };
3481
+ export { APIError, type APIToken, type APITokenCreateResponse, type APITokenListResponse, type APITokenScope, APITokensResource, AccountingAccountExistsError, type AccountingCredentials, AccountingResource, type AccountingResourceOptions, AccountingServiceUnavailableError, type AgentConfig, type AgentErrorEvent, type AgentEvent, type AgentHistoryMessage, type AgentMessageEvent, type RequestInputEvent as AgentRequestInputEvent, AgentResource, AgentSessionClient, type SessionCompletedEvent as AgentSessionCompletedEvent, type SessionCreatedEvent as AgentSessionCreatedEvent, AgentSessionError, type SessionFailedEvent as AgentSessionFailedEvent, type AgentSessionOptions, type AgentSessionState, type StatusEvent as AgentStatusEvent, type ThinkingEvent as AgentThinkingEvent, type TokenEvent as AgentTokenEvent, type ToolCallEvent as AgentToolCallEvent, type ToolResultEvent as AgentToolResultEvent, AggregatorError, AggregatorsResource, type AuthConfig, type AuthTokens, AuthenticationError, AuthorizationError, type Billing, type BillingEntry, type BrowseOptions, type ChatMetadata, type ChatOptions, ChatResource, type ChatResponse, type ChatStreamEvent, ConfigurationError, type Connection, type CreateAPITokenInput, type DataSourceQueryResult, type Document, type DocumentSource, type DoneEvent, type Endpoint, type EndpointCreateInput, type EndpointPublic, type EndpointRef, EndpointResolutionError, EndpointType, type EndpointUpdateInput, type ErrorEvent, GenerationError, type GenerationStartEvent, type HeartbeatInput, type HeartbeatResponse, InvalidAccountingPasswordError, type ListEndpointsOptions, type Message, NetworkError, NotFoundError, type PageFetcher, PageIterator, type PasswordChangeInput, type PasswordResetConfirmInput, type PasswordResetRequestInput, type Policy, type PolicyMetadata, type QueryDataSourceOptions, type QueryModelOptions, type ReasonCode, type Recipient, type RegisterResult, type RetrievalCompleteEvent, RetrievalError, type RetrievalStartEvent, type SearchDocument, type SearchQueryOptions, SearchResource, type SearchResponse, type SourceCompleteEvent, type SourceInfo, type SourceStatus, SyftAIResource, SyftHubClient, type SyftHubClientOptions, SyftHubError, type SyncEndpointsResponse, type TokenEvent$1 as TokenEvent, type Transaction, type TransactionTokensResponse, type TransactionsOptions, type TrendingOptions, type UpdateAPITokenInput, type User, type UserAggregator, type UserAggregatorCreateInput, type UserAggregatorUpdateInput, UserAlreadyExistsError, type UserRegisterInput, UserRole, type UserUpdateInput, ValidationError, type VerifyOTPInput, Visibility, type WalletBalance, type WalletInfo, type WalletTransaction, createAccountingResource, getEndpointPublicPath };