WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
package searchutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
)
|
||||
|
||||
func TestSliceContentByDocumentRange(t *testing.T) {
|
||||
parent := "aaaPAGE1bbbPAGE2ccc"
|
||||
got := SliceContentByDocumentRange(parent, 100, 103, 108)
|
||||
want := "PAGE1"
|
||||
if got != want {
|
||||
t.Fatalf("slice: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterImageInfoByMatchRange(t *testing.T) {
|
||||
parent := "\n\n\n\n"
|
||||
matchStart := len([]rune("\n\n"))
|
||||
matchEnd := matchStart + len([]rune(""))
|
||||
all := []types.ImageInfo{
|
||||
{URL: "u1"}, {URL: "u2"}, {URL: "u3"},
|
||||
}
|
||||
raw, err := json.Marshal(all)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := FilterImageInfoByMatchRange(parent, 0, matchStart, matchEnd, string(raw))
|
||||
var filtered []types.ImageInfo
|
||||
if err := json.Unmarshal([]byte(got), &filtered); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filtered) != 1 || filtered[0].URL != "u2" {
|
||||
t.Fatalf("filtered: %+v", filtered)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterImageInfoByContentURLs(t *testing.T) {
|
||||
content := "intro\n\noutro"
|
||||
all := []types.ImageInfo{
|
||||
{URL: "local://img1.jpg", OCRText: "one"},
|
||||
{URL: "local://img3.jpg", OCRText: "three"},
|
||||
}
|
||||
raw, err := json.Marshal(all)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := FilterImageInfoByContentURLs(content, string(raw))
|
||||
var filtered []types.ImageInfo
|
||||
if err := json.Unmarshal([]byte(got), &filtered); err != nil {
|
||||
t.Fatalf("unmarshal filtered: %v", err)
|
||||
}
|
||||
if len(filtered) != 1 || filtered[0].URL != "local://img3.jpg" {
|
||||
t.Fatalf("filtered: %+v", filtered)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPruneMarkdownImagesOutsideRange(t *testing.T) {
|
||||
parent := "\n\n\n\n"
|
||||
matchStart := len([]rune("\n\n"))
|
||||
matchEnd := matchStart + len([]rune(""))
|
||||
got := PruneMarkdownImagesOutsideRange(parent, 0, matchStart, matchEnd)
|
||||
if got != "" {
|
||||
t.Fatalf("prune: got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPruneMarkdownImagesByImageInfoIgnoresShiftedOffsets(t *testing.T) {
|
||||
content := "a manually inserted prefix that shifts every parser offset\n\n" +
|
||||
"\n\nbody\n\n"
|
||||
raw, err := json.Marshal([]types.ImageInfo{{URL: "u2"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := PruneMarkdownImagesByImageInfo(content, string(raw))
|
||||
if strings.Contains(got, "u1") {
|
||||
t.Fatalf("unscoped image remained: %q", got)
|
||||
}
|
||||
if !strings.Contains(got, "") {
|
||||
t.Fatalf("scoped image was removed: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnrichContentWithImageInfoForChat_SkipsUnmatched(t *testing.T) {
|
||||
content := "\n\n"
|
||||
raw, _ := json.Marshal([]types.ImageInfo{{URL: "u2", OCRText: "two"}})
|
||||
got := EnrichContentWithImageInfoForChat(content, string(raw))
|
||||
if strings.Contains(got, "<image") {
|
||||
t.Fatalf("chat context should not contain internal image XML: %s", got)
|
||||
}
|
||||
if !strings.Contains(got, "") {
|
||||
t.Fatalf("unmatched markdown should remain: %s", got)
|
||||
}
|
||||
if !strings.Contains(got, "") {
|
||||
t.Fatalf("matched markdown should remain renderable: %s", got)
|
||||
}
|
||||
if !strings.Contains(got, "> **Image text (OCR):** two") {
|
||||
t.Fatalf("matched image should be enriched: %s", got)
|
||||
}
|
||||
if strings.Count(got, "\n\nafter"
|
||||
raw, _ := json.Marshal([]types.ImageInfo{
|
||||
{
|
||||
URL: "resource://AbCdEfGhIjKlMnOpQrStUv",
|
||||
Caption: "目标说话人提取流程图",
|
||||
OCRText: "输入\n目标说话人提取\n输出",
|
||||
},
|
||||
})
|
||||
|
||||
got := EnrichContentWithImageInfoForChat(content, string(raw))
|
||||
for _, want := range []string{
|
||||
"",
|
||||
"> **Image caption:** 目标说话人提取流程图",
|
||||
"> **Image text (OCR):** 输入",
|
||||
"> 目标说话人提取",
|
||||
"> 输出",
|
||||
} {
|
||||
if !strings.Contains(got, want) {
|
||||
t.Fatalf("expected %q in enriched Markdown:\n%s", want, got)
|
||||
}
|
||||
}
|
||||
if strings.Contains(got, "<image") {
|
||||
t.Fatalf("chat context should be Markdown-only for image content: %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnrichContentWithImageInfoForChat_EnrichesRepeatedImagesOnceEach(t *testing.T) {
|
||||
content := "\n\n"
|
||||
raw, _ := json.Marshal([]types.ImageInfo{{URL: "u1", Caption: "same caption"}})
|
||||
|
||||
got := EnrichContentWithImageInfoForChat(content, string(raw))
|
||||
if strings.Count(got, "") != 2 {
|
||||
t.Fatalf("expected both Markdown images to remain: %s", got)
|
||||
}
|
||||
if strings.Count(got, "> **Image caption:** same caption") != 2 {
|
||||
t.Fatalf("expected each image to be enriched exactly once: %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildImageInfoMarkdownWithURL(t *testing.T) {
|
||||
got := BuildImageInfoMarkdownWithURL(
|
||||
"resource://AbCdEfGhIjKlMnOpQrStUv",
|
||||
&types.ImageInfo{Caption: "流程图 [测试]", OCRText: "输入\n输出"},
|
||||
)
|
||||
for _, want := range []string{
|
||||
`![流程图 \[测试\]](resource://AbCdEfGhIjKlMnOpQrStUv)`,
|
||||
"> **Image caption:** 流程图 [测试]",
|
||||
"> **Image text (OCR):** 输入",
|
||||
"> 输出",
|
||||
} {
|
||||
if !strings.Contains(got, want) {
|
||||
t.Fatalf("expected %q in image Markdown:\n%s", want, got)
|
||||
}
|
||||
}
|
||||
if strings.Contains(got, "<image") {
|
||||
t.Fatalf("LLM-facing image context must not use image XML: %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageURLsInContent(t *testing.T) {
|
||||
content := " x "
|
||||
urls := ImageURLsInContent(content)
|
||||
if !urls["u1"] || !urls["u2"] || len(urls) != 2 {
|
||||
t.Fatalf("urls: %#v", urls)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user