feat: harden support, localize knowledge and add operator availability [skip ci]

Source-only publication of reviewed commit 64e96a7f423673dc29ad56485be9fc79bce8af1c.

Passed in isolation: focused frontend/backend tests, race checks, TypeScript typecheck, lint, Go compilation, Flowgram build, and deterministic SDK build/tests.

Not accepted as a production release: Next.js export/native assembly remains blocked by environment memory limits; browser interaction and MySQL staging acceptance remain unverified. No production server, database/schema, runtime configuration, deployment, release tag, or workflow execution was performed.

Expected source tree: 0a4a7528e9.
This commit is contained in:
2026-10-16 15:21:42 +00:00
parent 299ea50fb5
commit 2f7a491666
176 changed files with 11869 additions and 2716 deletions

View File

@@ -1,8 +1,10 @@
// Modified in the independent AgentDesk fork: localized knowledge workflows and safe display errors.
package services
import (
"bytes"
"encoding/json"
"reflect"
"testing"
"agent-desk/internal/models"
@@ -18,7 +20,7 @@ import (
)
func TestKnowledgeFAQExcelTemplateContainsExpectedHeaders(t *testing.T) {
file, err := KnowledgeFAQService.BuildKnowledgeFAQImportTemplate()
file, err := KnowledgeFAQService.BuildKnowledgeFAQImportTemplate("zh-CN")
if err != nil {
t.Fatalf("BuildKnowledgeFAQImportTemplate() error = %v", err)
}
@@ -247,3 +249,82 @@ func stubKnowledgeFAQImportIndex(t *testing.T) func() {
indexKnowledgeFAQAfterImport = original
}
}
func TestKnowledgeFAQExcelLocalizedTemplatesRoundTrip(t *testing.T) {
for _, tc := range []struct {
locale string
headers []string
question string
}{
{"en-US", []string{"Primary question", "Answer", "Similar questions", "Notes"}, "How do I reset my password?"},
{"ru-RU", []string{"Основной вопрос", "Ответ", "Похожие вопросы", "Примечания"}, "Как сбросить пароль?"},
{"zh-CN", []string{"标准问题", "答案", "相似问", "备注"}, "如何重置密码?"},
} {
t.Run(tc.locale, func(t *testing.T) {
file, err := KnowledgeFAQService.BuildKnowledgeFAQImportTemplate(tc.locale)
if err != nil {
t.Fatal(err)
}
workbook, err := excelize.OpenReader(bytes.NewReader(file.Data))
if err != nil {
t.Fatal(err)
}
defer workbook.Close()
table, err := workbook.GetRows("FAQ")
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(table[0], tc.headers) || table[1][0] != tc.question {
t.Fatalf("wrong template: %#v", table)
}
rows, result, err := parseKnowledgeFAQImportRows(bytes.NewReader(file.Data), tc.locale)
if err != nil || result.Failed != 0 || len(rows) != 1 || rows[0].Question != tc.question {
t.Fatalf("round trip = %+v, %+v, %v", rows, result, err)
}
})
}
}
func TestKnowledgeFAQExcelImportAcceptsLegacyAndRussianHeaders(t *testing.T) {
for _, headers := range [][]string{
{"question", "answer", "similarQuestions", "remark"},
{"标准问题", "答案", "相似问", "备注"},
{"\ufeffОсновной вопрос", "ОТВЕТ", "Похожие вопросы", "Примечания"},
{"Вопрос", "Ответ"},
} {
question, answer := " Author question 原文 ", "\n Answer 回答:原文\nnext "
data := buildKnowledgeFAQExcelWorkbook(t, [][]string{headers, {question, answer}})
rows, result, err := parseKnowledgeFAQImportRows(bytes.NewReader(data), "ru-RU")
if err != nil || result.Failed != 0 || len(rows) != 1 {
t.Fatalf("parse %v = %+v, %v", headers, result, err)
}
if rows[0].Question != question || rows[0].Answer != answer {
t.Fatalf("authored data modified: %+v", rows[0])
}
if len(rows[0].SimilarQuestions) != 0 || rows[0].Remark != "" {
t.Fatalf("missing optional columns copied question: %+v", rows[0])
}
}
}
func TestKnowledgeFAQExcelLocalizedExportPreservesRows(t *testing.T) {
setupKnowledgeFAQExcelTestDB(t)
kb := createKnowledgeFAQExcelTestBase(t, enums.StatusOk)
item := &models.KnowledgeFAQ{KnowledgeBaseID: kb.ID, Question: " Original 问题 ", Answer: "\nОтвет <tag>原文</tag> ", SimilarQuestions: `[" same question ","相似问"]`, Remark: " Notes 原文 ", Status: enums.StatusOk}
if err := repositories.KnowledgeFAQRepository.Create(sqls.DB(), item); err != nil {
t.Fatal(err)
}
for _, locale := range []string{"en-US", "ru-RU"} {
file, err := KnowledgeFAQService.ExportKnowledgeFAQs(kb.ID, locale)
if err != nil {
t.Fatal(err)
}
rows, result, err := parseKnowledgeFAQImportRows(bytes.NewReader(file.Data), locale)
if err != nil || result.Failed != 0 || len(rows) != 1 {
t.Fatalf("export round trip: %+v, %v", result, err)
}
if rows[0].Question != item.Question || rows[0].Answer != item.Answer || rows[0].Remark != item.Remark || !reflect.DeepEqual(rows[0].SimilarQuestions, []string{" same question ", "相似问"}) {
t.Fatalf("row changed: %+v", rows[0])
}
}
}