Skip to content

Commit 4d87df8

Browse files
committed
Updates for anthropic
1 parent db433cd commit 4d87df8

File tree

8 files changed

+70
-195
lines changed

8 files changed

+70
-195
lines changed

cmd/agent/chat.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ func (cmd *ChatCmd) Run(globals *Globals) error {
4040
opts := []llm.Opt{}
4141
if !cmd.NoStream {
4242
opts = append(opts, llm.WithStream(func(cc llm.ContextContent) {
43-
fmt.Println("STREAM", cc)
43+
if text := cc.Text(); text != "" {
44+
fmt.Println(text)
45+
}
4446
}))
4547
}
4648
if cmd.System != "" {
@@ -80,13 +82,13 @@ func (cmd *ChatCmd) Run(globals *Globals) error {
8082
break
8183
}
8284
if session.Text() != "" {
83-
fmt.Println("Calling", session.Text())
85+
globals.term.Println(session.Text())
8486
} else {
8587
var names []string
8688
for _, call := range calls {
8789
names = append(names, call.Name())
8890
}
89-
fmt.Println("Calling", strings.Join(names, ", "))
91+
globals.term.Println("Calling", strings.Join(names, ", "))
9092
}
9193
if results, err := globals.toolkit.Run(ctx, calls...); err != nil {
9294
return err
@@ -96,7 +98,7 @@ func (cmd *ChatCmd) Run(globals *Globals) error {
9698
}
9799

98100
// Print the response
99-
fmt.Println("SESSION", session.Text())
101+
globals.term.Println("\n" + session.Text() + "\n")
100102
}
101103
})
102104
}

cmd/agent/term.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package main
22

33
import (
4+
"fmt"
45
"io"
56
"os"
67

78
// Packages
8-
"golang.org/x/term"
9+
format "github.com/MichaelMure/go-term-text"
10+
color "github.com/fatih/color"
11+
term "golang.org/x/term"
912
)
1013

