Skip to content

Commit d629e4a

Browse files
committed
add websearch tool for anthropic
1 parent 0ae4165 commit d629e4a

4 files changed

Lines changed: 44 additions & 28 deletions

File tree

frontend/app/aipanel/aipanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ const AIPanelComponentInner = memo(() => {
306306
};
307307

308308
useEffect(() => {
309-
globalStore.set(model.isAIStreaming, status == "streaming");
309+
globalStore.set(model.isAIStreaming, status === "streaming" || status === "submitted");
310310
}, [status]);
311311

312312
useEffect(() => {

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/aiusechat/anthropic/anthropic-backend.go

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ func (m *anthropicChatMessage) GetUsage() *uctypes.AIUsage {
5858
}
5959

6060
return &uctypes.AIUsage{
61-
APIType: uctypes.APIType_AnthropicMessages,
62-
Model: m.Usage.Model,
63-
InputTokens: m.Usage.InputTokens,
64-
OutputTokens: m.Usage.OutputTokens,
61+
APIType: uctypes.APIType_AnthropicMessages,
62+
Model: m.Usage.Model,
63+
InputTokens: m.Usage.InputTokens,
64+
OutputTokens: m.Usage.OutputTokens,
65+
NativeWebSearchCount: m.Usage.NativeWebSearchCount,
6566
}
6667
}
6768

@@ -181,10 +182,15 @@ type anthropicStreamRequest struct {
181182
Stream bool `json:"stream"`
182183
System []anthropicMessageContentBlock `json:"system,omitempty"`
183184
ToolChoice any `json:"tool_choice,omitempty"`
184-
Tools []uctypes.ToolDefinition `json:"tools,omitempty"`
185+
Tools []any `json:"tools,omitempty"` // *uctypes.ToolDefinition or *anthropicWebSearchTool
185186
Thinking *anthropicThinkingOpts `json:"thinking,omitempty"`
186187
}
187188

189+
type anthropicWebSearchTool struct {
190+
Type string `json:"type"` // "web_search_20250305"
191+
Name string `json:"name"` // "web_search"
192+
}
193+
188194
type anthropicCacheControl struct {
189195
Type string `json:"type"` // "ephemeral"
190196
TTL string `json:"ttl"` // "5m" or "1h"
@@ -232,8 +238,9 @@ type anthropicUsageType struct {
232238
CacheCreationInputTokens int `json:"cache_creation_input_tokens,omitempty"`
233239
CacheReadInputTokens int `json:"cache_read_input_tokens,omitempty"`
234240

235-
// internal field for Wave use (not sent to API)
236-
Model string `json:"model,omitempty"`
241+
// internal fields for Wave use (not sent to API)
242+
Model string `json:"model,omitempty"`
243+
NativeWebSearchCount int `json:"nativewebsearchcount,omitempty"`
237244

238245
// for reference, but we dont keep thsese up to date or track them
239246
CacheCreation *anthropicCacheCreationType `json:"cache_creation,omitempty"` // breakdown of cached tokens by TTL
@@ -294,15 +301,16 @@ type partialJSON struct {
294301
}
295302

296303
type streamingState struct {
297-
blockMap map[int]*blockState
298-
toolCalls []uctypes.WaveToolCall
299-
stopFromDelta string
300-
msgID string
301-
model string
302-
stepStarted bool
303-
rtnMessage *anthropicChatMessage
304-
usage *anthropicUsageType
305-
chatOpts uctypes.WaveChatOpts
304+
blockMap map[int]*blockState
305+
toolCalls []uctypes.WaveToolCall
306+
stopFromDelta string
307+
msgID string
308+
model string
309+
stepStarted bool
310+
rtnMessage *anthropicChatMessage
311+
usage *anthropicUsageType
312+
chatOpts uctypes.WaveChatOpts
313+
webSearchCount int
306314
}
307315

308316
func (p *partialJSON) Write(s string) {
@@ -547,8 +555,10 @@ func handleAnthropicStreamingResp(
547555
defer func() {
548556
// Set usage in the returned message
549557
if state.usage != nil {
550-
// Set model in usage for internal use
551558
state.usage.Model = state.model
559+
if state.webSearchCount > 0 {
560+
state.usage.NativeWebSearchCount = state.webSearchCount
561+
}
552562
state.rtnMessage.Usage = state.usage
553563
}
554564

@@ -759,6 +769,10 @@ func handleAnthropicEvent(
759769
}
760770
state.blockMap[idx] = st
761771
_ = sse.AiMsgToolInputStart(tcID, tName)
772+
case "server_tool_use":
773+
if ev.ContentBlock.Name == "web_search" {
774+
state.webSearchCount++
775+
}
762776
default:
763777
// ignore other block types gracefully per Anthropic guidance :contentReference[oaicite:18]{index=18}
764778
}

pkg/aiusechat/anthropic/anthropic-convertmessage.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,31 +122,33 @@ func buildAnthropicHTTPRequest(ctx context.Context, msgs []anthropicInputMessage
122122
reqBody.System = systemBlocks
123123
}
124124

125-
if len(chatOpts.Tools) > 0 {
126-
cleanedTools := make([]uctypes.ToolDefinition, len(chatOpts.Tools))
127-
for i, tool := range chatOpts.Tools {
128-
cleanedTools[i] = *tool.Clean()
129-
}
130-
reqBody.Tools = cleanedTools
125+
for _, tool := range chatOpts.Tools {
126+
cleanedTool := tool.Clean()
127+
reqBody.Tools = append(reqBody.Tools, cleanedTool)
131128
}
132129
for _, tool := range chatOpts.TabTools {
133-
cleanedTool := *tool.Clean()
130+
cleanedTool := tool.Clean()
134131
reqBody.Tools = append(reqBody.Tools, cleanedTool)
135132
}
133+
if chatOpts.AllowNativeWebSearch {
134+
reqBody.Tools = append(reqBody.Tools, &anthropicWebSearchTool{Type: "web_search_20250305", Name: "web_search"})
135+
}
136136

137137
// Enable extended thinking based on level
138138
reqBody.Thinking = makeThinkingOpts(opts.ThinkingLevel, maxTokens)
139139

140140
// pretty print json of anthropicMsgs
141141
if jsonStr, err := utilfn.MarshalIndentNoHTMLString(convertedMsgs, "", " "); err == nil {
142-
logutil.DevPrintf("system-prompt: %v\n", chatOpts.SystemPrompt)
143142
var toolNames []string
144143
for _, tool := range chatOpts.Tools {
145144
toolNames = append(toolNames, tool.Name)
146145
}
147146
for _, tool := range chatOpts.TabTools {
148147
toolNames = append(toolNames, tool.Name)
149148
}
149+
if chatOpts.AllowNativeWebSearch {
150+
toolNames = append(toolNames, "web_search[server]")
151+
}
150152
logutil.DevPrintf("tools: %s\n", strings.Join(toolNames, ", "))
151153
logutil.DevPrintf("anthropicMsgs JSON:\n%s", jsonStr)
152154
logutil.DevPrintf("has-api-key: %v\n", opts.APIToken != "")

0 commit comments

Comments
 (0)