feat(api): My Wave sessions with a Go fallback and wave metrics (M4)
- /wave/options, POST /wave/sessions (activity, mood, seed), /next with reactions, PATCH to switch the context on the fly, DELETE - the recommender is called with an 800 ms budget; on failure the api serves a fallback wave of likes, favourite artists and random available tracks with the same dislike / recent / served filters - every served track is an impression with its source and model; wave events (context_type wave) set its outcome, reactions win - library status shows the analysis queue and 7-day wave metrics: listen-through, early skip and like rate Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ef29b85320
commit
3908814cda
13 files changed
+1811
-162
No files matched your search
@@ -809,6 +809,79 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/wave/options": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** Занятия и настроения (ключи для i18n и иконки) */
|
||||
get: operations["getWaveOptions"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/wave/sessions": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/** Начать «Мою волну» */
|
||||
post: operations["startWave"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/wave/sessions/{id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: components["parameters"]["EntityId"];
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
/** Завершить сессию волны */
|
||||
delete: operations["endWave"];
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** Сменить занятие / настроение на лету — пачка пересобирается */
|
||||
patch: operations["updateWave"];
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/wave/sessions/{id}/next": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: components["parameters"]["EntityId"];
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/** Следующая пачка с учётом реакций на выданные треки */
|
||||
post: operations["nextWave"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
@@ -1098,6 +1171,8 @@ export interface components {
|
||||
error: string | null;
|
||||
};
|
||||
LibraryStatus: {
|
||||
analysis: components["schemas"]["AnalysisStatus"];
|
||||
wave: components["schemas"]["WaveMetrics"];
|
||||
artists: number;
|
||||
albums: number;
|
||||
tracks: number;
|
||||
@@ -1306,6 +1381,64 @@ export interface components {
|
||||
ReactionInput: {
|
||||
reaction: components["schemas"]["Reaction"];
|
||||
};
|
||||
WaveOption: {
|
||||
/** @example running */
|
||||
key: string;
|
||||
/** @description Имя иконки Material Symbols */
|
||||
icon: string;
|
||||
};
|
||||
WaveOptions: {
|
||||
activities: components["schemas"]["WaveOption"][];
|
||||
moods: components["schemas"]["WaveOption"][];
|
||||
};
|
||||
WaveContext: {
|
||||
activity?: string | null;
|
||||
mood?: string | null;
|
||||
};
|
||||
WaveStart: {
|
||||
activity?: string | null;
|
||||
mood?: string | null;
|
||||
seed?: {
|
||||
/** @enum {string} */
|
||||
type: "track" | "album" | "artist";
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
WaveFeedback: {
|
||||
/** Format: uuid */
|
||||
track_id: string;
|
||||
/** @enum {string} */
|
||||
outcome: "complete" | "skip" | "skip_early" | "like" | "dislike";
|
||||
};
|
||||
WaveNext: {
|
||||
feedback?: components["schemas"]["WaveFeedback"][];
|
||||
};
|
||||
WaveBatch: {
|
||||
/** Format: uuid */
|
||||
session_id: string;
|
||||
activity: string | null;
|
||||
mood: string | null;
|
||||
tracks: components["schemas"]["Track"][];
|
||||
/** @description Рекомендатель недоступен — пачка собрана упрощённо (лайки, любимые исполнители) */
|
||||
fallback: boolean;
|
||||
};
|
||||
AnalysisStatus: {
|
||||
queued: number;
|
||||
running: number;
|
||||
done: number;
|
||||
failed: number;
|
||||
analyzer_ver: string | null;
|
||||
};
|
||||
/** @description Метрики волны за 7 дней */
|
||||
WaveMetrics: {
|
||||
served: number;
|
||||
listen_through_rate: number | null;
|
||||
early_skip_rate: number | null;
|
||||
/** @description Лайков на 100 треков */
|
||||
like_rate: number | null;
|
||||
sessions: number;
|
||||
};
|
||||
Session: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
@@ -2580,4 +2713,125 @@ export interface operations {
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
getWaveOptions: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Варианты */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveOptions"];
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
startWave: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveStart"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Сессия и первая пачка */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveBatch"];
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
endWave: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: components["parameters"]["EntityId"];
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Завершена */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
updateWave: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: components["parameters"]["EntityId"];
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveContext"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Новая пачка */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveBatch"];
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
nextWave: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: components["parameters"]["EntityId"];
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveNext"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Пачка */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["WaveBatch"];
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user