Skip to content

Commit

Permalink
fix: credential overrides for credential aliases (#511)
Browse files Browse the repository at this point in the history
Signed-off-by: Grant Linville <[email protected]>
  • Loading branch information
g-linville authored Jun 18, 2024
1 parent 02a3cee commit 64d0748
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 23 deletions.
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

0 comments on commit 64d0748

Please sign in to comment.