mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-09 06:23:52 +08:00
feat: add chat style
This commit is contained in:
@@ -1 +1 @@
|
|||||||
v5.0.0-beta-2505170008
|
v5.0.0-beta-2505170100
|
||||||
|
|||||||
@@ -311,9 +311,6 @@ func (p *Parser) CallMCPTool(ctx context.Context, serverName,
|
|||||||
return nil, fmt.Errorf("mcphost is not initialized")
|
return nil, fmt.Errorf("mcphost is not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
tools := p.MCPHost.GetTools(ctx)
|
|
||||||
log.Warn().Interface("tools", tools).Msg("tools")
|
|
||||||
|
|
||||||
result, err := p.MCPHost.InvokeTool(ctx, serverName, funcName, arguments)
|
result, err := p.MCPHost.InvokeTool(ctx, serverName, funcName, arguments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "invoke tool %s/%s failed", serverName, funcName)
|
return nil, errors.Wrapf(err, "invoke tool %s/%s failed", serverName, funcName)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package mcphost
|
package mcphost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -10,6 +9,7 @@ import (
|
|||||||
"github.com/bytedance/sonic"
|
"github.com/bytedance/sonic"
|
||||||
"github.com/charmbracelet/glamour"
|
"github.com/charmbracelet/glamour"
|
||||||
"github.com/charmbracelet/glamour/styles"
|
"github.com/charmbracelet/glamour/styles"
|
||||||
|
"github.com/charmbracelet/huh"
|
||||||
"github.com/charmbracelet/huh/spinner"
|
"github.com/charmbracelet/huh/spinner"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/charmbracelet/lipgloss/list"
|
"github.com/charmbracelet/lipgloss/list"
|
||||||
@@ -24,8 +24,8 @@ import (
|
|||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tokyo Night theme colors
|
|
||||||
var (
|
var (
|
||||||
|
// Tokyo Night theme colors
|
||||||
tokyoPurple = lipgloss.Color("99") // #9d7cd8
|
tokyoPurple = lipgloss.Color("99") // #9d7cd8
|
||||||
tokyoCyan = lipgloss.Color("73") // #7dcfff
|
tokyoCyan = lipgloss.Color("73") // #7dcfff
|
||||||
tokyoBlue = lipgloss.Color("111") // #7aa2f7
|
tokyoBlue = lipgloss.Color("111") // #7aa2f7
|
||||||
@@ -36,6 +36,18 @@ var (
|
|||||||
tokyoGray = lipgloss.Color("237") // #3b4261
|
tokyoGray = lipgloss.Color("237") // #3b4261
|
||||||
tokyoBg = lipgloss.Color("234") // #1a1b26
|
tokyoBg = lipgloss.Color("234") // #1a1b26
|
||||||
|
|
||||||
|
promptStyle = lipgloss.NewStyle().
|
||||||
|
Foreground(tokyoBlue).
|
||||||
|
PaddingLeft(2)
|
||||||
|
|
||||||
|
responseStyle = lipgloss.NewStyle().
|
||||||
|
Foreground(tokyoFg).
|
||||||
|
PaddingLeft(2)
|
||||||
|
|
||||||
|
errorStyle = lipgloss.NewStyle().
|
||||||
|
Foreground(tokyoRed).
|
||||||
|
Bold(true)
|
||||||
|
|
||||||
toolNameStyle = lipgloss.NewStyle().
|
toolNameStyle = lipgloss.NewStyle().
|
||||||
Foreground(tokyoCyan).
|
Foreground(tokyoCyan).
|
||||||
Bold(true)
|
Bold(true)
|
||||||
@@ -127,10 +139,25 @@ func (c *Chat) Start() error {
|
|||||||
c.showWelcome()
|
c.showWelcome()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
fmt.Print("\nYou: ")
|
var input string
|
||||||
input, err := readInput()
|
err := huh.NewForm(huh.NewGroup(huh.NewText().
|
||||||
|
Title("Enter your prompt (Type /help for commands, Ctrl+C to quit)").
|
||||||
|
Value(&input).
|
||||||
|
CharLimit(5000)),
|
||||||
|
).WithWidth(getTerminalWidth()).
|
||||||
|
WithTheme(huh.ThemeCharm()).
|
||||||
|
Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
// Check if it's a user abort (Ctrl+C)
|
||||||
|
if errors.Is(err, huh.ErrUserAborted) {
|
||||||
|
fmt.Println("\nGoodbye!")
|
||||||
|
return nil // Exit cleanly
|
||||||
|
}
|
||||||
|
return err // Return other errors normally
|
||||||
|
}
|
||||||
|
|
||||||
|
if input == "" {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle commands
|
// Handle commands
|
||||||
@@ -150,6 +177,8 @@ func (c *Chat) Start() error {
|
|||||||
|
|
||||||
// runPrompt run prompt with MCP tools
|
// runPrompt run prompt with MCP tools
|
||||||
func (c *Chat) runPrompt(prompt string) error {
|
func (c *Chat) runPrompt(prompt string) error {
|
||||||
|
fmt.Printf("\n%s\n", promptStyle.Render("You: "+prompt))
|
||||||
|
|
||||||
// Create user message
|
// Create user message
|
||||||
userMsg := &schema.Message{
|
userMsg := &schema.Message{
|
||||||
Role: schema.User,
|
Role: schema.User,
|
||||||
@@ -158,8 +187,12 @@ func (c *Chat) runPrompt(prompt string) error {
|
|||||||
c.history = append(c.history, userMsg)
|
c.history = append(c.history, userMsg)
|
||||||
for {
|
for {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
spinner.New().Type(spinner.Dots).Title("Thinking...").Run()
|
var resp *schema.Message
|
||||||
resp, err := c.model.Generate(ctx, c.history)
|
var err error
|
||||||
|
action := func() {
|
||||||
|
resp, err = c.model.Generate(ctx, c.history)
|
||||||
|
}
|
||||||
|
_ = spinner.New().Title("Thinking...").Action(action).Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -214,10 +247,11 @@ func (c *Chat) runPrompt(prompt string) error {
|
|||||||
|
|
||||||
// Render and display response
|
// Render and display response
|
||||||
if rendered, err := c.renderer.Render(resp.Content); err == nil {
|
if rendered, err := c.renderer.Render(resp.Content); err == nil {
|
||||||
fmt.Printf("\nAssistant: %s\n", rendered)
|
fmt.Printf("\n%s", responseStyle.Render("Assistant: "+rendered))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\nAssistant: %s\n", resp.Content)
|
fmt.Printf("\n%s", errorStyle.Render("Assistant: "+resp.Content))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,7 +362,9 @@ func (c *Chat) showTools() {
|
|||||||
} else {
|
} else {
|
||||||
for _, tool := range serverTools.Tools {
|
for _, tool := range serverTools.Tools {
|
||||||
descStyle := lipgloss.NewStyle().Foreground(tokyoFg).Width(contentWidth).Align(lipgloss.Left)
|
descStyle := lipgloss.NewStyle().Foreground(tokyoFg).Width(contentWidth).Align(lipgloss.Left)
|
||||||
toolDesc := list.New().EnumeratorStyle(lipgloss.NewStyle().Foreground(tokyoGreen).MarginRight(1)).Item(descStyle.Render(tool.Description))
|
toolDesc := list.New().EnumeratorStyle(
|
||||||
|
lipgloss.NewStyle().Foreground(tokyoGreen).MarginRight(1),
|
||||||
|
).Item(descStyle.Render(tool.Description))
|
||||||
serverList.Item(toolNameStyle.Render(tool.Name)).Item(toolDesc)
|
serverList.Item(toolNameStyle.Render(tool.Name)).Item(toolDesc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,15 +390,6 @@ func loadSystemPrompt(filePath string) (string, error) {
|
|||||||
return string(data), nil
|
return string(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readInput() (string, error) {
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
input, err := reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(input), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTerminalWidth() int {
|
func getTerminalWidth() int {
|
||||||
width, _, err := term.GetSize(int(os.Stdout.Fd()))
|
width, _, err := term.GetSize(int(os.Stdout.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -24,17 +24,17 @@ func TestNewChat(t *testing.T) {
|
|||||||
assert.NotNil(t, chat.tools)
|
assert.NotNil(t, chat.tools)
|
||||||
}
|
}
|
||||||
|
|
||||||
// func TestRunPromptWithNoToolCall(t *testing.T) {
|
func TestRunPromptWithNoToolCall(t *testing.T) {
|
||||||
// host, err := NewMCPHost("./testdata/test.mcp.json")
|
host, err := NewMCPHost("./testdata/test.mcp.json")
|
||||||
// require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// chat, err := host.NewChat(context.Background(), "")
|
chat, err := host.NewChat(context.Background(), "")
|
||||||
// assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// err = chat.runPrompt("hi")
|
err = chat.runPrompt("hi")
|
||||||
// assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// assert.True(t, len(chat.history) > 1)
|
assert.True(t, len(chat.history) > 1)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// func TestRunPromptWithToolCall(t *testing.T) {
|
// func TestRunPromptWithToolCall(t *testing.T) {
|
||||||
// host, err := NewMCPHost("./testdata/test.mcp.json")
|
// host, err := NewMCPHost("./testdata/test.mcp.json")
|
||||||
|
|||||||
Reference in New Issue
Block a user