1114
type Term struct {
@@ -41,6 +44,15 @@ func (t *Term) Size() (int, int) {
4144
return 0, 0
4245
}
4346

47+
func (t *Term) Println(v ...any) {
48+
text := fmt.Sprint(v...)
49+
w, _ := t.Size()
50+
if w > 0 {
51+
text, _ = format.Wrap(text, w)
52+
}
53+
fmt.Fprintln(os.Stdout, text)
54+
}
55+
4456
func (t *Term) ReadLine(prompt string) (string, error) {
4557
// Set terminal raw mode
4658
if t.Terminal != nil {
@@ -51,8 +63,9 @@ func (t *Term) ReadLine(prompt string) (string, error) {
5163
defer term.Restore(t.fd, state)
5264
}
5365

54-
// Set the prompt
66+
// Set the prompt with color
5567
if t.Terminal != nil {
68+
prompt = color.New(color.Bold).Sprint(prompt)
5669
t.Terminal.SetPrompt(prompt)
5770
}
5871

pkg/anthropic/message.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type Content struct {
2222
Type string `json:"type"` // image, document, text, tool_use
2323
ContentText
2424
ContentAttachment
25-
ContentTool
25+
*ContentTool
2626
ContentToolResult
2727
CacheControl *cachecontrol `json:"cache_control,omitempty"` // ephemeral
2828
}
@@ -34,7 +34,7 @@ type ContentText struct {
3434
type ContentTool struct {
3535
Id string `json:"id,omitempty"` // tool id
3636
Name string `json:"name,omitempty"` // tool name
37-
Input map[string]any `json:"input,omitempty"` // tool input
37+
Input map[string]any `json:"input"` // tool input
3838
InputJson string `json:"partial_json,omitempty"` // partial json input (for streaming)
3939
}
4040

@@ -107,6 +107,22 @@ func (m MessageMeta) String() string {
107107
///////////////////////////////////////////////////////////////////////////////
108108
// PRIVATE METHODS
109109

110+
func (m MessageMeta) Text() string {
111+
if len(m.Content) == 0 {
112+
return ""
113+
}
114+
var text []string
115+
for _, content := range m.Content {
116+
if content.Type == "text" {
117+
text = append(text, content.ContentText.Text)
118+
}
119+
}
120+
return strings.Join(text, "\n")
121+
}
122+
123+
///////////////////////////////////////////////////////////////////////////////
124+
// PRIVATE METHODS
125+
110126
var (
111127
supportedAttachments = map[string]string{
112128
"image/jpeg": "image",

pkg/anthropic/messages.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ func (r Response) String() string {
4848

4949
type reqMessages struct {
5050
Model string `json:"model"`
51-
Messages []*MessageMeta `json:"messages"`
52-
Tools []llm.Tool `json:"tools,omitempty"`
5351
MaxTokens uint `json:"max_tokens,omitempty"`
5452
Metadata *optmetadata `json:"metadata,omitempty"`
5553
StopSequences []string `json:"stop_sequences,omitempty"`
@@ -58,6 +56,8 @@ type reqMessages struct {
5856
Temperature float64 `json:"temperature,omitempty"`
5957
TopK uint64 `json:"top_k,omitempty"`
6058
TopP float64 `json:"top_p,omitempty"`
59+
Messages []*MessageMeta `json:"messages"`
60+
Tools []llm.Tool `json:"tools,omitempty"`
6161
}
6262

6363
func (anthropic *Client) Messages(ctx context.Context, context llm.Context, opts ...llm.Opt) (*Response, error) {
@@ -231,11 +231,7 @@ func (response Response) Role() string {
231231
}
232232

233233
func (response Response) Text() string {
234-
data, err := json.MarshalIndent(response.MessageMeta.Content, "", " ")
235-
if err != nil {
236-
return err.Error()
237-
}
238-
return string(data)
234+
return response.MessageMeta.Text()
239235
}
240236

241237
func (response Response) ToolCalls() []llm.ToolCall {

pkg/anthropic/session.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,7 @@ func (session *session) Text() string {
8282
return ""
8383
}
8484
meta := session.seq[len(session.seq)-1]
85-
data, err := json.MarshalIndent(meta.Content, "", " ")
86-
if err != nil {
87-
return err.Error()
88-
}
89-
return string(data)
85+
return meta.Text()
9086
}
9187

9288
// Return the current session tool calls, or empty if no tool calls were made

pkg/newsapi/agent.go

Lines changed: 22 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,14 @@ import (
1010
)
1111

1212
///////////////////////////////////////////////////////////////////////////////
13-
// TYPES
13+
// HEADLINES
1414

1515
type headlines struct {
1616
*Client `json:"-"`
17-
// CountryCode string `json:"country_code,omitempty" help:"The two-letter countrycode to return headlines for. Leave empty for worldwide headlines."`
18-
}
19-
20-
type search struct {
21-
*Client `json:"-"`
22-
Query string `json:"query" help:"A phrase used to search for news headlines." required:"true"`
23-
}
24-
25-
type category struct {
26-
*Client `json:"-"`
27-
Category string `json:"category" enum:"business, entertainment, health, science, sports, technology" help:"business, entertainment, health, science, sports, technology" required:"true"`
2817
}
2918

3019
var _ llm.Tool = (*headlines)(nil)
3120

32-
var (
33-
categories = []string{"business", "entertainment", "health", "science", "sports", "technology"}
34-
)
35-
36-
///////////////////////////////////////////////////////////////////////////////
37-
// HEADLINES
38-
3921
func (headlines) Name() string {
4022
return "news_headlines"
4123
}
@@ -51,6 +33,13 @@ func (headlines *headlines) Run(ctx context.Context) (any, error) {
5133
///////////////////////////////////////////////////////////////////////////////
5234
// SEARCH
5335

36+
type search struct {
37+
*Client `json:"-"`
38+
Query string `json:"query" help:"A phrase used to search for news headlines." required:"true"`
39+
}
40+
41+
var _ llm.Tool = (*search)(nil)
42+
5443
func (search) Name() string {
5544
return "news_search"
5645
}
@@ -63,13 +52,24 @@ func (search *search) Run(ctx context.Context) (any, error) {
6352
if search.Query == "" {
6453
return nil, nil
6554
}
66-
fmt.Printf("search for %q\n", search.Query)
55+
fmt.Printf(" => Search for %q\n", search.Query)
6756
return search.Articles(OptQuery(search.Query), OptLimit(10))
6857
}
6958

7059
///////////////////////////////////////////////////////////////////////////////
7160
// CATEGORY
7261

62+
type category struct {
63+
*Client `json:"-"`
64+
Category string `json:"category" enum:"business, entertainment, health, science, sports, technology" help:"business, entertainment, health, science, sports, technology" required:"true"`
65+
}
66+
67+
var _ llm.Tool = (*category)(nil)
68+
69+
var (
70+
categories = []string{"business", "entertainment", "health", "science", "sports", "technology"}
71+
)
72+
7373
func (category) Name() string {
7474
return "news_headlines_category"
7575
}
@@ -80,158 +80,9 @@ func (category) Description() string {
8080

8181
func (category *category) Run(ctx context.Context) (any, error) {
8282
if !slices.Contains(categories, category.Category) {
83-
fmt.Printf("search for %q\n", category.Category)
83+
fmt.Printf(" => Search for %q\n", category.Category)
8484
return category.Articles(OptQuery(category.Category), OptLimit(10))
8585
}
86-
fmt.Printf("category for %q\n", category.Category)
86+
fmt.Printf(" => Headlines for %q\n", category.Category)
8787
return category.Headlines(OptCategory(category.Category), OptLimit(10))
8888
}
89-
90-
/*
91-
// Return all the agent tools for the weatherapi
92-
func (c *Client) Tools() []agent.Tool {
93-
return []agent.Tool{
94-
&tool{
95-
name: "current_headlines",
96-
description: "Return the current news headlines",
97-
run: c.agentCurrentHeadlines,
98-
}, &tool{
99-
name: "current_headlines_country",
100-
description: "Return the current news headlines for a country",
101-
run: c.agentCountryHeadlines,
102-
params: []agent.ToolParameter{
103-
{
104-
Name: "countrycode",
105-
Description: "The two-letter country code to return headlines for",
106-
Required: true,
107-
},
108-
},
109-
}, &tool{
110-
name: "current_headlines_category",
111-
description: "Return the current news headlines for a business, entertainment, health, science, sports or technology",
112-
run: c.agentCategoryHeadlines,
113-
params: []agent.ToolParameter{
114-
{
115-
Name: "category",
116-
Description: "business, entertainment, health, science, sports, technology",
117-
Required: true,
118-
},
119-
},
120-
}, &tool{
121-
name: "search_news",
122-
description: "Return the news headlines with a search query",
123-
run: c.agentSearchNews,
124-
params: []agent.ToolParameter{
125-
{
126-
Name: "query",
127-
Description: "A phrase used to search for news headlines",
128-
Required: true,
129-
},
130-
},
131-
},
132-
}
133-
}
134-
135-
///////////////////////////////////////////////////////////////////////////////
136-
// PRIVATE METHODS - TOOL
137-
138-
func (*tool) Provider() string {
139-
return "newsapi"
140-
}
141-
142-
func (t *tool) Name() string {
143-
return t.name
144-
}
145-
146-
func (t *tool) Description() string {
147-
return t.description
148-
}
149-
150-
func (t *tool) Params() []agent.ToolParameter {
151-
return t.params
152-
}
153-
154-
func (t *tool) Run(ctx context.Context, call *agent.ToolCall) (*agent.ToolResult, error) {
155-
return t.run(ctx, call)
156-
}
157-
158-
///////////////////////////////////////////////////////////////////////////////
159-
// PRIVATE METHODS - TOOL
160-
161-
// Return the current general headlines
162-
func (c *Client) agentCurrentHeadlines(_ context.Context, call *agent.ToolCall) (*agent.ToolResult, error) {
163-
response, err := c.Headlines(OptCategory("general"), OptLimit(5))
164-
if err != nil {
165-
return nil, err
166-
}
167-
return &agent.ToolResult{
168-
Id: call.Id,
169-
Result: map[string]any{
170-
"type": "text",
171-
"headlines": response,
172-
},
173-
}, nil
174-
}
175-
176-
// Return the headlines for a specific country
177-
func (c *Client) agentCountryHeadlines(_ context.Context, call *agent.ToolCall) (*agent.ToolResult, error) {
178-
country, err := call.String("countrycode")
179-
if err != nil {
180-
return nil, err
181-
}
182-
country = strings.ToLower(country)
183-
response, err := c.Headlines(OptCountry(country), OptLimit(5))
184-
if err != nil {
185-
return nil, err
186-
}
187-
return &agent.ToolResult{
188-
Id: call.Id,
189-
Result: map[string]any{
190-
"type": "text",
191-
"country": country,
192-
"headlines": response,
193-
},
194-
}, nil
195-
}
196-
197-
// Return the headlines for a specific category
198-
func (c *Client) agentCategoryHeadlines(_ context.Context, call *agent.ToolCall) (*agent.ToolResult, error) {
199-
category, err := call.String("category")
200-
if err != nil {
201-
return nil, err
202-
}
203-
category = strings.ToLower(category)
204-
response, err := c.Headlines(OptCategory(category), OptLimit(5))
205-
if err != nil {
206-
return nil, err
207-
}
208-
return &agent.ToolResult{
209-
Id: call.Id,
210-
Result: map[string]any{
211-
"type": "text",
212-
"category": category,
213-
"headlines": response,
214-
},
215-
}, nil
216-
}
217-
218-
// Return the headlines for a specific query
219-
func (c *Client) agentSearchNews(_ context.Context, call *agent.ToolCall) (*agent.ToolResult, error) {
220-
query, err := call.String("query")
221-
if err != nil {
222-
return nil, err
223-
}
224-
response, err := c.Articles(OptQuery(query), OptLimit(5))
225-
if err != nil {
226-
return nil, err
227-
}
228-
return &agent.ToolResult{
229-
Id: call.Id,
230-
Result: map[string]any{
231-
"type": "text",
232-
"query": query,
233-
"headlines": response,
234-
},
235-
}, nil
236-
}
237-
*/

0 commit comments

Comments
 (0)