mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:30:42 +00:00
fix(docs): bound i18n codex prompt cleanup
This commit is contained in:
25
scripts/docs-i18n/codex_command_unix.go
Normal file
25
scripts/docs-i18n/codex_command_unix.go
Normal file
@@ -0,0 +1,25 @@
|
||||
//go:build !windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func configureCodexPromptCommand(command *exec.Cmd) {
|
||||
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
command.Cancel = func() error {
|
||||
if command.Process == nil {
|
||||
return os.ErrProcessDone
|
||||
}
|
||||
err := syscall.Kill(-command.Process.Pid, syscall.SIGKILL)
|
||||
if errors.Is(err, syscall.ESRCH) {
|
||||
return os.ErrProcessDone
|
||||
}
|
||||
return err
|
||||
}
|
||||
command.WaitDelay = docsI18nCommandWaitDelay()
|
||||
}
|
||||
9
scripts/docs-i18n/codex_command_windows.go
Normal file
9
scripts/docs-i18n/codex_command_windows.go
Normal file
@@ -0,0 +1,9 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
import "os/exec"
|
||||
|
||||
func configureCodexPromptCommand(command *exec.Cmd) {
|
||||
command.WaitDelay = docsI18nCommandWaitDelay()
|
||||
}
|
||||
@@ -14,11 +14,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
translateMaxAttempts = 3
|
||||
translateBaseDelay = 15 * time.Second
|
||||
defaultPromptTimeout = 2 * time.Minute
|
||||
envDocsI18nPromptTimeout = "OPENCLAW_DOCS_I18N_PROMPT_TIMEOUT"
|
||||
envDocsI18nCodexExecutable = "OPENCLAW_DOCS_I18N_CODEX_EXECUTABLE"
|
||||
translateMaxAttempts = 3
|
||||
translateBaseDelay = 15 * time.Second
|
||||
defaultPromptTimeout = 2 * time.Minute
|
||||
defaultCommandWaitDelay = 15 * time.Second
|
||||
envDocsI18nPromptTimeout = "OPENCLAW_DOCS_I18N_PROMPT_TIMEOUT"
|
||||
envDocsI18nCommandWaitDelay = "OPENCLAW_DOCS_I18N_COMMAND_WAIT_DELAY"
|
||||
envDocsI18nCodexExecutable = "OPENCLAW_DOCS_I18N_CODEX_EXECUTABLE"
|
||||
)
|
||||
|
||||
var errEmptyTranslation = errors.New("empty translation")
|
||||
@@ -214,6 +216,7 @@ func runCodexExecPrompt(ctx context.Context, req codexPromptRequest) (string, er
|
||||
"-",
|
||||
}
|
||||
command := exec.CommandContext(ctx, docsCodexExecutable(), args...)
|
||||
configureCodexPromptCommand(command)
|
||||
command.Stdin = strings.NewReader(buildCodexTranslationPrompt(req.SystemPrompt, req.Message))
|
||||
command.Env = append(os.Environ(), "CODEX_HOME="+codexHome)
|
||||
var stdout bytes.Buffer
|
||||
@@ -327,3 +330,15 @@ func docsI18nPromptTimeout() time.Duration {
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
func docsI18nCommandWaitDelay() time.Duration {
|
||||
value := strings.TrimSpace(os.Getenv(envDocsI18nCommandWaitDelay))
|
||||
if value == "" {
|
||||
return defaultCommandWaitDelay
|
||||
}
|
||||
parsed, err := time.ParseDuration(value)
|
||||
if err != nil || parsed <= 0 {
|
||||
return defaultCommandWaitDelay
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
@@ -56,6 +56,14 @@ func TestDocsI18nPromptTimeoutUsesEnvOverride(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocsI18nCommandWaitDelayUsesEnvOverride(t *testing.T) {
|
||||
t.Setenv(envDocsI18nCommandWaitDelay, "50ms")
|
||||
|
||||
if got := docsI18nCommandWaitDelay(); got != 50*time.Millisecond {
|
||||
t.Fatalf("expected 50ms wait delay, got %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsRetryableTranslateErrorRejectsDeadlineExceeded(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -235,6 +243,37 @@ printf 'translated from codex\n' > "$out"
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCodexExecPromptDoesNotHangOnInheritedPipesAfterTimeout(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
fakeCodex := filepath.Join(dir, "codex")
|
||||
if err := os.WriteFile(fakeCodex, []byte(`#!/bin/sh
|
||||
set -eu
|
||||
(sleep 10) &
|
||||
sleep 10
|
||||
`), 0o755); err != nil {
|
||||
t.Fatalf("write fake codex: %v", err)
|
||||
}
|
||||
t.Setenv(envDocsI18nCodexExecutable, fakeCodex)
|
||||
t.Setenv(envDocsI18nCommandWaitDelay, "20ms")
|
||||
t.Setenv("OPENAI_API_KEY", "test-openai-key")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond)
|
||||
defer cancel()
|
||||
started := time.Now()
|
||||
_, err := runCodexExecPrompt(ctx, codexPromptRequest{
|
||||
SystemPrompt: "Translate.",
|
||||
Message: "Hello",
|
||||
Model: "gpt-5.5",
|
||||
Thinking: "high",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected timeout error")
|
||||
}
|
||||
if elapsed := time.Since(started); elapsed > 2*time.Second {
|
||||
t.Fatalf("expected bounded timeout, took %s", elapsed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreviewCommandOutputFlattensAndTruncates(t *testing.T) {
|
||||
input := "line one\n\nline two\tline three " + strings.Repeat("x", 600)
|
||||
preview := previewCommandOutput(input, "")
|
||||
|
||||
Reference in New Issue
Block a user