Compare commits

...

2 Commits

Author SHA1 Message Date
5b780addba
ci: test ci with the workflow file 2026-08-05 20:44:21 +08:00
fc9f41839c
ci: test ci with workflow file 2026-08-05 19:44:08 +08:00
6 changed files with 414 additions and 175 deletions

View File

@ -6,8 +6,6 @@ permissions:
on: on:
issues: issues:
types: [opened, labeled] types: [opened, labeled]
issue_comment:
types: [created]
jobs: jobs:
welcome-new-issues: welcome-new-issues:
@ -28,30 +26,6 @@ jobs:
- 💬 加入[QQ交流群](https://qm.qq.com/q/TpeP9Uv2yk) - 💬 加入[QQ交流群](https://qm.qq.com/q/TpeP9Uv2yk)
- 🔍 搜索[现有issues](https://github.com/neteasecloudmusicapienhanced/api-enhanced/issues) 看是否有类似问题 - 🔍 搜索[现有issues](https://github.com/neteasecloudmusicapienhanced/api-enhanced/issues) 看是否有类似问题
handle-help-wanted:
if: contains(github.event.issue.labels.*.name, 'question')
runs-on: ubuntu-latest
steps:
- name: Add help resources
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ github.event.issue.number }}
body: |
🆘 需要帮助?
这里有一些可能对您有用的资源:
📚 **文档资源**
- [项目文档](https://neteasecloudmusicapienhanced.js.org)
🔍 **常见问题**
- 搜索[已关闭的issues](https://github.com/neteasecloudmusicapienhanced/api-enhanced/issues?q=is%3Aissue+is%3Aclosed) 看看是否有类似的问题已经被解答。
💬 **即时帮助**
- 加入QQ群https://qm.qq.com/q/TpeP9Uv2yk
如果以上资源无法解决您的问题,请提供更多详细信息,我们会尽快为您解答!
stale-issues: stale-issues:
if: github.event.action == 'opened' if: github.event.action == 'opened'
runs-on: ubuntu-latest runs-on: ubuntu-latest

59
.github/workflows/opencode-auto.yml vendored Normal file
View File

@ -0,0 +1,59 @@
name: OpenCode Automation
on:
issues:
types: [opened]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: write
issues: write
pull-requests: write
concurrency:
group: auto-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: false
jobs:
automate:
# 排除机器人自己的触发,防止自我循环
if: |
github.actor != 'takanashi-hoshino-agent[bot]' &&
github.actor != 'github-actions[bot]' &&
github.actor != 'opencode-agent[bot]'
runs-on: ubuntu-latest
steps:
- name: Generate bot token
id: token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout
uses: actions/checkout@v6
with:
token: ${{ steps.token.outputs.token }}
fetch-depth: 0
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Install opencode
run: npm i -g opencode-ai@latest
- name: Run automation
env:
GITHUB_TOKEN: ${{ steps.token.outputs.token }}
MODEL: opencode/deepseek-v4-flash-free
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
ISSUE_PROMPT: ${{ secrets.OPENCODE_PROMPT }}
PR_PROMPT: |
${{ secrets.OPENCODE_PROMPT }}
${{ secrets.PR_REVIEW_PROMPT }}
run: node scripts/opencode-automation.mjs

View File

@ -5,8 +5,6 @@ on:
types: [created] types: [created]
pull_request_review_comment: pull_request_review_comment:
types: [created] types: [created]
issues:
types: [opened]
permissions: permissions:
contents: write contents: write
@ -16,10 +14,13 @@ permissions:
jobs: jobs:
bot: bot:
if: | if: |
contains(github.event.comment.body, ' /oc') || (contains(github.event.comment.body, ' /oc') ||
startsWith(github.event.comment.body, '/oc') || startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') || contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode') startsWith(github.event.comment.body, '/opencode')) &&
github.actor != 'opencode-agent[bot]' &&
github.actor != 'takanashi-hoshino-agent[bot]' &&
github.actor != 'github-actions[bot]'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@ -51,4 +52,5 @@ jobs:
with: with:
model: opencode/deepseek-v4-flash-free model: opencode/deepseek-v4-flash-free
use_github_token: true use_github_token: true
prompt: ${{ secrets.OPENCODE_PROMPT }} prompt: |
${{ secrets.OPENCODE_PROMPT }}

View File

@ -75,8 +75,8 @@
"data" "data"
], ],
"dependencies": { "dependencies": {
"@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.3.4", "@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.4.0",
"axios": "^1.18.1", "axios": "^1.19.0",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dotenv": "^17.4.2", "dotenv": "^17.4.2",
"express": "^5.2.1", "express": "^5.2.1",
@ -89,7 +89,7 @@
"safe-decode-uri-component": "^1.2.1", "safe-decode-uri-component": "^1.2.1",
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
"xml2js": "^0.6.2", "xml2js": "^0.6.2",
"yargs": "^18.0.0" "yargs": "^18.1.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.3.6", "@eslint/eslintrc": "^3.3.6",
@ -98,17 +98,17 @@
"@types/express-fileupload": "^1.5.1", "@types/express-fileupload": "^1.5.1",
"@types/mocha": "^10.0.10", "@types/mocha": "^10.0.10",
"@types/node": "25.9.2", "@types/node": "25.9.2",
"@typescript-eslint/eslint-plugin": "^8.65.0", "@typescript-eslint/eslint-plugin": "^8.66.0",
"@typescript-eslint/parser": "^8.65.0", "@typescript-eslint/parser": "^8.66.0",
"eslint": "^9.39.5", "eslint": "^9.39.5",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-html": "^8.1.4", "eslint-plugin-html": "^8.1.4",
"eslint-plugin-prettier": "^5.5.6", "eslint-plugin-prettier": "^5.5.6",
"globals": "^17.7.0", "globals": "^17.9.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"intelli-espower-loader": "^1.1.0", "intelli-espower-loader": "^1.1.0",
"lint-staged": "^16.4.0", "lint-staged": "^16.4.0",
"mocha": "^11.7.6", "mocha": "^11.8.0",
"nodemon": "^3.1.14", "nodemon": "^3.1.14",
"pkg": "^5.8.1", "pkg": "^5.8.1",
"power-assert": "^1.6.1", "power-assert": "^1.6.1",

270
pnpm-lock.yaml generated
View File

@ -9,11 +9,11 @@ importers:
.: .:
dependencies: dependencies:
'@neteasecloudmusicapienhanced/unblockmusic-utils': '@neteasecloudmusicapienhanced/unblockmusic-utils':
specifier: ^0.3.4 specifier: ^0.4.0
version: 0.3.4 version: 0.4.0
axios: axios:
specifier: ^1.18.1 specifier: ^1.19.0
version: 1.18.1 version: 1.19.0
crypto-js: crypto-js:
specifier: ^4.2.0 specifier: ^4.2.0
version: 4.2.0 version: 4.2.0
@ -51,8 +51,8 @@ importers:
specifier: ^0.6.2 specifier: ^0.6.2
version: 0.6.2 version: 0.6.2
yargs: yargs:
specifier: ^18.0.0 specifier: ^18.1.0
version: 18.0.0 version: 18.1.0
devDependencies: devDependencies:
'@eslint/eslintrc': '@eslint/eslintrc':
specifier: ^3.3.6 specifier: ^3.3.6
@ -73,11 +73,11 @@ importers:
specifier: 25.9.2 specifier: 25.9.2
version: 25.9.2 version: 25.9.2
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^8.65.0 specifier: ^8.66.0
version: 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3) version: 8.66.0(@typescript-eslint/parser@8.66.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^8.65.0 specifier: ^8.66.0
version: 8.65.0(eslint@9.39.5)(typescript@5.9.3) version: 8.66.0(eslint@9.39.5)(typescript@5.9.3)
eslint: eslint:
specifier: ^9.39.5 specifier: ^9.39.5
version: 9.39.5 version: 9.39.5
@ -91,8 +91,8 @@ importers:
specifier: ^5.5.6 specifier: ^5.5.6
version: 5.5.6(eslint-config-prettier@10.1.8(eslint@9.39.5))(eslint@9.39.5)(prettier@3.9.6) version: 5.5.6(eslint-config-prettier@10.1.8(eslint@9.39.5))(eslint@9.39.5)(prettier@3.9.6)
globals: globals:
specifier: ^17.7.0 specifier: ^17.9.0
version: 17.7.0 version: 17.9.0
husky: husky:
specifier: ^9.1.7 specifier: ^9.1.7
version: 9.1.7 version: 9.1.7
@ -103,8 +103,8 @@ importers:
specifier: ^16.4.0 specifier: ^16.4.0
version: 16.4.0 version: 16.4.0
mocha: mocha:
specifier: ^11.7.6 specifier: ^11.8.0
version: 11.7.6 version: 11.8.0
nodemon: nodemon:
specifier: ^3.1.14 specifier: ^3.1.14
version: 3.1.14 version: 3.1.14
@ -222,8 +222,8 @@ packages:
'@jridgewell/trace-mapping@0.3.31': '@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@neteasecloudmusicapienhanced/unblockmusic-utils@0.3.4': '@neteasecloudmusicapienhanced/unblockmusic-utils@0.4.0':
resolution: {integrity: sha512-3Lu/eYnDqf9/rHxa5G38TZxM7QVUBZpzKMWBmT6STHaMb6ztFRfrVrejIC1r7IUvtCWkoRulD+8UlllNTEsd6g==} resolution: {integrity: sha512-KUDdBEe3IK4tPSt2UHdFweYbhoZUYGBxbt8FuqQu5bZdpymfpecZxLf+a8G/JvIYHph4H+KxYlq6+MD9oXCfjg==}
hasBin: true hasBin: true
'@nodelib/fs.scandir@2.1.5': '@nodelib/fs.scandir@2.1.5':
@ -271,8 +271,8 @@ packages:
'@types/express-fileupload@1.5.1': '@types/express-fileupload@1.5.1':
resolution: {integrity: sha512-DllImBVI1lCyjl2klky/TEwk60mbNebgXv1669h66g9TfptWSrEFq5a/raHSutaFzjSm1tmn9ypdNfu4jPSixQ==} resolution: {integrity: sha512-DllImBVI1lCyjl2klky/TEwk60mbNebgXv1669h66g9TfptWSrEFq5a/raHSutaFzjSm1tmn9ypdNfu4jPSixQ==}
'@types/express-serve-static-core@5.1.2': '@types/express-serve-static-core@5.1.3':
resolution: {integrity: sha512-d3KvEXBSo/lOAMc2u6fkyDHBvetBHeqD7wm/AcXfLpSOQwlmG9D/aQ0SFswVjv05p7ullQS7Mjohj6/VdbZuTg==} resolution: {integrity: sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==}
'@types/express@5.0.6': '@types/express@5.0.6':
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
@ -301,63 +301,63 @@ packages:
'@types/serve-static@2.2.0': '@types/serve-static@2.2.0':
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
'@typescript-eslint/eslint-plugin@8.65.0': '@typescript-eslint/eslint-plugin@8.66.0':
resolution: {integrity: sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==} resolution: {integrity: sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.65.0 '@typescript-eslint/parser': ^8.66.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/parser@8.65.0': '@typescript-eslint/parser@8.66.0':
resolution: {integrity: sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==} resolution: {integrity: sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/project-service@8.65.0': '@typescript-eslint/project-service@8.66.0':
resolution: {integrity: sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==} resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/scope-manager@8.65.0': '@typescript-eslint/scope-manager@8.66.0':
resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==} resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.65.0': '@typescript-eslint/tsconfig-utils@8.66.0':
resolution: {integrity: sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==} resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/type-utils@8.65.0': '@typescript-eslint/type-utils@8.66.0':
resolution: {integrity: sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==} resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/types@8.65.0': '@typescript-eslint/types@8.66.0':
resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==} resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.65.0': '@typescript-eslint/typescript-estree@8.66.0':
resolution: {integrity: sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==} resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/utils@8.65.0': '@typescript-eslint/utils@8.66.0':
resolution: {integrity: sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==} resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/visitor-keys@8.65.0': '@typescript-eslint/visitor-keys@8.66.0':
resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==} resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@unblockneteasemusic/server@0.28.0': '@unblockneteasemusic/server@0.28.0':
@ -386,8 +386,8 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
acorn@8.17.0: acorn@8.18.0:
resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
@ -485,8 +485,8 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
axios@1.18.1: axios@1.19.0:
resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} resolution: {integrity: sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==}
balanced-match@1.0.2: balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@ -517,14 +517,14 @@ packages:
resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==}
engines: {node: '>=18'} engines: {node: '>=18'}
brace-expansion@1.1.16: brace-expansion@1.1.18:
resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==}
brace-expansion@2.1.2: brace-expansion@2.1.4:
resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
brace-expansion@5.0.8: brace-expansion@5.0.9:
resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==} resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
braces@3.0.3: braces@3.0.3:
@ -1153,8 +1153,8 @@ packages:
flatstr@1.0.12: flatstr@1.0.12:
resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==} resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==}
flatted@3.4.3: flatted@3.4.4:
resolution: {integrity: sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==} resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==}
follow-redirects@1.16.0: follow-redirects@1.16.0:
resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
@ -1262,8 +1262,8 @@ packages:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
globals@17.7.0: globals@17.9.0:
resolution: {integrity: sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==} resolution: {integrity: sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==}
engines: {node: '>=18'} engines: {node: '>=18'}
globalthis@1.0.4: globalthis@1.0.4:
@ -1400,8 +1400,8 @@ packages:
resolution: {integrity: sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==} resolution: {integrity: sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==}
engines: {node: '>=10'} engines: {node: '>=10'}
ip-address@10.2.0: ip-address@10.4.0:
resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} resolution: {integrity: sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==}
engines: {node: '>= 12'} engines: {node: '>= 12'}
ipaddr.js@1.9.1: ipaddr.js@1.9.1:
@ -1565,8 +1565,8 @@ packages:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'} engines: {node: '>=10'}
js-yaml@4.3.0: js-yaml@4.3.1:
resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==}
hasBin: true hasBin: true
jsesc@2.5.2: jsesc@2.5.2:
@ -1699,8 +1699,8 @@ packages:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
minimatch@10.2.5: minimatch@10.2.6:
resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
engines: {node: 18 || 20 || >=22} engines: {node: 18 || 20 || >=22}
minimatch@3.1.5: minimatch@3.1.5:
@ -1720,8 +1720,8 @@ packages:
mkdirp-classic@0.5.3: mkdirp-classic@0.5.3:
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
mocha@11.7.6: mocha@11.8.0:
resolution: {integrity: sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==} resolution: {integrity: sha512-VyCeUdGN3A9lmCTTgG4yuvY9ixxaDk+xt2R/7/+1AP6EqNG+G9OKkzBwhVtVYoNX8YsxNSgAl8mOv3IAeOpFbw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true hasBin: true
@ -2158,8 +2158,8 @@ packages:
safer-buffer@2.1.2: safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sax@1.6.0: sax@1.6.1:
resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==}
engines: {node: '>=11.0.0'} engines: {node: '>=11.0.0'}
secure-json-parse@2.7.0: secure-json-parse@2.7.0:
@ -2400,8 +2400,8 @@ packages:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
tinyexec@1.2.4: tinyexec@1.3.0:
resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
tinyglobby@0.2.17: tinyglobby@0.2.17:
@ -2655,8 +2655,8 @@ packages:
resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==}
engines: {node: '>=12'} engines: {node: '>=12'}
yargs@18.0.0: yargs@18.1.0:
resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==}
engines: {node: ^20.19.0 || ^22.12.0 || >=23} engines: {node: ^20.19.0 || ^22.12.0 || >=23}
yocto-queue@0.1.0: yocto-queue@0.1.0:
@ -2718,7 +2718,7 @@ snapshots:
globals: 14.0.0 globals: 14.0.0
ignore: 5.3.2 ignore: 5.3.2
import-fresh: 3.3.1 import-fresh: 3.3.1
js-yaml: 4.3.0 js-yaml: 4.3.1
minimatch: 3.1.5 minimatch: 3.1.5
strip-json-comments: 3.1.1 strip-json-comments: 3.1.1
transitivePeerDependencies: transitivePeerDependencies:
@ -2772,10 +2772,10 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2 '@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
'@neteasecloudmusicapienhanced/unblockmusic-utils@0.3.4': '@neteasecloudmusicapienhanced/unblockmusic-utils@0.4.0':
dependencies: dependencies:
'@unblockneteasemusic/server': 0.28.0 '@unblockneteasemusic/server': 0.28.0
axios: 1.18.1 axios: 1.19.0
dotenv: 17.4.2 dotenv: 17.4.2
express: 4.22.2 express: 4.22.2
https: 1.0.0 https: 1.0.0
@ -2831,7 +2831,7 @@ snapshots:
'@types/busboy': 1.5.4 '@types/busboy': 1.5.4
'@types/express': 5.0.6 '@types/express': 5.0.6
'@types/express-serve-static-core@5.1.2': '@types/express-serve-static-core@5.1.3':
dependencies: dependencies:
'@types/node': 25.9.2 '@types/node': 25.9.2
'@types/qs': 6.15.1 '@types/qs': 6.15.1
@ -2841,7 +2841,7 @@ snapshots:
'@types/express@5.0.6': '@types/express@5.0.6':
dependencies: dependencies:
'@types/body-parser': 1.19.6 '@types/body-parser': 1.19.6
'@types/express-serve-static-core': 5.1.2 '@types/express-serve-static-core': 5.1.3
'@types/serve-static': 2.2.0 '@types/serve-static': 2.2.0
'@types/http-errors@2.0.5': {} '@types/http-errors@2.0.5': {}
@ -2867,14 +2867,14 @@ snapshots:
'@types/http-errors': 2.0.5 '@types/http-errors': 2.0.5
'@types/node': 25.9.2 '@types/node': 25.9.2
'@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)': '@typescript-eslint/eslint-plugin@8.66.0(@typescript-eslint/parser@8.66.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.2 '@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.65.0(eslint@9.39.5)(typescript@5.9.3) '@typescript-eslint/parser': 8.66.0(eslint@9.39.5)(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.65.0 '@typescript-eslint/scope-manager': 8.66.0
'@typescript-eslint/type-utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3) '@typescript-eslint/type-utils': 8.66.0(eslint@9.39.5)(typescript@5.9.3)
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3) '@typescript-eslint/utils': 8.66.0(eslint@9.39.5)(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.65.0 '@typescript-eslint/visitor-keys': 8.66.0
eslint: 9.39.5 eslint: 9.39.5
ignore: 7.0.6 ignore: 7.0.6
natural-compare: 1.4.0 natural-compare: 1.4.0
@ -2883,41 +2883,41 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.65.0(eslint@9.39.5)(typescript@5.9.3)': '@typescript-eslint/parser@8.66.0(eslint@9.39.5)(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.65.0 '@typescript-eslint/scope-manager': 8.66.0
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.66.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.65.0 '@typescript-eslint/visitor-keys': 8.66.0
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.5 eslint: 9.39.5
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/project-service@8.65.0(typescript@5.9.3)': '@typescript-eslint/project-service@8.66.0(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@5.9.3)
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
debug: 4.4.3 debug: 4.4.3
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.65.0': '@typescript-eslint/scope-manager@8.66.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
'@typescript-eslint/visitor-keys': 8.65.0 '@typescript-eslint/visitor-keys': 8.66.0
'@typescript-eslint/tsconfig-utils@8.65.0(typescript@5.9.3)': '@typescript-eslint/tsconfig-utils@8.66.0(typescript@5.9.3)':
dependencies: dependencies:
typescript: 5.9.3 typescript: 5.9.3
'@typescript-eslint/type-utils@8.65.0(eslint@9.39.5)(typescript@5.9.3)': '@typescript-eslint/type-utils@8.66.0(eslint@9.39.5)(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.66.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.65.0(eslint@9.39.5)(typescript@5.9.3) '@typescript-eslint/utils': 8.66.0(eslint@9.39.5)(typescript@5.9.3)
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.5 eslint: 9.39.5
ts-api-utils: 2.5.0(typescript@5.9.3) ts-api-utils: 2.5.0(typescript@5.9.3)
@ -2925,16 +2925,16 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/types@8.65.0': {} '@typescript-eslint/types@8.66.0': {}
'@typescript-eslint/typescript-estree@8.65.0(typescript@5.9.3)': '@typescript-eslint/typescript-estree@8.66.0(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/project-service': 8.65.0(typescript@5.9.3) '@typescript-eslint/project-service': 8.66.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@5.9.3)
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
'@typescript-eslint/visitor-keys': 8.65.0 '@typescript-eslint/visitor-keys': 8.66.0
debug: 4.4.3 debug: 4.4.3
minimatch: 10.2.5 minimatch: 10.2.6
semver: 7.8.5 semver: 7.8.5
tinyglobby: 0.2.17 tinyglobby: 0.2.17
ts-api-utils: 2.5.0(typescript@5.9.3) ts-api-utils: 2.5.0(typescript@5.9.3)
@ -2942,20 +2942,20 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.65.0(eslint@9.39.5)(typescript@5.9.3)': '@typescript-eslint/utils@8.66.0(eslint@9.39.5)(typescript@5.9.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5) '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
'@typescript-eslint/scope-manager': 8.65.0 '@typescript-eslint/scope-manager': 8.66.0
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
'@typescript-eslint/typescript-estree': 8.65.0(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.66.0(typescript@5.9.3)
eslint: 9.39.5 eslint: 9.39.5
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/visitor-keys@8.65.0': '@typescript-eslint/visitor-keys@8.66.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.65.0 '@typescript-eslint/types': 8.66.0
eslint-visitor-keys: 5.0.1 eslint-visitor-keys: 5.0.1
'@unblockneteasemusic/server@0.28.0': '@unblockneteasemusic/server@0.28.0':
@ -2976,13 +2976,13 @@ snapshots:
acorn-es7-plugin@1.1.7: {} acorn-es7-plugin@1.1.7: {}
acorn-jsx@5.3.2(acorn@8.17.0): acorn-jsx@5.3.2(acorn@8.18.0):
dependencies: dependencies:
acorn: 8.17.0 acorn: 8.18.0
acorn@5.7.4: {} acorn@5.7.4: {}
acorn@8.17.0: {} acorn@8.18.0: {}
agent-base@6.0.2: agent-base@6.0.2:
dependencies: dependencies:
@ -3072,7 +3072,7 @@ snapshots:
dependencies: dependencies:
possible-typed-array-names: 1.1.0 possible-typed-array-names: 1.1.0
axios@1.18.1: axios@1.19.0:
dependencies: dependencies:
follow-redirects: 1.16.0 follow-redirects: 1.16.0
form-data: 4.0.6 form-data: 4.0.6
@ -3129,16 +3129,16 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
brace-expansion@1.1.16: brace-expansion@1.1.18:
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
concat-map: 0.0.1 concat-map: 0.0.1
brace-expansion@2.1.2: brace-expansion@2.1.4:
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
brace-expansion@5.0.8: brace-expansion@5.0.9:
dependencies: dependencies:
balanced-match: 4.0.4 balanced-match: 4.0.4
@ -3765,8 +3765,8 @@ snapshots:
espree@10.4.0: espree@10.4.0:
dependencies: dependencies:
acorn: 8.17.0 acorn: 8.18.0
acorn-jsx: 5.3.2(acorn@8.17.0) acorn-jsx: 5.3.2(acorn@8.18.0)
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
esprima@2.7.3: {} esprima@2.7.3: {}
@ -3959,14 +3959,14 @@ snapshots:
flat-cache@4.0.1: flat-cache@4.0.1:
dependencies: dependencies:
flatted: 3.4.3 flatted: 3.4.4
keyv: 4.5.4 keyv: 4.5.4
flat@5.0.2: {} flat@5.0.2: {}
flatstr@1.0.12: {} flatstr@1.0.12: {}
flatted@3.4.3: {} flatted@3.4.4: {}
follow-redirects@1.16.0: {} follow-redirects@1.16.0: {}
@ -4085,7 +4085,7 @@ snapshots:
globals@14.0.0: {} globals@14.0.0: {}
globals@17.7.0: {} globals@17.9.0: {}
globalthis@1.0.4: globalthis@1.0.4:
dependencies: dependencies:
@ -4219,7 +4219,7 @@ snapshots:
from2: 2.3.0 from2: 2.3.0
p-is-promise: 3.0.0 p-is-promise: 3.0.0
ip-address@10.2.0: {} ip-address@10.4.0: {}
ipaddr.js@1.9.1: {} ipaddr.js@1.9.1: {}
@ -4378,7 +4378,7 @@ snapshots:
joycon@3.1.1: {} joycon@3.1.1: {}
js-yaml@4.3.0: js-yaml@4.3.1:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
@ -4418,7 +4418,7 @@ snapshots:
listr2: 9.0.5 listr2: 9.0.5
picomatch: 4.0.5 picomatch: 4.0.5
string-argv: 0.3.2 string-argv: 0.3.2
tinyexec: 1.2.4 tinyexec: 1.3.0
yaml: 2.9.0 yaml: 2.9.0
listr2@9.0.5: listr2@9.0.5:
@ -4498,17 +4498,17 @@ snapshots:
mimic-response@3.1.0: {} mimic-response@3.1.0: {}
minimatch@10.2.5: minimatch@10.2.6:
dependencies: dependencies:
brace-expansion: 5.0.8 brace-expansion: 5.0.9
minimatch@3.1.5: minimatch@3.1.5:
dependencies: dependencies:
brace-expansion: 1.1.16 brace-expansion: 1.1.18
minimatch@9.0.9: minimatch@9.0.9:
dependencies: dependencies:
brace-expansion: 2.1.2 brace-expansion: 2.1.4
minimist@1.2.8: {} minimist@1.2.8: {}
@ -4516,7 +4516,7 @@ snapshots:
mkdirp-classic@0.5.3: {} mkdirp-classic@0.5.3: {}
mocha@11.7.6: mocha@11.8.0:
dependencies: dependencies:
browser-stdout: 1.3.1 browser-stdout: 1.3.1
chokidar: 4.0.3 chokidar: 4.0.3
@ -4527,7 +4527,7 @@ snapshots:
glob: 10.5.0 glob: 10.5.0
he: 1.2.0 he: 1.2.0
is-path-inside: 3.0.3 is-path-inside: 3.0.3
js-yaml: 4.3.0 js-yaml: 4.3.1
log-symbols: 4.1.0 log-symbols: 4.1.0
minimatch: 9.0.9 minimatch: 9.0.9
ms: 2.1.3 ms: 2.1.3
@ -4602,7 +4602,7 @@ snapshots:
chokidar: 3.6.0 chokidar: 3.6.0
debug: 4.4.3(supports-color@5.5.0) debug: 4.4.3(supports-color@5.5.0)
ignore-by-default: 1.0.1 ignore-by-default: 1.0.1
minimatch: 10.2.5 minimatch: 10.2.6
pstree.remy: 1.1.8 pstree.remy: 1.1.8
semver: 7.8.5 semver: 7.8.5
simple-update-notifier: 2.0.0 simple-update-notifier: 2.0.0
@ -5073,7 +5073,7 @@ snapshots:
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
sax@1.6.0: {} sax@1.6.1: {}
secure-json-parse@2.7.0: {} secure-json-parse@2.7.0: {}
@ -5233,7 +5233,7 @@ snapshots:
socks@2.8.9: socks@2.8.9:
dependencies: dependencies:
ip-address: 10.2.0 ip-address: 10.4.0
smart-buffer: 4.2.0 smart-buffer: 4.2.0
sonic-boom@1.4.1: sonic-boom@1.4.1:
@ -5387,7 +5387,7 @@ snapshots:
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 3.6.2 readable-stream: 3.6.2
tinyexec@1.2.4: {} tinyexec@1.3.0: {}
tinyglobby@0.2.17: tinyglobby@0.2.17:
dependencies: dependencies:
@ -5620,7 +5620,7 @@ snapshots:
xml2js@0.6.2: xml2js@0.6.2:
dependencies: dependencies:
sax: 1.6.0 sax: 1.6.1
xmlbuilder: 11.0.1 xmlbuilder: 11.0.1
xml@1.0.1: {} xml@1.0.1: {}
@ -5687,12 +5687,12 @@ snapshots:
y18n: 5.0.8 y18n: 5.0.8
yargs-parser: 21.1.1 yargs-parser: 21.1.1
yargs@18.0.0: yargs@18.1.0:
dependencies: dependencies:
cliui: 9.0.1 cliui: 9.0.1
escalade: 3.2.0 escalade: 3.2.0
get-caller-file: 2.0.5 get-caller-file: 2.0.5
string-width: 7.2.0 string-width: 8.2.2
y18n: 5.0.8 y18n: 5.0.8
yargs-parser: 22.0.0 yargs-parser: 22.0.0

View File

@ -0,0 +1,204 @@
#!/usr/bin/env node
import { spawnSync } from 'node:child_process'
import { readFileSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
const eventName = process.env.GITHUB_EVENT_NAME
const eventPath = process.env.GITHUB_EVENT_PATH
const token = process.env.GITHUB_TOKEN
const repo = process.env.GITHUB_REPOSITORY
const model = process.env.MODEL || 'opencode/deepseek-v4-flash-free'
const botLogin = process.env.BOT_LOGIN || 'takanashi-hoshino-agent[bot]'
if (!eventPath || !token || !repo) {
console.error(
'Missing required env: GITHUB_EVENT_PATH / GITHUB_TOKEN / GITHUB_REPOSITORY',
)
process.exit(1)
}
if (!process.env.OPENCODE_API_KEY) {
console.error('Missing OPENCODE_API_KEY')
process.exit(1)
}
const event = JSON.parse(readFileSync(eventPath, 'utf8'))
const [owner, repoName] = repo.split('/')
const api = `https://api.github.com/repos/${owner}/${repoName}`
const headers = {
Authorization: `Bearer ${token}`,
Accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
'User-Agent': 'opencode-automation',
}
async function get(path) {
const res = await fetch(`${api}${path}`, { headers })
if (!res.ok) throw new Error(`GET ${path}: HTTP ${res.status}`)
return res.json()
}
async function post(path, body) {
const res = await fetch(`${api}${path}`, {
method: 'POST',
headers,
body: JSON.stringify(body),
})
const text = await res.text()
if (!res.ok) throw new Error(`POST ${path}: HTTP ${res.status} ${text}`)
return text ? JSON.parse(text) : null
}
/** 无头模式跑 opencode返回模型输出的文本 */
function runOpencode(prompt, contextFile) {
const args = ['run', '--auto', '-m', model, '--format', 'default', prompt]
if (contextFile) args.push('-f', contextFile)
console.log(
`Running: opencode run --auto -m ${model} (prompt ${prompt.length} chars${contextFile ? ', context attached' : ''})`,
)
const res = spawnSync('opencode', args, {
encoding: 'utf8',
maxBuffer: 128 * 1024 * 1024,
})
if (res.error) throw res.error
if (res.status !== 0) {
if (res.stderr) console.error('opencode stderr:\n' + res.stderr)
throw new Error(`opencode exited with code ${res.status}`)
}
return (res.stdout || '').trim()
}
/** 该 issue/PR 是否已有 bot 评论(用于去重,避免 synchronize 重复评论) */
async function hasBotComment(target) {
const comments = await get(`/issues/${target}/comments?per_page=100`)
return comments.some((c) => c.user?.login === botLogin)
}
async function comment(target, body) {
if (!body) {
console.log('No output from agent, skip comment')
return
}
if (body.length > 60000) body = body.slice(0, 60000) + '\n\n_...(truncated)_'
await post(`/issues/${target}/comments`, { body })
console.log(`Commented on #${target}`)
}
async function handleIssue(issue) {
const n = issue.number
console.log(`Handling issue #${n}`)
if (await hasBotComment(n)) {
console.log(`Already handled by bot, skip`)
return
}
const comments = await get(`/issues/${n}/comments?per_page=100`)
const thread = comments
.filter((c) => c.user?.login !== botLogin)
.map(
(c) =>
`- **${c.user?.login}** (${c.created_at}):\n ${(c.body || '').replace(/\n/g, '\n ')}`,
)
.join('\n')
const ctx = [
`# Issue #${n}: ${issue.title}`,
``,
`- State: ${issue.state}`,
`- Author: ${issue.user?.login}`,
`- Created: ${issue.created_at}`,
``,
`## Body`,
``,
issue.body || '(empty)',
...(thread ? [`\n## Comments\n\n${thread}`] : []),
].join('\n')
const ctxFile = join(tmpdir(), 'opencode-issue-context.md')
writeFileSync(ctxFile, ctx)
const prompt =
process.env.ISSUE_PROMPT ||
[
`You are a maintainer bot for the ${repo} repository.`,
`Read the attached file for the issue context.`,
`If the issue has a clear fix or points to relevant docs, reply with documentation links and/or`,
`error-handling guidance for code examples. If nothing actionable, reply with exactly "NO_ACTION".`,
`Do NOT modify any files, do NOT commit, do NOT push. Output only the comment text.`,
].join('\n')
const output = runOpencode(prompt, ctxFile)
if (output === 'NO_ACTION' || output.startsWith('NO_ACTION')) {
console.log('Agent decided no action needed')
return
}
await comment(n, output)
}
async function handlePullRequest(pr) {
const n = pr.number
console.log(`Handling PR #${n}`)
if (await hasBotComment(n)) {
console.log(`Already handled by bot, skip`)
return
}
let files = []
try {
files = await get(`/pulls/${n}/files?per_page=100`)
} catch (e) {
console.warn(`Failed to fetch changed files: ${e.message}`)
}
const fileList = files
.map((f) => `- ${f.status} ${f.filename} (+${f.additions}/-${f.deletions})`)
.join('\n')
const ctx = [
`# PR #${n}: ${pr.title}`,
``,
`- State: ${pr.state}`,
`- Author: ${pr.user?.login}`,
`- Base: ${pr.base?.ref} <- Head: ${pr.head?.ref}`,
`- Created: ${pr.created_at}`,
`- Stats: +${pr.additions}/-${pr.deletions}, ${pr.changed_files} files`,
``,
`## Body`,
``,
pr.body || '(empty)',
...(fileList ? [`\n## Changed files\n\n${fileList}`] : []),
].join('\n')
const ctxFile = join(tmpdir(), 'opencode-pr-context.md')
writeFileSync(ctxFile, ctx)
const prompt =
process.env.PR_PROMPT ||
[
`You are a maintainer bot for the ${repo} repository.`,
`Read the attached file for the PR context. The PR branch is already checked out.`,
`Run \`git diff HEAD^1 HEAD\` (or \`git diff origin/${pr.base?.ref}...HEAD\`) to see the changes.`,
`Review the code changes: point out bugs, risks and improvements, and suggest fixes for obvious issues.`,
`If the PR looks good, say so concisely.`,
`Do NOT modify any files, do NOT commit, do NOT push. Output only the review comment text.`,
].join('\n')
const output = runOpencode(prompt, ctxFile)
await comment(n, output)
}
async function main() {
console.log(`Event: ${eventName} on ${repo}`)
if (eventName === 'issues') {
await handleIssue(event.issue)
} else if (eventName === 'pull_request') {
await handlePullRequest(event.pull_request)
} else {
console.log(`Unhandled event type: ${eventName}`)
}
}
main().catch((e) => {
console.error(`Automation failed: ${e.message}`)
process.exit(1)
})