mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-12 03:27:47 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f08fa88d71 | ||
|
|
95408e7fa7 | ||
|
|
22987b5f74 | ||
|
|
90f9a131fe | ||
|
|
017ad5e4d9 | ||
|
|
15b4176afb |
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@@ -47,6 +47,10 @@ jobs:
|
|||||||
goarch: amd64
|
goarch: amd64
|
||||||
- goos: darwin
|
- goos: darwin
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
|
- goos: windows
|
||||||
|
goarch: amd64
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -58,6 +62,7 @@ jobs:
|
|||||||
go-version: '1.21'
|
go-version: '1.21'
|
||||||
|
|
||||||
- name: Build binary
|
- name: Build binary
|
||||||
|
id: build
|
||||||
working-directory: codex-wrapper
|
working-directory: codex-wrapper
|
||||||
env:
|
env:
|
||||||
GOOS: ${{ matrix.goos }}
|
GOOS: ${{ matrix.goos }}
|
||||||
@@ -66,14 +71,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
VERSION=${GITHUB_REF#refs/tags/}
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
OUTPUT_NAME=codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }}
|
OUTPUT_NAME=codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
|
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||||
|
OUTPUT_NAME="${OUTPUT_NAME}.exe"
|
||||||
|
fi
|
||||||
go build -ldflags="-s -w -X main.version=${VERSION}" -o ${OUTPUT_NAME} .
|
go build -ldflags="-s -w -X main.version=${VERSION}" -o ${OUTPUT_NAME} .
|
||||||
chmod +x ${OUTPUT_NAME}
|
chmod +x ${OUTPUT_NAME}
|
||||||
|
echo "artifact_path=codex-wrapper/${OUTPUT_NAME}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }}
|
name: codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
path: codex-wrapper/codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }}
|
path: ${{ steps.build.outputs.artifact_path }}
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
@@ -92,7 +101,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p release
|
mkdir -p release
|
||||||
find artifacts -type f -name "codex-wrapper-*" -exec mv {} release/ \;
|
find artifacts -type f -name "codex-wrapper-*" -exec mv {} release/ \;
|
||||||
cp install.sh release/
|
cp install.sh install.bat release/
|
||||||
ls -la release/
|
ls -la release/
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -23,7 +23,7 @@ This system leverages a **dual-agent architecture**:
|
|||||||
- Codex excels at focused code generation and execution
|
- Codex excels at focused code generation and execution
|
||||||
- Together they provide better results than either alone
|
- Together they provide better results than either alone
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start(Please execute in Powershell on Windows)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/cexll/myclaude.git
|
git clone https://github.com/cexll/myclaude.git
|
||||||
@@ -238,6 +238,33 @@ python3 install.py --module dev
|
|||||||
bash install.sh
|
bash install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Windows
|
||||||
|
|
||||||
|
Windows installs place `codex-wrapper.exe` in `%USERPROFILE%\bin`.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# PowerShell (recommended)
|
||||||
|
powershell -ExecutionPolicy Bypass -File install.ps1
|
||||||
|
|
||||||
|
# Batch (cmd)
|
||||||
|
install.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
**Add to PATH** (if installer doesn't detect it):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# PowerShell - persistent for current user
|
||||||
|
[Environment]::SetEnvironmentVariable('PATH', "$HOME\bin;" + [Environment]::GetEnvironmentVariable('PATH','User'), 'User')
|
||||||
|
|
||||||
|
# PowerShell - current session only
|
||||||
|
$Env:PATH = "$HOME\bin;$Env:PATH"
|
||||||
|
```
|
||||||
|
|
||||||
|
```batch
|
||||||
|
REM cmd.exe - persistent for current user
|
||||||
|
setx PATH "%USERPROFILE%\bin;%PATH%"
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Workflow Selection Guide
|
## Workflow Selection Guide
|
||||||
|
|||||||
29
README_CN.md
29
README_CN.md
@@ -20,7 +20,7 @@
|
|||||||
- Codex 擅长专注的代码生成和执行
|
- Codex 擅长专注的代码生成和执行
|
||||||
- 两者结合效果优于单独使用
|
- 两者结合效果优于单独使用
|
||||||
|
|
||||||
## 快速开始
|
## 快速开始(windows上请在Powershell中执行)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/cexll/myclaude.git
|
git clone https://github.com/cexll/myclaude.git
|
||||||
@@ -235,6 +235,33 @@ python3 install.py --module dev
|
|||||||
bash install.sh
|
bash install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Windows 系统
|
||||||
|
|
||||||
|
Windows 系统会将 `codex-wrapper.exe` 安装到 `%USERPROFILE%\bin`。
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# PowerShell(推荐)
|
||||||
|
powershell -ExecutionPolicy Bypass -File install.ps1
|
||||||
|
|
||||||
|
# 批处理(cmd)
|
||||||
|
install.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
**添加到 PATH**(如果安装程序未自动检测):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# PowerShell - 永久添加(当前用户)
|
||||||
|
[Environment]::SetEnvironmentVariable('PATH', "$HOME\bin;" + [Environment]::GetEnvironmentVariable('PATH','User'), 'User')
|
||||||
|
|
||||||
|
# PowerShell - 仅当前会话
|
||||||
|
$Env:PATH = "$HOME\bin;$Env:PATH"
|
||||||
|
```
|
||||||
|
|
||||||
|
```batch
|
||||||
|
REM cmd.exe - 永久添加(当前用户)
|
||||||
|
setx PATH "%USERPROFILE%\bin;%PATH%"
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 工作流选择指南
|
## 工作流选择指南
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -925,21 +926,30 @@ func (b *tailBuffer) String() string {
|
|||||||
|
|
||||||
func forwardSignals(ctx context.Context, cmd *exec.Cmd, logErrorFn func(string)) {
|
func forwardSignals(ctx context.Context, cmd *exec.Cmd, logErrorFn func(string)) {
|
||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
signals := []os.Signal{syscall.SIGINT}
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
signals = append(signals, syscall.SIGTERM)
|
||||||
|
}
|
||||||
|
signal.Notify(sigCh, signals...)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer signal.Stop(sigCh)
|
defer signal.Stop(sigCh)
|
||||||
select {
|
select {
|
||||||
case sig := <-sigCh:
|
case sig := <-sigCh:
|
||||||
logErrorFn(fmt.Sprintf("Received signal: %v", sig))
|
logErrorFn(fmt.Sprintf("Received signal: %v", sig))
|
||||||
if cmd.Process != nil {
|
if cmd.Process == nil {
|
||||||
cmd.Process.Signal(syscall.SIGTERM)
|
return
|
||||||
time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() {
|
|
||||||
if cmd.Process != nil {
|
|
||||||
cmd.Process.Kill()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
_ = cmd.Process.Kill()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = cmd.Process.Signal(syscall.SIGTERM)
|
||||||
|
time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() {
|
||||||
|
if cmd.Process != nil {
|
||||||
|
_ = cmd.Process.Kill()
|
||||||
|
}
|
||||||
|
})
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -962,6 +972,11 @@ func terminateProcess(cmd *exec.Cmd) *time.Timer {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
_ = cmd.Process.Kill()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
_ = cmd.Process.Signal(syscall.SIGTERM)
|
_ = cmd.Process.Signal(syscall.SIGTERM)
|
||||||
|
|
||||||
return time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() {
|
return time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() {
|
||||||
|
|||||||
163
install.bat
Normal file
163
install.bat
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
set "EXIT_CODE=0"
|
||||||
|
set "REPO=cexll/myclaude"
|
||||||
|
set "VERSION=latest"
|
||||||
|
set "OS=windows"
|
||||||
|
|
||||||
|
call :detect_arch
|
||||||
|
if errorlevel 1 goto :fail
|
||||||
|
|
||||||
|
set "BINARY_NAME=codex-wrapper-%OS%-%ARCH%.exe"
|
||||||
|
set "URL=https://github.com/%REPO%/releases/%VERSION%/download/%BINARY_NAME%"
|
||||||
|
set "TEMP_FILE=%TEMP%\codex-wrapper-%ARCH%-%RANDOM%.exe"
|
||||||
|
set "DEST_DIR=%USERPROFILE%\bin"
|
||||||
|
set "DEST=%DEST_DIR%\codex-wrapper.exe"
|
||||||
|
|
||||||
|
echo Downloading codex-wrapper for %ARCH% ...
|
||||||
|
echo %URL%
|
||||||
|
call :download
|
||||||
|
if errorlevel 1 goto :fail
|
||||||
|
|
||||||
|
if not exist "%TEMP_FILE%" (
|
||||||
|
echo ERROR: download failed to produce "%TEMP_FILE%".
|
||||||
|
goto :fail
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Installing to "%DEST%" ...
|
||||||
|
if not exist "%DEST_DIR%" (
|
||||||
|
mkdir "%DEST_DIR%" >nul 2>nul || goto :fail
|
||||||
|
)
|
||||||
|
|
||||||
|
move /y "%TEMP_FILE%" "%DEST%" >nul 2>nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo ERROR: unable to place file in "%DEST%".
|
||||||
|
goto :fail
|
||||||
|
)
|
||||||
|
|
||||||
|
"%DEST%" --version >nul 2>nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo ERROR: installation verification failed.
|
||||||
|
goto :fail
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo codex-wrapper installed successfully at:
|
||||||
|
echo %DEST%
|
||||||
|
|
||||||
|
rem Automatically ensure %USERPROFILE%\bin is in the USER (HKCU) PATH
|
||||||
|
rem 1) Read current user PATH from registry (REG_SZ or REG_EXPAND_SZ)
|
||||||
|
set "USER_PATH_RAW="
|
||||||
|
set "USER_PATH_TYPE="
|
||||||
|
for /f "tokens=1,2,*" %%A in ('reg query "HKCU\Environment" /v Path 2^>nul ^| findstr /I /R "^ *Path *REG_"') do (
|
||||||
|
set "USER_PATH_TYPE=%%B"
|
||||||
|
set "USER_PATH_RAW=%%C"
|
||||||
|
)
|
||||||
|
rem Trim leading spaces from USER_PATH_RAW
|
||||||
|
for /f "tokens=* delims= " %%D in ("!USER_PATH_RAW!") do set "USER_PATH_RAW=%%D"
|
||||||
|
|
||||||
|
rem Normalize DEST_DIR by removing a trailing backslash if present
|
||||||
|
if "!DEST_DIR:~-1!"=="\" set "DEST_DIR=!DEST_DIR:~0,-1!"
|
||||||
|
|
||||||
|
rem Build search tokens (expanded and literal)
|
||||||
|
set "PCT=%%"
|
||||||
|
set "SEARCH_EXP=;!DEST_DIR!;"
|
||||||
|
set "SEARCH_EXP2=;!DEST_DIR!\;"
|
||||||
|
set "SEARCH_LIT=;!PCT!USERPROFILE!PCT!\bin;"
|
||||||
|
set "SEARCH_LIT2=;!PCT!USERPROFILE!PCT!\bin\;"
|
||||||
|
|
||||||
|
rem Prepare user PATH variants for containment tests
|
||||||
|
set "CHECK_RAW=;!USER_PATH_RAW!;"
|
||||||
|
set "USER_PATH_EXP=!USER_PATH_RAW!"
|
||||||
|
if defined USER_PATH_EXP call set "USER_PATH_EXP=%%USER_PATH_EXP%%"
|
||||||
|
set "CHECK_EXP=;!USER_PATH_EXP!;"
|
||||||
|
|
||||||
|
rem Check if already present in user PATH (literal or expanded, with/without trailing backslash)
|
||||||
|
set "ALREADY_IN_USERPATH=0"
|
||||||
|
echo !CHECK_RAW! | findstr /I /C:"!SEARCH_LIT!" /C:"!SEARCH_LIT2!" >nul && set "ALREADY_IN_USERPATH=1"
|
||||||
|
if "!ALREADY_IN_USERPATH!"=="0" (
|
||||||
|
echo !CHECK_EXP! | findstr /I /C:"!SEARCH_EXP!" /C:"!SEARCH_EXP2!" >nul && set "ALREADY_IN_USERPATH=1"
|
||||||
|
)
|
||||||
|
|
||||||
|
if "!ALREADY_IN_USERPATH!"=="1" (
|
||||||
|
echo User PATH already includes %%USERPROFILE%%\bin.
|
||||||
|
) else (
|
||||||
|
rem Not present: append to user PATH using setx without duplicating system PATH
|
||||||
|
if defined USER_PATH_RAW (
|
||||||
|
set "USER_PATH_NEW=!USER_PATH_RAW!"
|
||||||
|
if not "!USER_PATH_NEW:~-1!"==";" set "USER_PATH_NEW=!USER_PATH_NEW!;"
|
||||||
|
set "USER_PATH_NEW=!USER_PATH_NEW!!PCT!USERPROFILE!PCT!\bin"
|
||||||
|
) else (
|
||||||
|
set "USER_PATH_NEW=!PCT!USERPROFILE!PCT!\bin"
|
||||||
|
)
|
||||||
|
rem Persist update to HKCU\Environment\Path (user scope)
|
||||||
|
setx PATH "!USER_PATH_NEW!" >nul
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo WARNING: Failed to append %%USERPROFILE%%\bin to your user PATH.
|
||||||
|
) else (
|
||||||
|
echo Added %%USERPROFILE%%\bin to your user PATH.
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
rem Update current session PATH so codex-wrapper is immediately available
|
||||||
|
set "CURPATH=;%PATH%;"
|
||||||
|
echo !CURPATH! | findstr /I /C:"!SEARCH_EXP!" /C:"!SEARCH_EXP2!" /C:"!SEARCH_LIT!" /C:"!SEARCH_LIT2!" >nul
|
||||||
|
if errorlevel 1 set "PATH=!DEST_DIR!;!PATH!"
|
||||||
|
|
||||||
|
goto :cleanup
|
||||||
|
|
||||||
|
:detect_arch
|
||||||
|
set "ARCH=%PROCESSOR_ARCHITECTURE%"
|
||||||
|
if defined PROCESSOR_ARCHITEW6432 set "ARCH=%PROCESSOR_ARCHITEW6432%"
|
||||||
|
|
||||||
|
if /I "%ARCH%"=="AMD64" (
|
||||||
|
set "ARCH=amd64"
|
||||||
|
exit /b 0
|
||||||
|
) else if /I "%ARCH%"=="ARM64" (
|
||||||
|
set "ARCH=arm64"
|
||||||
|
exit /b 0
|
||||||
|
) else (
|
||||||
|
echo ERROR: unsupported architecture "%ARCH%". 64-bit Windows on AMD64 or ARM64 is required.
|
||||||
|
set "EXIT_CODE=1"
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
:download
|
||||||
|
where curl >nul 2>nul
|
||||||
|
if %errorlevel%==0 (
|
||||||
|
echo Using curl ...
|
||||||
|
curl -fL --retry 3 --connect-timeout 10 "%URL%" -o "%TEMP_FILE%"
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo ERROR: curl download failed.
|
||||||
|
set "EXIT_CODE=1"
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
where powershell >nul 2>nul
|
||||||
|
if %errorlevel%==0 (
|
||||||
|
echo Using PowerShell ...
|
||||||
|
powershell -NoLogo -NoProfile -Command " $ErrorActionPreference='Stop'; try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072 -bor 768 -bor 192 } catch {} ; $wc = New-Object System.Net.WebClient; $wc.DownloadFile('%URL%','%TEMP_FILE%') "
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo ERROR: PowerShell download failed.
|
||||||
|
set "EXIT_CODE=1"
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
echo ERROR: neither curl nor PowerShell is available to download the installer.
|
||||||
|
set "EXIT_CODE=1"
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:fail
|
||||||
|
echo Installation failed.
|
||||||
|
set "EXIT_CODE=1"
|
||||||
|
goto :cleanup
|
||||||
|
|
||||||
|
:cleanup
|
||||||
|
if exist "%TEMP_FILE%" del /f /q "%TEMP_FILE%" >nul 2>nul
|
||||||
|
set "CODE=%EXIT_CODE%"
|
||||||
|
endlocal & exit /b %CODE%
|
||||||
@@ -285,6 +285,8 @@ def op_run_command(op: Dict[str, Any], ctx: Dict[str, Any]) -> None:
|
|||||||
env[key] = value.replace("${install_dir}", str(ctx["install_dir"]))
|
env[key] = value.replace("${install_dir}", str(ctx["install_dir"]))
|
||||||
|
|
||||||
command = op.get("command", "")
|
command = op.get("command", "")
|
||||||
|
if sys.platform == "win32" and command.strip() == "bash install.sh":
|
||||||
|
command = "cmd /c install.bat"
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
command,
|
command,
|
||||||
shell=True,
|
shell=True,
|
||||||
|
|||||||
Reference in New Issue
Block a user