mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-22 01:48:11 +00:00
fix: LLM 工具循环 400、中断消息注入、ConPTY 终端支持
- agent: 工具轮请求尾部补 user 占位(zen 网关强制),tool 消息正确配对 - agent: 工具提醒/中断以 system 角色注入并带 [中断消息] 前缀,不进用户履历;系统提示词说明中断消息格式 - agentcli: 基于 ConPTY 的交互式终端(ptywin fork),terminal_create/read/write/resize/close/watch - webui: server 输出通道适配器(保留 reasoning_content/disable_thinking) - GUI: 沉浸式标题栏、icon 圆角重制、mascot 等打磨
This commit is contained in:
65
internal/plugins/agentcli/pty_windows_test.go
Normal file
65
internal/plugins/agentcli/pty_windows_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
//go:build windows
|
||||
|
||||
package agentcli
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestNewCommandPtyConPTY 验证 Windows ConPTY 后端:一次性命令输出可读,
|
||||
// 交互式会话可写读往返。
|
||||
func TestNewCommandPtyConPTY(t *testing.T) {
|
||||
ta, _, err := newCommandPty("cmd.exe /c echo conpty-ok", 24, 80)
|
||||
if err != nil {
|
||||
t.Fatalf("once: %v", err)
|
||||
}
|
||||
outA := drainFor(ta, 3*time.Second)
|
||||
if !strings.Contains(string(outA), "conpty-ok") {
|
||||
t.Fatalf("once output missing echo: %q", string(outA))
|
||||
}
|
||||
ta.Close()
|
||||
|
||||
tb, _, err := newCommandPty("cmd.exe", 24, 80)
|
||||
if err != nil {
|
||||
t.Fatalf("interactive: %v", err)
|
||||
}
|
||||
defer tb.Close()
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
if _, err := tb.WriteString("echo hi-123\r\n"); err != nil {
|
||||
t.Fatalf("write: %v", err)
|
||||
}
|
||||
outB := drainFor(tb, 3*time.Second)
|
||||
if !strings.Contains(string(outB), "hi-123") {
|
||||
t.Fatalf("interactive output missing echo: %q", string(outB))
|
||||
}
|
||||
if !tb.Running() {
|
||||
t.Fatalf("interactive shell should still be running")
|
||||
}
|
||||
}
|
||||
|
||||
func drainFor(term ptyTerm, dur time.Duration) []byte {
|
||||
deadline := time.Now().Add(dur)
|
||||
buf := make([]byte, 4096)
|
||||
var out []byte
|
||||
for time.Now().Before(deadline) {
|
||||
ch := make(chan struct{ N int; E error }, 1)
|
||||
go func() {
|
||||
n, e := term.Read(buf)
|
||||
ch <- struct{ N int; E error }{n, e}
|
||||
}()
|
||||
select {
|
||||
case r := <-ch:
|
||||
if r.N > 0 {
|
||||
out = append(out, buf[:r.N]...)
|
||||
}
|
||||
if r.E != nil {
|
||||
return out
|
||||
}
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
return out
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user