Add reusable PromptKit request flags
This commit is contained in:
196
integrations/ckprompt/request_flags.go
Normal file
196
integrations/ckprompt/request_flags.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package ckprompt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
commandkit "go.maximumdirect.net/commandkit"
|
||||
promptkit "go.maximumdirect.net/promptkit"
|
||||
)
|
||||
|
||||
// requestFlagDefinition keeps the canonical spellings, help text, and optional
|
||||
// command-scoped aliases together for consumers of the standard flag sets.
|
||||
type requestFlagDefinition struct {
|
||||
meta commandkit.FlagMeta
|
||||
aliases []string
|
||||
}
|
||||
|
||||
var requestFlags = struct {
|
||||
Endpoint requestFlagDefinition
|
||||
Model requestFlagDefinition
|
||||
Temperature requestFlagDefinition
|
||||
MaxTokens requestFlagDefinition
|
||||
TopP requestFlagDefinition
|
||||
TimeoutSeconds requestFlagDefinition
|
||||
ServiceTier requestFlagDefinition
|
||||
ReasoningEffort requestFlagDefinition
|
||||
APIKeyEnv requestFlagDefinition
|
||||
TransientRetries requestFlagDefinition
|
||||
ExtraParams requestFlagDefinition
|
||||
Prompt requestFlagDefinition
|
||||
Profile requestFlagDefinition
|
||||
Backend requestFlagDefinition
|
||||
SessionID requestFlagDefinition
|
||||
Var requestFlagDefinition
|
||||
InputText requestFlagDefinition
|
||||
InputFile requestFlagDefinition
|
||||
}{
|
||||
Endpoint: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-endpoint", Usage: "Execution endpoint override."}, []string{"endpoint"}},
|
||||
Model: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-model", Usage: "Execution model override."}, []string{"model"}},
|
||||
Temperature: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-temperature", Usage: "Execution temperature override."}, []string{"temperature"}},
|
||||
MaxTokens: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-max-tokens", Usage: "Execution maximum tokens override."}, []string{"max-tokens"}},
|
||||
TopP: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-top-p", Usage: "Execution top-p override."}, []string{"top-p"}},
|
||||
TimeoutSeconds: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-timeout-seconds", Usage: "Execution timeout override in seconds."}, []string{"timeout-seconds"}},
|
||||
ServiceTier: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-service-tier", Usage: "Execution service tier."}, []string{"service-tier"}},
|
||||
ReasoningEffort: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-reasoning-effort", Usage: "Execution reasoning effort override."}, []string{"reasoning-effort"}},
|
||||
APIKeyEnv: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-api-key-env", Usage: "Execution API key environment variable."}, []string{"api-key-env"}},
|
||||
TransientRetries: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-transient-retries", Usage: "Inference transient retry count."}, []string{"transient-retries"}},
|
||||
ExtraParams: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-extra-params", Usage: "Execution provider parameters as a JSON object."}, []string{"extra-params"}},
|
||||
Prompt: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-prompt", Usage: "PromptKit prompt ID."}, []string{"prompt"}},
|
||||
Profile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-profile", Usage: "PromptKit profile ID."}, []string{"profile"}},
|
||||
Backend: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-backend", Usage: "PromptKit backend ID."}, []string{"backend"}},
|
||||
SessionID: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-session-id", Usage: "PromptKit session ID."}, []string{"session-id"}},
|
||||
Var: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-var", Usage: "Caller variable assignment KEY=VALUE."}, []string{"var"}},
|
||||
InputText: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-input-text", Usage: "Literal prompt input assignment NAME=TEXT."}, []string{"input-text", "llm-input", "input"}},
|
||||
InputFile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-input-file", Usage: "Prompt input file assignment NAME=PATH."}, []string{"input-file"}},
|
||||
}
|
||||
|
||||
// ExecutionInput contains request-scoped execution controls supplied on the CLI.
|
||||
// A nil override or retry count leaves the corresponding native default intact.
|
||||
type ExecutionInput struct {
|
||||
Execution *promptkit.ExecutionTargetOverride
|
||||
TransientRetries *int
|
||||
}
|
||||
|
||||
// ExecutionFlags exposes independently selectable execution-control bindings.
|
||||
type ExecutionFlags[I any] struct {
|
||||
Endpoint, Model, Temperature, MaxTokens, TopP, TimeoutSeconds commandkit.Flag[I]
|
||||
ServiceTier, ReasoningEffort, APIKeyEnv, TransientRetries, ExtraParams commandkit.Flag[I]
|
||||
}
|
||||
|
||||
// All returns all execution controls.
|
||||
func (f ExecutionFlags[I]) All() []commandkit.Flag[I] {
|
||||
return []commandkit.Flag[I]{f.Endpoint, f.Model, f.Temperature, f.MaxTokens, f.TopP, f.TimeoutSeconds, f.ServiceTier, f.ReasoningEffort, f.APIKeyEnv, f.TransientRetries, f.ExtraParams}
|
||||
}
|
||||
|
||||
// NewExecutionFlags binds execution controls to a field of the caller's input.
|
||||
func NewExecutionFlags[I any](destination func(*I) *ExecutionInput) ExecutionFlags[I] {
|
||||
target := func(input *I) *promptkit.ExecutionTargetOverride {
|
||||
value := destination(input)
|
||||
if value.Execution == nil {
|
||||
value.Execution = &promptkit.ExecutionTargetOverride{}
|
||||
}
|
||||
return value.Execution
|
||||
}
|
||||
return ExecutionFlags[I]{
|
||||
Endpoint: executionFlag(requestFlags.Endpoint.meta, parseDefinitionString, func(i *I, v string) { target(i).Endpoint = v }),
|
||||
Model: executionFlag(requestFlags.Model.meta, parseDefinitionString, func(i *I, v string) { target(i).Model = v }),
|
||||
Temperature: executionFlag(requestFlags.Temperature.meta, parseExecutionFloat, func(i *I, v float64) { target(i).Temperature = &v }),
|
||||
MaxTokens: executionFlag(requestFlags.MaxTokens.meta, strconv.Atoi, func(i *I, v int) { target(i).MaxTokens = &v }),
|
||||
TopP: executionFlag(requestFlags.TopP.meta, parseExecutionFloat, func(i *I, v float64) { target(i).TopP = &v }),
|
||||
TimeoutSeconds: executionFlag(requestFlags.TimeoutSeconds.meta, strconv.Atoi, func(i *I, v int) { target(i).TimeoutSeconds = &v }),
|
||||
ServiceTier: executionFlag(requestFlags.ServiceTier.meta, parseDefinitionString, func(i *I, v string) { target(i).ServiceTier = v }),
|
||||
ReasoningEffort: executionFlag(requestFlags.ReasoningEffort.meta, parseDefinitionString, func(i *I, v string) { target(i).ReasoningEffort = &v }),
|
||||
APIKeyEnv: executionFlag(requestFlags.APIKeyEnv.meta, parseDefinitionString, func(i *I, v string) { target(i).APIKeyEnv = v }),
|
||||
TransientRetries: executionFlag(requestFlags.TransientRetries.meta, strconv.Atoi, func(i *I, v int) { destination(i).TransientRetries = &v }),
|
||||
ExtraParams: executionFlag(requestFlags.ExtraParams.meta, parseExtraParams, func(i *I, v map[string]any) { target(i).ExtraParams = v }),
|
||||
}
|
||||
}
|
||||
|
||||
func executionFlag[I, V any](meta commandkit.FlagMeta, parse func(string) (V, error), set func(*I, V)) commandkit.Flag[I] {
|
||||
return commandkit.ValueFlag(meta, (*V)(nil), parse, func(i *I, value commandkit.Supplied[V]) {
|
||||
if value.Set {
|
||||
set(i, value.Value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func parseExtraParams(raw string) (map[string]any, error) {
|
||||
value, err := commandkit.ParseCLIJSON(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
object, ok := value.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("provider parameters must be a JSON object")
|
||||
}
|
||||
return object, nil
|
||||
}
|
||||
|
||||
// ResourceInput retains whether each resource identifier was explicitly supplied.
|
||||
type ResourceInput struct {
|
||||
Prompt, Profile, Backend, SessionID commandkit.Supplied[string]
|
||||
}
|
||||
|
||||
// ResourceFlags exposes independently selectable resource and session bindings.
|
||||
type ResourceFlags[I any] struct {
|
||||
Prompt, Profile, Backend, SessionID commandkit.Flag[I]
|
||||
}
|
||||
|
||||
// All returns all resource bindings.
|
||||
func (f ResourceFlags[I]) All() []commandkit.Flag[I] {
|
||||
return []commandkit.Flag[I]{f.Prompt, f.Profile, f.Backend, f.SessionID}
|
||||
}
|
||||
|
||||
// NewResourceFlags binds resource identifiers to a field of the caller's input.
|
||||
func NewResourceFlags[I any](destination func(*I) *ResourceInput) ResourceFlags[I] {
|
||||
flag := func(meta commandkit.FlagMeta, selectField func(*ResourceInput) *commandkit.Supplied[string]) commandkit.Flag[I] {
|
||||
return commandkit.ValueFlag(meta, (*string)(nil), parseDefinitionString, func(i *I, v commandkit.Supplied[string]) { *selectField(destination(i)) = v })
|
||||
}
|
||||
return ResourceFlags[I]{
|
||||
Prompt: flag(requestFlags.Prompt.meta, func(v *ResourceInput) *commandkit.Supplied[string] { return &v.Prompt }),
|
||||
Profile: flag(requestFlags.Profile.meta, func(v *ResourceInput) *commandkit.Supplied[string] { return &v.Profile }),
|
||||
Backend: flag(requestFlags.Backend.meta, func(v *ResourceInput) *commandkit.Supplied[string] { return &v.Backend }),
|
||||
SessionID: flag(requestFlags.SessionID.meta, func(v *ResourceInput) *commandkit.Supplied[string] { return &v.SessionID }),
|
||||
}
|
||||
}
|
||||
|
||||
// PromptInputs contains caller variables and native artifact references.
|
||||
type PromptInputs struct {
|
||||
Vars map[string]string
|
||||
Inputs map[string]promptkit.ArtifactRef
|
||||
}
|
||||
|
||||
// PromptInputFlags exposes variable and named artifact input bindings.
|
||||
type PromptInputFlags[I any] struct {
|
||||
Variable, Text, File commandkit.Flag[I]
|
||||
}
|
||||
|
||||
// All returns all variable and input bindings.
|
||||
func (f PromptInputFlags[I]) All() []commandkit.Flag[I] {
|
||||
return []commandkit.Flag[I]{f.Variable, f.Text, f.File}
|
||||
}
|
||||
|
||||
// NewPromptInputFlags binds caller variables and input references to a field of
|
||||
// the caller's input.
|
||||
func NewPromptInputFlags[I any](destination func(*I) *PromptInputs) PromptInputFlags[I] {
|
||||
variable := commandkit.RepeatFlag(requestFlags.Var.meta, []variableAssignment(nil), parseVariableAssignment, func(i *I, v commandkit.Supplied[[]variableAssignment]) {
|
||||
if !v.Set {
|
||||
return
|
||||
}
|
||||
values := make(map[string]string, len(v.Value))
|
||||
for _, assignment := range v.Value {
|
||||
values[assignment.key] = assignment.value
|
||||
}
|
||||
destination(i).Vars = values
|
||||
})
|
||||
inputFlag := func(meta commandkit.FlagMeta, makeRef func(string) promptkit.ArtifactRef) commandkit.Flag[I] {
|
||||
return commandkit.RepeatFlag(meta, []inputAssignment(nil), parseInputAssignment, func(i *I, v commandkit.Supplied[[]inputAssignment]) {
|
||||
if !v.Set {
|
||||
return
|
||||
}
|
||||
input := destination(i)
|
||||
if input.Inputs == nil {
|
||||
input.Inputs = make(map[string]promptkit.ArtifactRef)
|
||||
}
|
||||
for _, assignment := range v.Value {
|
||||
input.Inputs[assignment.name] = makeRef(assignment.path)
|
||||
}
|
||||
})
|
||||
}
|
||||
return PromptInputFlags[I]{Variable: variable, Text: inputFlag(requestFlags.InputText.meta, promptkit.Inline), File: inputFlag(requestFlags.InputFile.meta, promptkit.File)}
|
||||
}
|
||||
|
||||
func parseExecutionFloat(value string) (float64, error) {
|
||||
return strconv.ParseFloat(value, 64)
|
||||
}
|
||||
Reference in New Issue
Block a user