feat: 添加 GitHub 集成命令(issue、share、autofix-pr)

- /issue: 通过 gh CLI 创建 GitHub issue,支持标签/指派
- /share: 会话日志分享到 GitHub Gist,支持密钥脱敏
- /autofix-pr: 自动修复 CI 失败的 PR,进度追踪
- launchCommand: 共享命令启动器

Co-Authored-By: glm-5-turbo <zai-org@claude-code-best.win>
This commit is contained in:
claude-code-best
2026-05-09 23:04:23 +08:00
parent 4f0aa8615a
commit 6766f08e47
27 changed files with 5019 additions and 6 deletions

View File

@@ -0,0 +1,59 @@
type MonitorState = {
taskId: string
owner: string
repo: string
prNumber: number
abortController: AbortController
startedAt: number
}
let active: MonitorState | null = null
export function getActiveMonitor(): Readonly<MonitorState> | null {
return active
}
/**
* Atomic check-and-set. Returns true if the lock was acquired, false if a
* monitor is already active. Use this instead of getActiveMonitor + setActiveMonitor
* — those two together race because the caller may await between them.
*/
export function trySetActiveMonitor(state: MonitorState): boolean {
if (active) return false
active = state
return true
}
/**
* Sets the active monitor unconditionally. Throws if a monitor is already
* active. Prefer trySetActiveMonitor for race-free acquisition.
*/
export function setActiveMonitor(state: MonitorState): void {
if (active)
throw new Error(`Monitor already active: ${active.repo}#${active.prNumber}`)
active = state
}
/**
* Releases the active monitor. If `taskId` is provided, only releases when the
* active monitor's taskId matches — prevents a late-arriving cleanup from
* clobbering a freshly-acquired lock owned by a different task.
*/
export function clearActiveMonitor(taskId?: string): void {
if (!active) return
if (taskId && active.taskId !== taskId) return
active.abortController.abort()
active = null
}
export function isMonitoring(
owner: string,
repo: string,
prNumber: number,
): boolean {
return (
active?.owner === owner &&
active?.repo === repo &&
active?.prNumber === prNumber
)
}