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

This commit is contained in:
yawan
2026-09-22 16:19:06 +08:00
commit f7fc992f57
3929 changed files with 1006607 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
package wecom
import (
"testing"
)
func TestStripAtMentionBasic(t *testing.T) {
tests := []struct {
name string
content string
want string
}{
{"no mention", "hello world", "hello world"},
{"empty string", "", ""},
{"mention only no content", "@Bot", "@Bot"},
{"single-word bot double-space", "@Bot /stop", "/stop"},
{"single-word bot single-space", "@Bot /stop", "/stop"},
{"single-word bot double-space chinese", "@Bot 你好世界", "你好世界"},
{"multi-word bot double-space", "@WeKnora Bot /stop", "/stop"},
{"multi-word bot double-space chinese", "@WeKnora Bot 什么是上下文工程", "什么是上下文工程"},
{"multi-word bot single-space command", "@WeKnora Bot /stop", "/stop"},
{"multi-word bot single-space chinese", "@WeKnora Bot 什么是老登", "什么是老登"},
{"leading whitespace", " @Bot hello ", "hello"},
{"double-space in user content", "@Bot hello world", "hello world"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := stripAtMentionBasic(tt.content)
if got != tt.want {
t.Errorf("stripAtMentionBasic(%q) = %q, want %q", tt.content, got, tt.want)
}
})
}
}
func TestLongConnClient_StripAtMention(t *testing.T) {
t.Run("learns bot name from double-space then handles single-space", func(t *testing.T) {
c := &LongConnClient{}
// First message: double-space → learn "WeKnora Bot"
got := c.stripAtMention("@WeKnora Bot 什么是上下文工程")
if got != "什么是上下文工程" {
t.Errorf("first message: got %q, want %q", got, "什么是上下文工程")
}
// Verify bot name was cached
if name, _ := c.botDisplayName.Load().(string); name != "WeKnora Bot" {
t.Errorf("cached bot name = %q, want %q", name, "WeKnora Bot")
}
// Second message: single-space → should use cached name
got = c.stripAtMention("@WeKnora Bot /stop")
if got != "/stop" {
t.Errorf("second message: got %q, want %q", got, "/stop")
}
// Single-space with chinese content
got = c.stripAtMention("@WeKnora Bot 什么是B+树")
if got != "什么是B+树" {
t.Errorf("chinese single-space: got %q, want %q", got, "什么是B+树")
}
})
t.Run("preconfigured bot name", func(t *testing.T) {
c := &LongConnClient{}
c.botDisplayName.Store("WeKnora Bot")
// Single-space should work immediately without learning
got := c.stripAtMention("@WeKnora Bot /stop")
if got != "/stop" {
t.Errorf("got %q, want %q", got, "/stop")
}
})
t.Run("cached name must not partial-match a longer bot name", func(t *testing.T) {
c := &LongConnClient{}
c.botDisplayName.Store("Bot")
// "@BotX /stop" should NOT match cached "Bot" — "BotX" is a different name.
// Falls through to Strategy 3 (strip first @word).
got := c.stripAtMention("@BotX /stop")
if got != "/stop" {
t.Errorf("got %q, want %q", got, "/stop")
}
})
t.Run("NewLongConnClient with bot name", func(t *testing.T) {
c, err := NewLongConnClient("id", "secret", "", "My Bot", nil)
if err != nil {
t.Fatal(err)
}
got := c.stripAtMention("@My Bot /help")
if got != "/help" {
t.Errorf("got %q, want %q", got, "/help")
}
})
t.Run("does not overwrite cached name from user double-spaces", func(t *testing.T) {
c := &LongConnClient{}
c.botDisplayName.Store("Bot")
// User content has double space — should NOT overwrite "Bot" with "Bot hello"
got := c.stripAtMention("@Bot hello world")
if got != "hello world" {
t.Errorf("got %q, want %q", got, "hello world")
}
// Cached name should still be "Bot"
if name, _ := c.botDisplayName.Load().(string); name != "Bot" {
t.Errorf("cached bot name = %q, want %q", name, "Bot")
}
})
t.Run("no mention passthrough", func(t *testing.T) {
c := &LongConnClient{}
got := c.stripAtMention("hello world")
if got != "hello world" {
t.Errorf("got %q, want %q", got, "hello world")
}
})
t.Run("empty string", func(t *testing.T) {
c := &LongConnClient{}
got := c.stripAtMention("")
if got != "" {
t.Errorf("got %q, want %q", got, "")
}
})
t.Run("cold start single-space command", func(t *testing.T) {
c := &LongConnClient{}
// No cached name, single space → heuristic detects " /" boundary
got := c.stripAtMention("@WeKnora Bot /stop")
if got != "/stop" {
t.Errorf("got %q, want %q", got, "/stop")
}
})
t.Run("cold start single-space chinese", func(t *testing.T) {
c := &LongConnClient{}
// No cached name, single space → heuristic detects non-ASCII boundary
got := c.stripAtMention("@WeKnora Bot 什么是老登")
if got != "什么是老登" {
t.Errorf("got %q, want %q", got, "什么是老登")
}
})
t.Run("cold start all-ascii content falls back to first word", func(t *testing.T) {
c := &LongConnClient{}
// No cached name, all ASCII → heuristic can't find boundary, strips first @word
got := c.stripAtMention("@WeKnora Bot hello")
if got != "Bot hello" {
t.Errorf("got %q, want %q", got, "Bot hello")
}
})
}