Skip to content

fix: credential overrides for credential aliases #511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/docs/03-tools/04-credential-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ need to be aware of which environment variables the credential tool sets. You ca

### Format

:::info
In the examples that follow, `toolA`, `toolB`, etc. are the names of credentials.
By default, a credential has the same name as the tool that created it.
This can be overridden with a credential alias, i.e. `credential: my-cred-tool.gpt as myAlias`.
If the credential has an alias, use it instead of the tool name when you specify an override.
:::

The `--credential-override` argument must be formatted in one of the following three ways:

#### 1. Key-Value Pairs
Expand Down
2 changes: 0 additions & 2 deletions docs/docs/04-command-line-reference/gptscript.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,13 @@ gptscript [flags] PROGRAM_FILE [INPUT...]
-f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT)
--list-models List the models available and exit ($GPTSCRIPT_LIST_MODELS)
--list-tools List built-in tools and exit ($GPTSCRIPT_LIST_TOOLS)
--listen-address string Server listen address ($GPTSCRIPT_LISTEN_ADDRESS) (default "127.0.0.1:0")
--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)
--save-chat-state-file string A file to save the chat state to so that a conversation can be resumed with --chat-state ($GPTSCRIPT_SAVE_CHAT_STATE_FILE)
--server Start server ($GPTSCRIPT_SERVER)
--sub-tool string Use tool of this name, not the first tool in file ($GPTSCRIPT_SUB_TOOL)
--ui Launch the UI ($GPTSCRIPT_UI)
--workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ gptscript credential [flags]

* [gptscript](gptscript.md) -
* [gptscript credential delete](gptscript_credential_delete.md) - Delete a stored credential
* [gptscript credential show](gptscript_credential_show.md) - Show the secret value of a stored credential

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ title: "gptscript credential delete"
Delete a stored credential

```
gptscript credential delete <tool name> [flags]
gptscript credential delete <credential name> [flags]
```

### Options
Expand Down
27 changes: 27 additions & 0 deletions docs/docs/04-command-line-reference/gptscript_credential_show.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: "gptscript credential show"
---
## gptscript credential show

Show the secret value of a stored credential

```
gptscript credential show <credential name> [flags]
```

### Options

```
-h, --help help for show
```

### Options inherited from parent commands

```
--credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default")
```

### SEE ALSO

* [gptscript credential](gptscript_credential.md) - List stored credentials

14 changes: 7 additions & 7 deletions pkg/runner/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ 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 three things:
// tool1:ENV1,ENV2;tool2:ENV1,ENV2 (direct mapping of environment variables)
// tool1:ENV1=VALUE1,ENV2=VALUE2;tool2:ENV1=VALUE1,ENV2=VALUE2 (key-value pairs)
// tool1:ENV1->OTHER_ENV1,ENV2->OTHER_ENV2;tool2:ENV1->OTHER_ENV1,ENV2->OTHER_ENV2 (mapping to other environment variables)
// 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->OTHER_ENV1,ENV2->OTHER_ENV2;cred2:ENV1->OTHER_ENV1,ENV2->OTHER_ENV2 (mapping to other environment variables)
//
// This function turns it into a map[string]map[string]string like this:
//
// {
// "tool1": {
// "cred1": {
// "ENV1": "VALUE1",
// "ENV2": "VALUE2",
// },
// "tool2": {
// "cred2": {
// "ENV1": "VALUE1",
// "ENV2": "VALUE2",
// },
Expand All @@ -28,7 +28,7 @@ func parseCredentialOverrides(override string) (map[string]map[string]string, er
credentialOverrides := make(map[string]map[string]string)

for _, o := range strings.Split(override, ";") {
toolName, envs, found := strings.Cut(o, ":")
credName, envs, found := strings.Cut(o, ":")
if !found {
return nil, fmt.Errorf("invalid credential override: %s", o)
}
Expand All @@ -48,7 +48,7 @@ func parseCredentialOverrides(override string) (map[string]map[string]string, er
}
envMap[key] = value
}
credentialOverrides[toolName] = envMap
credentialOverrides[credName] = envMap
}

return credentialOverrides, nil
Expand Down
27 changes: 14 additions & 13 deletions pkg/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -813,19 +813,24 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env
}

for _, credToolName := range callCtx.Tool.Credentials {
toolName, credentialAlias, args, err := types.ParseCredentialArgs(credToolName, callCtx.Input)
if err != nil {
return nil, fmt.Errorf("failed to parse credential tool %q: %w", credToolName, err)
}

credName := toolName
if credentialAlias != "" {
credName = credentialAlias
}

// Check whether the credential was overridden before we attempt to find it in the store or run the tool.
if override, exists := credOverrides[credToolName]; exists {
if override, exists := credOverrides[credName]; exists {
for k, v := range override {
env = append(env, fmt.Sprintf("%s=%s", k, v))
}
continue
}

toolName, credentialAlias, args, err := types.ParseCredentialArgs(credToolName, callCtx.Input)
if err != nil {
return nil, fmt.Errorf("failed to parse credential tool %q: %w", credToolName, err)
}

var (
cred *credentials.Credential
exists bool
Expand Down Expand Up @@ -884,13 +889,9 @@ func (r *Runner) handleCredentials(callCtx engine.Context, monitor Monitor, env
}

cred = &credentials.Credential{
Type: credentials.CredentialTypeTool,
Env: envMap.Env,
}
if credentialAlias != "" {
cred.ToolName = credentialAlias
} else {
cred.ToolName = toolName
Type: credentials.CredentialTypeTool,
Env: envMap.Env,
ToolName: credName,
}

isEmpty := true
Expand Down
Loading