Files
sanguo_vnpy_v2/.claude/workflows/helpers/gitea-mcp-adapter.js
T
claude_dev 918bbed0fc fix: 修复登录500错误和移除明文密码提示
- 修复 deps.py 中 get_vn_service 的引用错误 (vn_service.vn_service -> vn_service)
- 移除登录页面上的明文密码提示
- 改进前端错误处理,避免数据加载失败导致登录显示错误
2026-07-02 12:23:55 +08:00

446 lines
10 KiB
JavaScript

/**
* Gitea MCP 适配层
*
* 封装 Gitea MCP 工具调用,提供统一的接口
*/
import fs from 'fs'
import path from 'path'
/**
* 加载 Gitea 配置
*/
function loadConfig() {
const configPath = path.join(process.cwd(), '.claude', 'gitea-config.json')
try {
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'))
return config
} catch (error) {
throw new Error(`无法加载配置文件: ${configPath}`)
}
}
/**
* 获取仓库信息
*/
function getRepoInfo() {
const config = loadConfig()
return {
baseUrl: config.gitea.baseUrl,
owner: config.gitea.owner,
repo: config.gitea.repo,
defaultBranch: config.gitea.defaultBranch
}
}
/**
* Gitea MCP 适配器类
*/
export class GiteaMCPAdapter {
constructor() {
this.config = loadConfig()
this.repoInfo = getRepoInfo()
}
/**
* 获取仓库信息
*/
getRepoInfo() {
return this.repoInfo
}
/**
* 创建 Issue
*
* @param {Object} options - Issue 选项
* @param {string} options.title - Issue 标题
* @param {string} options.body - Issue 正文
* @param {string[]} options.labels - Issue 标签
* @returns {Promise<Object>} Issue 信息
*/
async createIssue(options) {
const { title, body, labels = [] } = options
const { owner, repo } = this.repoInfo
try {
// 调用 Gitea MCP 工具创建 Issue
const result = await mcp__gitea__issue_write({
method: 'create',
owner,
repo,
title,
body,
labels
})
return {
id: result.id,
number: result.number,
url: `${this.repoInfo.baseUrl}/${owner}/${repo}/issues/${result.number}`,
title: result.title,
body: result.body
}
} catch (error) {
throw new Error(`创建 Issue 失败: ${error.message}`)
}
}
/**
* 更新 Issue
*
* @param {number} issueNumber - Issue 编号
* @param {Object} options - 更新选项
* @returns {Promise<Object>} 更新后的 Issue 信息
*/
async updateIssue(issueNumber, options) {
const { owner, repo } = this.repoInfo
const { state, body } = options
try {
const result = await mcp__gitea__issue_write({
method: 'update',
owner,
repo,
issue_number: issueNumber,
state,
body
})
return result
} catch (error) {
throw new Error(`更新 Issue 失败: ${error.message}`)
}
}
/**
* 关闭 Issue
*
* @param {number} issueNumber - Issue 编号
* @returns {Promise<Object>} 关闭后的 Issue 信息
*/
async closeIssue(issueNumber) {
return this.updateIssue(issueNumber, { state: 'closed' })
}
/**
* 读取 Issue Comments
*
* @param {number} issueNumber - Issue 编号
* @returns {Promise<Array>} Comments 列表
*/
async getIssueComments(issueNumber) {
const { owner, repo } = this.repoInfo
try {
const comments = await mcp__gitea__issue_read({
method: 'get_comments',
owner,
repo,
issue_number: issueNumber
})
return comments
} catch (error) {
throw new Error(`读取 Issue Comments 失败: ${error.message}`)
}
}
/**
* 添加 Issue Comment
*
* @param {number} issueNumber - Issue 编号
* @param {string} body - Comment 内容
* @returns {Promise<Object>} Comment 信息
*/
async createIssueComment(issueNumber, body) {
const { owner, repo } = this.repoInfo
try {
const comment = await mcp__gitea__issue_write({
method: 'add_comment',
owner,
repo,
issue_number: issueNumber,
body
})
return comment
} catch (error) {
throw new Error(`添加 Comment 失败: ${error.message}`)
}
}
/**
* 创建分支
*
* @param {string} branchName - 分支名称
* @param {string} oldBranch - 源分支(默认为主分支)
* @returns {Promise<Object>} 分支信息
*/
async createBranch(branchName, oldBranch = null) {
const { owner, repo, defaultBranch } = this.repoInfo
const sourceBranch = oldBranch || defaultBranch
try {
const result = await mcp__gitea__create_branch({
owner,
repo,
branch: branchName,
old_branch: sourceBranch
})
return result
} catch (error) {
throw new Error(`创建分支失败: ${error.message}`)
}
}
/**
* 列出分支
*
* @returns {Promise<Array>} 分支列表
*/
async listBranches() {
const { owner, repo } = this.repoInfo
try {
const branches = await mcp__gitea__list_branches({
owner,
repo
})
return branches
} catch (error) {
throw new Error(`列出分支失败: ${error.message}`)
}
}
/**
* 创建 Pull Request
*
* @param {Object} options - PR 选项
* @param {string} options.title - PR 标题
* @param {string} options.body - PR 正文
* @param {string} options.head - 源分支
* @param {string} options.base - 目标分支
* @returns {Promise<Object>} PR 信息
*/
async createPullRequest(options) {
const { title, body, head, base } = options
const { owner, repo, defaultBranch } = this.repoInfo
const targetBranch = base || defaultBranch
try {
const result = await mcp__gitea__pull_request_write({
method: 'create',
owner,
repo,
title,
body,
head,
base: targetBranch
})
return {
id: result.id,
number: result.number,
url: `${this.repoInfo.baseUrl}/${owner}/${repo}/pulls/${result.number}`,
title: result.title,
body: result.body,
head: result.head,
base: result.base
}
} catch (error) {
throw new Error(`创建 PR 失败: ${error.message}`)
}
}
/**
* 合并 Pull Request
*
* @param {number} pullNumber - PR 编号
* @param {Object} options - 合并选项
* @returns {Promise<Object>} 合并后的 PR 信息
*/
async mergePullRequest(pullNumber, options = {}) {
const { owner, repo } = this.repoInfo
const { deleteBranch = true, mergeStyle = 'merge' } = options
try {
const result = await mcp__gitea__pull_request_write({
method: 'merge',
owner,
repo,
pull_number: pullNumber,
delete_branch_after_merge: deleteBranch,
merge_style: mergeStyle
})
return result
} catch (error) {
throw new Error(`合并 PR 失败: ${error.message}`)
}
}
/**
* 获取 Pull Request
*
* @param {number} pullNumber - PR 编号
* @returns {Promise<Object>} PR 信息
*/
async getPullRequest(pullNumber) {
const { owner, repo } = this.repoInfo
try {
const pr = await mcp__gitea__pull_request_read({
method: 'get',
owner,
repo,
pull_number: pullNumber
})
return pr
} catch (error) {
throw new Error(`获取 PR 失败: ${error.message}`)
}
}
/**
* 列出 Pull Request
*
* @param {Object} options - 查询选项
* @returns {Promise<Array>} PR 列表
*/
async listPullRequests(options = {}) {
const { owner, repo } = this.repoInfo
const { state = 'open' } = options
try {
const prs = await mcp__gitea__list_pull_requests({
owner,
repo,
state
})
return prs
} catch (error) {
throw new Error(`列出 PR 失败: ${error.message}`)
}
}
/**
* 创建或更新文件
*
* @param {Object} options - 文件选项
* @param {string} options.path - 文件路径
* @param {string} options.content - 文件内容
* @param {string} options.message - Commit 消息
* @param {string} options.branch - 分支名称
* @param {string} options.sha - 文件 SHA(更新时需要)
* @returns {Promise<Object>} 文件信息
*/
async createOrUpdateFile(options) {
const { path: filePath, content, message, branch, sha } = options
const { owner, repo } = this.repoInfo
try {
const result = await mcp__gitea__create_or_update_file({
owner,
repo,
path: filePath,
content: Buffer.from(content).toString('base64'),
message,
branch_name: branch,
sha
})
return result
} catch (error) {
throw new Error(`创建/更新文件失败: ${error.message}`)
}
}
/**
* 获取文件内容
*
* @param {string} filePath - 文件路径
* @param {string} ref - 分支或 commit
* @returns {Promise<Object>} 文件内容
*/
async getFileContents(filePath, ref = null) {
const { owner, repo, defaultBranch } = this.repoInfo
const targetRef = ref || defaultBranch
try {
const file = await mcp__gitea__get_file_contents({
owner,
repo,
path: filePath,
ref: targetRef
})
return file
} catch (error) {
throw new Error(`获取文件内容失败: ${error.message}`)
}
}
/**
* 列出提交
*
* @param {Object} options - 查询选项
* @returns {Promise<Array>} 提交列表
*/
async listCommits(options = {}) {
const { owner, repo } = this.repoInfo
const { sha, path } = options
try {
const commits = await mcp__gitea__list_commits({
owner,
repo,
sha,
path
})
return commits
} catch (error) {
throw new Error(`列出提交失败: ${error.message}`)
}
}
/**
* 带重试的操作
*
* @param {Function} operation - 操作函数
* @param {number} maxRetries - 最大重试次数
* @returns {Promise<any>} 操作结果
*/
async withRetry(operation, maxRetries = 3) {
let lastError
for (let i = 0; i < maxRetries; i++) {
try {
return await operation()
} catch (error) {
lastError = error
console.warn(`操作失败,重试 ${i + 1}/${maxRetries}: ${error.message}`)
// 等待后重试
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
}
}
throw lastError
}
}
/**
* 创建适配器实例
*/
export function createGiteaAdapter() {
return new GiteaMCPAdapter()
}
/**
* 导出单例
*/
export default createGiteaAdapter()