在对话窗口里听歌找歌,还能扫码逛 B站
31.3/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add littlexie1/qian-music-dsh该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · tool
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 80 处,展示前 75 条)
- 发起网络请求index.mjs:39
tool('qian_bili_status','查看当前用户自己的B站账号登录状态,不返回Cookie。',{},(_a,e)=>bili.request('status',{},e.signal)); - 发起网络请求index.mjs:41
tool('qian_bili_discover','推荐浏览或按keyword搜索B站视频,page从1开始。元信息不能替代实际观看。',{keyword:{type:'string'},page:{type:'integer'}},(a,e)=>bili.request('discover',a - 发起网络请求index.mjs:42
tool('qian_bili_info','读取B站视频详情和分P信息,支持BV、完整链接和b23.tv。',{bvid:{type:'string',required:true}},async(a,e)=>bili.request('info',{bvid:await bili.resolveI - 发起网络请求index.mjs:43
tool('qian_bili_comments','读取视频评论与热评,offset翻页。热评是外部参考,不是你看过视频的证据。',{bvid:{type:'string',required:true},offset:{type:'string'}},(a,e)=>bili.request('co - 发起网络请求index.mjs:47
tool('qian_bili_comment','按用户授权在B站视频发表评论或回复指定root/parent。text为原文;mentions_json可提供真实用户名到UID的映射。评价视频内容前先watch原生看。sync_to_dynamic可原生转发到动态;默认按本机配置。保存回执,结果 - 发起网络请求index.mjs:50
tool('qian_bili_find_user','按名字查询B站用户及真实UID,用于核对@对象。',{name:{type:'string',required:true}},(a,e)=>bili.request('find_user',a,e.signal)); - 写入本地文件index.mjs:68
tool('qian_music_listen','获取指定来源候选的实际音源并交给本主模型原生听,下一轮才能给听感。key必须来自qian_music_search。',{key:{type:'string',required:true}},async(a,e)=>{const s=await r - 读取本地文件index.mjs:68
tool('qian_music_listen','获取指定来源候选的实际音源并交给本主模型原生听,下一轮才能给听感。key必须来自qian_music_search。',{key:{type:'string',required:true}},async(a,e)=>{const s=await r - 写入本地文件index.mjs:68
tool('qian_music_listen','获取指定来源候选的实际音源并交给本主模型原生听,下一轮才能给听感。key必须来自qian_music_search。',{key:{type:'string',required:true}},async(a,e)=>{const s=await r - 删除本地文件递归index.mjs:68
tool('qian_music_listen','获取指定来源候选的实际音源并交给本主模型原生听,下一轮才能给听感。key必须来自qian_music_search。',{key:{type:'string',required:true}},async(a,e)=>{const s=await r - 写入本地文件index.mjs:68
tool('qian_music_listen','获取指定来源候选的实际音源并交给本主模型原生听,下一轮才能给听感。key必须来自qian_music_search。',{key:{type:'string',required:true}},async(a,e)=>{const s=await r - 发起网络请求client.cjs:10
async function api(path,body){if(!connection)throw Error('播放器服务尚未就绪,请重新加载DSH');const r=await fetch(connection.base+path,{method:body?'POST':'GET',head - 发起网络请求client.cjs:26
async function importFiles(event){const files=[...event.target.files];event.target.value='';let count=0;await attempt(async()=>{for(const file of file - 读取本地文件lib/config.mjs:8
export function config(){const file=join(privateRoot(),'config.json');const {musicRoomURL,...saved}=existsSync(file)?JSON.parse(readFileSync(file,'utf - 读取本地文件lib/config.mjs:8
export function config(){const file=join(privateRoot(),'config.json');const {musicRoomURL,...saved}=existsSync(file)?JSON.parse(readFileSync(file,'utf - 写入本地文件lib/config.mjs:9
export function saveConfig(value){const url=new URL(value.baseURL);if(url.protocol!=='https:'||url.username||url.password||url.search||url.hash)throw - 写入本地文件lib/config.mjs:9
export function saveConfig(value){const url=new URL(value.baseURL);if(url.protocol!=='https:'||url.username||url.password||url.search||url.hash)throw - 读取本地文件lib/config.mjs:10
export function keyConfigured(){return Boolean(process.env.QIAN_OMNI_API_KEY||process.env.DASHSCOPE_API_KEY)||existsSync(join(privateRoot(),'qwen-key. - 读取密钥环境变量lib/config.mjs:10
export function keyConfigured(){return Boolean(process.env.QIAN_OMNI_API_KEY||process.env.DASHSCOPE_API_KEY)||existsSync(join(privateRoot(),'qwen-key. - 执行外部命令固定命令lib/config.mjs:12
export function getKey(){const env=process.env.QIAN_OMNI_API_KEY||process.env.DASHSCOPE_API_KEY;if(env)return env;const file=join(privateRoot(),'qwen- - 读取本地文件lib/config.mjs:12
export function getKey(){const env=process.env.QIAN_OMNI_API_KEY||process.env.DASHSCOPE_API_KEY;if(env)return env;const file=join(privateRoot(),'qwen- - 读取本地文件lib/config.mjs:12
export function getKey(){const env=process.env.QIAN_OMNI_API_KEY||process.env.DASHSCOPE_API_KEY;if(env)return env;const file=join(privateRoot(),'qwen- - 读取密钥环境变量lib/config.mjs:12
export function getKey(){const env=process.env.QIAN_OMNI_API_KEY||process.env.DASHSCOPE_API_KEY;if(env)return env;const file=join(privateRoot(),'qwen- - 执行外部命令固定命令lib/config.mjs:13
export function saveKey(key){if(typeof key!=='string'||!key.trim())throw Error('请填写 API Key。');const r=spawnSync('pwsh',['-NoProfile','-File',join(plu - 写入本地文件lib/native.mjs:11
const c=config(),key=getKey(),root=join(privateRoot(),'uploads');await mkdir(root,{recursive:true});const cache=join(root,createHash('sha256').update( - 读取本地文件lib/native.mjs:11
const c=config(),key=getKey(),root=join(privateRoot(),'uploads');await mkdir(root,{recursive:true});const cache=join(root,createHash('sha256').update( - 读取本地文件lib/native.mjs:12
try{const old=JSON.parse(await readFile(cache,'utf8'));if(old.expires>Date.now())return old.url;}catch{} - 发起网络请求lib/native.mjs:13
const target=new URL('/api/v1/uploads',new URL(c.baseURL).origin);target.searchParams.set('action','getPolicy');target.searchParams.set('model',c.mode - 写入本地文件lib/native.mjs:15
const r=await fetch(host,{method:'POST',body:form,signal});if(!r.ok)throw Error('音视频上传失败:HTTP '+r.status);await r.arrayBuffer();const url='oss://'+obj - 发起网络请求lib/native.mjs:15
const r=await fetch(host,{method:'POST',body:form,signal});if(!r.ok)throw Error('音视频上传失败:HTTP '+r.status);await r.arrayBuffer();const url='oss://'+obj - 读取本地文件lib/native.mjs:17
export async function mediaMarker(path,signal,songKey){const absolute=resolve(path),type=mediaKind(absolute);if(!(await stat(absolute)).isFile())throw - 读取本地文件lib/providers.mjs:4
export async function importLocalSong(value){const input=value.path||value.url;if(typeof input!=='string')throw Error('需要本地文件路径');const path=await rea - 读取本地文件lib/providers.mjs:4
export async function importLocalSong(value){const input=value.path||value.url;if(typeof input!=='string')throw Error('需要本地文件路径');const path=await rea - 发起网络请求lib/providers.mjs:5
async function json(url,options={},signal){const r=await fetch(url,{...options,signal:signal?AbortSignal.any([signal,AbortSignal.timeout(15000)]):Abor - 读取本地文件lib/providers.mjs:24
if(s.source==='local'){if(!(await stat(s.localPath)).isFile())throw Error('本地音源不存在');return {...s,raw:undefined};} - 读取本地文件lib/lyrics.mjs:11
if(s.source==='local'){try{const bytes=await readFile(s.localPath.slice(0,-extname(s.localPath).length)+'.lrc');let text=new TextDecoder('utf-8').deco - 发起网络请求lib/lyrics.mjs:17
try{const r=await fetch(url,{headers,signal:signal?AbortSignal.any([signal,AbortSignal.timeout(12000)]):AbortSignal.timeout(12000)});if(!r.ok)throw Er - 读取本地文件lib/session.mjs:9
async load(){try{this.memory=JSON.parse(await readFile(join(this.root,'music-memory.json'),'utf8'));}catch(e){if(e.code!=='ENOENT')throw e;}return thi - 写入本地文件lib/session.mjs:10
async save(){const text=JSON.stringify(this.memory,null,2);this.writes=this.writes.catch(()=>{}).then(async()=>{await mkdir(this.root,{recursive:true} - 写入本地文件lib/session.mjs:10
async save(){const text=JSON.stringify(this.memory,null,2);this.writes=this.writes.catch(()=>{}).then(async()=>{await mkdir(this.root,{recursive:true} - 写入本地文件lib/session.mjs:10
async save(){const text=JSON.stringify(this.memory,null,2);this.writes=this.writes.catch(()=>{}).then(async()=>{await mkdir(this.root,{recursive:true} - 写入本地文件lib/session.mjs:12
async history(event){await mkdir(this.root,{recursive:true});await appendFile(join(this.root,'listening-history.jsonl'),JSON.stringify({at:new Date(). - 写入本地文件lib/session.mjs:12
async history(event){await mkdir(this.root,{recursive:true});await appendFile(join(this.root,'listening-history.jsonl'),JSON.stringify({at:new Date(). - 读取本地文件lib/session.mjs:13
async readHistory(offset=0,limit=100){if(!Number.isInteger(offset)||offset<0||!Number.isInteger(limit)||limit<1)throw Error('无效页码参数');let rows=[];try{ - 读取本地文件lib/bilibili.mjs:12
start(){if(this.proc)return;if(!existsSync(this.python)&&this.spawnWorker===spawn)throw Error('B站运行环境未安装。请在插件目录运行 node setup-bili.mjs;音乐播放器可继续使用。');co - 执行外部命令固定命令lib/bilibili.mjs:15
stopWorker(){const proc=this.proc;if(!proc)return;this.proc=null;this.fail(Error('B站请求已取消'));if(process.platform==='win32'){const killer=spawn('taskki - 发起网络请求lib/bilibili.mjs:16
async login(action='start',signal){if(action==='start'){const result=await this.request('login_start',{},signal);this.qr=result;return {...result,note - 发起网络请求lib/bilibili.mjs:17
async resolveId(value,signal){try{return videoId(value);}catch{let url;try{url=new URL(value);}catch{throw Error('请提供BV号、B站视频链接或b23.tv链接');}if(url.pro - 读取本地文件lib/bilibili.mjs:18
async account(action){if(!['status','start','poll','logout'].includes(action))throw Error('未知登录动作');const data=await this.login(action);if(this.qr?.qr - 发起网络请求lib/bilibili.mjs:19
async watch(args,signal){const bvid=await this.resolveId(args.bvid,signal),page=args.page||1,mode=args.mode||'video';if(!Number.isInteger(page)||page< - 写入本地文件lib/bilibili.mjs:20
async finishVideo(args){const key=args.watch_key;if(!this.processed(key))throw Error('主模型尚未成功处理本次原始媒体,请先qian_bili_watch并在下一轮听看。');if(!args.impression? - 写入本地文件lib/bilibili.mjs:20
async finishVideo(args){const key=args.watch_key;if(!this.processed(key))throw Error('主模型尚未成功处理本次原始媒体,请先qian_bili_watch并在下一轮听看。');if(!args.impression? - 读取本地文件lib/bilibili.mjs:21
async history(){try{return {notes:(await readFile(join(this.root,'watch-history.jsonl'),'utf8')).trim().split('\n').filter(Boolean).map(x=>JSON.parse( - 读取本地文件lib/bilibili.mjs:22
async inbox(signal){if(!this.acksLoaded){try{for(const line of (await readFile(join(this.root,'inbox-acks.jsonl'),'utf8')).split('\n').filter(Boolean) - 发起网络请求lib/bilibili.mjs:22
async inbox(signal){if(!this.acksLoaded){try{for(const line of (await readFile(join(this.root,'inbox-acks.jsonl'),'utf8')).split('\n').filter(Boolean) - 写入本地文件lib/bilibili.mjs:23
async ack(key,note=''){if(!key)throw Error('需要通知key');this.seen.add(key);await mkdir(this.root,{recursive:true});await appendFile(join(this.root,'inbo - 写入本地文件lib/bilibili.mjs:23
async ack(key,note=''){if(!key)throw Error('需要通知key');this.seen.add(key);await mkdir(this.root,{recursive:true});await appendFile(join(this.root,'inbo - 发起网络请求lib/bilibili.mjs:24
async reply(args,signal){const n=this.notifications.get(args.notification_key);if(!n?.replyable)throw Error('请先查询通知,并使用可回复通知的key');const result=await - 读取本地文件lib/library.mjs:7
async load(){try{this.data={...this.data,...JSON.parse(await readFile(join(this.root,'player-library.json'),'utf8'))};}catch(e){if(e.code!=='ENOENT')t - 写入本地文件lib/library.mjs:8
save(){const text=JSON.stringify(this.data,null,2);const write=this.writes.catch(()=>{}).then(async()=>{await mkdir(this.root,{recursive:true});const - 写入本地文件lib/library.mjs:8
save(){const text=JSON.stringify(this.data,null,2);const write=this.writes.catch(()=>{}).then(async()=>{await mkdir(this.root,{recursive:true});const - 写入本地文件lib/library.mjs:8
save(){const text=JSON.stringify(this.data,null,2);const write=this.writes.catch(()=>{}).then(async()=>{await mkdir(this.root,{recursive:true});const - 读取本地文件lib/local-media.mjs:9
export async function serveLocal(req,res,key){const song=cachedSong(key);if(song.source!=='local'||!song.localPath)throw Error('未导入此本地音源');const file= - 读取本地文件lib/local-media.mjs:9
export async function serveLocal(req,res,key){const song=cachedSong(key);if(song.source!=='local'||!song.localPath)throw Error('未导入此本地音源');const file= - 写入本地文件lib/local-media.mjs:10
export async function uploadLocal(req,root,name){const extension=extname(name).toLowerCase();if(!localExtensions.has(extension))throw Error('请选择音频文件或M - 写入本地文件lib/local-media.mjs:10
export async function uploadLocal(req,root,name){const extension=extname(name).toLowerCase();if(!localExtensions.has(extension))throw Error('请选择音频文件或M - 写入本地文件lib/local-media.mjs:10
export async function uploadLocal(req,root,name){const extension=extname(name).toLowerCase();if(!localExtensions.has(extension))throw Error('请选择音频文件或M - 删除本地文件递归lib/local-media.mjs:10
export async function uploadLocal(req,root,name){const extension=extname(name).toLowerCase();if(!localExtensions.has(extension))throw Error('请选择音频文件或M - 写入本地文件install.mjs:8
await mkdir(dir,{recursive:true}); - 读取本地文件install.mjs:9
let text='';try{text=await readFile(patch,'utf8');await copyFile(patch,patch+'.backup-'+Date.now());}catch(e){if(e.code!=='ENOENT')throw e;} - 写入本地文件install.mjs:9
let text='';try{text=await readFile(patch,'utf8');await copyFile(patch,patch+'.backup-'+Date.now());}catch(e){if(e.code!=='ENOENT')throw e;} - 写入本地文件install.mjs:17
await writeFile(patch,text); - 读取本地文件install.mjs:19
try{await stat(skillTarget);await cp(skillTarget,join(home,'skill-backups','qian-music-'+Date.now()),{recursive:true});}catch(e){if(e.code!=='ENOENT') - 写入本地文件setup-bili.mjs:5
const root=join(privateRoot(),'bilibili'),venv=join(root,'venv');await mkdir(root,{recursive:true}); - 执行外部命令来自配置/变量setup-bili.mjs:6
async function run(command,args){await new Promise((yes,no)=>{const p=spawn(command,args,{stdio:'inherit',windowsHide:true});p.on('error',no);p.on('ex
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-llm@deepseek-ai/dsh-tools@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
千小姐的音乐工具箱:Qwen Omni 原生音视频理解、聚合找歌、DSH 内置播放器与 B站互动
README
由 DeepSeek 最新模型翻译生成千小姐 · Qian Music for DSH
让 Qwen Omni 原生听歌,再按你的要求找歌、试听、建歌单。轻量播放器直接在 DSH 窗口底部运行,无需旧音乐室,也不另开浏览器。
v0.3 加入 B站原生视频工具链:用户扫码登录,搜索和浏览视频,下载合并实际音视频,交给当前 Omni 主会话直接听看;可读取评论、通知,并在用户授权下发表评论、回复或动态。不会用字幕、抽帧摘要或另一个模型代替观看。
DSH 内的千小姐播放器
下载与配置入口
- 项目源码 · 安装包与版本说明
- 安装与模型配置 · B站登录与使用 · 网易云账号配置
- DSH 桌面版下载 · Node.js 24 · PowerShell 7 · Python(B站扩展)
- 百炼控制台与 API Key · Qwen Omni 接口说明
- 网易云开发者开放平台 · 开发者入驻 · 官方 CLI 配置说明
这是 DSH 插件版。另一个项目 千小姐的音乐室 是独立应用,安装方式与本插件不同。
基础功能
- 播放控制:播放、暂停、上一首、下一首、音量、进度条拖动。
- 本地音源:点击“导入本地音源”多选文件加入队列,或让千小姐用本地路径导入;支持收藏到歌单、重启后继续使用。路径导入可读取同名 LRC 歌词。播放本地文件不上传云端,原生试听时才提供给模型。
展开完整文档(README 剩余 1 节)
千小姐 · Qian Music for DSH 让 Qwen Omni 原生听歌,再按你的要求找歌、试听、建歌单。轻量播放器直接在 DSH 窗口底部运行,无需旧音乐室,也不另开浏览器。 v0.3 加入 B站原生视频工具链:用户扫码登录,搜索和浏览视频,下载合并实际音视频,交给当前 Omni 主会话直接听看;可读取评论、通知,并在用户授权下发表评论、回复或动态。不会用字幕、抽帧摘要或另一个模型代替观看。 DSH 内的千小姐播放器 下载与配置入口 - 项目源码 · 安装包与版本说明 - 安装与模型配置 · B站登录与使用 · 网易云账号配置 - DSH 桌面版下载 · Node.js 24 · PowerShell 7 · Python(B站扩展) - 百炼控制台与 API Key · Qwen Omni 接口说明 - 网易云开发者开放平台 · 开发者入驻 · 官方 CLI 配置说明 这是 DSH 插件版。另一个项目 千小姐的音乐室 是独立应用,安装方式与本插件不同。 基础功能 - 播放控制:播放、暂停、上一首、下一首、音量、进度条拖动。 - 本地音源:点击“导入本地音源”多选文件加入队列,或让千小姐用本地路径导入;支持收藏到歌单、重启后继续使用。路径导入可读取同名 LRC 歌词。播放本地文件不上传云端,原生试听时才提供给模型。 - 播放列表:追加、点播、上移下移、移除、清空;播放单曲保留已有队列。 - 四种模式:顺序播放、随机播放、单曲循环、列表循环。 - 本地歌单:新建、收藏当前歌曲、加到已有歌单、改名、移除歌曲、加入队列;删除整个歌单弹窗确认。 - 滚动歌词:按真实时间轴高亮,点歌词跳转;来源没有歌词时如实显示。 - 展开与收起:收起后继续播放,保留基本控制条。 - 自主找歌:智能体聚合搜索 QQ、酷狗、酷我、咪咕和网易云,获取实际音源后原生听,再筛选和编排队列。 - 本地音视频理解:DSH 附件或本地路径通过 qian_media 原生读取,不以字幕或 ASR 代替听感。 音源和歌词以平台实际返回为准,搜索成功不代表可播。网易云开发者 Key 与账号登录为可选扩展:安装脚本会同时安装千小姐音乐技能,指导她调用官方 CLI 管理云歌单、红心、推荐和账号历史。不会把账号能力变成播放器启动前提,也不会保证会员音源一定开放。 陪听、自动续歌、DJ、歌曲时间点操作、计时、偏好和试听笔记都有对应工具。听歌记录和记忆可在展开面板中查看。功能对应关系与边界见 能力对照。 快速开始 需要 DSH 桌面版与 Node.js 24。当前实机兼容验证:Windows、DSH 0.2.1-rc.5。 解压到固定目录,在该目录运行: node ./install.mjs --profile desktop pwsh -File ./setup-key.ps1 pwsh -File ./start-dsh.ps1 配置时填写自己的百炼服务地址、模型和 API Key。启动脚本首次询问你安装的 DSH 桌面程序路径。自定义 DSH 数据目录先设置 DSH_HOME,详细步骤见 安装说明。 回到 DSH,选择 Qwen Omni · 千小姐,点击底部“启用播放”。将 人设说明 合并到自己的千小姐工作区后,就可以说: 找几首和《碎镜》感觉接近的中 V,星尘优先。你先实际听听,挑三首加入队列,收藏到我的歌单。 把第二首移到下一首,音量调到 30%,切成随机播放。 我发了一段视频,听听里面的声音,再帮我找相近的歌。 可选:B站原生观看与互动 需要自己的 Python 3.10+。在插件目录执行: node setup-bili.mjs 在 DSH 点“展开播放器”→“B站账号”扫码,或让千小姐调用 qian_bili_login。账号在本机加密保存,不使用作者账号。详情见 B站指南。 看一下这个 B站视频,直接听里面的声音和画面,告诉我笑点在哪里。 搜几个以声音为笑点的视频,原生看过再挑。先别发评论。 看完这条后帮我发一句简短评论,并转到动态。 音视频准备成功不等于已观看:原始媒体会进入下一轮主模型请求,处理后才能保存观看笔记。原始文件保留在用户自己的缓存中。 智能体工具 | 工具 | 用途 | | qian_sources / qian_music_search | 来源状态与聚合检索 | | qian_music_listen / qian_media | 把实际原始音视频交给主模型理解 | | qian_music_lyrics | 获取来源歌词 | | qian_player_open / qian_player_state | 启用指引和真实播放状态 | | qian_music_play / qian_queue_add | 播放、追加、编排接下来的歌曲 | | qian_music_import | 导入官方 CLI 实际返回的歌曲与音源 | | qian_player_control | 暂停、切歌、音量、定位、模式与队列操作 | | qian_playlist | 本地歌单管理 | | qian_current_time / qian_sleep / qian_timer | 真实时间、等待、提醒和歌曲定点控制 | | qian_listening_mode | 同一主会话的陪听、自动续歌和 DJ | | qian_memory / qian_history | 偏好、实际试听笔记、本机播放事件 | | qian_bili_login / qian_bili_status | B站扫码、登录状态与退出 | | qian_bili_discover / qian_bili_info | 搜索、推荐和分P详情 | | qian_bili_watch / qian_bili_finish_video | 下载真实音视频、当前主模型原生听看与笔记 | | qian_bili_comments / qian_bili_comment | 读评论、按授权发表或回复评论,支持转动态 | | qian_bili_inbox / qian_bili_reply / qian_bili_notifications | @、回复、可选后台通知唤醒同一会话 | | qian_bili_activity / qian_bili_dynamic / qian_bili_receipts / qian_bili_verify | 动态、写入回执与可见性核验 | 播放器只在本机回环地址建立带随机令牌的控制连接,音频由 DSH 自身界面播放。智能体等待实际执行回执,不把「发出命令」当作「已经播放」。歌单、队列、音量和模式保存在用户数据目录;时效音源在播放时重新解析。 分发与验证 包内没有个人 Key、平台账号、登录态、历史对话、歌曲文件和 DSH 主程序。聚合检索与基础播放使用公开接口,不需要网易云开发者凭证;可选官方 CLI 的账号操作使用用户自己的应用和登录态。两条通道都受平台实际能力与权限影响。 node --test tests/*.test.mjs 验证队列、控制回执、模式、歌单持久化、来源隔离及歌词解析。实际界面验证覆盖播放、进度跳转、音量、模式、暂停继续、下一首、收起后继续播放与删除确认。验证不调用付费模型。 参考:DSH 官方项目;聚合接口研究参考 Listen1,未打包其源码。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
littlexie1/qian-music-dsh
在对话窗口里听歌找歌,还能扫码逛 B站
相关插件 · 工具 / 效率
破甲管控台kingcharleslzy-ai/dsh-purge
dsh-purge Community · DeepSeek Harness 社区维护版:宿主兼容、状态诊断、提示词管理、更新与本机备份回滚。基于小杨 / YuJunZhiXue 的 dsh-purge。
★ 4,330已汉化DeepSeek 客户端
74.5
网文长卷lingfengQAQ/webnovel-writer
基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200…
★ 7,636已汉化DSH
72.2
多智能体协作HKUDS/AutoSwarm
AutoSwarm: Unify Your Agents. Unify Your Context (Codex · Claude Code · DeepSeek Harness · Muse · Grok · WorkBuddy· nanobot · and more)
★ 2,349已汉化DSH
71.6
Vox 拼贴视频生成Alisa0808/vox-director
🎬 Vox Director拼贴动效导演
★ 2,129已汉化DSH
71.4
Agent 演化引擎Q00/ouroboros
智能体 OS:智能体自己变聪明,我们只守住底线:面试准入、分阶段评估、带预算的进化循环。MCP 服务器,14 种运行时:Claude Code、Codex CLI、Gemini CLI、OpenCode、Copilot、Kiro 等。
★ 6,311已汉化DSH
71.4
智能体运行框架路由HarnessRouter/harnessrouter
智能体 harness 的统一接口。
★ 3,984已汉化DSH
71.3
这是你的仓库?认领条目