Files
geo/server/internal/tenant/app/kol_assist_runtime_test.go
T
root 4bbce5f083 feat(kol): add SSE streaming for prompt assist
- Extract assist runtime (prompt building, response parsing, finalize)
  from the worker into kol_assist_runtime so the sync streaming path
  and the async task path share the same logic.
- Add POST /kol/manage/assist/stream as a Server-Sent Events endpoint
  emitting start/delta/completed/error events, and wire it to a
  streamAssist helper on kolManageApi that reports ApiClientError with
  the server's error envelope.
- Stream generated content live in KolPromptEditor and KolGenerateView,
  switching KolPromptEditArea to a boolean aiBusy flag and refining the
  generator page layout.
- Add KolAssistStreamEvent to shared types.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 16:17:11 +08:00

82 lines
2.5 KiB
Go

package app
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestFinalizeKolAssistResultRepairsDuplicateVariableIDs(t *testing.T) {
t.Parallel()
result, err := FinalizeKolAssistResult(
AssistRequest{Mode: kolAssistModeGenerate},
&KolAssistResult{
Content: "围绕 {{城市}} 和 {{目标词}} 输出内容",
Schema: KolSchemaJSON{
Variables: []KolVariableDefinition{
{ID: "var_dup", Key: "城市", Label: "城市", Type: KolVariableTypeInput, Required: true},
{ID: "var_dup", Key: "目标词", Label: "目标词", Type: KolVariableTypeInput, Required: true},
},
},
},
)
require.NoError(t, err)
require.Len(t, result.Schema.Variables, 2)
require.NotEqual(t, result.Schema.Variables[0].ID, result.Schema.Variables[1].ID)
require.Equal(t, "城市", result.Schema.Variables[0].Key)
require.Equal(t, "目标词", result.Schema.Variables[1].Key)
}
func TestFinalizeKolAssistResultOptimizePreservesExistingSchemaByKey(t *testing.T) {
t.Parallel()
originalMaxLength := 80
result, err := FinalizeKolAssistResult(
AssistRequest{
Mode: kolAssistModeOptimize,
Schema: &KolSchemaJSON{
Variables: []KolVariableDefinition{
{ID: "var_city", Key: "城市", Label: "城市", Type: KolVariableTypeInput, Required: true, MaxLength: intPtr(originalMaxLength)},
},
},
},
&KolAssistResult{
Content: "围绕 {{城市}} 优化提示词",
Schema: KolSchemaJSON{
Variables: []KolVariableDefinition{
{ID: "var_dup", Key: "城市", Label: "城市", Type: KolVariableTypeTextarea, Required: false},
},
},
},
)
require.NoError(t, err)
require.Len(t, result.Schema.Variables, 1)
require.Equal(t, "var_city", result.Schema.Variables[0].ID)
require.Equal(t, KolVariableTypeInput, result.Schema.Variables[0].Type)
require.NotNil(t, result.Schema.Variables[0].MaxLength)
require.Equal(t, originalMaxLength, *result.Schema.Variables[0].MaxLength)
}
func TestParseKolAssistResponseSupportsStringVariables(t *testing.T) {
t.Parallel()
result, err := ParseKolAssistResponse(`{"content":"围绕 {{城市}} 写内容","schema":{"variables":["城市"]}}`)
require.NoError(t, err)
require.Equal(t, "围绕 {{城市}} 写内容", result.Content)
require.Len(t, result.Schema.Variables, 1)
require.Equal(t, "城市", result.Schema.Variables[0].Key)
}
func TestExtractKolAssistContentFromPartialJSON(t *testing.T) {
t.Parallel()
content := extractKolAssistContentFromPartialJSON("{\"content\":\"第一段\\n第二")
require.Equal(t, "第一段\n第二", content)
}