diff --git a/docs/docs/03-tools/04-credential-tools.md b/docs/docs/03-tools/04-credential-tools.md index 981a708c..9aaa7601 100644 --- a/docs/docs/03-tools/04-credential-tools.md +++ b/docs/docs/03-tools/04-credential-tools.md @@ -153,6 +153,8 @@ You can bypass credential tools and stored credentials by setting the `--credent need to be aware of which environment variables the credential tool sets. You can find this out by running the `gptscript credential --show-env-vars` command. +To override multiple credentials, specify the `--credential-override` argument multiple times. + ### Format :::info @@ -171,10 +173,6 @@ The `--credential-override` argument must be formatted in one of the following t In this example, both `toolA` provides the variables `ENV_VAR_1` and `ENV_VAR_2`. This will set the environment variables `ENV_VAR_1` and `ENV_VAR_2` to the specific values `value1` and `value2`. -:::info -To override more than one credential, use `;` as a separator. For example, `toolA:ENV_VAR_1=value1;toolB:ENV_VAR_2=value2`. -::: - #### 2. Environment Variables `toolA:ENV_VAR_1,ENV_VAR_2` diff --git a/docs/docs/04-command-line-reference/gptscript.md b/docs/docs/04-command-line-reference/gptscript.md index 4da342fb..0c485603 100644 --- a/docs/docs/04-command-line-reference/gptscript.md +++ b/docs/docs/04-command-line-reference/gptscript.md @@ -19,7 +19,7 @@ gptscript [flags] PROGRAM_FILE [INPUT...] --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") - --credential-override string Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) + --credential-override strings Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) --debug Enable debug logging ($GPTSCRIPT_DEBUG) --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") diff --git a/docs/docs/04-command-line-reference/gptscript_eval.md b/docs/docs/04-command-line-reference/gptscript_eval.md index 4c485c7c..0fdd0249 100644 --- a/docs/docs/04-command-line-reference/gptscript_eval.md +++ b/docs/docs/04-command-line-reference/gptscript_eval.md @@ -25,27 +25,27 @@ gptscript eval [flags] ### Options inherited from parent commands ``` - --cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR) - -C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR) - --color Use color in output (default true) ($GPTSCRIPT_COLOR) - --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) - --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) - --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") - --credential-override string Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) - --debug Enable debug logging ($GPTSCRIPT_DEBUG) - --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) - --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") - --disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE) - --dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE) - --events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO) - -f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE) - --no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC) - --openai-api-key string OpenAI API KEY ($OPENAI_API_KEY) - --openai-base-url string OpenAI base URL ($OPENAI_BASE_URL) - --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) - -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) - -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) - --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) + --cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR) + -C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR) + --color Use color in output (default true) ($GPTSCRIPT_COLOR) + --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) + --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) + --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") + --credential-override strings Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) + --debug Enable debug logging ($GPTSCRIPT_DEBUG) + --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) + --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") + --disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE) + --dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE) + --events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO) + -f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE) + --no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC) + --openai-api-key string OpenAI API KEY ($OPENAI_API_KEY) + --openai-base-url string OpenAI base URL ($OPENAI_BASE_URL) + --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) + -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) + -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` ### SEE ALSO diff --git a/docs/docs/04-command-line-reference/gptscript_fmt.md b/docs/docs/04-command-line-reference/gptscript_fmt.md index 511132d9..5780c838 100644 --- a/docs/docs/04-command-line-reference/gptscript_fmt.md +++ b/docs/docs/04-command-line-reference/gptscript_fmt.md @@ -19,27 +19,27 @@ gptscript fmt [flags] ### Options inherited from parent commands ``` - --cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR) - -C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR) - --color Use color in output (default true) ($GPTSCRIPT_COLOR) - --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) - --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) - --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") - --credential-override string Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) - --debug Enable debug logging ($GPTSCRIPT_DEBUG) - --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) - --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") - --disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE) - --dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE) - --events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO) - -f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE) - --no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC) - --openai-api-key string OpenAI API KEY ($OPENAI_API_KEY) - --openai-base-url string OpenAI base URL ($OPENAI_BASE_URL) - --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) - -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) - -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) - --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) + --cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR) + -C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR) + --color Use color in output (default true) ($GPTSCRIPT_COLOR) + --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) + --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) + --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") + --credential-override strings Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) + --debug Enable debug logging ($GPTSCRIPT_DEBUG) + --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) + --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") + --disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE) + --dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE) + --events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO) + -f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE) + --no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC) + --openai-api-key string OpenAI API KEY ($OPENAI_API_KEY) + --openai-base-url string OpenAI base URL ($OPENAI_BASE_URL) + --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) + -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) + -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` ### SEE ALSO diff --git a/docs/docs/04-command-line-reference/gptscript_parse.md b/docs/docs/04-command-line-reference/gptscript_parse.md index 3dde0073..680aebf6 100644 --- a/docs/docs/04-command-line-reference/gptscript_parse.md +++ b/docs/docs/04-command-line-reference/gptscript_parse.md @@ -19,27 +19,27 @@ gptscript parse [flags] ### Options inherited from parent commands ``` - --cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR) - -C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR) - --color Use color in output (default true) ($GPTSCRIPT_COLOR) - --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) - --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) - --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") - --credential-override string Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) - --debug Enable debug logging ($GPTSCRIPT_DEBUG) - --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) - --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") - --disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE) - --dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE) - --events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO) - -f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE) - --no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC) - --openai-api-key string OpenAI API KEY ($OPENAI_API_KEY) - --openai-base-url string OpenAI base URL ($OPENAI_BASE_URL) - --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) - -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) - -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) - --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) + --cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR) + -C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR) + --color Use color in output (default true) ($GPTSCRIPT_COLOR) + --config string Path to GPTScript config file ($GPTSCRIPT_CONFIG) + --confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM) + --credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default") + --credential-override strings Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE) + --debug Enable debug logging ($GPTSCRIPT_DEBUG) + --debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES) + --default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o") + --disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE) + --dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE) + --events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO) + -f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE) + --no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC) + --openai-api-key string OpenAI API KEY ($OPENAI_API_KEY) + --openai-base-url string OpenAI base URL ($OPENAI_BASE_URL) + --openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID) + -o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT) + -q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET) + --workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE) ``` ### SEE ALSO diff --git a/pkg/cli/gptscript.go b/pkg/cli/gptscript.go index 3ba5e8c7..735fd8d3 100644 --- a/pkg/cli/gptscript.go +++ b/pkg/cli/gptscript.go @@ -53,24 +53,24 @@ type GPTScript struct { Output string `usage:"Save output to a file, or - for stdout" short:"o"` EventsStreamTo string `usage:"Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\\\.\\pipe\\my-pipe)" name:"events-stream-to"` // Input should not be using GPTSCRIPT_INPUT env var because that is the same value that is set in tool executions - Input string `usage:"Read input from a file (\"-\" for stdin)" short:"f" env:"GPTSCRIPT_INPUT_FILE"` - SubTool string `usage:"Use tool of this name, not the first tool in file" local:"true"` - Assemble bool `usage:"Assemble tool to a single artifact, saved to --output" hidden:"true" local:"true"` - ListModels bool `usage:"List the models available and exit" local:"true"` - ListTools bool `usage:"List built-in tools and exit" local:"true"` - ListenAddress string `usage:"Server listen address" default:"127.0.0.1:0" hidden:"true"` - Chdir string `usage:"Change current working directory" short:"C"` - Daemon bool `usage:"Run tool as a daemon" local:"true" hidden:"true"` - Ports string `usage:"The port range to use for ephemeral daemon ports (ex: 11000-12000)" hidden:"true"` - CredentialContext string `usage:"Context name in which to store credentials" default:"default"` - CredentialOverride string `usage:"Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234)"` - ChatState string `usage:"The chat state to continue, or null to start a new chat and return the state" local:"true"` - ForceChat bool `usage:"Force an interactive chat session if even the top level tool is not a chat tool" local:"true"` - ForceSequential bool `usage:"Force parallel calls to run sequentially" local:"true"` - Workspace string `usage:"Directory to use for the workspace, if specified it will not be deleted on exit"` - UI bool `usage:"Launch the UI" local:"true" name:"ui"` - DisableTUI bool `usage:"Don't use chat TUI but instead verbose output" local:"true" name:"disable-tui"` - SaveChatStateFile string `usage:"A file to save the chat state to so that a conversation can be resumed with --chat-state" local:"true"` + Input string `usage:"Read input from a file (\"-\" for stdin)" short:"f" env:"GPTSCRIPT_INPUT_FILE"` + SubTool string `usage:"Use tool of this name, not the first tool in file" local:"true"` + Assemble bool `usage:"Assemble tool to a single artifact, saved to --output" hidden:"true" local:"true"` + ListModels bool `usage:"List the models available and exit" local:"true"` + ListTools bool `usage:"List built-in tools and exit" local:"true"` + ListenAddress string `usage:"Server listen address" default:"127.0.0.1:0" hidden:"true"` + Chdir string `usage:"Change current working directory" short:"C"` + Daemon bool `usage:"Run tool as a daemon" local:"true" hidden:"true"` + Ports string `usage:"The port range to use for ephemeral daemon ports (ex: 11000-12000)" hidden:"true"` + CredentialContext string `usage:"Context name in which to store credentials" default:"default"` + CredentialOverride []string `usage:"Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234)"` + ChatState string `usage:"The chat state to continue, or null to start a new chat and return the state" local:"true"` + ForceChat bool `usage:"Force an interactive chat session if even the top level tool is not a chat tool" local:"true"` + ForceSequential bool `usage:"Force parallel calls to run sequentially" local:"true"` + Workspace string `usage:"Directory to use for the workspace, if specified it will not be deleted on exit"` + UI bool `usage:"Launch the UI" local:"true" name:"ui"` + DisableTUI bool `usage:"Don't use chat TUI but instead verbose output" local:"true" name:"disable-tui"` + SaveChatStateFile string `usage:"A file to save the chat state to so that a conversation can be resumed with --chat-state" local:"true"` readData []byte } @@ -130,8 +130,8 @@ func (r *GPTScript) NewGPTScriptOpts() (gptscript.Options, error) { OpenAI: openai.Options(r.OpenAIOptions), Monitor: monitor.Options(r.DisplayOptions), Runner: runner.Options{ - CredentialOverride: r.CredentialOverride, - Sequential: r.ForceSequential, + CredentialOverrides: r.CredentialOverride, + Sequential: r.ForceSequential, }, Quiet: r.Quiet, Env: os.Environ(), diff --git a/pkg/runner/credentials.go b/pkg/runner/credentials.go index f1c5d0dd..d2fbb00e 100644 --- a/pkg/runner/credentials.go +++ b/pkg/runner/credentials.go @@ -8,8 +8,8 @@ import ( // parseCredentialOverrides parses a string of credential overrides that the user provided as a command line arg. // The format of credential overrides can be one of two things: -// cred1:ENV1,ENV2;cred2:ENV1,ENV2 (direct mapping of environment variables) -// cred1:ENV1=VALUE1,ENV2=VALUE2;cred2:ENV1=VALUE1,ENV2=VALUE2 (key-value pairs) +// cred1:ENV1,ENV2 (direct mapping of environment variables) +// cred1:ENV1=VALUE1,ENV2=VALUE2 (key-value pairs) // // This function turns it into a map[string]map[string]string like this: // @@ -17,16 +17,12 @@ import ( // "cred1": { // "ENV1": "VALUE1", // "ENV2": "VALUE2", -// }, -// "cred2": { -// "ENV1": "VALUE1", -// "ENV2": "VALUE2", -// }, +// } // } -func parseCredentialOverrides(override string) (map[string]map[string]string, error) { +func parseCredentialOverrides(overrides []string) (map[string]map[string]string, error) { credentialOverrides := make(map[string]map[string]string) - for _, o := range strings.Split(override, ";") { + for _, o := range overrides { credName, envs, found := strings.Cut(o, ":") if !found { return nil, fmt.Errorf("invalid credential override: %s", o) diff --git a/pkg/runner/credentials_test.go b/pkg/runner/credentials_test.go index 548bc3b5..c568d6be 100644 --- a/pkg/runner/credentials_test.go +++ b/pkg/runner/credentials_test.go @@ -11,13 +11,18 @@ func TestParseCredentialOverrides(t *testing.T) { cases := []struct { name string envs map[string]string - in string + in []string out map[string]map[string]string expectErr bool }{ + { + name: "nil", + in: nil, + out: map[string]map[string]string{}, + }, { name: "empty", - in: "", + in: []string{""}, expectErr: true, }, { @@ -25,7 +30,7 @@ func TestParseCredentialOverrides(t *testing.T) { envs: map[string]string{ "ENV1": "VALUE1", }, - in: "cred1:ENV1", + in: []string{"cred1:ENV1"}, out: map[string]map[string]string{ "cred1": { "ENV1": "VALUE1", @@ -38,7 +43,7 @@ func TestParseCredentialOverrides(t *testing.T) { "ENV1": "VALUE1", "ENV2": "VALUE2", }, - in: "cred1:ENV1,ENV2", + in: []string{"cred1:ENV1,ENV2"}, out: map[string]map[string]string{ "cred1": { "ENV1": "VALUE1", @@ -52,7 +57,7 @@ func TestParseCredentialOverrides(t *testing.T) { "ENV1": "VALUE1", "ENV2": "VALUE2", }, - in: "cred1:ENV1=OTHERVALUE1,ENV2=OTHERVALUE2", + in: []string{"cred1:ENV1=OTHERVALUE1,ENV2=OTHERVALUE2"}, out: map[string]map[string]string{ "cred1": { "ENV1": "OTHERVALUE1", @@ -66,7 +71,7 @@ func TestParseCredentialOverrides(t *testing.T) { "ENV1": "VALUE1", "ENV2": "VALUE2", }, - in: "cred1:ENV1,ENV2;cred2:ENV1,ENV2", + in: []string{"cred1:ENV1,ENV2", "cred2:ENV1,ENV2"}, out: map[string]map[string]string{ "cred1": { "ENV1": "VALUE1", @@ -84,7 +89,7 @@ func TestParseCredentialOverrides(t *testing.T) { "ENV1": "VALUE1", "ENV2": "VALUE2", }, - in: "cred1:ENV1=OTHERVALUE1,ENV2=OTHERVALUE2;cred2:ENV1=OTHERVALUE3,ENV2=OTHERVALUE4", + in: []string{"cred1:ENV1=OTHERVALUE1,ENV2=OTHERVALUE2", "cred2:ENV1=OTHERVALUE3,ENV2=OTHERVALUE4"}, out: map[string]map[string]string{ "cred1": { "ENV1": "OTHERVALUE1", @@ -98,7 +103,7 @@ func TestParseCredentialOverrides(t *testing.T) { }, { name: "invalid format", - in: "cred1=ENV1,ENV2", + in: []string{"cred1=ENV1,ENV2"}, expectErr: true, }, } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 41e4f058..cc5a3927 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -30,13 +30,13 @@ type Monitor interface { } type Options struct { - MonitorFactory MonitorFactory `usage:"-"` - RuntimeManager engine.RuntimeManager `usage:"-"` - StartPort int64 `usage:"-"` - EndPort int64 `usage:"-"` - CredentialOverride string `usage:"-"` - Sequential bool `usage:"-"` - Authorizer AuthorizerFunc `usage:"-"` + MonitorFactory MonitorFactory `usage:"-"` + RuntimeManager engine.RuntimeManager `usage:"-"` + StartPort int64 `usage:"-"` + EndPort int64 `usage:"-"` + CredentialOverrides []string `usage:"-"` + Sequential bool `usage:"-"` + Authorizer AuthorizerFunc `usage:"-"` } type AuthorizerResponse struct { @@ -58,11 +58,13 @@ func Complete(opts ...Options) (result Options) { result.RuntimeManager = types.FirstSet(opt.RuntimeManager, result.RuntimeManager) result.StartPort = types.FirstSet(opt.StartPort, result.StartPort) result.EndPort = types.FirstSet(opt.EndPort, result.EndPort) - result.CredentialOverride = types.FirstSet(opt.CredentialOverride, result.CredentialOverride) result.Sequential = types.FirstSet(opt.Sequential, result.Sequential) if opt.Authorizer != nil { result.Authorizer = opt.Authorizer } + if opt.CredentialOverrides != nil { + result.CredentialOverrides = append(result.CredentialOverrides, opt.CredentialOverrides...) + } } return } @@ -90,7 +92,7 @@ type Runner struct { factory MonitorFactory runtimeManager engine.RuntimeManager credMutex sync.Mutex - credOverrides string + credOverrides []string credStore credentials.CredentialStore sequential bool } @@ -103,7 +105,7 @@ func New(client engine.Model, credStore credentials.CredentialStore, opts ...Opt factory: opt.MonitorFactory, runtimeManager: opt.RuntimeManager, credMutex: sync.Mutex{}, - credOverrides: opt.CredentialOverride, + credOverrides: opt.CredentialOverrides, credStore: credStore, sequential: opt.Sequential, auth: opt.Authorizer, @@ -836,7 +838,7 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env credOverrides map[string]map[string]string err error ) - if r.credOverrides != "" { + if r.credOverrides != nil { credOverrides, err = parseCredentialOverrides(r.credOverrides) if err != nil { return nil, fmt.Errorf("failed to parse credential overrides: %w", err) diff --git a/pkg/sdkserver/routes.go b/pkg/sdkserver/routes.go index 176552b1..c16b4429 100644 --- a/pkg/sdkserver/routes.go +++ b/pkg/sdkserver/routes.go @@ -200,8 +200,8 @@ func (s *server) execHandler(w http.ResponseWriter, r *http.Request) { CredentialContext: reqObject.CredentialContext, Runner: runner.Options{ // Set the monitor factory so that we can get events from the server. - MonitorFactory: NewSessionFactory(s.events), - CredentialOverride: reqObject.CredentialOverride, + MonitorFactory: NewSessionFactory(s.events), + CredentialOverrides: reqObject.CredentialOverrides, }, } diff --git a/pkg/sdkserver/types.go b/pkg/sdkserver/types.go index e6325956..6f940c8b 100644 --- a/pkg/sdkserver/types.go +++ b/pkg/sdkserver/types.go @@ -52,15 +52,15 @@ type toolOrFileRequest struct { cacheOptions `json:",inline"` openAIOptions `json:",inline"` - ToolDefs toolDefs `json:"toolDefs,inline"` - SubTool string `json:"subTool"` - Input string `json:"input"` - ChatState string `json:"chatState"` - Workspace string `json:"workspace"` - Env []string `json:"env"` - CredentialContext string `json:"credentialContext"` - CredentialOverride string `json:"credentialOverride"` - Confirm bool `json:"confirm"` + ToolDefs toolDefs `json:"toolDefs,inline"` + SubTool string `json:"subTool"` + Input string `json:"input"` + ChatState string `json:"chatState"` + Workspace string `json:"workspace"` + Env []string `json:"env"` + CredentialContext string `json:"credentialContext"` + CredentialOverrides []string `json:"credentialOverrides"` + Confirm bool `json:"confirm"` } type content struct {