Forward Scriptorium credentials through the shared adapter path

This commit is contained in:
2026-09-29 17:50:30 +00:00
parent 9389f69eb0
commit 44a318694b
20 changed files with 270 additions and 73 deletions

View File

@@ -28,7 +28,12 @@ func (r *SubprocessRunner) RunArtifact(ctx context.Context, req RunArtifactReque
if r == nil {
return ArtifactResult{}, fmt.Errorf("scriptorium subprocess runner is nil")
}
credentialPresent, err := validateCommonRunRequest(req.Binary, req.ConfigPath, req.PromptID, req.OutputPath, req.Timeout, req.APIKeyEnv, req.InputPaths, req.Vars)
err := validateCommonRunRequest(req.Binary, req.ConfigPath, req.PromptID, req.OutputPath, req.Timeout, req.InputPaths, req.Vars)
if err != nil {
return ArtifactResult{}, err
}
envOverrides, sensitiveNames, err := subprocess.CredentialEnvironment(req.Credentials)
if err != nil {
return ArtifactResult{}, err
}
@@ -46,8 +51,7 @@ func (r *SubprocessRunner) RunArtifact(ctx context.Context, req RunArtifactReque
InputPaths: cloneStringMap(req.InputPaths),
Vars: cloneStringMap(req.Vars),
OutputPath: req.OutputPath,
APIKeyEnv: strings.TrimSpace(req.APIKeyEnv),
APIKeyEnvPresent: credentialPresent,
CredentialNames: sensitiveNames,
WorkingDir: req.WorkingDir,
RenderFormat: "",
RenderPromptStore: false,
@@ -56,7 +60,6 @@ func (r *SubprocessRunner) RunArtifact(ctx context.Context, req RunArtifactReque
}
}
envOverrides, sensitiveNames := credentialEnvironment(req.APIKeyEnv)
runRes, runErr := subprocess.Run(ctx, subprocess.RunRequest{
Executable: req.Binary,
Args: args,
@@ -80,12 +83,11 @@ func (r *SubprocessRunner) RunArtifact(ctx context.Context, req RunArtifactReque
PromptID: req.PromptID,
ProfileID: req.ProfileID,
Metadata: map[string]any{
"adapter": "scriptorium_subprocess",
"config_path": strings.TrimSpace(req.ConfigPath),
"inputs_count": len(req.InputPaths),
"vars_count": len(req.Vars),
"api_key_env": strings.TrimSpace(req.APIKeyEnv),
"api_key_env_present": credentialPresent,
"adapter": "scriptorium_subprocess",
"config_path": strings.TrimSpace(req.ConfigPath),
"inputs_count": len(req.InputPaths),
"vars_count": len(req.Vars),
"credential_env_names": sensitiveNames,
},
}
@@ -114,7 +116,12 @@ func (r *SubprocessRunner) RenderArtifact(ctx context.Context, req RenderArtifac
if r == nil {
return ArtifactResult{}, fmt.Errorf("scriptorium subprocess runner is nil")
}
credentialPresent, err := validateCommonRunRequest(req.Binary, req.ConfigPath, req.PromptID, req.OutputPath, req.Timeout, req.APIKeyEnv, req.InputPaths, req.Vars)
err := validateCommonRunRequest(req.Binary, req.ConfigPath, req.PromptID, req.OutputPath, req.Timeout, req.InputPaths, req.Vars)
if err != nil {
return ArtifactResult{}, err
}
envOverrides, sensitiveNames, err := subprocess.CredentialEnvironment(req.Credentials)
if err != nil {
return ArtifactResult{}, err
}
@@ -132,8 +139,7 @@ func (r *SubprocessRunner) RenderArtifact(ctx context.Context, req RenderArtifac
InputPaths: cloneStringMap(req.InputPaths),
Vars: cloneStringMap(req.Vars),
OutputPath: req.OutputPath,
APIKeyEnv: strings.TrimSpace(req.APIKeyEnv),
APIKeyEnvPresent: credentialPresent,
CredentialNames: sensitiveNames,
WorkingDir: req.WorkingDir,
RenderFormat: "json",
RenderPromptStore: false,
@@ -142,7 +148,6 @@ func (r *SubprocessRunner) RenderArtifact(ctx context.Context, req RenderArtifac
}
}
envOverrides, sensitiveNames := credentialEnvironment(req.APIKeyEnv)
runRes, runErr := subprocess.Run(ctx, subprocess.RunRequest{
Executable: req.Binary,
Args: args,
@@ -166,13 +171,12 @@ func (r *SubprocessRunner) RenderArtifact(ctx context.Context, req RenderArtifac
PromptID: req.PromptID,
ProfileID: req.ProfileID,
Metadata: map[string]any{
"adapter": "scriptorium_subprocess",
"config_path": strings.TrimSpace(req.ConfigPath),
"inputs_count": len(req.InputPaths),
"vars_count": len(req.Vars),
"api_key_env": strings.TrimSpace(req.APIKeyEnv),
"api_key_env_present": credentialPresent,
"format": "json",
"adapter": "scriptorium_subprocess",
"config_path": strings.TrimSpace(req.ConfigPath),
"inputs_count": len(req.InputPaths),
"vars_count": len(req.Vars),
"credential_env_names": sensitiveNames,
"format": "json",
},
}
@@ -191,57 +195,39 @@ func validateCommonRunRequest(
promptID string,
outputPath string,
timeout time.Duration,
apiKeyEnv string,
inputPaths map[string]string,
vars map[string]string,
) (bool, error) {
) error {
if strings.TrimSpace(binary) == "" {
return false, fmt.Errorf("scriptorium binary is required")
return fmt.Errorf("scriptorium binary is required")
}
if strings.TrimSpace(configPath) == "" && configPath != "" {
return false, fmt.Errorf("scriptorium config path must be non-empty when provided")
return fmt.Errorf("scriptorium config path must be non-empty when provided")
}
if strings.TrimSpace(promptID) == "" {
return false, fmt.Errorf("scriptorium prompt id is required")
return fmt.Errorf("scriptorium prompt id is required")
}
if strings.TrimSpace(outputPath) == "" {
return false, fmt.Errorf("scriptorium output path is required")
return fmt.Errorf("scriptorium output path is required")
}
if timeout <= 0 {
return false, fmt.Errorf("scriptorium timeout must be > 0")
return fmt.Errorf("scriptorium timeout must be > 0")
}
for name, path := range inputPaths {
if strings.TrimSpace(name) == "" {
return false, fmt.Errorf("scriptorium input names must be non-empty")
return fmt.Errorf("scriptorium input names must be non-empty")
}
if strings.TrimSpace(path) == "" {
return false, fmt.Errorf("scriptorium input %q path is required", name)
return fmt.Errorf("scriptorium input %q path is required", name)
}
}
for name := range vars {
if strings.TrimSpace(name) == "" {
return false, fmt.Errorf("scriptorium variable names must be non-empty")
return fmt.Errorf("scriptorium variable names must be non-empty")
}
}
trimmedEnv := strings.TrimSpace(apiKeyEnv)
if trimmedEnv == "" {
return false, nil
}
value, ok := os.LookupEnv(trimmedEnv)
if !ok || strings.TrimSpace(value) == "" {
return false, fmt.Errorf("scriptorium required credential environment variable %s is not set", trimmedEnv)
}
return true, nil
}
func credentialEnvironment(apiKeyEnv string) (map[string]string, []string) {
name := strings.TrimSpace(apiKeyEnv)
if name == "" {
return nil, nil
}
value, _ := os.LookupEnv(name)
return map[string]string{name: value}, []string{name}
return nil
}
func buildRunArgs(req RunArtifactRequest) []string {
@@ -258,9 +244,6 @@ func buildRunArgs(req RunArtifactRequest) []string {
for _, kv := range sortedKeyValues(req.Vars) {
args = append(args, "--var", kv)
}
if envName := strings.TrimSpace(req.APIKeyEnv); envName != "" {
args = append(args, "--api-key-env", envName)
}
args = append(args, "--timeout", req.Timeout.String())
args = append(args, "--out", req.OutputPath)
return args
@@ -280,9 +263,6 @@ func buildRenderArgs(req RenderArtifactRequest) []string {
for _, kv := range sortedKeyValues(req.Vars) {
args = append(args, "--var", kv)
}
if envName := strings.TrimSpace(req.APIKeyEnv); envName != "" {
args = append(args, "--api-key-env", envName)
}
args = append(args, "--timeout", req.Timeout.String())
args = append(args, "--format", "json")
args = append(args, "--out", req.OutputPath)
@@ -316,8 +296,7 @@ type invocationPayload struct {
InputPaths map[string]string
Vars map[string]string
OutputPath string
APIKeyEnv string
APIKeyEnvPresent bool
CredentialNames []string
WorkingDir string
RenderFormat string
RenderPromptStore bool
@@ -336,8 +315,7 @@ func writeInvocationConfig(path string, payload invocationPayload) error {
"input_paths": payload.InputPaths,
"vars": payload.Vars,
"output_path": payload.OutputPath,
"api_key_env": payload.APIKeyEnv,
"api_key_env_present": payload.APIKeyEnvPresent,
"credential_env_names": payload.CredentialNames,
"working_dir": payload.WorkingDir,
"render_format": payload.RenderFormat,
"render_prompt_logged": payload.RenderPromptStore,