Claude Code + Codex + Gemini 多模型协作工作流系统 ## 核心功能 - 6阶段开发工作流 (/ccg:dev) - 智能路由:前端→Gemini,后端→Codex - Prompt 增强 (Auggie MCP prompt-enhancer) - 双模型代码审查和技术分析 ## 命令列表 - /ccg:dev - 完整开发工作流 - /ccg:frontend - 前端任务 - /ccg:backend - 后端任务 - /ccg:review - 代码审查 - /ccg:analyze - 技术分析 - /ccg:enhance - Prompt 增强 - /ccg:commit - 智能提交 - /ccg:rollback - 交互式回滚 - /ccg:clean-branches - 清理分支 - /ccg:worktree - Worktree 管理 - /ccg:init - 项目初始化 ## 特性 - 预编译二进制(无需 Go 环境) - 专家系统提示词(Codex/Gemini) - 一键安装脚本
88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"syscall"
|
|
"time"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
processQueryLimitedInformation = 0x1000
|
|
stillActive = 259 // STILL_ACTIVE exit code
|
|
)
|
|
|
|
var (
|
|
findProcess = os.FindProcess
|
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
getProcessTimes = kernel32.NewProc("GetProcessTimes")
|
|
fileTimeToUnixFn = fileTimeToUnix
|
|
)
|
|
|
|
// isProcessRunning returns true if a process with the given pid is running on Windows.
|
|
func isProcessRunning(pid int) bool {
|
|
if pid <= 0 {
|
|
return false
|
|
}
|
|
|
|
if _, err := findProcess(pid); err != nil {
|
|
return false
|
|
}
|
|
|
|
handle, err := syscall.OpenProcess(processQueryLimitedInformation, false, uint32(pid))
|
|
if err != nil {
|
|
if errors.Is(err, syscall.ERROR_ACCESS_DENIED) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
defer syscall.CloseHandle(handle)
|
|
|
|
var exitCode uint32
|
|
if err := syscall.GetExitCodeProcess(handle, &exitCode); err != nil {
|
|
return true
|
|
}
|
|
|
|
return exitCode == stillActive
|
|
}
|
|
|
|
// getProcessStartTime returns the start time of a process on Windows.
|
|
// Returns zero time if the start time cannot be determined.
|
|
func getProcessStartTime(pid int) time.Time {
|
|
if pid <= 0 {
|
|
return time.Time{}
|
|
}
|
|
|
|
handle, err := syscall.OpenProcess(processQueryLimitedInformation, false, uint32(pid))
|
|
if err != nil {
|
|
return time.Time{}
|
|
}
|
|
defer syscall.CloseHandle(handle)
|
|
|
|
var creationTime, exitTime, kernelTime, userTime syscall.Filetime
|
|
ret, _, _ := getProcessTimes.Call(
|
|
uintptr(handle),
|
|
uintptr(unsafe.Pointer(&creationTime)),
|
|
uintptr(unsafe.Pointer(&exitTime)),
|
|
uintptr(unsafe.Pointer(&kernelTime)),
|
|
uintptr(unsafe.Pointer(&userTime)),
|
|
)
|
|
|
|
if ret == 0 {
|
|
return time.Time{}
|
|
}
|
|
|
|
return fileTimeToUnixFn(creationTime)
|
|
}
|
|
|
|
// fileTimeToUnix converts Windows FILETIME to Unix time.
|
|
func fileTimeToUnix(ft syscall.Filetime) time.Time {
|
|
// FILETIME is 100-nanosecond intervals since January 1, 1601 UTC
|
|
nsec := ft.Nanoseconds()
|
|
return time.Unix(0, nsec)
|
|
}
|