Files
cc-connect/core/progress_compact_test.go
T
Claude e0e2be4e31 fix(core): 出站限流补全、工具结果展示与 i18n 收紧
- waitOutgoing/sendWithError:重启通知、SendToSession(含图片/文件)、权限与 AskQuestion 内联按钮路径纳入出站令牌桶

- EventResult 分块与 channelClosed 收尾使用 sendWithError,首包失败即停止发送

- ProgressStyleProvider 且 progress_style=legacy 时不再单独推送 EventToolResult 聊天消息(compact/card 仍走 writer)

- 工具结果 fallback 标签改为 MsgKey,补全日/西/繁中翻译

- config.example.toml:说明小数 max_per_second 时 burst 取 ceil

- 修复 processInteractiveEvents 测试参数;新增 SuppressStandaloneToolResultEvent 单测

- fix(codex): 假 codex 脚本用 stdin 读 prompt,适配 --json -
2026-03-28 00:42:35 +08:00

118 lines
4.2 KiB
Go

package core
import (
"context"
"strings"
"testing"
)
type suppressTestPlatform struct {
style string
}
func (s *suppressTestPlatform) Name() string { return "test" }
func (s *suppressTestPlatform) Start(MessageHandler) error { return nil }
func (s *suppressTestPlatform) Reply(context.Context, any, string) error { return nil }
func (s *suppressTestPlatform) Send(context.Context, any, string) error { return nil }
func (s *suppressTestPlatform) Stop() error { return nil }
func (s *suppressTestPlatform) ProgressStyle() string { return s.style }
func TestSuppressStandaloneToolResultEvent(t *testing.T) {
if SuppressStandaloneToolResultEvent(&stubPlatformNoProgress{}) {
t.Fatal("platform without ProgressStyleProvider should not suppress")
}
if !SuppressStandaloneToolResultEvent(&suppressTestPlatform{style: "legacy"}) {
t.Fatal("legacy ProgressStyleProvider should suppress standalone tool results")
}
if SuppressStandaloneToolResultEvent(&suppressTestPlatform{style: "compact"}) {
t.Fatal("compact should not suppress (writer absorbs tool results)")
}
if SuppressStandaloneToolResultEvent(&suppressTestPlatform{style: "card"}) {
t.Fatal("card should not suppress")
}
}
// stubPlatformNoProgress is a minimal Platform without ProgressStyleProvider.
type stubPlatformNoProgress struct{}
func (stubPlatformNoProgress) Name() string { return "plain" }
func (stubPlatformNoProgress) Start(MessageHandler) error { return nil }
func (stubPlatformNoProgress) Reply(context.Context, any, string) error { return nil }
func (stubPlatformNoProgress) Send(context.Context, any, string) error { return nil }
func (stubPlatformNoProgress) Stop() error { return nil }
func TestBuildAndParseProgressCardPayload(t *testing.T) {
payload := BuildProgressCardPayload([]string{" step1 ", "", "step2"}, true)
if payload == "" {
t.Fatal("BuildProgressCardPayload returned empty string")
}
if !strings.HasPrefix(payload, ProgressCardPayloadPrefix) {
t.Fatalf("payload = %q, want prefix %q", payload, ProgressCardPayloadPrefix)
}
parsed, ok := ParseProgressCardPayload(payload)
if !ok {
t.Fatalf("ParseProgressCardPayload should succeed, payload=%q", payload)
}
if len(parsed.Entries) != 2 {
t.Fatalf("entries = %d, want 2", len(parsed.Entries))
}
if parsed.Entries[0] != "step1" || parsed.Entries[1] != "step2" {
t.Fatalf("entries = %#v, want [step1 step2]", parsed.Entries)
}
if !parsed.Truncated {
t.Fatal("parsed.Truncated = false, want true")
}
if len(parsed.Items) != 2 {
t.Fatalf("items = %d, want 2", len(parsed.Items))
}
if parsed.Items[0].Kind != ProgressEntryInfo || parsed.Items[0].Text != "step1" {
t.Fatalf("items[0] = %#v, want info/step1", parsed.Items[0])
}
}
func TestBuildAndParseProgressCardPayloadV2(t *testing.T) {
payload := BuildProgressCardPayloadV2([]ProgressCardEntry{
{Kind: ProgressEntryThinking, Text: " plan "},
{Kind: ProgressEntryToolUse, Tool: "Bash", Text: "pwd"},
}, false, "Codex", LangChinese, ProgressCardStateRunning)
if payload == "" {
t.Fatal("BuildProgressCardPayloadV2 returned empty string")
}
parsed, ok := ParseProgressCardPayload(payload)
if !ok {
t.Fatalf("ParseProgressCardPayload should succeed, payload=%q", payload)
}
if parsed.Version != 2 {
t.Fatalf("version = %d, want 2", parsed.Version)
}
if parsed.Agent != "Codex" {
t.Fatalf("agent = %q, want Codex", parsed.Agent)
}
if parsed.Lang != string(LangChinese) {
t.Fatalf("lang = %q, want %q", parsed.Lang, LangChinese)
}
if parsed.State != ProgressCardStateRunning {
t.Fatalf("state = %q, want %q", parsed.State, ProgressCardStateRunning)
}
if len(parsed.Items) != 2 {
t.Fatalf("items = %d, want 2", len(parsed.Items))
}
if parsed.Items[1].Kind != ProgressEntryToolUse || parsed.Items[1].Tool != "Bash" {
t.Fatalf("items[1] = %#v, want tool_use/Bash", parsed.Items[1])
}
}
func TestParseProgressCardPayloadRejectsInvalid(t *testing.T) {
if _, ok := ParseProgressCardPayload("plain text"); ok {
t.Fatal("expected parse failure for plain text")
}
if _, ok := ParseProgressCardPayload(ProgressCardPayloadPrefix + "{not-json"); ok {
t.Fatal("expected parse failure for invalid json")
}
if _, ok := ParseProgressCardPayload(ProgressCardPayloadPrefix + `{"entries":[]}`); ok {
t.Fatal("expected parse failure for empty entries")
}
}