fix: adapt openclaw wait timeout by task

This commit is contained in:
Haitao Pan 2026-05-23 13:45:41 +08:00
parent d13f7f54c2
commit 1805ce1994
4 changed files with 82 additions and 10 deletions

View File

@ -22,7 +22,9 @@ type SessionOrchestrator struct {
}
const (
openClawAgentWaitTimeout = 9 * time.Minute
openClawAgentWaitDefaultTimeout = 6 * time.Minute
openClawAgentWaitMaxTimeout = 18 * time.Minute
openClawAgentWaitHTTPMargin = time.Minute
openClawNoDisplayableText = "OpenClaw completed without displayable output."
openClawArtifactExportAttemptedField = "_openClawArtifactExportAttempted"
)
@ -360,15 +362,16 @@ func (o *SessionOrchestrator) runOpenClawGatewayChat(
}
logOpenClawArtifactSync(gatewayProvider, sessionKey, runID, "prepare", true, false, false)
}
waitTimeout := openClawAgentWaitTimeout(params, chatParams)
waitStarted := time.Now()
waitResult := o.openClawGatewayRequestWithRetry(
gatewayProvider,
"agent.wait",
map[string]any{
"runId": runID,
"timeoutMs": openClawAgentWaitTimeout.Milliseconds(),
"timeoutMs": waitTimeout.Milliseconds(),
},
openClawAgentWaitTimeout,
waitTimeout,
notifyWithCollection,
)
logOpenClawGatewayTiming(
@ -630,6 +633,48 @@ func openClawChatSendParams(
return chatParams, nil
}
func openClawAgentWaitTimeout(params map[string]any, chatParams map[string]any) time.Duration {
message := strings.TrimSpace(shared.StringArg(chatParams, "message", ""))
if message == "" {
message = openClawCurrentTurnMessage(params)
}
timeout := openClawAgentWaitDefaultTimeout
lowerMessage := strings.ToLower(message)
for _, keyword := range []string{
"video",
"mp4",
"hyperframes",
"remotion",
"ffmpeg",
"render",
"视频",
"渲染",
"口播",
"字幕",
} {
if strings.Contains(lowerMessage, keyword) {
timeout += 8 * time.Minute
break
}
}
if strings.Contains(lowerMessage, "it-infra-evolution-video") ||
strings.Contains(lowerMessage, "ai-tech-news-video") ||
strings.Contains(lowerMessage, "product-intro-video") {
timeout += 4 * time.Minute
}
if len([]rune(message)) > 1200 {
timeout += 2 * time.Minute
}
if attachments := shared.ListArg(params, "attachments"); len(attachments) > 0 {
timeout += time.Duration(min(len(attachments), 6)) * time.Minute
}
if timeout > openClawAgentWaitMaxTimeout {
return openClawAgentWaitMaxTimeout
}
return timeout
}
func openClawCurrentTurnMessage(params map[string]any) string {
if params == nil {
return ""

View File

@ -521,8 +521,8 @@ func TestExecuteSessionTaskGatewayAutoConnectsLocalOpenClaw(t *testing.T) {
if !ok {
t.Fatalf("expected numeric OpenClaw agent.wait timeoutMs, got %#v", waitParams)
}
if got := int64(timeoutMs); got != openClawAgentWaitTimeout.Milliseconds() {
t.Fatalf("expected OpenClaw agent.wait timeoutMs %d, got %#v", openClawAgentWaitTimeout.Milliseconds(), waitParams)
if got := int64(timeoutMs); got != openClawAgentWaitDefaultTimeout.Milliseconds() {
t.Fatalf("expected default OpenClaw agent.wait timeoutMs %d, got %#v", openClawAgentWaitDefaultTimeout.Milliseconds(), waitParams)
}
if got := int64(timeoutMs); got <= 120000 {
t.Fatalf("expected OpenClaw agent.wait timeout to exceed the previous 120s cap, got %#v", waitParams)
@ -542,6 +542,33 @@ func TestExecuteSessionTaskGatewayAutoConnectsLocalOpenClaw(t *testing.T) {
}
}
func TestOpenClawAgentWaitTimeoutAdaptsToVideoWork(t *testing.T) {
base := openClawAgentWaitTimeout(
map[string]any{"taskPrompt": "say pong"},
map[string]any{"message": "say pong"},
)
video := openClawAgentWaitTimeout(
map[string]any{
"taskPrompt": "测试制作 云原生ServiceMesh网络 主题的 科普视频,使用 it-infra-evolution-video skill 渲染 mp4",
"attachments": []any{
map[string]any{"path": "assets/images/001.png"},
map[string]any{"path": "assets/images/002.png"},
},
},
map[string]any{"message": "测试制作 云原生ServiceMesh网络 主题的 科普视频,使用 it-infra-evolution-video skill 渲染 mp4"},
)
if base != openClawAgentWaitDefaultTimeout {
t.Fatalf("expected simple task to use default timeout, got %s", base)
}
if video <= base {
t.Fatalf("expected video task timeout %s to exceed simple task timeout %s", video, base)
}
if video > openClawAgentWaitMaxTimeout {
t.Fatalf("expected video task timeout %s to stay within max %s", video, openClawAgentWaitMaxTimeout)
}
}
func TestGatewayRequestForwardsOpenClawSkillsStatus(t *testing.T) {
gateway := newAcpFakeOpenClawGateway(t)
defer gateway.Close()

View File

@ -36,7 +36,7 @@ func newHTTPServer(addr string, handler http.Handler) *http.Server {
Addr: strings.TrimSpace(addr),
Handler: handler,
ReadTimeout: 30 * time.Second,
WriteTimeout: openClawAgentWaitTimeout + time.Minute,
WriteTimeout: openClawAgentWaitMaxTimeout + openClawAgentWaitHTTPMargin,
IdleTimeout: 2 * time.Minute,
}
}

View File

@ -15,14 +15,14 @@ func TestHTTPServerWriteTimeoutCoversOpenClawAgentWait(t *testing.T) {
if server.IdleTimeout != 2*time.Minute {
t.Fatalf("expected fixed idle timeout, got %s", server.IdleTimeout)
}
if server.WriteTimeout <= openClawAgentWaitTimeout {
if server.WriteTimeout <= openClawAgentWaitMaxTimeout {
t.Fatalf(
"expected write timeout %s to exceed OpenClaw agent.wait timeout %s",
"expected write timeout %s to exceed OpenClaw max agent.wait timeout %s",
server.WriteTimeout,
openClawAgentWaitTimeout,
openClawAgentWaitMaxTimeout,
)
}
if got, want := server.WriteTimeout-openClawAgentWaitTimeout, time.Minute; got != want {
if got, want := server.WriteTimeout-openClawAgentWaitMaxTimeout, openClawAgentWaitHTTPMargin; got != want {
t.Fatalf("expected one-minute write timeout margin, got %s", got)
}
}