From 7b808540967448868f0cb6b4c555bc7b911d58d9 Mon Sep 17 00:00:00 2001 From: Dylan Audius Date: Fri, 22 May 2026 15:39:11 -0700 Subject: [PATCH 1/2] feat(for-you): switch useForYouFeed to dedicated /users/{id}/feed/for-you endpoint The endpoint was re-introduced in AudiusProject/api#817 with a lean 3-source pipeline (in-network, trending, underground) + linear ranking + diversity pass. Previous implementation fell back to the generic recommended-tracks endpoint; this wires the hook to the purpose-built one. Changes: - Add GetUserFeedForYouRequest interface + getUserFeedForYou method to the generated UsersApi (mirrors the pattern of getUserRecommendedTracks) - Update useForYouFeed to call getUserFeedForYou, dropping the now-unused timeRange param Co-Authored-By: Claude Sonnet 4.6 --- .../api/tan-query/lineups/useForYouFeed.ts | 15 ++--- .../api/generated/default/apis/UsersApi.ts | 63 +++++++++++++++++++ 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/packages/common/src/api/tan-query/lineups/useForYouFeed.ts b/packages/common/src/api/tan-query/lineups/useForYouFeed.ts index 6e2fee98dae..9ff6b880c49 100644 --- a/packages/common/src/api/tan-query/lineups/useForYouFeed.ts +++ b/packages/common/src/api/tan-query/lineups/useForYouFeed.ts @@ -1,4 +1,4 @@ -import { Id, GetUserRecommendedTracksTimeRangeEnum } from '@audius/sdk' +import { Id } from '@audius/sdk' import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query' import { userTrackMetadataFromSDK } from '~/adapters/track' @@ -24,11 +24,9 @@ export const getForYouFeedQueryKey = (userId: ID | null | undefined) => { } /** - * "For You" feed for the Feed page. Backed by the same recommended-tracks - * endpoint that powers the Explore page's For You section - * (`GET /v1/users/{id}/recommended-tracks`). The dedicated - * `/feed/for-you` endpoint has been retired in favor of consolidating on - * the recommended-tracks source — see the API repo for the deletion. + * "For You" feed for the Feed page. Backed by the dedicated + * `GET /v1/users/{id}/feed/for-you` endpoint — a lean 3-source pipeline + * (in-network, trending, underground) with linear ranking and diversity pass. */ export const useForYouFeed = ( { @@ -57,12 +55,11 @@ export const useForYouFeed = ( const isFirstPage = pageParam === 0 const currentPageSize = isFirstPage ? initialPageSize : loadMorePageSize const sdk = await audiusSdk() - const { data = [] } = await sdk.users.getUserRecommendedTracks({ + const { data = [] } = await sdk.users.getUserFeedForYou({ id: Id.parse(currentUserId), userId: Id.parse(currentUserId), limit: currentPageSize, - offset: pageParam, - timeRange: GetUserRecommendedTracksTimeRangeEnum.Week + offset: pageParam }) const tracks = primeTrackData({ diff --git a/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts b/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts index db501182c5d..00c0726eacd 100644 --- a/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts +++ b/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts @@ -744,6 +744,14 @@ export interface GetUserRecommendedTracksRequest { timeRange?: GetUserRecommendedTracksTimeRangeEnum; } +export interface GetUserFeedForYouRequest { + id: string; + offset?: number; + limit?: number; + userId?: string; + maxPerArtist?: number; +} + export interface GetUserTracksDownloadCountRequest { id: string; } @@ -4172,6 +4180,61 @@ export class UsersApi extends runtime.BaseAPI { return await response.value(); } + /** + * Gets the personalized For You feed for a user. + * Twitter-style multi-source pipeline — candidate retrieval (in-network, + * trending, underground) → linear ranking → diversity pass. + */ + async getUserFeedForYouRaw(params: GetUserFeedForYouRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (params.id === null || params.id === undefined) { + throw new runtime.RequiredError('id', 'Required parameter params.id was null or undefined when calling getUserFeedForYou.'); + } + + const queryParameters: any = {}; + + if (params.offset !== undefined) { + queryParameters['offset'] = params.offset; + } + + if (params.limit !== undefined) { + queryParameters['limit'] = params.limit; + } + + if (params.userId !== undefined) { + queryParameters['user_id'] = params.userId; + } + + if (params.maxPerArtist !== undefined) { + queryParameters['max_per_artist'] = params.maxPerArtist; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (!headerParameters["Authorization"] && this.configuration && this.configuration.accessToken) { + const token = await this.configuration.accessToken("OAuth2", ["read"]); + if (token) { + headerParameters["Authorization"] = token; + } + } + + const response = await this.request({ + path: `/users/{id}/feed/for-you`.replace(`{${"id"}}`, encodeURIComponent(String(params.id))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => TracksFromJSON(jsonValue)); + } + + /** + * Gets the personalized For You feed for a user. + */ + async getUserFeedForYou(params: GetUserFeedForYouRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getUserFeedForYouRaw(params, initOverrides); + return await response.value(); + } + /** * @hidden * Gets User IDs from any Ethereum wallet address or Solana account address associated with their Audius account. From d6c3742e0cdb53b7b791df32b3117be5260e85a1 Mon Sep 17 00:00:00 2001 From: Dylan Audius Date: Fri, 22 May 2026 15:59:28 -0700 Subject: [PATCH 2/2] fix(sdk): regenerate UsersApi for /users/{id}/feed/for-you instead of hand-editing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prior commit on this branch hand-added getUserFeedForYou to the generated UsersApi.ts, which is the wrong layer — those files are produced by openapi-generator from the API repo's swagger spec. Manual edits get wiped on the next codegen run and the method name doesn't match the spec's operationId. This re-runs `node ./src/sdk/api/generator/gen.js --spec ` against the swagger from AudiusProject/api main (the for-you endpoint isn't in prod swagger yet, so --env prod can't be used until it deploys). The generated method is named `getUserForYouFeed` (from operationId "Get User For You Feed"), not `getUserFeedForYou` as the hand-edit assumed — hook updated to match. Co-Authored-By: Claude Opus 4.7 --- .../api/tan-query/lineups/useForYouFeed.ts | 2 +- .../api/generated/default/apis/UsersApi.ts | 45 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/common/src/api/tan-query/lineups/useForYouFeed.ts b/packages/common/src/api/tan-query/lineups/useForYouFeed.ts index 9ff6b880c49..9a0a16b864d 100644 --- a/packages/common/src/api/tan-query/lineups/useForYouFeed.ts +++ b/packages/common/src/api/tan-query/lineups/useForYouFeed.ts @@ -55,7 +55,7 @@ export const useForYouFeed = ( const isFirstPage = pageParam === 0 const currentPageSize = isFirstPage ? initialPageSize : loadMorePageSize const sdk = await audiusSdk() - const { data = [] } = await sdk.users.getUserFeedForYou({ + const { data = [] } = await sdk.users.getUserForYouFeed({ id: Id.parse(currentUserId), userId: Id.parse(currentUserId), limit: currentPageSize, diff --git a/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts b/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts index 00c0726eacd..729b339d9c8 100644 --- a/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts +++ b/packages/sdk/src/sdk/api/generated/default/apis/UsersApi.ts @@ -687,6 +687,14 @@ export interface GetUserFeedRequest { encodedDataSignature?: string; } +export interface GetUserForYouFeedRequest { + id: string; + limit?: number; + offset?: number; + maxPerArtist?: number; + userId?: string; +} + export interface GetUserIDsByAddressesRequest { address: Array; } @@ -744,14 +752,6 @@ export interface GetUserRecommendedTracksRequest { timeRange?: GetUserRecommendedTracksTimeRangeEnum; } -export interface GetUserFeedForYouRequest { - id: string; - offset?: number; - limit?: number; - userId?: string; - maxPerArtist?: number; -} - export interface GetUserTracksDownloadCountRequest { id: string; } @@ -4181,33 +4181,33 @@ export class UsersApi extends runtime.BaseAPI { } /** - * Gets the personalized For You feed for a user. - * Twitter-style multi-source pipeline — candidate retrieval (in-network, - * trending, underground) → linear ranking → diversity pass. + * @hidden + * Returns a personalized For You feed for the user identified in the path. Twitter-style multi-source pipeline — candidate retrieval (in-network, trending, underground) → linear ranking (recency decay × engagement × social affinity, weighted by source) → diversity (per-artist cap + consecutive-same-artist lookahead). + * Get For You feed for user */ - async getUserFeedForYouRaw(params: GetUserFeedForYouRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getUserForYouFeedRaw(params: GetUserForYouFeedRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { if (params.id === null || params.id === undefined) { - throw new runtime.RequiredError('id', 'Required parameter params.id was null or undefined when calling getUserFeedForYou.'); + throw new runtime.RequiredError('id','Required parameter params.id was null or undefined when calling getUserForYouFeed.'); } const queryParameters: any = {}; - if (params.offset !== undefined) { - queryParameters['offset'] = params.offset; - } - if (params.limit !== undefined) { queryParameters['limit'] = params.limit; } - if (params.userId !== undefined) { - queryParameters['user_id'] = params.userId; + if (params.offset !== undefined) { + queryParameters['offset'] = params.offset; } if (params.maxPerArtist !== undefined) { queryParameters['max_per_artist'] = params.maxPerArtist; } + if (params.userId !== undefined) { + queryParameters['user_id'] = params.userId; + } + const headerParameters: runtime.HTTPHeaders = {}; if (!headerParameters["Authorization"] && this.configuration && this.configuration.accessToken) { @@ -4228,10 +4228,11 @@ export class UsersApi extends runtime.BaseAPI { } /** - * Gets the personalized For You feed for a user. + * Returns a personalized For You feed for the user identified in the path. Twitter-style multi-source pipeline — candidate retrieval (in-network, trending, underground) → linear ranking (recency decay × engagement × social affinity, weighted by source) → diversity (per-artist cap + consecutive-same-artist lookahead). + * Get For You feed for user */ - async getUserFeedForYou(params: GetUserFeedForYouRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - const response = await this.getUserFeedForYouRaw(params, initOverrides); + async getUserForYouFeed(params: GetUserForYouFeedRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getUserForYouFeedRaw(params, initOverrides); return await response.value(); }