fix(opencode): считать реальный прогресс стрима для idle-детекции
Растущий в один text-парт стрим (text-delta) и reasoning больше не выглядят как зависшая нейронка: idle-таймер сбрасывается по росту числа партов и суммарной длины text/reasoning.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -16,7 +17,10 @@ import (
|
||||
// - нормальный: Prompt ставит active=false и в messages кладётся финальное
|
||||
// assistant-сообщение (verdictText) → Runner собирает вердикт;
|
||||
// - blockPrompt: «агент завис» — active=true всегда, сообщений нет → idle abort;
|
||||
// - failCreate / failMessages — имитация ошибок.
|
||||
// - failCreate / failMessages — имитация ошибок;
|
||||
// - growStream: стрим одного растущего парта — текст/reasoning растёт с
|
||||
// каждым опросом GET /message (streamPolls раз), active=true, затем
|
||||
// active=false + финальное завершённое сообщение.
|
||||
type fakeAPIServer struct {
|
||||
sessionID string
|
||||
created bool
|
||||
@@ -28,6 +32,14 @@ type fakeAPIServer struct {
|
||||
failMessages bool
|
||||
createdModel *ModelRef // модель, полученная на POST /api/session
|
||||
promptCalls int
|
||||
|
||||
// streamGrow: стрим одного растущего парта — текст/reasoning растёт с
|
||||
// каждым опросом GET /message, active=true, пока messageCalls не дойдёт до
|
||||
// streamPolls; затем active=false + финальное завершённое сообщение.
|
||||
streamGrow bool
|
||||
streamReasoning bool // растущий парт — reasoning вместо text
|
||||
streamPolls int // сколько опросов длится «стрим» до завершения
|
||||
messageCalls int
|
||||
}
|
||||
|
||||
func (f *fakeAPIServer) handler() http.Handler {
|
||||
@@ -96,6 +108,27 @@ func (f *fakeAPIServer) handler() http.Handler {
|
||||
http.Error(w, "db error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if f.streamGrow {
|
||||
f.messageCalls++
|
||||
now := time.Now().UnixMilli()
|
||||
done := f.messageCalls >= f.streamPolls
|
||||
msg := v2Message{ID: "msg_stream", Type: "assistant", Time: v2Time{Created: &now}}
|
||||
switch {
|
||||
case done:
|
||||
msg.Content = []v2Part{{Type: "text", Text: "done-stream"}}
|
||||
msg.Finish = "end_turn"
|
||||
msg.Time.Completed = &now
|
||||
f.active = false
|
||||
case f.streamReasoning:
|
||||
msg.Content = []v2Part{{Type: "reasoning", Text: strings.Repeat("r", f.messageCalls)}}
|
||||
f.active = true
|
||||
default:
|
||||
msg.Content = []v2Part{{Type: "text", Text: strings.Repeat("x", f.messageCalls)}}
|
||||
f.active = true
|
||||
}
|
||||
writeJSON(w, map[string]any{"data": []v2Message{msg}})
|
||||
return
|
||||
}
|
||||
msgs := f.messages
|
||||
if msgs == nil && f.verdictText != "" && !f.blockPrompt {
|
||||
msgs = []v2Message{f.assistantMsg(f.verdictText)}
|
||||
|
||||
Reference in New Issue
Block a user