@syfthub/sdk 0.2.1 → 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.cjs +355 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +442 -146
- package/dist/index.d.ts +442 -146
- package/dist/index.js +355 -152
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -679,6 +679,116 @@ var APITokensResource = class {
|
|
|
679
679
|
}
|
|
680
680
|
};
|
|
681
681
|
|
|
682
|
+
// src/resources/aggregators.ts
|
|
683
|
+
var AggregatorsResource = class {
|
|
684
|
+
constructor(http) {
|
|
685
|
+
this.http = http;
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* List all aggregator configurations for the current user.
|
|
689
|
+
*
|
|
690
|
+
* @returns Array of UserAggregator objects
|
|
691
|
+
* @throws {AuthenticationError} If not authenticated
|
|
692
|
+
*
|
|
693
|
+
* @example
|
|
694
|
+
* const aggregators = await client.users.aggregators.list();
|
|
695
|
+
* for (const agg of aggregators) {
|
|
696
|
+
* if (agg.isDefault) {
|
|
697
|
+
* console.log(`Default: ${agg.name}`);
|
|
698
|
+
* }
|
|
699
|
+
* }
|
|
700
|
+
*/
|
|
701
|
+
async list() {
|
|
702
|
+
return this.http.get("/api/v1/users/me/aggregators");
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Get a specific aggregator configuration by ID.
|
|
706
|
+
*
|
|
707
|
+
* @param aggregatorId - The aggregator ID
|
|
708
|
+
* @returns The UserAggregator object
|
|
709
|
+
* @throws {AuthenticationError} If not authenticated
|
|
710
|
+
* @throws {NotFoundError} If aggregator not found
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* const agg = await client.users.aggregators.get(1);
|
|
714
|
+
* console.log(`${agg.name}: ${agg.url}`);
|
|
715
|
+
*/
|
|
716
|
+
async get(aggregatorId) {
|
|
717
|
+
return this.http.get(`/api/v1/users/me/aggregators/${aggregatorId}`);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Create a new aggregator configuration.
|
|
721
|
+
*
|
|
722
|
+
* The first aggregator created is automatically set as the default.
|
|
723
|
+
*
|
|
724
|
+
* @param input - Aggregator creation input
|
|
725
|
+
* @returns The created UserAggregator object
|
|
726
|
+
* @throws {AuthenticationError} If not authenticated
|
|
727
|
+
* @throws {ValidationError} If input is invalid
|
|
728
|
+
*
|
|
729
|
+
* @example
|
|
730
|
+
* const agg = await client.users.aggregators.create({
|
|
731
|
+
* name: 'My Custom Aggregator',
|
|
732
|
+
* url: 'https://my-aggregator.example.com'
|
|
733
|
+
* });
|
|
734
|
+
* console.log(`Created: ${agg.id}`);
|
|
735
|
+
*/
|
|
736
|
+
async create(input) {
|
|
737
|
+
return this.http.post("/api/v1/users/me/aggregators", input);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Update an aggregator configuration.
|
|
741
|
+
*
|
|
742
|
+
* Only provided fields will be updated.
|
|
743
|
+
*
|
|
744
|
+
* @param aggregatorId - The aggregator ID to update
|
|
745
|
+
* @param input - Fields to update
|
|
746
|
+
* @returns The updated UserAggregator object
|
|
747
|
+
* @throws {AuthenticationError} If not authenticated
|
|
748
|
+
* @throws {NotFoundError} If aggregator not found
|
|
749
|
+
* @throws {ValidationError} If input is invalid
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* const agg = await client.users.aggregators.update(1, {
|
|
753
|
+
* name: 'Updated Name'
|
|
754
|
+
* });
|
|
755
|
+
*/
|
|
756
|
+
async update(aggregatorId, input) {
|
|
757
|
+
return this.http.put(`/api/v1/users/me/aggregators/${aggregatorId}`, input);
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Delete an aggregator configuration.
|
|
761
|
+
*
|
|
762
|
+
* @param aggregatorId - The aggregator ID to delete
|
|
763
|
+
* @throws {AuthenticationError} If not authenticated
|
|
764
|
+
* @throws {NotFoundError} If aggregator not found
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* await client.users.aggregators.delete(1);
|
|
768
|
+
*/
|
|
769
|
+
async delete(aggregatorId) {
|
|
770
|
+
await this.http.delete(`/api/v1/users/me/aggregators/${aggregatorId}`);
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Set an aggregator as the default.
|
|
774
|
+
*
|
|
775
|
+
* Only one aggregator can be the default at a time. Setting a new default
|
|
776
|
+
* automatically unsets the previous one.
|
|
777
|
+
*
|
|
778
|
+
* @param aggregatorId - The aggregator ID to set as default
|
|
779
|
+
* @returns The updated UserAggregator object with isDefault=true
|
|
780
|
+
* @throws {AuthenticationError} If not authenticated
|
|
781
|
+
* @throws {NotFoundError} If aggregator not found
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* const agg = await client.users.aggregators.setDefault(2);
|
|
785
|
+
* console.log(`${agg.name} is now the default`);
|
|
786
|
+
*/
|
|
787
|
+
async setDefault(aggregatorId) {
|
|
788
|
+
return this.http.patch(`/api/v1/users/me/aggregators/${aggregatorId}/default`);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
|
|
682
792
|
// src/resources/auth.ts
|
|
683
793
|
init_errors();
|
|
684
794
|
var AuthResource = class {
|
|
@@ -1066,116 +1176,6 @@ var AuthResource = class {
|
|
|
1066
1176
|
}
|
|
1067
1177
|
};
|
|
1068
1178
|
|
|
1069
|
-
// src/resources/aggregators.ts
|
|
1070
|
-
var AggregatorsResource = class {
|
|
1071
|
-
constructor(http) {
|
|
1072
|
-
this.http = http;
|
|
1073
|
-
}
|
|
1074
|
-
/**
|
|
1075
|
-
* List all aggregator configurations for the current user.
|
|
1076
|
-
*
|
|
1077
|
-
* @returns Array of UserAggregator objects
|
|
1078
|
-
* @throws {AuthenticationError} If not authenticated
|
|
1079
|
-
*
|
|
1080
|
-
* @example
|
|
1081
|
-
* const aggregators = await client.users.aggregators.list();
|
|
1082
|
-
* for (const agg of aggregators) {
|
|
1083
|
-
* if (agg.isDefault) {
|
|
1084
|
-
* console.log(`Default: ${agg.name}`);
|
|
1085
|
-
* }
|
|
1086
|
-
* }
|
|
1087
|
-
*/
|
|
1088
|
-
async list() {
|
|
1089
|
-
return this.http.get("/api/v1/users/me/aggregators");
|
|
1090
|
-
}
|
|
1091
|
-
/**
|
|
1092
|
-
* Get a specific aggregator configuration by ID.
|
|
1093
|
-
*
|
|
1094
|
-
* @param aggregatorId - The aggregator ID
|
|
1095
|
-
* @returns The UserAggregator object
|
|
1096
|
-
* @throws {AuthenticationError} If not authenticated
|
|
1097
|
-
* @throws {NotFoundError} If aggregator not found
|
|
1098
|
-
*
|
|
1099
|
-
* @example
|
|
1100
|
-
* const agg = await client.users.aggregators.get(1);
|
|
1101
|
-
* console.log(`${agg.name}: ${agg.url}`);
|
|
1102
|
-
*/
|
|
1103
|
-
async get(aggregatorId) {
|
|
1104
|
-
return this.http.get(`/api/v1/users/me/aggregators/${aggregatorId}`);
|
|
1105
|
-
}
|
|
1106
|
-
/**
|
|
1107
|
-
* Create a new aggregator configuration.
|
|
1108
|
-
*
|
|
1109
|
-
* The first aggregator created is automatically set as the default.
|
|
1110
|
-
*
|
|
1111
|
-
* @param input - Aggregator creation input
|
|
1112
|
-
* @returns The created UserAggregator object
|
|
1113
|
-
* @throws {AuthenticationError} If not authenticated
|
|
1114
|
-
* @throws {ValidationError} If input is invalid
|
|
1115
|
-
*
|
|
1116
|
-
* @example
|
|
1117
|
-
* const agg = await client.users.aggregators.create({
|
|
1118
|
-
* name: 'My Custom Aggregator',
|
|
1119
|
-
* url: 'https://my-aggregator.example.com'
|
|
1120
|
-
* });
|
|
1121
|
-
* console.log(`Created: ${agg.id}`);
|
|
1122
|
-
*/
|
|
1123
|
-
async create(input) {
|
|
1124
|
-
return this.http.post("/api/v1/users/me/aggregators", input);
|
|
1125
|
-
}
|
|
1126
|
-
/**
|
|
1127
|
-
* Update an aggregator configuration.
|
|
1128
|
-
*
|
|
1129
|
-
* Only provided fields will be updated.
|
|
1130
|
-
*
|
|
1131
|
-
* @param aggregatorId - The aggregator ID to update
|
|
1132
|
-
* @param input - Fields to update
|
|
1133
|
-
* @returns The updated UserAggregator object
|
|
1134
|
-
* @throws {AuthenticationError} If not authenticated
|
|
1135
|
-
* @throws {NotFoundError} If aggregator not found
|
|
1136
|
-
* @throws {ValidationError} If input is invalid
|
|
1137
|
-
*
|
|
1138
|
-
* @example
|
|
1139
|
-
* const agg = await client.users.aggregators.update(1, {
|
|
1140
|
-
* name: 'Updated Name'
|
|
1141
|
-
* });
|
|
1142
|
-
*/
|
|
1143
|
-
async update(aggregatorId, input) {
|
|
1144
|
-
return this.http.put(`/api/v1/users/me/aggregators/${aggregatorId}`, input);
|
|
1145
|
-
}
|
|
1146
|
-
/**
|
|
1147
|
-
* Delete an aggregator configuration.
|
|
1148
|
-
*
|
|
1149
|
-
* @param aggregatorId - The aggregator ID to delete
|
|
1150
|
-
* @throws {AuthenticationError} If not authenticated
|
|
1151
|
-
* @throws {NotFoundError} If aggregator not found
|
|
1152
|
-
*
|
|
1153
|
-
* @example
|
|
1154
|
-
* await client.users.aggregators.delete(1);
|
|
1155
|
-
*/
|
|
1156
|
-
async delete(aggregatorId) {
|
|
1157
|
-
await this.http.delete(`/api/v1/users/me/aggregators/${aggregatorId}`);
|
|
1158
|
-
}
|
|
1159
|
-
/**
|
|
1160
|
-
* Set an aggregator as the default.
|
|
1161
|
-
*
|
|
1162
|
-
* Only one aggregator can be the default at a time. Setting a new default
|
|
1163
|
-
* automatically unsets the previous one.
|
|
1164
|
-
*
|
|
1165
|
-
* @param aggregatorId - The aggregator ID to set as default
|
|
1166
|
-
* @returns The updated UserAggregator object with isDefault=true
|
|
1167
|
-
* @throws {AuthenticationError} If not authenticated
|
|
1168
|
-
* @throws {NotFoundError} If aggregator not found
|
|
1169
|
-
*
|
|
1170
|
-
* @example
|
|
1171
|
-
* const agg = await client.users.aggregators.setDefault(2);
|
|
1172
|
-
* console.log(`${agg.name} is now the default`);
|
|
1173
|
-
*/
|
|
1174
|
-
async setDefault(aggregatorId) {
|
|
1175
|
-
return this.http.patch(`/api/v1/users/me/aggregators/${aggregatorId}/default`);
|
|
1176
|
-
}
|
|
1177
|
-
};
|
|
1178
|
-
|
|
1179
1179
|
// src/resources/users.ts
|
|
1180
1180
|
var UsersResource = class {
|
|
1181
1181
|
constructor(http) {
|
|
@@ -2189,10 +2189,11 @@ function getEndpointPublicPath(endpoint) {
|
|
|
2189
2189
|
|
|
2190
2190
|
// src/resources/chat.ts
|
|
2191
2191
|
var AggregatorError = class extends exports.SyftHubError {
|
|
2192
|
-
constructor(message, status, detail) {
|
|
2192
|
+
constructor(message, status, detail, billing) {
|
|
2193
2193
|
super(message);
|
|
2194
2194
|
this.status = status;
|
|
2195
2195
|
this.detail = detail;
|
|
2196
|
+
this.billing = billing;
|
|
2196
2197
|
this.name = "AggregatorError";
|
|
2197
2198
|
}
|
|
2198
2199
|
};
|
|
@@ -2398,7 +2399,7 @@ var ChatResource = class _ChatResource {
|
|
|
2398
2399
|
* Resolves endpoints, fetches tokens, and builds the aggregator request body.
|
|
2399
2400
|
* Returns the request body and the resolved aggregator URL.
|
|
2400
2401
|
*/
|
|
2401
|
-
async prepareRequest(options, stream) {
|
|
2402
|
+
async prepareRequest(options, stream, retrievalOnly = false) {
|
|
2402
2403
|
const modelRef = await this.resolveEndpointRef(options.model, "model");
|
|
2403
2404
|
const expandedDataSources = await this.expandCollectivePaths(options.dataSources ?? []);
|
|
2404
2405
|
const dsRefs = [];
|
|
@@ -2433,7 +2434,8 @@ var ChatResource = class _ChatResource {
|
|
|
2433
2434
|
stream,
|
|
2434
2435
|
messages: options.messages,
|
|
2435
2436
|
peerToken,
|
|
2436
|
-
peerChannel
|
|
2437
|
+
peerChannel,
|
|
2438
|
+
retrievalOnly
|
|
2437
2439
|
}
|
|
2438
2440
|
);
|
|
2439
2441
|
const effectiveAggregatorUrl = (options.aggregatorUrl ?? this.aggregatorUrl).replace(
|
|
@@ -2447,12 +2449,14 @@ var ChatResource = class _ChatResource {
|
|
|
2447
2449
|
*/
|
|
2448
2450
|
async handleAggregatorErrorResponse(response) {
|
|
2449
2451
|
let message = `HTTP ${response.status}`;
|
|
2452
|
+
let billing;
|
|
2450
2453
|
try {
|
|
2451
2454
|
const data = await response.json();
|
|
2452
|
-
message = String(data["message"] ?? data["error"] ?? message);
|
|
2455
|
+
message = String(data["message"] ?? data["error"] ?? data["detail"] ?? message);
|
|
2456
|
+
billing = this.parseBilling(data);
|
|
2453
2457
|
} catch {
|
|
2454
2458
|
}
|
|
2455
|
-
throw new AggregatorError(`Aggregator error: ${message}`, response.status);
|
|
2459
|
+
throw new AggregatorError(`Aggregator error: ${message}`, response.status, void 0, billing);
|
|
2456
2460
|
}
|
|
2457
2461
|
/**
|
|
2458
2462
|
* Build the request body for the aggregator.
|
|
@@ -2496,6 +2500,9 @@ var ChatResource = class _ChatResource {
|
|
|
2496
2500
|
if (options.peerChannel) {
|
|
2497
2501
|
body["peer_channel"] = options.peerChannel;
|
|
2498
2502
|
}
|
|
2503
|
+
if (options.retrievalOnly) {
|
|
2504
|
+
body["retrieval_only"] = true;
|
|
2505
|
+
}
|
|
2499
2506
|
return body;
|
|
2500
2507
|
}
|
|
2501
2508
|
/**
|
|
@@ -2529,6 +2536,60 @@ var ChatResource = class _ChatResource {
|
|
|
2529
2536
|
totalTokens: Number(data["total_tokens"] ?? 0)
|
|
2530
2537
|
};
|
|
2531
2538
|
}
|
|
2539
|
+
/**
|
|
2540
|
+
* Parse a single billing/policy-metadata entry from a raw (snake_case) dict.
|
|
2541
|
+
*
|
|
2542
|
+
* Shared by {@link parseBilling} (aggregated, carries `source`) and the
|
|
2543
|
+
* direct-path `policy_metadata` parsing in {@link SyftAIResource}.
|
|
2544
|
+
*/
|
|
2545
|
+
static parseBillingEntry(raw) {
|
|
2546
|
+
const recipientRaw = raw["recipient"];
|
|
2547
|
+
const recipient = recipientRaw && typeof recipientRaw === "object" ? {
|
|
2548
|
+
username: recipientRaw["username"],
|
|
2549
|
+
email: recipientRaw["email"],
|
|
2550
|
+
walletAddress: recipientRaw["wallet_address"]
|
|
2551
|
+
} : void 0;
|
|
2552
|
+
const transactionRaw = raw["transaction"];
|
|
2553
|
+
const transaction = transactionRaw && typeof transactionRaw === "object" ? {
|
|
2554
|
+
rail: String(transactionRaw["rail"] ?? ""),
|
|
2555
|
+
id: String(transactionRaw["id"] ?? ""),
|
|
2556
|
+
reference: transactionRaw["reference"]
|
|
2557
|
+
} : void 0;
|
|
2558
|
+
return {
|
|
2559
|
+
source: raw["source"],
|
|
2560
|
+
policyType: String(raw["policy_type"] ?? ""),
|
|
2561
|
+
kind: String(raw["kind"] ?? ""),
|
|
2562
|
+
status: String(raw["status"] ?? ""),
|
|
2563
|
+
amount: raw["amount"] == null ? void 0 : Number(raw["amount"]),
|
|
2564
|
+
currency: raw["currency"],
|
|
2565
|
+
recipient,
|
|
2566
|
+
transaction,
|
|
2567
|
+
reasonCode: raw["reason_code"],
|
|
2568
|
+
reason: raw["reason"],
|
|
2569
|
+
details: raw["details"] ?? {}
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
/**
|
|
2573
|
+
* Parse the aggregated `billing` block from a raw aggregator response.
|
|
2574
|
+
*
|
|
2575
|
+
* Returns undefined when no `billing` object is present (e.g. an error body
|
|
2576
|
+
* with no policy metadata). The wire keys are snake_case.
|
|
2577
|
+
*/
|
|
2578
|
+
parseBilling(data) {
|
|
2579
|
+
const b = data["billing"];
|
|
2580
|
+
if (!b || typeof b !== "object") {
|
|
2581
|
+
return void 0;
|
|
2582
|
+
}
|
|
2583
|
+
const billing = b;
|
|
2584
|
+
const entriesRaw = Array.isArray(billing["entries"]) ? billing["entries"] : [];
|
|
2585
|
+
return {
|
|
2586
|
+
totalCost: billing["total_cost"] == null ? null : Number(billing["total_cost"]),
|
|
2587
|
+
currency: billing["currency"] ?? null,
|
|
2588
|
+
entries: entriesRaw.map(
|
|
2589
|
+
(e) => _ChatResource.parseBillingEntry(e)
|
|
2590
|
+
)
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2532
2593
|
/**
|
|
2533
2594
|
* Parse document sources from raw data.
|
|
2534
2595
|
* The new format is a dict mapping document title to {slug, content}.
|
|
@@ -2596,15 +2657,82 @@ var ChatResource = class _ChatResource {
|
|
|
2596
2657
|
const usageData = data["usage"];
|
|
2597
2658
|
const usage = usageData ? this.parseUsage(usageData) : void 0;
|
|
2598
2659
|
const profitShare = data["profit_share"];
|
|
2660
|
+
const billing = this.parseBilling(data);
|
|
2599
2661
|
return {
|
|
2600
2662
|
response: String(data["response"] ?? ""),
|
|
2601
2663
|
sources,
|
|
2602
2664
|
retrievalInfo,
|
|
2603
2665
|
metadata,
|
|
2604
2666
|
usage,
|
|
2605
|
-
profitShare
|
|
2667
|
+
profitShare,
|
|
2668
|
+
billing
|
|
2606
2669
|
};
|
|
2607
2670
|
}
|
|
2671
|
+
/**
|
|
2672
|
+
* Placeholder model for retrieval-only requests. The aggregator requires a
|
|
2673
|
+
* `model` field on every request, but short-circuits before dereferencing it
|
|
2674
|
+
* when `retrieval_only` is set, so an empty ref is never contacted.
|
|
2675
|
+
*/
|
|
2676
|
+
static RETRIEVAL_ONLY_MODEL = {
|
|
2677
|
+
url: "",
|
|
2678
|
+
slug: "",
|
|
2679
|
+
name: "retrieval-only"
|
|
2680
|
+
};
|
|
2681
|
+
/**
|
|
2682
|
+
* Retrieve documents from data sources without model generation.
|
|
2683
|
+
*
|
|
2684
|
+
* Drives the aggregator's retrieval-only path: data sources are queried in
|
|
2685
|
+
* parallel (with satellite-token auth and MPP payment handled server-side,
|
|
2686
|
+
* exactly like {@link complete}), but no model is invoked.
|
|
2687
|
+
*
|
|
2688
|
+
* Prefer the symmetric `client.search.query(...)` facade; this is the
|
|
2689
|
+
* underlying primitive.
|
|
2690
|
+
*
|
|
2691
|
+
* @param options - Search options
|
|
2692
|
+
* @returns SearchResponse with retrieved documents and per-source metadata
|
|
2693
|
+
* @throws {EndpointResolutionError} If a data source cannot be resolved
|
|
2694
|
+
* @throws {AggregatorError} If the aggregator service fails
|
|
2695
|
+
*/
|
|
2696
|
+
async retrieve(options) {
|
|
2697
|
+
const chatOptions = {
|
|
2698
|
+
prompt: options.prompt,
|
|
2699
|
+
model: _ChatResource.RETRIEVAL_ONLY_MODEL,
|
|
2700
|
+
dataSources: options.dataSources,
|
|
2701
|
+
topK: options.topK,
|
|
2702
|
+
similarityThreshold: options.similarityThreshold,
|
|
2703
|
+
aggregatorUrl: options.aggregatorUrl,
|
|
2704
|
+
guestMode: options.guestMode
|
|
2705
|
+
};
|
|
2706
|
+
const { requestBody, effectiveAggregatorUrl } = await this.prepareRequest(
|
|
2707
|
+
chatOptions,
|
|
2708
|
+
false,
|
|
2709
|
+
true
|
|
2710
|
+
);
|
|
2711
|
+
const response = await fetch(`${effectiveAggregatorUrl}/chat`, {
|
|
2712
|
+
method: "POST",
|
|
2713
|
+
headers: { "Content-Type": "application/json" },
|
|
2714
|
+
body: JSON.stringify(requestBody),
|
|
2715
|
+
signal: options.signal
|
|
2716
|
+
});
|
|
2717
|
+
if (!response.ok) {
|
|
2718
|
+
return this.handleAggregatorErrorResponse(response);
|
|
2719
|
+
}
|
|
2720
|
+
const data = await response.json();
|
|
2721
|
+
const sources = this.parseDocumentSources(
|
|
2722
|
+
data["sources"]
|
|
2723
|
+
);
|
|
2724
|
+
const documents = Object.entries(sources).map(([title, source]) => ({
|
|
2725
|
+
title,
|
|
2726
|
+
slug: source.slug,
|
|
2727
|
+
content: source.content
|
|
2728
|
+
}));
|
|
2729
|
+
const retrievalInfo = this.parseRetrievalInfo(
|
|
2730
|
+
data["retrieval_info"]
|
|
2731
|
+
);
|
|
2732
|
+
const metadata = this.parseMetadata(data["metadata"] ?? {});
|
|
2733
|
+
const billing = this.parseBilling(data);
|
|
2734
|
+
return { documents, retrievalInfo, metadata, billing };
|
|
2735
|
+
}
|
|
2608
2736
|
/**
|
|
2609
2737
|
* Send a chat request and stream response events.
|
|
2610
2738
|
*
|
|
@@ -2703,13 +2831,24 @@ var ChatResource = class _ChatResource {
|
|
|
2703
2831
|
const usageData = data["usage"];
|
|
2704
2832
|
const usage = usageData ? this.parseUsage(usageData) : void 0;
|
|
2705
2833
|
const profitShare = data["profit_share"];
|
|
2834
|
+
const billing = this.parseBilling(data);
|
|
2706
2835
|
const response = data["response"];
|
|
2707
|
-
return {
|
|
2836
|
+
return {
|
|
2837
|
+
type: "done",
|
|
2838
|
+
sources,
|
|
2839
|
+
retrievalInfo,
|
|
2840
|
+
metadata,
|
|
2841
|
+
usage,
|
|
2842
|
+
profitShare,
|
|
2843
|
+
billing,
|
|
2844
|
+
response
|
|
2845
|
+
};
|
|
2708
2846
|
}
|
|
2709
2847
|
case "error":
|
|
2710
2848
|
return {
|
|
2711
2849
|
type: "error",
|
|
2712
|
-
message: String(data["message"] ?? "Unknown error")
|
|
2850
|
+
message: String(data["message"] ?? "Unknown error"),
|
|
2851
|
+
billing: this.parseBilling(data)
|
|
2713
2852
|
};
|
|
2714
2853
|
default:
|
|
2715
2854
|
console.warn(`[SyftHub] Unknown SSE event type received from aggregator: ${eventType}`);
|
|
@@ -2750,6 +2889,34 @@ var ChatResource = class _ChatResource {
|
|
|
2750
2889
|
}
|
|
2751
2890
|
};
|
|
2752
2891
|
|
|
2892
|
+
// src/resources/search.ts
|
|
2893
|
+
var SearchResource = class {
|
|
2894
|
+
/**
|
|
2895
|
+
* @param chat - The chat resource that owns aggregator communication and
|
|
2896
|
+
* request preparation (satellite tokens, MPP, collective expansion). Search
|
|
2897
|
+
* reuses it rather than duplicating that logic.
|
|
2898
|
+
*/
|
|
2899
|
+
constructor(chat) {
|
|
2900
|
+
this.chat = chat;
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Retrieve documents from data sources without model generation.
|
|
2904
|
+
*
|
|
2905
|
+
* @param options - Search options (prompt, data sources, top-k, etc.)
|
|
2906
|
+
* @returns SearchResponse with retrieved documents and per-source metadata
|
|
2907
|
+
*
|
|
2908
|
+
* @example
|
|
2909
|
+
* const result = await client.search.query({
|
|
2910
|
+
* prompt: 'Hello, world!',
|
|
2911
|
+
* dataSources: ['epfl-news/epfl-news'],
|
|
2912
|
+
* });
|
|
2913
|
+
* console.log(result.documents.length, 'documents');
|
|
2914
|
+
*/
|
|
2915
|
+
async query(options) {
|
|
2916
|
+
return this.chat.retrieve(options);
|
|
2917
|
+
}
|
|
2918
|
+
};
|
|
2919
|
+
|
|
2753
2920
|
// src/resources/syftai.ts
|
|
2754
2921
|
init_errors();
|
|
2755
2922
|
var RetrievalError = class extends exports.SyftHubError {
|
|
@@ -2865,6 +3032,28 @@ var SyftAIResource = class {
|
|
|
2865
3032
|
}
|
|
2866
3033
|
return documents;
|
|
2867
3034
|
}
|
|
3035
|
+
/**
|
|
3036
|
+
* Parse the raw `policy_metadata` block from a syft-space response.
|
|
3037
|
+
*
|
|
3038
|
+
* The direct path (Boundary A) carries a top-level `policy_metadata` object
|
|
3039
|
+
* shaped `{ outcome, entries: [...] }`. Entries reuse the {@link BillingEntry}
|
|
3040
|
+
* shape (with `source` absent), so this delegates entry parsing to
|
|
3041
|
+
* {@link ChatResource.parseBillingEntry}. The wire keys are snake_case.
|
|
3042
|
+
*/
|
|
3043
|
+
parsePolicyMetadata(data) {
|
|
3044
|
+
const pm = data["policy_metadata"];
|
|
3045
|
+
if (!pm || typeof pm !== "object") {
|
|
3046
|
+
return void 0;
|
|
3047
|
+
}
|
|
3048
|
+
const meta = pm;
|
|
3049
|
+
const entriesRaw = Array.isArray(meta["entries"]) ? meta["entries"] : [];
|
|
3050
|
+
return {
|
|
3051
|
+
outcome: String(meta["outcome"] ?? ""),
|
|
3052
|
+
entries: entriesRaw.map(
|
|
3053
|
+
(e) => ChatResource.parseBillingEntry(e)
|
|
3054
|
+
)
|
|
3055
|
+
};
|
|
3056
|
+
}
|
|
2868
3057
|
/**
|
|
2869
3058
|
* Query a data source endpoint directly.
|
|
2870
3059
|
*
|
|
@@ -2874,7 +3063,9 @@ var SyftAIResource = class {
|
|
|
2874
3063
|
* owner is known (`ownerUsername` option or `endpoint.ownerUsername`).
|
|
2875
3064
|
*
|
|
2876
3065
|
* @param options - Query options
|
|
2877
|
-
* @returns
|
|
3066
|
+
* @returns DataSourceQueryResult — the retrieved documents plus the raw
|
|
3067
|
+
* `policyMetadata` block from the syft-space response (price, recipient,
|
|
3068
|
+
* transaction, status).
|
|
2878
3069
|
* @throws {RetrievalError} If the query fails
|
|
2879
3070
|
*/
|
|
2880
3071
|
async queryDataSource(options) {
|
|
@@ -2945,8 +3136,10 @@ var SyftAIResource = class {
|
|
|
2945
3136
|
throw new RetrievalError(`Data source query failed: ${message}`, endpoint.slug);
|
|
2946
3137
|
}
|
|
2947
3138
|
const data = await response.json();
|
|
2948
|
-
|
|
2949
|
-
|
|
3139
|
+
return {
|
|
3140
|
+
documents: this.parseDocuments(data),
|
|
3141
|
+
policyMetadata: this.parsePolicyMetadata(data)
|
|
3142
|
+
};
|
|
2950
3143
|
}
|
|
2951
3144
|
/**
|
|
2952
3145
|
* Query a model endpoint directly.
|
|
@@ -3083,8 +3276,10 @@ var SyftHubClient = class {
|
|
|
3083
3276
|
_myEndpoints;
|
|
3084
3277
|
_hub;
|
|
3085
3278
|
_accounting;
|
|
3279
|
+
_aggregators;
|
|
3086
3280
|
_agent;
|
|
3087
3281
|
_chat;
|
|
3282
|
+
_search;
|
|
3088
3283
|
_syftai;
|
|
3089
3284
|
_apiTokens;
|
|
3090
3285
|
/**
|
|
@@ -3203,43 +3398,23 @@ var SyftHubClient = class {
|
|
|
3203
3398
|
* const balance = await client.accounting.getBalance();
|
|
3204
3399
|
*/
|
|
3205
3400
|
get accounting() {
|
|
3206
|
-
if (this._accounting) {
|
|
3207
|
-
return this._accounting;
|
|
3208
|
-
}
|
|
3209
|
-
throw new exports.AuthenticationError(
|
|
3210
|
-
"Accounting not initialized. Call `await client.initAccounting()` after login."
|
|
3211
|
-
);
|
|
3212
|
-
}
|
|
3213
|
-
/**
|
|
3214
|
-
* Initialize the accounting (wallet) resource.
|
|
3215
|
-
*
|
|
3216
|
-
* The wallet API uses the same SyftHub authentication as other resources.
|
|
3217
|
-
* This method simply verifies authentication and creates the resource.
|
|
3218
|
-
*
|
|
3219
|
-
* @returns The initialized AccountingResource
|
|
3220
|
-
* @throws {AuthenticationError} If not authenticated
|
|
3221
|
-
*
|
|
3222
|
-
* @example
|
|
3223
|
-
* // Login first, then initialize accounting
|
|
3224
|
-
* await client.auth.login('alice', 'password');
|
|
3225
|
-
* await client.initAccounting();
|
|
3226
|
-
*
|
|
3227
|
-
* // Now accounting is available
|
|
3228
|
-
* const wallet = await client.accounting.getWallet();
|
|
3229
|
-
* const balance = await client.accounting.getBalance();
|
|
3230
|
-
*/
|
|
3231
|
-
async initAccounting() {
|
|
3232
|
-
if (this._accounting) {
|
|
3233
|
-
return this._accounting;
|
|
3234
|
-
}
|
|
3235
3401
|
if (!this.isAuthenticated) {
|
|
3236
3402
|
throw new exports.AuthenticationError(
|
|
3237
3403
|
"Must be logged in to use accounting. Call client.auth.login() first."
|
|
3238
3404
|
);
|
|
3239
3405
|
}
|
|
3240
|
-
|
|
3406
|
+
if (!this._accounting) {
|
|
3407
|
+
this._accounting = new AccountingResource(this.http);
|
|
3408
|
+
}
|
|
3241
3409
|
return this._accounting;
|
|
3242
3410
|
}
|
|
3411
|
+
/**
|
|
3412
|
+
* @deprecated Accounting is now initialized automatically on first access.
|
|
3413
|
+
* This method is kept for backward compatibility and is a no-op.
|
|
3414
|
+
*/
|
|
3415
|
+
async initAccounting() {
|
|
3416
|
+
return this.accounting;
|
|
3417
|
+
}
|
|
3243
3418
|
/**
|
|
3244
3419
|
* Chat resource for RAG-augmented conversations via the Aggregator.
|
|
3245
3420
|
*
|
|
@@ -3272,6 +3447,28 @@ var SyftHubClient = class {
|
|
|
3272
3447
|
}
|
|
3273
3448
|
return this._chat;
|
|
3274
3449
|
}
|
|
3450
|
+
/**
|
|
3451
|
+
* Retrieval-only search via the Aggregator (no model generation).
|
|
3452
|
+
*
|
|
3453
|
+
* Symmetric counterpart to {@link chat}: queries data sources for relevant
|
|
3454
|
+
* documents without invoking a model. Satellite-token auth and MPP payment
|
|
3455
|
+
* are handled by the aggregator exactly as for chat.
|
|
3456
|
+
*
|
|
3457
|
+
* @example
|
|
3458
|
+
* const result = await client.search.query({
|
|
3459
|
+
* prompt: 'Hello, world!',
|
|
3460
|
+
* dataSources: ['epfl-news/epfl-news'],
|
|
3461
|
+
* });
|
|
3462
|
+
* for (const doc of result.documents) {
|
|
3463
|
+
* console.log(doc.title, doc.content.slice(0, 80));
|
|
3464
|
+
* }
|
|
3465
|
+
*/
|
|
3466
|
+
get search() {
|
|
3467
|
+
if (!this._search) {
|
|
3468
|
+
this._search = new SearchResource(this.chat);
|
|
3469
|
+
}
|
|
3470
|
+
return this._search;
|
|
3471
|
+
}
|
|
3275
3472
|
/**
|
|
3276
3473
|
* SyftAI-Space resource for direct endpoint queries (low-level API).
|
|
3277
3474
|
*
|
|
@@ -3322,6 +3519,12 @@ var SyftHubClient = class {
|
|
|
3322
3519
|
* // Revoke a token
|
|
3323
3520
|
* await client.apiTokens.revoke(tokenId);
|
|
3324
3521
|
*/
|
|
3522
|
+
get aggregators() {
|
|
3523
|
+
if (!this._aggregators) {
|
|
3524
|
+
this._aggregators = new AggregatorsResource(this.http);
|
|
3525
|
+
}
|
|
3526
|
+
return this._aggregators;
|
|
3527
|
+
}
|
|
3325
3528
|
get apiTokens() {
|
|
3326
3529
|
if (!this._apiTokens) {
|
|
3327
3530
|
this._apiTokens = new APITokensResource(this.http);
|
|
@@ -3417,6 +3620,7 @@ exports.EndpointType = EndpointType;
|
|
|
3417
3620
|
exports.GenerationError = GenerationError;
|
|
3418
3621
|
exports.PageIterator = PageIterator;
|
|
3419
3622
|
exports.RetrievalError = RetrievalError;
|
|
3623
|
+
exports.SearchResource = SearchResource;
|
|
3420
3624
|
exports.SyftAIResource = SyftAIResource;
|
|
3421
3625
|
exports.SyftHubClient = SyftHubClient;
|
|
3422
3626
|
exports.UserRole = UserRole;
|