初始化仓库
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
package kimi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chenhg5/cc-connect/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewKimiSession(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, err := newKimiSession(ctx, "kimi", "/tmp", "kimi-k2", "default", "resume-123", nil, 0)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, ks)
|
||||
assert.True(t, ks.Alive())
|
||||
assert.Equal(t, "resume-123", ks.CurrentSessionID())
|
||||
|
||||
err = ks.Close()
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, ks.Alive())
|
||||
}
|
||||
|
||||
func TestExtractResumeSessionID(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{"To resume this session: kimi -r e3690555-60eb-4d50-874b-e3647e9cee5b", "e3690555-60eb-4d50-874b-e3647e9cee5b"},
|
||||
{"To resume this session: kimi --resume abc-def", ""},
|
||||
{"To resume this session: no-id-here", ""},
|
||||
{"random text", ""},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.expected, extractResumeSessionID(c.input), "input: %s", c.input)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleAssistantWithText(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, _ := newKimiSession(ctx, "kimi", "/tmp", "", "default", "", nil, 0)
|
||||
defer ks.Close()
|
||||
|
||||
ks.handleEvent(map[string]any{
|
||||
"role": "assistant",
|
||||
"content": []any{
|
||||
map[string]any{"type": "text", "text": "Hello!"},
|
||||
},
|
||||
})
|
||||
|
||||
// pendingMsgs should buffer the text
|
||||
assert.Len(t, ks.pendingMsgs, 1)
|
||||
assert.Equal(t, "Hello!", ks.pendingMsgs[0])
|
||||
}
|
||||
|
||||
func TestHandleAssistantWithThink(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, _ := newKimiSession(ctx, "kimi", "/tmp", "", "default", "", nil, 0)
|
||||
defer ks.Close()
|
||||
|
||||
ks.handleEvent(map[string]any{
|
||||
"role": "assistant",
|
||||
"content": []any{
|
||||
map[string]any{"type": "think", "think": "Let me think..."},
|
||||
map[string]any{"type": "text", "text": "Done!"},
|
||||
},
|
||||
})
|
||||
|
||||
events := drainEvents(ks.events, 2)
|
||||
require.Len(t, events, 1)
|
||||
assert.Equal(t, core.EventThinking, events[0].Type)
|
||||
assert.Equal(t, "Let me think...", events[0].Content)
|
||||
assert.Equal(t, "Done!", ks.pendingMsgs[0])
|
||||
}
|
||||
|
||||
func TestHandleAssistantWithToolCalls(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, _ := newKimiSession(ctx, "kimi", "/tmp", "", "default", "", nil, 0)
|
||||
defer ks.Close()
|
||||
|
||||
ks.handleEvent(map[string]any{
|
||||
"role": "assistant",
|
||||
"content": []any{
|
||||
map[string]any{"type": "text", "text": "I will run a command"},
|
||||
},
|
||||
"tool_calls": []any{
|
||||
map[string]any{
|
||||
"id": "tool_abc",
|
||||
"function": map[string]any{
|
||||
"name": "Shell",
|
||||
"arguments": `{"command":"echo hello"}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
events := drainEvents(ks.events, 3)
|
||||
require.Len(t, events, 2)
|
||||
assert.Equal(t, core.EventThinking, events[0].Type)
|
||||
assert.Equal(t, "I will run a command", events[0].Content)
|
||||
assert.Equal(t, core.EventToolUse, events[1].Type)
|
||||
assert.Equal(t, "Shell", events[1].ToolName)
|
||||
assert.Equal(t, `{"command":"echo hello"}`, events[1].ToolInput)
|
||||
assert.Equal(t, "tool_abc", events[1].RequestID)
|
||||
}
|
||||
|
||||
func TestHandleTool(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, _ := newKimiSession(ctx, "kimi", "/tmp", "", "default", "", nil, 0)
|
||||
defer ks.Close()
|
||||
|
||||
ks.handleEvent(map[string]any{
|
||||
"role": "tool",
|
||||
"tool_call_id": "tool_abc",
|
||||
"content": []any{
|
||||
map[string]any{"type": "text", "text": "hello\n"},
|
||||
},
|
||||
})
|
||||
|
||||
events := drainEvents(ks.events, 1)
|
||||
require.Len(t, events, 1)
|
||||
assert.Equal(t, core.EventToolResult, events[0].Type)
|
||||
assert.Equal(t, "tool_abc", events[0].ToolName)
|
||||
assert.Contains(t, events[0].ToolResult, "hello")
|
||||
}
|
||||
|
||||
func TestFlushPendingAsText(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, _ := newKimiSession(ctx, "kimi", "/tmp", "", "default", "", nil, 0)
|
||||
defer ks.Close()
|
||||
|
||||
ks.pendingMsgs = []string{"Hello", " ", "world"}
|
||||
ks.flushPendingAsText()
|
||||
|
||||
events := drainEvents(ks.events, 1)
|
||||
require.Len(t, events, 1)
|
||||
assert.Equal(t, core.EventText, events[0].Type)
|
||||
assert.Equal(t, "Hello world", events[0].Content)
|
||||
assert.Empty(t, ks.pendingMsgs)
|
||||
}
|
||||
|
||||
func TestFlushPendingAsThinking(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ks, _ := newKimiSession(ctx, "kimi", "/tmp", "", "default", "", nil, 0)
|
||||
defer ks.Close()
|
||||
|
||||
ks.pendingMsgs = []string{"Thinking..."}
|
||||
ks.flushPendingAsThinking()
|
||||
|
||||
events := drainEvents(ks.events, 1)
|
||||
require.Len(t, events, 1)
|
||||
assert.Equal(t, core.EventThinking, events[0].Type)
|
||||
assert.Equal(t, "Thinking...", events[0].Content)
|
||||
}
|
||||
|
||||
func TestTruncate(t *testing.T) {
|
||||
assert.Equal(t, "hello", truncate("hello", 10))
|
||||
assert.Equal(t, "hello world", truncate("hello world", 11))
|
||||
assert.Equal(t, "hello worl...", truncate("hello world", 10))
|
||||
}
|
||||
|
||||
func drainEvents(ch <-chan core.Event, max int) []core.Event {
|
||||
var events []core.Event
|
||||
timeout := time.After(500 * time.Millisecond)
|
||||
for i := 0; i < max; i++ {
|
||||
select {
|
||||
case evt := <-ch:
|
||||
events = append(events, evt)
|
||||
case <-timeout:
|
||||
return events
|
||||
}
|
||||
}
|
||||
return events
|
||||
}
|
||||
Reference in New Issue
Block a user