feat(runner): gate llm source on --generator flag

This commit is contained in:
pj committed 2026-07-13 07:07:06 +05:30
1 parent dcf7c4a02a
commit c7402e8f7d
2 files changed
+19 -10

No files matched your search

+4
View File
@@ -36,6 +36,10 @@ type Options struct {
Verifier *verifier.Verifier Verifier *verifier.Verifier
TraceWriter *trace.Writer TraceWriter *trace.Writer
Logger *slog.Logger Logger *slog.Logger
// Generator selects the action picker: "llm" drives selection with the
// spec's generator = llm({...}) config; anything else (the default) uses the
// seeded weighted picker. Both draw from the same actionsRoot candidate set.
Generator string
} }
type Summary struct { type Summary struct {
+15 -10
View File
@@ -63,25 +63,29 @@ func (s webSource) ExtractorOverrides(ctx context.Context) (map[int]json.RawMess
} }
// pickSources selects the runtime's action and extractor sources ONCE at setup // pickSources selects the runtime's action and extractor sources ONCE at setup
// from the driver's capabilities and the spec, so the step loop never // from the driver's capabilities, the --generator flag, and the spec, so the
// type-asserts. When the spec selected the LLM action backend (actions = // step loop never type-asserts. With --generator llm and a spec-declared
// llm({...})) it constructs the chat-completions client and returns an // generator = llm({...}) it constructs the chat-completions client and returns
// llmSource for selection while extractor overrides still come from the goja // an llmSource for selection while extractor overrides still come from the goja
// path. // path. Otherwise the seeded goja picker drives.
func pickSources(options Options) (ActionSource, ExtractorSource, error) { func pickSources(options Options) (ActionSource, ExtractorSource, error) {
if web, ok := options.Driver.(driver.WebDriver); ok { if web, ok := options.Driver.(driver.WebDriver); ok {
source := webSource{web: web} source := webSource{web: web}
return source, source, nil return source, source, nil
} }
if config, ok := options.Verifier.LLMConfig(); ok {
client, err := llmclient.New()
if err != nil {
return nil, nil, fmt.Errorf("llm action backend: %w", err)
}
logger := options.Logger logger := options.Logger
if logger == nil { if logger == nil {
logger = slog.Default() logger = slog.Default()
} }
if options.Generator == "llm" {
config, ok := options.Verifier.LLMConfig()
if !ok {
logger.Warn("--generator llm requested but spec declares no generator = llm(); using the seeded picker")
} else {
client, err := llmclient.New()
if err != nil {
return nil, nil, fmt.Errorf("llm action generator: %w", err)
}
action := &llmSource{ action := &llmSource{
verifier: options.Verifier, verifier: options.Verifier,
client: client, client: client,
@@ -92,6 +96,7 @@ func pickSources(options Options) (ActionSource, ExtractorSource, error) {
} }
return action, gojaSource{verifier: options.Verifier}, nil return action, gojaSource{verifier: options.Verifier}, nil
} }
}
source := gojaSource{verifier: options.Verifier} source := gojaSource{verifier: options.Verifier}
return source, source, nil return source, source, nil
} }