Skip to content

Commit c1af895

Browse files
authored
feat: add web search tool provider (#2181)
1 parent 5cad5e4 commit c1af895

8 files changed

Lines changed: 1028 additions & 50 deletions

File tree

object/merge_agent_tools.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func buildMergedBuiltinRegistry(store *Store, lang string) *builtin_tool.ToolReg
3434
if err != nil || p == nil || p.Category != "Tool" {
3535
continue
3636
}
37-
tp, err := tool.NewProvider(p.Category, p.Type, lang)
37+
tp, err := tool.NewProvider(getToolProviderConfig(p), lang)
3838
if err != nil {
3939
continue
4040
}

object/message_tool.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func buildAgentClientsForToolProvider(toolProviderName string, lang string) (*ag
3838
return nil, nil
3939
}
4040

41-
tp, err := tool.NewProvider(p.Category, p.Type, lang)
41+
tp, err := tool.NewProvider(getToolProviderConfig(p), lang)
4242
if err != nil {
4343
return nil, err
4444
}

object/provider.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,9 +706,16 @@ func TestMcpProvider(p *Provider, lang string) (string, error) {
706706

707707
// TestToolProvider parses provider.testContent as {"tool":"...","arguments":{}} and invokes one builtin tool.
708708
func TestToolProvider(p *Provider, lang string) (string, error) {
709+
return p.testToolProviderWithLoader(lang, getProvider)
710+
}
711+
712+
func (p *Provider) testToolProviderWithLoader(lang string, loadProvider func(owner string, name string) (*Provider, error)) (string, error) {
709713
if p.Category != "Tool" {
710714
return "", fmt.Errorf(i18n.Translate(lang, "object:provider is not a Tool provider"))
711715
}
716+
if err := p.restoreMaskedToolProviderSecrets(loadProvider); err != nil {
717+
return "", err
718+
}
712719

713720
var payload struct {
714721
Tool string `json:"tool"`
@@ -724,7 +731,7 @@ func TestToolProvider(p *Provider, lang string) (string, error) {
724731
payload.Arguments = map[string]interface{}{}
725732
}
726733

727-
tp, err := tool.NewProvider(p.Category, p.Type, lang)
734+
tp, err := tool.NewProvider(getToolProviderConfig(p), lang)
728735
if err != nil {
729736
return "", err
730737
}
@@ -760,6 +767,55 @@ func TestToolProvider(p *Provider, lang string) (string, error) {
760767
return output, nil
761768
}
762769

770+
func getToolProviderConfig(p *Provider) tool.ProviderConfig {
771+
return tool.ProviderConfig{
772+
Category: p.Category,
773+
Type: p.Type,
774+
SubType: p.SubType,
775+
ProviderUrl: p.ProviderUrl,
776+
ClientId: p.ClientId,
777+
ClientSecret: p.ClientSecret,
778+
}
779+
}
780+
781+
func (p *Provider) restoreMaskedToolProviderSecrets(loadProvider func(owner string, name string) (*Provider, error)) error {
782+
if p == nil {
783+
return nil
784+
}
785+
786+
maskedClientSecret := p.ClientSecret == "***"
787+
maskedUserKey := p.UserKey == "***"
788+
maskedSignKey := p.SignKey == "***"
789+
if !maskedClientSecret && !maskedUserKey && !maskedSignKey {
790+
return nil
791+
}
792+
if strings.TrimSpace(p.Owner) == "" || strings.TrimSpace(p.Name) == "" {
793+
return fmt.Errorf("cannot restore masked tool provider secrets without owner and name")
794+
}
795+
796+
providerDb, err := loadProvider(p.Owner, p.Name)
797+
if err != nil {
798+
return err
799+
}
800+
if providerDb == nil {
801+
return fmt.Errorf("provider not found: %s/%s", p.Owner, p.Name)
802+
}
803+
804+
p.processProviderParams(providerDb)
805+
806+
if maskedClientSecret && (p.ClientSecret == "" || p.ClientSecret == "***") {
807+
return fmt.Errorf("masked clientSecret could not be restored")
808+
}
809+
if maskedUserKey && (p.UserKey == "" || p.UserKey == "***") {
810+
return fmt.Errorf("masked userKey could not be restored")
811+
}
812+
if maskedSignKey && (p.SignKey == "" || p.SignKey == "***") {
813+
return fmt.Errorf("masked signKey could not be restored")
814+
}
815+
816+
return nil
817+
}
818+
763819
func (p *Provider) processProviderParams(providerDb *Provider) {
764820
if p.ClientSecret == "***" {
765821
p.ClientSecret = providerDb.ClientSecret

tool/provider.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,29 @@ type Provider interface {
2626
BuiltinTools() []builtin_tool.BuiltinTool
2727
}
2828

29+
// ProviderConfig contains the Provider fields needed to construct builtin tools.
30+
type ProviderConfig struct {
31+
Category string
32+
Type string
33+
SubType string
34+
ProviderUrl string
35+
ClientId string
36+
ClientSecret string
37+
}
38+
2939
// NewProvider instantiates a Tool provider implementation from category and type.
30-
func NewProvider(category string, typ string, lang string) (Provider, error) {
31-
if category != "Tool" {
32-
return nil, fmt.Errorf(i18n.Translate(lang, "tool:expected category Tool, got %s"), category)
40+
func NewProvider(config ProviderConfig, lang string) (Provider, error) {
41+
if config.Category != "Tool" {
42+
return nil, fmt.Errorf(i18n.Translate(lang, "tool:expected category Tool, got %s"), config.Category)
3343
}
34-
switch typ {
44+
switch config.Type {
3545
case "Time":
3646
return &TimeProvider{}, nil
47+
case "WebSearch":
48+
return NewWebSearchProvider(config)
3749
case "Shell":
3850
return &ShellProvider{}, nil
3951
default:
40-
return nil, fmt.Errorf(i18n.Translate(lang, "tool:unsupported tool provider type: %s"), typ)
52+
return nil, fmt.Errorf(i18n.Translate(lang, "tool:unsupported tool provider type: %s"), config.Type)
4153
}
4254
}

0 commit comments

Comments
 (0)