fix: make docs i18n use gpt-5.4 overrides
This commit is contained in:
parent
3c6a49b27e
commit
edab939f4d
@ -73,8 +73,8 @@ func startDocsPiClient(ctx context.Context, options docsPiClientOptions) (*docsP
|
||||
args := append([]string{}, command.Args...)
|
||||
args = append(args,
|
||||
"--mode", "rpc",
|
||||
"--provider", "anthropic",
|
||||
"--model", modelVersion,
|
||||
"--provider", docsPiProvider(),
|
||||
"--model", docsPiModel(),
|
||||
"--thinking", options.Thinking,
|
||||
"--no-session",
|
||||
)
|
||||
|
||||
@ -64,8 +64,8 @@ func processFile(ctx context.Context, translator *PiTranslator, tm *TranslationM
|
||||
TextHash: seg.TextHash,
|
||||
Text: seg.Text,
|
||||
Translated: translated,
|
||||
Provider: providerName,
|
||||
Model: modelVersion,
|
||||
Provider: docsPiProvider(),
|
||||
Model: docsPiModel(),
|
||||
SrcLang: srcLang,
|
||||
TgtLang: tgtLang,
|
||||
UpdatedAt: time.Now().UTC().Format(time.RFC3339),
|
||||
@ -121,8 +121,8 @@ func encodeFrontMatter(frontData map[string]any, relPath string, source []byte)
|
||||
frontData["x-i18n"] = map[string]any{
|
||||
"source_path": relPath,
|
||||
"source_hash": hashBytes(source),
|
||||
"provider": providerName,
|
||||
"model": modelVersion,
|
||||
"provider": docsPiProvider(),
|
||||
"model": docsPiModel(),
|
||||
"workflow": workflowVersion,
|
||||
"generated_at": time.Now().UTC().Format(time.RFC3339),
|
||||
}
|
||||
@ -191,8 +191,8 @@ func translateSnippet(ctx context.Context, translator *PiTranslator, tm *Transla
|
||||
TextHash: textHash,
|
||||
Text: textValue,
|
||||
Translated: translated,
|
||||
Provider: providerName,
|
||||
Model: modelVersion,
|
||||
Provider: docsPiProvider(),
|
||||
Model: docsPiModel(),
|
||||
SrcLang: srcLang,
|
||||
TgtLang: tgtLang,
|
||||
UpdatedAt: time.Now().UTC().Format(time.RFC3339),
|
||||
|
||||
@ -4,14 +4,16 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
translateMaxAttempts = 3
|
||||
translateBaseDelay = 15 * time.Second
|
||||
translatePromptTimeout = 2 * time.Minute
|
||||
translateMaxAttempts = 3
|
||||
translateBaseDelay = 15 * time.Second
|
||||
defaultPromptTimeout = 2 * time.Minute
|
||||
envDocsI18nPromptTimeout = "OPENCLAW_DOCS_I18N_PROMPT_TIMEOUT"
|
||||
)
|
||||
|
||||
var errEmptyTranslation = errors.New("empty translation")
|
||||
@ -112,10 +114,16 @@ func isRetryableTranslateError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
|
||||
return false
|
||||
}
|
||||
if errors.Is(err, errEmptyTranslation) {
|
||||
return true
|
||||
}
|
||||
message := strings.ToLower(err.Error())
|
||||
if strings.Contains(message, "authentication failed") {
|
||||
return false
|
||||
}
|
||||
return strings.Contains(message, "placeholder missing") || strings.Contains(message, "rate limit") || strings.Contains(message, "429")
|
||||
}
|
||||
|
||||
@ -142,7 +150,7 @@ type promptRunner interface {
|
||||
}
|
||||
|
||||
func runPrompt(ctx context.Context, client promptRunner, message string) (string, error) {
|
||||
promptCtx, cancel := context.WithTimeout(ctx, translatePromptTimeout)
|
||||
promptCtx, cancel := context.WithTimeout(ctx, docsI18nPromptTimeout())
|
||||
defer cancel()
|
||||
|
||||
result, err := client.Prompt(promptCtx, message)
|
||||
@ -171,3 +179,15 @@ func normalizeThinking(value string) string {
|
||||
return "high"
|
||||
}
|
||||
}
|
||||
|
||||
func docsI18nPromptTimeout() time.Duration {
|
||||
value := strings.TrimSpace(os.Getenv(envDocsI18nPromptTimeout))
|
||||
if value == "" {
|
||||
return defaultPromptTimeout
|
||||
}
|
||||
parsed, err := time.ParseDuration(value)
|
||||
if err != nil || parsed <= 0 {
|
||||
return defaultPromptTimeout
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
@ -50,11 +50,35 @@ func TestRunPromptAddsTimeout(t *testing.T) {
|
||||
}
|
||||
|
||||
remaining := time.Until(deadline)
|
||||
if remaining <= time.Minute || remaining > translatePromptTimeout {
|
||||
if remaining <= time.Minute || remaining > docsI18nPromptTimeout() {
|
||||
t.Fatalf("unexpected timeout window %s", remaining)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocsI18nPromptTimeoutUsesEnvOverride(t *testing.T) {
|
||||
t.Setenv(envDocsI18nPromptTimeout, "5m")
|
||||
|
||||
if got := docsI18nPromptTimeout(); got != 5*time.Minute {
|
||||
t.Fatalf("expected 5m timeout, got %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsRetryableTranslateErrorRejectsDeadlineExceeded(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if isRetryableTranslateError(context.DeadlineExceeded) {
|
||||
t.Fatal("deadline exceeded should not retry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsRetryableTranslateErrorRejectsAuthenticationFailures(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if isRetryableTranslateError(errors.New(`Authentication failed for "openai"`)) {
|
||||
t.Fatal("auth failures should not retry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPromptIncludesStderr(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@ -10,13 +10,24 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
workflowVersion = 15
|
||||
providerName = "pi"
|
||||
modelVersion = "claude-opus-4-6"
|
||||
workflowVersion = 15
|
||||
docsI18nEngineName = "pi"
|
||||
envDocsI18nProvider = "OPENCLAW_DOCS_I18N_PROVIDER"
|
||||
envDocsI18nModel = "OPENCLAW_DOCS_I18N_MODEL"
|
||||
defaultOpenAIModel = "gpt-5.4"
|
||||
defaultAnthropicModel = "claude-opus-4-6"
|
||||
defaultFallbackProvider = "openai"
|
||||
defaultFallbackModelName = defaultOpenAIModel
|
||||
)
|
||||
|
||||
func cacheNamespace() string {
|
||||
return fmt.Sprintf("wf=%d|provider=%s|model=%s", workflowVersion, providerName, modelVersion)
|
||||
return fmt.Sprintf(
|
||||
"wf=%d|engine=%s|provider=%s|model=%s",
|
||||
workflowVersion,
|
||||
docsI18nEngineName,
|
||||
docsPiProvider(),
|
||||
docsPiModel(),
|
||||
)
|
||||
}
|
||||
|
||||
func cacheKey(namespace, srcLang, tgtLang, segmentID, textHash string) string {
|
||||
@ -40,6 +51,33 @@ func normalizeText(text string) string {
|
||||
return strings.Join(strings.Fields(strings.TrimSpace(text)), " ")
|
||||
}
|
||||
|
||||
func docsPiProvider() string {
|
||||
if value := strings.TrimSpace(os.Getenv(envDocsI18nProvider)); value != "" {
|
||||
return value
|
||||
}
|
||||
if strings.TrimSpace(os.Getenv("OPENAI_API_KEY")) != "" {
|
||||
return "openai"
|
||||
}
|
||||
if strings.TrimSpace(os.Getenv("ANTHROPIC_API_KEY")) != "" {
|
||||
return "anthropic"
|
||||
}
|
||||
return defaultFallbackProvider
|
||||
}
|
||||
|
||||
func docsPiModel() string {
|
||||
if value := strings.TrimSpace(os.Getenv(envDocsI18nModel)); value != "" {
|
||||
return value
|
||||
}
|
||||
switch docsPiProvider() {
|
||||
case "anthropic":
|
||||
return defaultAnthropicModel
|
||||
case "openai":
|
||||
return defaultOpenAIModel
|
||||
default:
|
||||
return defaultFallbackModelName
|
||||
}
|
||||
}
|
||||
|
||||
func segmentID(relPath, textHash string) string {
|
||||
shortHash := textHash
|
||||
if len(shortHash) > 16 {
|
||||
|
||||
41
scripts/docs-i18n/util_test.go
Normal file
41
scripts/docs-i18n/util_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDocsPiProviderPrefersExplicitOverride(t *testing.T) {
|
||||
t.Setenv(envDocsI18nProvider, "anthropic")
|
||||
t.Setenv("OPENAI_API_KEY", "openai-key")
|
||||
t.Setenv("ANTHROPIC_API_KEY", "anthropic-key")
|
||||
|
||||
if got := docsPiProvider(); got != "anthropic" {
|
||||
t.Fatalf("expected anthropic override, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocsPiProviderPrefersOpenAIEnvWhenAvailable(t *testing.T) {
|
||||
t.Setenv(envDocsI18nProvider, "")
|
||||
t.Setenv("OPENAI_API_KEY", "openai-key")
|
||||
t.Setenv("ANTHROPIC_API_KEY", "anthropic-key")
|
||||
|
||||
if got := docsPiProvider(); got != "openai" {
|
||||
t.Fatalf("expected openai provider, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocsPiModelUsesProviderDefault(t *testing.T) {
|
||||
t.Setenv(envDocsI18nProvider, "anthropic")
|
||||
t.Setenv(envDocsI18nModel, "")
|
||||
|
||||
if got := docsPiModel(); got != defaultAnthropicModel {
|
||||
t.Fatalf("expected anthropic default model, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocsPiModelPrefersExplicitOverride(t *testing.T) {
|
||||
t.Setenv(envDocsI18nProvider, "openai")
|
||||
t.Setenv(envDocsI18nModel, "gpt-5.2")
|
||||
|
||||
if got := docsPiModel(); got != "gpt-5.2" {
|
||||
t.Fatalf("expected explicit model override, got %q", got)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user