戰(zhàn)指南:為 AI Agent 接入 Spotify Web API)
Corsair Spotify 插件實(shí)戰(zhàn)指南為 AI Agent 接入 Spotify Web API【免費(fèi)下載鏈接】corsairConnect your users to their apps項(xiàng)目地址: https://gitcode.com/GitHub_Trending/corsa/corsair導(dǎo)讀corsair-dev/spotify是 Corsair 生態(tài)中的 Spotify 集成插件它將 Spotify Web API 的能力封裝為 30 個(gè)類型安全的端點(diǎn)albums、artists、player、playlists、tracks 等并內(nèi)置 OAuth 2.0 / API Key / Managed OAuth 三種認(rèn)證模式、限流重試與錯(cuò)誤處理、示例 Webhook 簽名校驗(yàn)。讀完本文你將掌握如何在 Corsair 應(yīng)用中安裝、配置并調(diào)用該插件理解其端點(diǎn)權(quán)限模型、認(rèn)證流程與底層請(qǐng)求實(shí)現(xiàn)能直接將其接入自己的 AI Agent 應(yīng)用。插件概覽該插件位于倉(cāng)庫(kù) packages/spotify發(fā)布名為corsair-dev/spotify許可證為 Apache-2.0。插件核心入口是 index.ts 中導(dǎo)出的spotify()工廠函數(shù)它實(shí)現(xiàn)了 Corsair 的CorsairPlugin接口對(duì)外暴露idspotify插件唯一標(biāo)識(shí)schema數(shù)據(jù)實(shí)體 Schematracks、albums、artists、playlists 等endpoints按命名空間分組的端點(diǎn)樹(shù)webhooks示例 Webhook 處理器endpointMeta每個(gè)端點(diǎn)的風(fēng)險(xiǎn)級(jí)別read / write元數(shù)據(jù)供 MCP 權(quán)限系統(tǒng)決定 allow / deny / require_approvaloauthConfigOAuth 2.0 授權(quán)端點(diǎn)、token 端點(diǎn)與 scope 列表keyBuilder按認(rèn)證類型從 Key Manager 或 Hub 獲取訪問(wèn)憑證errorHandlers限流、鑒權(quán)、權(quán)限、兜底四類錯(cuò)誤處理器。安裝使用 pnpm倉(cāng)庫(kù)采用 pnpm workspace 管理見(jiàn)根目錄 pnpm-workspace.yamlpnpm add corsair-dev/spotify從 package.json 可以看到該插件以corsair 0.1.120和zod ^4.1.13作為 peerDependencies需要與 Corsair 核心庫(kù)配合使用??焖俳尤胱?cè)插件并調(diào)用端點(diǎn)在 Corsair 應(yīng)用中通過(guò)createCorsair()注冊(cè)插件隨后即可使用類型安全的綁定端點(diǎn)import { createCorsair } from corsair; import { spotify } from corsair-dev/spotify; const corsair createCorsair({ plugins: [ spotify({ authType: oauth_2, // 默認(rèn)值即為 oauth_2 }), ], }); // 綁定后的端點(diǎn)可通過(guò)命名空間訪問(wèn)例如 // corsair.spotify.player.getCurrentlyPlaying() // corsair.spotify.tracks.search({ q: lofi, limit: 10 })spotify()工廠函數(shù)index.ts會(huì)把傳入的 options 與默認(rèn)值合并authType未指定時(shí)默認(rèn)為oauth_2。插件公開(kāi)的 options 類型SpotifyPluginOptions支持以下字段配置項(xiàng)類型說(shuō)明authTypeoauth_2 \| api_key \| managed認(rèn)證方式默認(rèn)oauth_2keystring直接提供 API Key繞過(guò) Key ManagerwebhookSecretstringWebhook 簽名校驗(yàn)密鑰hooksInternalSpotifyPlugin[hooks]生命周期鉤子webhookHooksInternalSpotifyPlugin[webhookHooks]Webhook 處理鉤子errorHandlersCorsairErrorHandler自定義錯(cuò)誤處理器與內(nèi)置處理器合并permissionsPluginPermissionsConfigtypeof spotifyEndpointsNested權(quán)限配置使用端點(diǎn)樹(shù)的點(diǎn)分路徑覆蓋默認(rèn)權(quán)限非法路徑會(huì)觸發(fā)類型錯(cuò)誤權(quán)限配置示例permissions使用從端點(diǎn)樹(shù)推導(dǎo)出的點(diǎn)分路徑如player.pause、playlists.removeItem編譯期即可校驗(yàn)路徑合法性spotify({ authType: oauth_2, permissions: { player.pause: allow, player.setVolume: require_approval, playlists.removeItem: deny, }, });風(fēng)險(xiǎn)級(jí)別元數(shù)據(jù)定義在 index.ts 的spotifyEndpointMeta中所有查詢類操作為read播放控制暫停、恢復(fù)、切歌、調(diào)音量、入隊(duì)、開(kāi)始播放與歌單增刪、創(chuàng)建為write。端點(diǎn)總覽插件覆蓋 Spotify Web API 的核心資源READMEpackages/spotify/README.md中的完整端點(diǎn)清單如下OperationOperation IDRiskDescriptionalbums.getspotify.api.albums.getreadGet info about an albumalbums.getNewReleasesspotify.api.albums.getNewReleasesreadGet new album releasesalbums.getTracksspotify.api.albums.getTracksreadGet tracks from an albumalbums.searchspotify.api.albums.searchreadSearch for albumsartists.getspotify.api.artists.getreadGet info about an artistartists.getAlbumsspotify.api.artists.getAlbumsreadGet albums by an artistartists.getRelatedArtistsspotify.api.artists.getRelatedArtistsreadGet artists related to an artistartists.getTopTracksspotify.api.artists.getTopTracksreadGet top tracks for an artistartists.searchspotify.api.artists.searchreadSearch for artistslibrary.getLikedTracksspotify.api.library.getLikedTracksreadGet the current users liked tracksmyData.getFollowedArtistsspotify.api.myData.getFollowedArtistsreadGet artists followed by the current userplayer.addToQueuespotify.api.player.addToQueuewriteAdd a track to the playback queueplayer.getCurrentlyPlayingspotify.api.player.getCurrentlyPlayingreadGet the currently playing trackplayer.getRecentlyPlayedspotify.api.player.getRecentlyPlayedreadGet recently played tracksplayer.pausespotify.api.player.pausewritePause playbackplayer.resumespotify.api.player.resumewriteResume playbackplayer.setVolumespotify.api.player.setVolumewriteSet the playback volumeplayer.skipToNextspotify.api.player.skipToNextwriteSkip to the next trackplayer.skipToPreviousspotify.api.player.skipToPreviouswriteSkip to the previous trackplayer.startPlaybackspotify.api.player.startPlaybackwriteStart playback of specified contentplaylists.addItemspotify.api.playlists.addItemwriteAdd a track to a playlistplaylists.createspotify.api.playlists.createwriteCreate a new playlistplaylists.getspotify.api.playlists.getreadGet info about a playlistplaylists.getTracksspotify.api.playlists.getTracksreadGet tracks in a playlistplaylists.getUserPlaylistsspotify.api.playlists.getUserPlaylistsreadGet the current users playlistsplaylists.removeItemspotify.api.playlists.removeItemwriteRemove a track from a playlistplaylists.searchspotify.api.playlists.searchreadSearch for playliststracks.getspotify.api.tracks.getreadGet info about a tracktracks.getAudioFeaturesspotify.api.tracks.getAudioFeaturesreadGet audio features for a tracktracks.searchspotify.api.tracks.searchreadSearch for tracks這些端點(diǎn)按命名空間組織在 endpoints/index.ts 中并映射為Albums、Artists、Library、MyData、Player、Playlists、Tracks七個(gè)對(duì)象。端點(diǎn)分組詳解與輸入?yún)?shù)每個(gè)端點(diǎn)的輸入/輸出都使用 zod 定義endpoints/types.ts運(yùn)行時(shí)校驗(yàn) 編譯期類型推導(dǎo)雙保險(xiǎn)。以下按資源分組說(shuō)明關(guān)鍵參數(shù)。專輯 Albums端點(diǎn)必填參數(shù)可選參數(shù)底層 APIalbums.getidmarketGET /albums/{id}albums.getNewReleases—limit、offset、countryGET /browse/new-releasesalbums.getTracksidlimit、offset、marketGET /albums/{id}/tracksalbums.searchqtype默認(rèn)album、market、limit、offsetGET /search實(shí)現(xiàn)細(xì)節(jié)endpoints/albums.tsalbums.get成功后會(huì)嘗試把結(jié)果upsertByEntityId寫入數(shù)據(jù)庫(kù)的albums表若ctx.db.albums存在失敗僅告警不中斷請(qǐng)求每個(gè)端點(diǎn)完成后都會(huì)通過(guò)logEventFromContext記錄一條completed事件如spotify.albums.get。藝人 Artists端點(diǎn)必填參數(shù)可選參數(shù)artists.getid—artists.getAlbumsidinclude_groups、market、limit、offsetartists.getRelatedArtistsid—artists.getTopTracksidmarketartists.searchqtype默認(rèn)artist、market、limit、offset用戶數(shù)據(jù) Library / MyData端點(diǎn)必填參數(shù)可選參數(shù)library.getLikedTracks—limit、offset、marketmyData.getFollowedArtists—type默認(rèn)artist、limit、after游標(biāo)播放控制 Player端點(diǎn)必填參數(shù)可選參數(shù)HTTP 方法與底層 APIplayer.addToQueueuridevice_idPOST /me/player/queueplayer.getCurrentlyPlaying—market、additional_typesGET /me/player/currently-playingplayer.getRecentlyPlayed—limit、after、before毫秒時(shí)間戳GET /me/player/recently-playedplayer.pause—device_idPUT /me/player/pauseplayer.resume—device_idPUT /me/player/playplayer.setVolumevolume_percent0–100device_idPUT /me/player/volumeplayer.skipToNext—device_idPOST /me/player/nextplayer.skipToPrevious—device_idPOST /me/player/previousplayer.startPlayback—device_id、context_uri、uris[]、offset{position\|uri}、position_msPUT /me/player/playbody 傳參注意見(jiàn) endpoints/player.tsplayer.resume與player.startPlayback都調(diào)用PUT /me/player/play區(qū)別在于startPlayback會(huì)把input作為請(qǐng)求體發(fā)送用于指定播放內(nèi)容、位置resume僅攜帶device_id查詢參數(shù)恢復(fù)播放。歌單 Playlists端點(diǎn)必填參數(shù)可選參數(shù)playlists.addItemplaylist_id、uris[]positionplaylists.createuser_id、namepublic、collaborative、descriptionplaylists.getplaylist_idmarket、fields、additional_typesplaylists.getTracksplaylist_idmarket、fields、limit、offset、additional_typesplaylists.getUserPlaylists—user_id、limit、offsetplaylists.removeItemplaylist_id、tracks[{uri}]snapshot_idplaylists.searchqtype默認(rèn)playlist、market、limit、offsetplaylists.addItem與playlists.removeItem的響應(yīng)均返回snapshot_id可用于樂(lè)觀并發(fā)控制。單曲 Tracks端點(diǎn)必填參數(shù)可選參數(shù)tracks.getidmarkettracks.getAudioFeaturesid—tracks.searchqtype默認(rèn)track、market、limit、offsettracks.getAudioFeatures返回AudioFeatures對(duì)象包含danceability、energy、key、loudness、valence、tempo、time_signature等音樂(lè)特征字段適合做推薦、歌單聚類等場(chǎng)景。認(rèn)證OAuth 2.0 / API Key / Managed OAuth插件支持三種認(rèn)證方式通過(guò)authType選擇README 說(shuō)明默認(rèn) OAuth 2.0OAuth 2.0默認(rèn)oauthConfigindex.ts內(nèi)置了 Spotify 的完整 OAuth 配置授權(quán)端點(diǎn)https://accounts.spotify.com/authorizeToken 端點(diǎn)https://accounts.spotify.com/api/tokenToken 認(rèn)證方式basicClient ID/Secret 走 HTTP Basic需要注冊(cè)重定向 URIrequiresRegisteredRedirect: true附加參數(shù)show_dialog: true每次授權(quán)都顯示確認(rèn)對(duì)話框默認(rèn)申請(qǐng)的 scope 覆蓋插件全部能力user-read-private, user-read-email, user-read-playback-state, user-modify-playback-state, user-read-currently-playing, user-read-recently-played, user-library-read, user-library-modify, user-follow-read, user-follow-modify, playlist-read-private, playlist-read-collaborative, playlist-modify-public, playlist-modify-private在keyBuilder中oauth_2路徑通過(guò)getOAuthAccessToken(ctx, { plugin: spotify, tokenUrl, tokenAuthMethod: basic })獲取訪問(wèn)令牌。API Keyapi_key模式通過(guò)ctx.keys.get_api_key()從 Key Manager 獲取憑證若在插件 options 中直接傳key則優(yōu)先使用該值keyBuilder的優(yōu)先級(jí)順序?yàn)橹苯?options → Key Manager。缺失時(shí)拋出AuthMissingError(spotify, api_key)。Managed OAuthHub 托管managed模式要求 Corsair 實(shí)例配置了hub否則拋出錯(cuò)誤[auth-missing:spotify:managed]: Hub config is required for managed auth. Pass hub: { ... } to createCorsair().。該模式下通過(guò)getManagedAccessToken(managedContext)獲取 Hub 托管的訪問(wèn)令牌并用attachManagedRefreshAuth注入自動(dòng)刷新邏輯相關(guān)能力來(lái)自corsair/hub模塊。請(qǐng)求層的 401 自動(dòng)刷新除keyBuilder外請(qǐng)求層還有兜底刷新機(jī)制client.ts 中的makeAuthenticatedSpotifyRequest在收到 401 且上下文存在_refreshAuth時(shí)會(huì)先取新令牌再重放一次請(qǐng)求避免偶發(fā) token 過(guò)期導(dǎo)致調(diào)用失敗。底層請(qǐng)求實(shí)現(xiàn)限流、錯(cuò)誤映射與重試所有端點(diǎn)最終都收斂到 client.ts 的makeSpotifyRequestBase URL 為https://api.spotify.com/v1Authorization: Bearer token內(nèi)置限流配置SPOTIFY_RATE_LIMIT_CONFIGmaxRetries: 3、initialRetryDelay: 1000ms、指數(shù)退避backoffMultiplier: 2并識(shí)別Retry-After響應(yīng)頭統(tǒng)一把底層錯(cuò)誤包裝為SpotifyAPIError攜帶status響應(yīng)體中的error字段也會(huì)被識(shí)別并拋出。對(duì)應(yīng)的錯(cuò)誤處理器定義在 error-handlers.ts四類處理器均可被用戶的options.errorHandlers覆蓋淺合并處理器匹配條件重試策略RATE_LIMIT_ERRORHTTP 429 或rate_limited/too_many_requests/429等maxRetries: 3優(yōu)先尊重Retry-AfterAUTH_ERRORHTTP 401 或invalid_auth/unauthorized/token_expired/invalid_grant等maxRetries: 0重試無(wú)意義PERMISSION_ERRORHTTP 403 或permission_denied/forbidden/insufficient_scope等maxRetries: 0DEFAULT兜底匹配所有錯(cuò)誤maxRetries: 0數(shù)據(jù)持久化數(shù)據(jù)庫(kù)實(shí)體 Schema插件的schemaschema/index.ts定義了 6 個(gè)實(shí)體對(duì)應(yīng) schema/database.ts 中的 zod 模型實(shí)體核心字段tracksid、name、artists[]、album、duration_ms、explicit、popularity、preview_urlalbumsid、name、album_type、total_tracks、available_markets、images[]、release_dateartistsid、name、followers.total、genres[]、popularity、images[]playlistsid、name、description、public、collaborative、owner、tracks.totalplaylistItemsid、playlist_id、track_id、added_at、positionusersid、display_name、followers.total、product、uri所有實(shí)體都帶createdAt時(shí)間戳字段。如前所述albums.get等端點(diǎn)會(huì)在請(qǐng)求成功后自動(dòng)把結(jié)果寫入對(duì)應(yīng)實(shí)體表通過(guò)ctx.db.entity.upsertByEntityId形成調(diào)用即緩存的數(shù)據(jù)流。Webhook簽名校驗(yàn)與租戶匹配插件處理 1 個(gè) Webhook 事件example.example完整流程見(jiàn) webhooks事件匹配createSpotifyMatch(example)根據(jù)請(qǐng)求體中的type字段匹配事件types.ts簽名校驗(yàn)verifySpotifyWebhookSignature讀取x-spotify-signature請(qǐng)求頭用 HMAC-SHA256 對(duì)原始 body 計(jì)算簽名并通過(guò)crypto.timingSafeEqual做常量時(shí)間比較防止時(shí)序攻擊types.ts。校驗(yàn)失敗返回 401Webhook 識(shí)別插件的pluginWebhookMatcher檢查請(qǐng)求頭是否包含x-spotify-signature或spotify-webhookindex.ts租戶匹配matchSpotifyTenantWebhook直接返回null——因?yàn)?Spotify 官方并未提供公開(kāi)的 Webhook API回調(diào)負(fù)載中不包含租戶標(biāo)識(shí)見(jiàn) tenant-matcher.ts 的注釋說(shuō)明因此該插件的 Webhook 屬于示例骨架真實(shí)業(yè)務(wù)事件類型需按 types.ts 中的 TODO 注釋自行擴(kuò)展ExampleEventSchema與SpotifyWebhookOutputs。Webhook 的簽名密鑰解析順序在keyBuilder中先取options.webhookSecret否則從ctx.keys.get_webhook_signature()獲取缺失時(shí)拋出[auth-missing:spotify:webhook_signature]錯(cuò)誤。測(cè)試與驗(yàn)證插件附帶了完整的測(cè)試套件可用于驗(yàn)證行為與作為集成參考api.test.ts端點(diǎn) API 行為測(cè)試integration.test.ts與 Corsair 核心的集成測(cè)試oauth-refresh-auth.test.tsOAuth 令牌刷新與認(rèn)證流程測(cè)試webhooks/types.test.tsWebhook 類型與匹配邏輯測(cè)試。運(yùn)行測(cè)試與構(gòu)建# 在 packages/spotify 目錄下 pnpm test # jest 單元測(cè)試 pnpm typecheck # tsc --noEmit 類型檢查 pnpm build # tsc --build --force tsup 產(chǎn)出 dist小結(jié)corsair-dev/spotify為 AI Agent 應(yīng)用提供了一個(gè)開(kāi)箱即用的 Spotify 集成層30 個(gè)類型安全端點(diǎn)覆蓋搜索、播放控制與歌單管理read/write風(fēng)險(xiǎn)元數(shù)據(jù)直接對(duì)接 MCP 權(quán)限系統(tǒng)三種認(rèn)證模式適配自托管與 Hub 托管場(chǎng)景內(nèi)置限流重試、錯(cuò)誤歸一化與可選的數(shù)據(jù)庫(kù)持久化。閱讀 packages/spotify/index.ts 與 endpoints/types.ts 可以了解插件工廠與全部輸入輸出 Schema將其作為自定義 Corsair 插件開(kāi)發(fā)的范本同樣合適?!久赓M(fèi)下載鏈接】corsairConnect your users to their apps項(xiàng)目地址: https://gitcode.com/GitHub_Trending/corsa/corsair創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考