mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-11 03:23:50 +08:00
fix(codeagent-wrapper): add timeout for Windows process termination
- Add forceKillWaitTimeout (5s) to prevent cmd.Wait() blocking forever - Enhance sendTermSignal with killProcessTree fallback using wmic - Update omo README: remove sisyphus, fix model names, update config Fixes #115 Generated with SWE-Agent.ai Co-Authored-By: SWE-Agent.ai <noreply@swe-agent.ai>
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
)
|
||||
|
||||
const postMessageTerminateDelay = 1 * time.Second
|
||||
const forceKillWaitTimeout = 5 * time.Second
|
||||
|
||||
// commandRunner abstracts exec.Cmd for testability
|
||||
type commandRunner interface {
|
||||
@@ -1109,7 +1110,8 @@ func runCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
||||
waitLoop:
|
||||
for {
|
||||
select {
|
||||
case waitErr = <-waitCh:
|
||||
case err := <-waitCh:
|
||||
waitErr = err
|
||||
break waitLoop
|
||||
case <-ctx.Done():
|
||||
ctxCancelled = true
|
||||
@@ -1120,8 +1122,17 @@ waitLoop:
|
||||
terminated = true
|
||||
}
|
||||
}
|
||||
waitErr = <-waitCh
|
||||
break waitLoop
|
||||
for {
|
||||
select {
|
||||
case err := <-waitCh:
|
||||
waitErr = err
|
||||
break waitLoop
|
||||
case <-time.After(forceKillWaitTimeout):
|
||||
if proc := cmd.Process(); proc != nil {
|
||||
_ = proc.Kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
case <-messageTimerCh:
|
||||
forcedAfterComplete = true
|
||||
messageTimerCh = nil
|
||||
@@ -1135,8 +1146,17 @@ waitLoop:
|
||||
// Close pipes to unblock stream readers, then wait for process exit.
|
||||
closeWithReason(stdout, "terminate")
|
||||
closeWithReason(stderr, "terminate")
|
||||
waitErr = <-waitCh
|
||||
break waitLoop
|
||||
for {
|
||||
select {
|
||||
case err := <-waitCh:
|
||||
waitErr = err
|
||||
break waitLoop
|
||||
case <-time.After(forceKillWaitTimeout):
|
||||
if proc := cmd.Process(); proc != nil {
|
||||
_ = proc.Kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
case <-completeSeen:
|
||||
completeSeenObserved = true
|
||||
if messageTimer != nil {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// sendTermSignal on Windows directly kills the process.
|
||||
@@ -31,6 +32,56 @@ func sendTermSignal(proc processHandle) error {
|
||||
if err := cmd.Run(); err == nil {
|
||||
return nil
|
||||
}
|
||||
if err := killProcessTree(pid); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return proc.Kill()
|
||||
}
|
||||
|
||||
func killProcessTree(pid int) error {
|
||||
if pid <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
wmic := "wmic"
|
||||
if root := os.Getenv("SystemRoot"); root != "" {
|
||||
wmic = filepath.Join(root, "System32", "wbem", "WMIC.exe")
|
||||
}
|
||||
|
||||
queryChildren := "(ParentProcessId=" + strconv.Itoa(pid) + ")"
|
||||
listCmd := exec.Command(wmic, "process", "where", queryChildren, "get", "ProcessId", "/VALUE")
|
||||
listCmd.Stderr = io.Discard
|
||||
out, err := listCmd.Output()
|
||||
if err == nil {
|
||||
for _, childPID := range parseWMICPIDs(out) {
|
||||
_ = killProcessTree(childPID)
|
||||
}
|
||||
}
|
||||
|
||||
querySelf := "(ProcessId=" + strconv.Itoa(pid) + ")"
|
||||
termCmd := exec.Command(wmic, "process", "where", querySelf, "call", "terminate")
|
||||
termCmd.Stdout = io.Discard
|
||||
termCmd.Stderr = io.Discard
|
||||
if termErr := termCmd.Run(); termErr != nil && err == nil {
|
||||
err = termErr
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func parseWMICPIDs(out []byte) []int {
|
||||
const prefix = "ProcessId="
|
||||
var pids []int
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(line, prefix) {
|
||||
continue
|
||||
}
|
||||
n, err := strconv.Atoi(strings.TrimSpace(strings.TrimPrefix(line, prefix)))
|
||||
if err != nil || n <= 0 {
|
||||
continue
|
||||
}
|
||||
pids = append(pids, n)
|
||||
}
|
||||
return pids
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
# OmO Multi-Agent Orchestration
|
||||
|
||||
OmO (Oh-My-OpenCode) is a multi-agent orchestration skill that uses Sisyphus as the primary coordinator to delegate tasks to specialized agents.
|
||||
OmO (Oh-My-OpenCode) is a multi-agent orchestration skill that delegates tasks to specialized agents based on routing signals.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
python3 install.py --module omo
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -12,19 +18,17 @@ OmO (Oh-My-OpenCode) is a multi-agent orchestration skill that uses Sisyphus as
|
||||
|
||||
| Agent | Role | Backend | Model |
|
||||
|-------|------|---------|-------|
|
||||
| sisyphus | Primary orchestrator | claude | claude-sonnet-4-20250514 |
|
||||
| oracle | Technical advisor (EXPENSIVE) | claude | claude-sonnet-4-20250514 |
|
||||
| librarian | External research | claude | claude-sonnet-4-5-20250514 |
|
||||
| explore | Codebase search (FREE) | opencode | opencode/grok-code |
|
||||
| develop | Code implementation | codex | (default) |
|
||||
| frontend-ui-ux-engineer | UI/UX specialist | gemini | gemini-3-pro-preview |
|
||||
| document-writer | Documentation | gemini | gemini-3-flash-preview |
|
||||
| oracle | Technical advisor | claude | claude-opus-4-5-20251101 |
|
||||
| librarian | External research | claude | claude-sonnet-4-5-20250929 |
|
||||
| explore | Codebase search | opencode | opencode/grok-code |
|
||||
| develop | Code implementation | codex | gpt-5.2 |
|
||||
| frontend-ui-ux-engineer | UI/UX specialist | gemini | gemini-3-pro-high |
|
||||
| document-writer | Documentation | gemini | gemini-3-flash |
|
||||
|
||||
## How It Works
|
||||
|
||||
1. `/omo` loads Sisyphus as the entry point
|
||||
2. Sisyphus analyzes your request via routing signals
|
||||
3. Based on task type, Sisyphus either:
|
||||
1. `/omo` analyzes your request via routing signals
|
||||
2. Based on task type, it either:
|
||||
- Answers directly (analysis/explanation tasks - no code changes)
|
||||
- Delegates to specialized agents (implementation tasks)
|
||||
- Fires parallel agents (exploration + research)
|
||||
@@ -44,7 +48,7 @@ OmO (Oh-My-OpenCode) is a multi-agent orchestration skill that uses Sisyphus as
|
||||
|
||||
## Agent Delegation
|
||||
|
||||
Sisyphus delegates via codeagent-wrapper with full Context Pack:
|
||||
Delegates via codeagent-wrapper with full Context Pack:
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --agent oracle - . <<'EOF'
|
||||
@@ -70,11 +74,43 @@ Agent-model mappings are configured in `~/.codeagent/models.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"default_backend": "opencode",
|
||||
"default_model": "opencode/grok-code",
|
||||
"default_backend": "codex",
|
||||
"default_model": "gpt-5.2",
|
||||
"agents": {
|
||||
"sisyphus": {"backend": "claude", "model": "claude-sonnet-4-20250514"},
|
||||
"oracle": {"backend": "claude", "model": "claude-sonnet-4-20250514"}
|
||||
"oracle": {
|
||||
"backend": "claude",
|
||||
"model": "claude-opus-4-5-20251101",
|
||||
"description": "Technical advisor",
|
||||
"yolo": true
|
||||
},
|
||||
"librarian": {
|
||||
"backend": "claude",
|
||||
"model": "claude-sonnet-4-5-20250929",
|
||||
"description": "Researcher",
|
||||
"yolo": true
|
||||
},
|
||||
"explore": {
|
||||
"backend": "opencode",
|
||||
"model": "opencode/grok-code",
|
||||
"description": "Code search"
|
||||
},
|
||||
"frontend-ui-ux-engineer": {
|
||||
"backend": "gemini",
|
||||
"model": "gemini-3-pro-high",
|
||||
"description": "Frontend engineer"
|
||||
},
|
||||
"document-writer": {
|
||||
"backend": "gemini",
|
||||
"model": "gemini-3-flash",
|
||||
"description": "Documentation"
|
||||
},
|
||||
"develop": {
|
||||
"backend": "codex",
|
||||
"model": "gpt-5.2",
|
||||
"description": "codex develop",
|
||||
"yolo": true,
|
||||
"reasoning": "xhigh"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -82,4 +118,4 @@ Agent-model mappings are configured in `~/.codeagent/models.json`:
|
||||
## Requirements
|
||||
|
||||
- codeagent-wrapper with `--agent` support
|
||||
- Backend CLIs: claude, opencode, gemini
|
||||
- Backend CLIs: claude, opencode, codex, gemini
|
||||
|
||||
Reference in New Issue
Block a user