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
+101
View File
@@ -0,0 +1,101 @@
package tools
import "testing"
// feedAll runs the splitter over a sequence of chunks and concatenates the
// think / answer outputs (including the final Flush), mirroring how the agent
// stream router consumes it.
func feedAll(sp *ThinkStreamSplitter, chunks []string) (think, answer string) {
for _, c := range chunks {
tk, ans := sp.Feed(c)
think += tk
answer += ans
}
tk, ans := sp.Flush()
think += tk
answer += ans
return think, answer
}
func TestThinkStreamSplitter(t *testing.T) {
tests := []struct {
name string
chunks []string
wantThink string
wantAnswer string
}{
{
name: "no think tags - all answer",
chunks: []string{"Hello ", "world"},
wantThink: "",
wantAnswer: "Hello world",
},
{
name: "single think block then answer",
chunks: []string{"<think>reasoning</think>The answer is 42."},
wantThink: "reasoning",
wantAnswer: "The answer is 42.",
},
{
name: "open tag split across chunks",
chunks: []string{"<thi", "nk>secret</think>visible"},
wantThink: "secret",
wantAnswer: "visible",
},
{
name: "close tag split across chunks",
chunks: []string{"<think>think part</thi", "nk>answer part"},
wantThink: "think part",
wantAnswer: "answer part",
},
{
name: "think content streamed across multiple chunks",
chunks: []string{"<think>a", "b", "c</think>", "done"},
wantThink: "abc",
wantAnswer: "done",
},
{
name: "answer before think block",
chunks: []string{"prefix <think>mid</think> suffix"},
wantThink: "mid",
wantAnswer: "prefix suffix",
},
{
name: "two think blocks",
chunks: []string{"<think>one</think>A<think>two</think>B"},
wantThink: "onetwo",
wantAnswer: "AB",
},
{
name: "unterminated think treated as think on flush",
chunks: []string{"<think>still thinking"},
wantThink: "still thinking",
wantAnswer: "",
},
{
name: "literal less-than in answer is preserved",
chunks: []string{"if a < ", "b then"},
wantThink: "",
wantAnswer: "if a < b then",
},
{
name: "empty chunks are no-ops",
chunks: []string{"", "answer", ""},
wantThink: "",
wantAnswer: "answer",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sp := NewThinkStreamSplitter()
think, answer := feedAll(sp, tt.chunks)
if think != tt.wantThink {
t.Errorf("think = %q, want %q", think, tt.wantThink)
}
if answer != tt.wantAnswer {
t.Errorf("answer = %q, want %q", answer, tt.wantAnswer)
}
})
}
}