mbd-studio-sdk 4.6.4 → 4.6.6

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.
Files changed (2) hide show
  1. package/llms.txt +466 -5
  2. package/package.json +1 -1
package/llms.txt CHANGED
@@ -36,12 +36,16 @@ The MBD Studio SDK provides search, features, scoring, and ranking for personali
36
36
  | Index | Description |
37
37
  |-------|-------------|
38
38
  | farcaster-items | Farcaster posts (casts, frames, etc.) |
39
+ | farcaster-users | Farcaster user preference/follow profile (lookup + terms_lookup based personalization) |
39
40
  | zora-coins | Zora coins/tokens |
40
41
  | polymarket-items | Polymarket prediction markets |
41
42
  | polymarket-wallets | Polymarket wallet profiles |
43
+ | token-items | Web3 tokens/instruments |
44
+ | wallet-users | Wallet portfolio + enrichment profile |
42
45
  | kalshi-items | Kalshi prediction markets |
46
+ | kalshi-wallets-v20260315 | Kalshi wallet preference/trade profile (UI alias; backend typically uses `kalshi-wallets`) |
43
47
 
44
- Canonical names (for features/scores): `farcaster-items`, `zora-coins`, `polymarket-items`, `polymarket-wallets`, `kalshi-items`. Index aliases may include version suffixes (e.g. `farcaster-items-v2`).
48
+ Canonical names (for features/scores): `farcaster-items`, `zora-coins`, `polymarket-items`, `polymarket-wallets`, `kalshi-items` (used by the SDK's `findIndex()` to attach features/scores). Index aliases may include version suffixes.
45
49
 
46
50
  ### farcaster-items
47
51
 
@@ -75,13 +79,49 @@ Canonical names (for features/scores): `farcaster-items`, `zora-coins`, `polymar
75
79
 
76
80
  **Filter types:** user_ids, ai_labels2, tags2, is_null, date, numeric_filters
77
81
 
78
- **Key fields:** user_id, name, pseudonym, pfp, updated_at, volume, pnl, events_per_day, ai_labels_med, tags (label_01..label_10, tag_01..tag_10)
82
+ **Key fields:** user_id, name, pseudonym, pfp, updated_at, volume, pnl, events_per_day, primary_labels, secondary_labels, primary_tags, secondary_tags, primary_similar_wallets, secondary_similar_wallets, text_vector (lookup fields used by `group_boost`: `label_01`..`label_10`, `tag_01`..`tag_10`)
83
+
84
+ ### farcaster-users
85
+
86
+ **Sort fields:** updated_at, events_per_day, score_spam, score_not_ok, null
87
+
88
+ **Filter types:** user_ids, ai_labels2, tags2, is_null, date, numeric_filters
89
+
90
+ **Key fields:** user_id, name, pseudonym, pfp, updated_at, volume, pnl, events_per_day, primary_labels, secondary_labels, primary_tags, secondary_tags, primary_similar_wallets, secondary_similar_wallets, text_vector
91
+
92
+ ### token-items
93
+
94
+ **Sort fields:** last_updated, market_cap, price_usd, price_diff_pct_1h, price_diff_pct_1d, volume_usd_1h, volume_usd_1d, volume_usd_24h, total_liquidity_usd, holders_count, circulating_supply, decimals, null
95
+
96
+ **Filter types:** item_ids, token_identifiers, date, keywords, numeric_filters
97
+
98
+ **Key fields:** item_id, token_address, symbol, chain, name, last_updated, market_cap, price_usd, price_diff_pct_1d, volume_usd_1d, volume_usd_24h, circulating_supply, decimals
99
+
100
+ ### wallet-users
101
+
102
+ **Sort fields:** last_trade_timestamp, zerion_last_enriched_at, portfolio_total_usd, portfolio_cash_usd, portfolio_fungibles_usd, portfolio_nfts_usd, pnl_pct_total, pnl_net_invested_usd, pnl_realized_usd, pnl_unrealized_usd, volume_usd_24h, volume_usd_7d, volume_usd_30d, num_trades_24h, num_trades_30d, null
103
+
104
+ **Filter types:** user_ids, date, numeric_filters
105
+
106
+ **Key fields:** wallet_address, chains, labels, tags, fungible_positions_tokens_list, last_trade_timestamp, zerion_last_enriched_at, allocation_cash_pct, allocation_fungibles_pct, allocation_nfts_pct, num_trades_24h, num_trades_30d, pnl_net_invested_usd, pnl_pct_total, pnl_realized_usd, pnl_unrealized_usd, portfolio_cash_usd, portfolio_fungibles_usd, portfolio_nfts_usd, portfolio_total_usd, volume_usd_24h, volume_usd_7d, volume_usd_30d
107
+
108
+ ### kalshi-wallets-v20260315
109
+
110
+ **Sort fields:** updated_at, last_trade_time, pnl, volume_quote, volume_outcome, markets_traded, events_per_day, null
111
+
112
+ **Filter types:** user_ids, ai_labels2, tags2, is_null, date, numeric_filters
113
+
114
+ **Key fields:** user_id, updated_at, last_trade_time, pnl, volume_quote, volume_outcome, markets_traded, events_per_day, primary_labels, secondary_labels, primary_tags, secondary_tags, text_vector, sem_embed, protocol
79
115
 
80
116
  ### kalshi-items
81
117
 
82
118
  **Sort fields:** created_at, updated_at, volume, start_date, end_date, null
83
119
 
84
- **Filter types:** item_ids, ai_labels, tags, series_category, series_tags, status, ticker, event_id, date, boolean_filters, keywords, numeric_filters
120
+ **Filter types (UI):** item_ids, ai_labels, tags, date, boolean_filters, keywords, numeric_filters
121
+
122
+ **Boost-only:** boost_wallet_labels, boost_wallet_tags
123
+
124
+ **Additional term/terms filterable fields (present in index mappings, but not exposed as dedicated UI filter types):** series_category, series_tags, status, ticker, event_id
85
125
 
86
126
  **Key fields:** item_id, event_id, ticker, question, description, status, active, closed, created_at, updated_at, start_date, end_date, volume, ai_labels_high, ai_labels_med, ai_labels_low, series_category, series_tags, tags, image_url, market_url
87
127
 
@@ -119,6 +159,8 @@ Backend: `{ "terms": { field: value } }`
119
159
 
120
160
  Numeric comparison. Operators: `>`, `>=`, `<`, `<=`.
121
161
 
162
+ UI note: the current `NumericFiltersSection` only exposes `>=` and `<=` (frontend restriction); the backend supports all four operators.
163
+
122
164
  ```js
123
165
  .include().numeric('volume', '>=', 10000)
124
166
  .exclude().numeric('score_spam', '>', 0.5)
@@ -183,7 +225,16 @@ Backend: `value` is used as-is.
183
225
 
184
226
  ### group_boost
185
227
 
186
- Boosts items by group membership from a lookup document. The lookup doc has paths `{group}_01`, `{group}_02`, … `{group}_n`. Items matching `{group}_01` get max_boost; `{group}_02` get slightly less; etc. Linear decay from max to min over n groups.
228
+ Boosts items by group membership from a lookup document (boost endpoint only).
229
+
230
+ Lookup doc must contain fields at paths `{group}_01`, `{group}_02`, … `{group}_n` (backend formats these as `{group}_{(i+1):02d}`).
231
+
232
+ For group index `i` (0-based), the backend computes per-group boost:
233
+
234
+ * if `max_boost == min_boost`: `boost_value = max_boost`
235
+ * else: `boost_value = max_boost - ((max_boost - min_boost) * i / (n - 1))`
236
+
237
+ It then builds a `bool.should` array with `terms` lookups for each `{group}_XX`, assigning each `terms` clause its own `boost` value (so `group_boost` does not use the per-filter boost multiplier that other boostable filters require).
187
238
 
188
239
  **Parameters:**
189
240
  - `lookup_index` – index containing the lookup doc
@@ -199,7 +250,7 @@ Boosts items by group membership from a lookup document. The lookup doc has path
199
250
  .boost().groupBoost('polymarket-wallets', 'tags', walletId, 'tag', 1, 3, 5)
200
251
  ```
201
252
 
202
- Backend: builds `bool.should` with `terms` lookup per group path, each with its own boost (linear interpolation).
253
+ Backend: `bool.should` + per-group boosted `terms` lookups, with linear interpolation between `max_boost` (group 01) and `min_boost` (group n).
203
254
 
204
255
  ### terms_lookup
205
256
 
@@ -242,6 +293,9 @@ A: `term` matches a single value exactly. `terms` matches any value in a list.
242
293
  **Q: What is the difference between term and match?**
243
294
  A: `term` is exact (keyword-like). `match` is full-text (analyzed, OR across keywords).
244
295
 
296
+ **Q: Which numeric operators are supported?**
297
+ A: The backend accepts `>`, `>=`, `<`, `<=`. The frontend numeric filter UI currently exposes only `>=` and `<=`.
298
+
245
299
  **Q: How does group_boost work with polymarket-wallets?**
246
300
  A: A wallet doc has `label_01`, `label_02`, … (or `tag_01`, …) with preferred labels/tags. Items matching label_01 get highest boost; label_02 get less; etc. Use `group` = `"label"` or `"tag"` and `field` = `ai_labels_med` or `tags`.
247
301
 
@@ -761,3 +815,410 @@ export function findIndex(index) {
761
815
  return null;
762
816
  }
763
817
  ```
818
+
819
+ ### package.json
820
+ ```json
821
+ {
822
+ "name": "mbd-studio-sdk",
823
+ "version": "0.1.0",
824
+ "description": "SDK for Embed Recommendation Engine APIs",
825
+ "keywords": [
826
+ "web3",
827
+ "AI",
828
+ "recommendations",
829
+ "polymarket",
830
+ "farcaster",
831
+ "zora"
832
+ ],
833
+ "type": "module",
834
+ "main": "index.js",
835
+ "types": "index.d.ts",
836
+ "exports": {
837
+ ".": {
838
+ "types": "./index.d.ts",
839
+ "import": "./index.js",
840
+ "default": "./index.js"
841
+ }
842
+ },
843
+ "files": [
844
+ "index.js",
845
+ "index.d.ts",
846
+ "StudioConfig.js",
847
+ "V1",
848
+ "llms.txt"
849
+ ],
850
+ "private": true
851
+ }
852
+ ```
853
+
854
+ ### index.d.ts
855
+ ```ts
856
+ /**
857
+ * MBD Studio SDK – search, features, scoring, and ranking for personalized feeds.
858
+ * @example
859
+ * const config = new StudioConfig({ apiKey, commonUrl });
860
+ * const studio = new StudioV1({ config });
861
+ * const hits = await studio.search().index('farcaster-items').include().term('type', 'cast').execute();
862
+ */
863
+
864
+ // --- StudioConfig ---
865
+
866
+ export interface StudioConfigOptions {
867
+ apiKey: string;
868
+ commonUrl?: string;
869
+ servicesUrl?: {
870
+ searchService: string;
871
+ storiesService: string;
872
+ featuresService: string;
873
+ scoringService: string;
874
+ rankingService: string;
875
+ };
876
+ log?: (msg: string) => void;
877
+ show?: (results?: unknown) => void;
878
+ }
879
+
880
+ export class StudioConfig {
881
+ constructor(options: StudioConfigOptions);
882
+ }
883
+
884
+ // --- Filter (abstract base, used by Search.filter()) ---
885
+
886
+ export class Filter {
887
+ constructor(filterType: string, field: string, boost?: number | null);
888
+ }
889
+
890
+ // --- Search ---
891
+
892
+ export interface SearchHit {
893
+ _index?: string;
894
+ _id?: string;
895
+ _source?: Record<string, unknown>;
896
+ _features?: Record<string, number>;
897
+ _scores?: Record<string, number>;
898
+ _info?: Record<string, unknown>;
899
+ _ranking_score?: number;
900
+ }
901
+
902
+ export interface SearchResult {
903
+ total_hits?: number;
904
+ hits?: SearchHit[];
905
+ took_es?: number;
906
+ took_backend?: number;
907
+ max_score?: number;
908
+ }
909
+
910
+ export interface FrequentValueItem {
911
+ id: string | number;
912
+ count: number;
913
+ }
914
+
915
+ export type FrequentValuesResult = FrequentValueItem[];
916
+
917
+ export class Search {
918
+ lastCall: { endpoint: string; payload: unknown } | null;
919
+ lastResult: unknown;
920
+
921
+ index(selected_index: string): this;
922
+ size(size: number): this;
923
+ onlyIds(value?: boolean): this;
924
+ includeVectors(value?: boolean): this;
925
+ selectFields(fields: string[] | null): this;
926
+ text(text: string): this;
927
+ vector(vector: number[]): this;
928
+ esQuery(rawQuery: Record<string, unknown>): this;
929
+ sortBy(field: string, direction?: 'asc' | 'desc', field2?: string, direction2?: 'asc' | 'desc'): this;
930
+ include(): this;
931
+ exclude(): this;
932
+ boost(): this;
933
+ filter(filterInstance: Filter): this;
934
+ term(field: string, value: string | number | boolean, boost?: number | null): this;
935
+ terms(field: string, values: (string | number | boolean)[], boost?: number | null): this;
936
+ numeric(field: string, operator: string, value: number, boost?: number | null): this;
937
+ date(field: string, dateFrom?: string | null, dateTo?: string | null, boost?: number | null): this;
938
+ geo(field: string, value: unknown, boost?: number | null): this;
939
+ match(field: string, value: string, boost?: number | null): this;
940
+ isNull(field: string, boost?: number | null): this;
941
+ notNull(field: string, boost?: number | null): this;
942
+ custom(field: string, value: unknown, boost?: number | null): this;
943
+ groupBoost(
944
+ lookup_index: string,
945
+ field: string,
946
+ value: unknown,
947
+ group: string,
948
+ min_boost?: number | null,
949
+ max_boost?: number | null,
950
+ n?: number | null
951
+ ): this;
952
+ termsLookup(
953
+ lookup_index: string,
954
+ field: string,
955
+ value: unknown,
956
+ path: string,
957
+ boost?: number | null
958
+ ): this;
959
+ consoleAccount(field: string, value: unknown, path: string, boost?: number | null): this;
960
+ execute(): Promise<SearchHit[]>;
961
+ frequentValues(field: string, size?: number): Promise<FrequentValuesResult>;
962
+ lookup(docId: string): Promise<unknown>;
963
+ log(string: string): void;
964
+ show(results?: unknown): void;
965
+ }
966
+
967
+ // --- Features ---
968
+
969
+ export interface FeaturesResult {
970
+ features?: Record<string, Record<string, Record<string, number>>>;
971
+ scores?: Record<string, Record<string, Record<string, number>>>;
972
+ info?: Record<string, Record<string, Record<string, unknown>>>;
973
+ took_backend?: number;
974
+ hit_rate?: number;
975
+ item_embed_rate?: number;
976
+ [key: string]: unknown;
977
+ }
978
+
979
+ export class Features {
980
+ lastCall: { endpoint: string; payload: unknown } | null;
981
+ lastResult: unknown;
982
+
983
+ version(v: string): this;
984
+ items(items: Array<{ index: string; id: string }>): this;
985
+ user(index: string, userId: string): this;
986
+ execute(): Promise<FeaturesResult>;
987
+ log(string: string): void;
988
+ show(results?: unknown): void;
989
+ }
990
+
991
+ // --- Scoring ---
992
+
993
+ export class Scoring {
994
+ lastCall: { endpoint: string; payload: unknown } | null;
995
+ lastResult: unknown;
996
+
997
+ model(endpoint: string): this;
998
+ userId(userId: string): this;
999
+ itemIds(itemIds: string[]): this;
1000
+ execute(): Promise<string[]>;
1001
+ log(string: string): void;
1002
+ show(results?: unknown): void;
1003
+ }
1004
+
1005
+ // --- Ranking ---
1006
+
1007
+ export interface RankingItem {
1008
+ item_id: string;
1009
+ score: number;
1010
+ }
1011
+
1012
+ export interface RankingResult {
1013
+ items: RankingItem[];
1014
+ [key: string]: unknown;
1015
+ }
1016
+
1017
+ export class Ranking {
1018
+ lastCall: { endpoint: string; payload: unknown } | null;
1019
+ lastResult: unknown;
1020
+
1021
+ sortingMethod(x: 'sort' | 'linear' | 'mix'): this;
1022
+ sortBy(
1023
+ field: string,
1024
+ direction?: 'asc' | 'desc',
1025
+ field2?: string,
1026
+ direction2?: 'asc' | 'desc'
1027
+ ): this;
1028
+ weight(field: string, w: number): this;
1029
+ mix(field: string, direction: 'asc' | 'desc', percentage: number): this;
1030
+ diversity(method: 'fields' | 'semantic'): this;
1031
+ fields(arrayOrItem: string | string[]): this;
1032
+ horizon(n: number): this;
1033
+ lambda(value: number): this;
1034
+ limitByField(): this;
1035
+ every(n: number): this;
1036
+ limit(field: string, max: number): this;
1037
+ candidates(candidates: SearchHit[]): this;
1038
+ execute(): Promise<RankingResult>;
1039
+ log(string: string): void;
1040
+ show(results?: unknown): void;
1041
+ }
1042
+
1043
+ // --- Studio (main client) ---
1044
+
1045
+ export interface StudioOptions {
1046
+ config?: StudioConfig;
1047
+ apiKey?: string;
1048
+ commonUrl?: string;
1049
+ servicesUrl?: StudioConfigOptions['servicesUrl'];
1050
+ log?: (msg: string) => void;
1051
+ show?: (results?: unknown) => void;
1052
+ origin?: string;
1053
+ }
1054
+
1055
+ export class Studio {
1056
+ constructor(options: StudioOptions);
1057
+
1058
+ version(): string;
1059
+ forUser(index: string, userId: string): void;
1060
+ search(): Search;
1061
+ frequentValues(index: string, field: string, size?: number): Promise<FrequentValuesResult>;
1062
+ addCandidates(array: SearchHit[]): void;
1063
+ features(version?: string): Features;
1064
+ addFeatures(featuresResult: FeaturesResult): void;
1065
+ scoring(): Scoring;
1066
+ addScores(scoringResult: Array<{ id: string; score: number }>, scoringKey: string): void;
1067
+ ranking(): Ranking;
1068
+ addRanking(rankingResult: { items?: RankingItem[] }): void;
1069
+ log(string: string): void;
1070
+ show(results?: SearchHit[]): void;
1071
+ getFeed(): SearchHit[];
1072
+ }
1073
+
1074
+ // --- Main export ---
1075
+
1076
+ export const StudioV1: typeof Studio;
1077
+ ```
1078
+
1079
+ ### README.md
1080
+ ```md
1081
+ # mbd-studio-sdk
1082
+
1083
+ SDK for MBD Studio backend services — search, features, scoring, and ranking.
1084
+
1085
+ ## Install
1086
+
1087
+ ```bash
1088
+ npm install mbd-studio-sdk
1089
+ ```
1090
+
1091
+ ## Setup
1092
+
1093
+ ```javascript
1094
+ import { StudioConfig, StudioV1 } from 'mbd-studio-sdk';
1095
+
1096
+ const config = new StudioConfig({ apiKey: 'YOUR_API_KEY' });
1097
+ const mbd = new StudioV1({ config });
1098
+ ```
1099
+
1100
+ ## Usage
1101
+
1102
+ ### Set the target user for personalization
1103
+
1104
+ ```javascript
1105
+ const polymarketWallet = '0x123...';
1106
+ mbd.forUser("polymarket-wallets", polymarketWallet);
1107
+ ```
1108
+
1109
+ ### Generate candidates
1110
+
1111
+ Search your mbd indices using inclide/exclude filters and boosting options.
1112
+
1113
+ ```javascript
1114
+ const candidates = await mbd.search()
1115
+ .index("polymarket-items")
1116
+ .includeVectors(true)
1117
+ .include()
1118
+ .numeric("volume_1wk", ">=", 10000)
1119
+ .exclude()
1120
+ .term("closed", true)
1121
+ .term("price_under05_or_over95", true)
1122
+ .boost()
1123
+ .groupBoost("polymarket-wallets", "ai_labels_med", polymarketWallet, "label", 1, 5, 10)
1124
+ .groupBoost("polymarket-wallets", "tags", polymarketWallet, "tag", 1, 5, 10)
1125
+ .execute();
1126
+ ```
1127
+
1128
+ ### Add candidates to current context
1129
+
1130
+ Attach the search results to the SDK so later steps can use them.
1131
+
1132
+ ```javascript
1133
+ mbd.addCandidates(candidates);
1134
+ ```
1135
+
1136
+ ### Enrich your data
1137
+
1138
+ Fetch features (signals, metadata) for each candidate.
1139
+
1140
+ ```javascript
1141
+ const features = await mbd.features("v1")
1142
+ .execute();
1143
+ mbd.addFeatures(features);
1144
+ ```
1145
+
1146
+ ### Run predictive and reranking AI models
1147
+
1148
+ Score candidates with ML models for relevance or reranking.
1149
+
1150
+ ```javascript
1151
+ const scores = await mbd.scoring()
1152
+ .model("/scoring/ranking_model/polymarket-rerank-v1")
1153
+ .execute();
1154
+ mbd.addScores(scores, "rerank_polymkt1");
1155
+ ```
1156
+
1157
+ ### Combine all the data into final recommendations
1158
+
1159
+ Merge signals and produce the final ranked list with diversity and limits.
1160
+
1161
+ ```javascript
1162
+ const ranking = await mbd.ranking()
1163
+ .sortingMethod('mix')
1164
+ .mix("topic_score", 'desc', 40)
1165
+ .mix("user_affinity_score", 'desc', 40)
1166
+ .mix("rerank_polymkt1", 'desc', 20)
1167
+ .diversity('semantic')
1168
+ .lambda(0.5)
1169
+ .horizon(20)
1170
+ .limitByField()
1171
+ .every(10)
1172
+ .limit("cluster_1", 1)
1173
+ .execute();
1174
+ mbd.addRanking(ranking);
1175
+ ```
1176
+
1177
+ ## API
1178
+
1179
+ | Method | Description |
1180
+ |--------|-------------|
1181
+ | `forUser(index, userId)` | Set user context for personalization |
1182
+ | `search()` | Build and run a search query |
1183
+ | `frequentValues(index, field, size?)` | Fetch frequent values in an index/field (default size: 25) |
1184
+ | `addCandidates(array)` | Add search hits to the current context |
1185
+ | `features(version)` | Fetch features for candidates |
1186
+ | `addFeatures(result)` | Attach features to candidates |
1187
+ | `scoring()` | Run scoring/reranking models |
1188
+ | `addScores(result, key)` | Attach model scores to candidates |
1189
+ | `ranking()` | Produce final ranked recommendations |
1190
+ | `addRanking(result)` | Attach ranking scores to candidates |
1191
+
1192
+ ## Useful links
1193
+
1194
+ - **Examples:** [https://github.com/ZKAI-Network/mbd_studio_demo](https://github.com/ZKAI-Network/mbd_studio_demo)
1195
+ - **Embed Studio webapp:** [https://api.mbd.xyz/v3/studio/frontend/](https://api.mbd.xyz/v3/studio/frontend/)
1196
+ ```
1197
+
1198
+ ### llms.prompt.txt
1199
+ ```text
1200
+ In @ds_frontend/packages/mbd-studio-sdk/llms.txt, concatenate all the source code in @ds_frontend/packages/mbd-studio-sdk
1201
+ and prepare it to be used by AI coding agents.
1202
+
1203
+ * Introduction:
1204
+ overall description of the sdk, entry points and typical flows.
1205
+
1206
+ * Data catalog:
1207
+ study the frontend in @ds_frontend/app/src and enumerate available indices for searching,
1208
+ and in each one, the different fields and filter types that can be used for filtering or boosting.
1209
+ For kalshi-items, include tags, series_category, series_tags, status, ticker, and event_id.
1210
+
1211
+ # Filter types:
1212
+ enumerate the available filter types and provide examples on how to use them.
1213
+ Use the implementation details in @ds_search/backend/candidate_generation to understand exactly how the filters work under the hood.
1214
+ For numeric filters, make sure you list the available operators.
1215
+ For groupBoost filter, make sure you explain how it works and document it enough to be used properly.
1216
+ In general, document all the filters so that the SDK consumers don't need to guess how to use them and which options are available.
1217
+
1218
+ * FAQ:
1219
+ Add useful tips that can be useful for consuming the sdk or debugging.
1220
+
1221
+ * Source code:
1222
+ Decide on the best order to present the files to optimize LLMs performance,
1223
+ Then dump the complete source code of the SDK, making it as compact as possible.
1224
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mbd-studio-sdk",
3
- "version": "4.6.4",
3
+ "version": "4.6.6",
4
4
  "description": "SDK for Embed Recommendation Engine APIs",
5
5
  "keywords": [
6
6
  "web3",