@@ -35,12 +35,16 @@ import (
3535 "github.com/googleapis/genai-toolbox/internal/auth"
3636 "github.com/googleapis/genai-toolbox/internal/log"
3737 "github.com/googleapis/genai-toolbox/internal/prebuiltconfigs"
38+ "github.com/googleapis/genai-toolbox/internal/prompts"
3839 "github.com/googleapis/genai-toolbox/internal/server"
3940 "github.com/googleapis/genai-toolbox/internal/sources"
4041 "github.com/googleapis/genai-toolbox/internal/telemetry"
4142 "github.com/googleapis/genai-toolbox/internal/tools"
4243 "github.com/googleapis/genai-toolbox/internal/util"
4344
45+ // Import prompt packages for side effect of registration
46+ _ "github.com/googleapis/genai-toolbox/internal/prompts/custom"
47+
4448 // Import tool packages for side effect of registration
4549 _ "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbcreatecluster"
4650 _ "github.com/googleapis/genai-toolbox/internal/tools/alloydb/alloydbcreateinstance"
@@ -360,12 +364,13 @@ type ToolsFile struct {
360364 AuthServices server.AuthServiceConfigs `yaml:"authServices"`
361365 Tools server.ToolConfigs `yaml:"tools"`
362366 Toolsets server.ToolsetConfigs `yaml:"toolsets"`
367+ Prompts server.PromptConfigs `yaml:"prompts"`
363368}
364369
365370// parseEnv replaces environment variables ${ENV_NAME} with their values.
366371// also support ${ENV_NAME:default_value}.
367372func parseEnv (input string ) (string , error ) {
368- re := regexp .MustCompile (`\$\{(\w+)(:(\w *))?\}` )
373+ re := regexp .MustCompile (`\$\{(\w+)(:([^}] *))?\}` )
369374
370375 var err error
371376 output := re .ReplaceAllStringFunc (input , func (match string ) string {
@@ -376,7 +381,7 @@ func parseEnv(input string) (string, error) {
376381 if value , found := os .LookupEnv (variableName ); found {
377382 return value
378383 }
379- if parts [2 ] != "" {
384+ if len ( parts ) >= 4 && parts [2 ] != "" {
380385 return parts [3 ]
381386 }
382387 err = fmt .Errorf ("environment variable not found: %q" , variableName )
@@ -412,6 +417,7 @@ func mergeToolsFiles(files ...ToolsFile) (ToolsFile, error) {
412417 AuthServices : make (server.AuthServiceConfigs ),
413418 Tools : make (server.ToolConfigs ),
414419 Toolsets : make (server.ToolsetConfigs ),
420+ Prompts : make (server.PromptConfigs ),
415421 }
416422
417423 var conflicts []string
@@ -461,11 +467,20 @@ func mergeToolsFiles(files ...ToolsFile) (ToolsFile, error) {
461467 merged .Toolsets [name ] = toolset
462468 }
463469 }
470+
471+ // Check for conflicts and merge prompts
472+ for name , prompt := range file .Prompts {
473+ if _ , exists := merged .Prompts [name ]; exists {
474+ conflicts = append (conflicts , fmt .Sprintf ("prompt '%s' (file #%d)" , name , fileIndex + 1 ))
475+ } else {
476+ merged .Prompts [name ] = prompt
477+ }
478+ }
464479 }
465480
466481 // If conflicts were detected, return an error
467482 if len (conflicts ) > 0 {
468- return ToolsFile {}, fmt .Errorf ("resource conflicts detected:\n - %s\n \n Please ensure each source, authService, tool, and toolset has a unique name across all files" , strings .Join (conflicts , "\n - " ))
483+ return ToolsFile {}, fmt .Errorf ("resource conflicts detected:\n - %s\n \n Please ensure each source, authService, tool, toolset and prompt has a unique name across all files" , strings .Join (conflicts , "\n - " ))
469484 }
470485
471486 return merged , nil
@@ -539,22 +554,22 @@ func handleDynamicReload(ctx context.Context, toolsFile ToolsFile, s *server.Ser
539554 panic (err )
540555 }
541556
542- sourcesMap , authServicesMap , toolsMap , toolsetsMap , err := validateReloadEdits (ctx , toolsFile )
557+ sourcesMap , authServicesMap , toolsMap , toolsetsMap , promptsMap , promptsetsMap , err := validateReloadEdits (ctx , toolsFile )
543558 if err != nil {
544559 errMsg := fmt .Errorf ("unable to validate reloaded edits: %w" , err )
545560 logger .WarnContext (ctx , errMsg .Error ())
546561 return err
547562 }
548563
549- s .ResourceMgr .SetResources (sourcesMap , authServicesMap , toolsMap , toolsetsMap )
564+ s .ResourceMgr .SetResources (sourcesMap , authServicesMap , toolsMap , toolsetsMap , promptsMap , promptsetsMap )
550565
551566 return nil
552567}
553568
554569// validateReloadEdits checks that the reloaded tools file configs can initialized without failing
555570func validateReloadEdits (
556571 ctx context.Context , toolsFile ToolsFile ,
557- ) (map [string ]sources.Source , map [string ]auth.AuthService , map [string ]tools.Tool , map [string ]tools.Toolset , error ,
572+ ) (map [string ]sources.Source , map [string ]auth.AuthService , map [string ]tools.Tool , map [string ]tools.Toolset , map [ string ]prompts. Prompt , map [ string ]prompts. Promptset , error ,
558573) {
559574 logger , err := util .LoggerFromContext (ctx )
560575 if err != nil {
@@ -577,16 +592,17 @@ func validateReloadEdits(
577592 AuthServiceConfigs : toolsFile .AuthServices ,
578593 ToolConfigs : toolsFile .Tools ,
579594 ToolsetConfigs : toolsFile .Toolsets ,
595+ PromptConfigs : toolsFile .Prompts ,
580596 }
581597
582- sourcesMap , authServicesMap , toolsMap , toolsetsMap , err := server .InitializeConfigs (ctx , reloadedConfig )
598+ sourcesMap , authServicesMap , toolsMap , toolsetsMap , promptsMap , promptsetsMap , err := server .InitializeConfigs (ctx , reloadedConfig )
583599 if err != nil {
584600 errMsg := fmt .Errorf ("unable to initialize reloaded configs: %w" , err )
585601 logger .WarnContext (ctx , errMsg .Error ())
586- return nil , nil , nil , nil , err
602+ return nil , nil , nil , nil , nil , nil , err
587603 }
588604
589- return sourcesMap , authServicesMap , toolsMap , toolsetsMap , nil
605+ return sourcesMap , authServicesMap , toolsMap , toolsetsMap , promptsMap , promptsetsMap , nil
590606}
591607
592608// watchChanges checks for changes in the provided yaml tools file(s) or folder.
@@ -877,7 +893,8 @@ func run(cmd *Command) error {
877893 }
878894 }
879895
880- cmd .cfg .SourceConfigs , cmd .cfg .AuthServiceConfigs , cmd .cfg .ToolConfigs , cmd .cfg .ToolsetConfigs = toolsFile .Sources , toolsFile .AuthServices , toolsFile .Tools , toolsFile .Toolsets
896+ cmd .cfg .SourceConfigs , cmd .cfg .AuthServiceConfigs , cmd .cfg .ToolConfigs , cmd .cfg .ToolsetConfigs , cmd .cfg .PromptConfigs = toolsFile .Sources , toolsFile .AuthServices , toolsFile .Tools , toolsFile .Toolsets , toolsFile .Prompts
897+
881898 authSourceConfigs := toolsFile .AuthSources
882899 if authSourceConfigs != nil {
883900 cmd .logger .WarnContext (ctx , "`authSources` is deprecated, use `authServices` instead" )
0 commit comments