Repository navigation
Declare the jev config scope so jev.* settings are recognized - #2
Conversation
The plugin reads jev.provider, apiKey, model, endpoint, timeout and cacheDir but never registered a ConfigScope, so Nextflow logged Unrecognized config option for each of them. JevScope declares those options with the same names, types and defaults, and is registered as an extension point. Co-authored-by: Edmund Miller <edmundmiller@users.noreply.github.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
pditommaso
left a comment
There was a problem hiding this comment.
Thanks, this fixes the warning: the jev scope ends up in META-INF/spec.json, and in 25.10.0 plugins are loaded before the config is validated, so jev.* is recognized.
I'd rather not add a second class next to JevConfig, though. JevScope repeats the option list, copies the defaults into its descriptions, and its JevScope(Map) constructor and fields are never used at runtime (Nextflow only reflects the declared fields and calls the no-arg constructor). In particular:
JevScope()callsthis([:]), which runs all ofJevConfig's resolution whenever the extension is loaded. If that ever throws, the extension is skipped without an error and the warnings come back.- A new option added only to
JevConfigwould passJevScopeTest, which hard-codes the same six names, and users would get "Unrecognized config option" again. - The descriptions hard-code
typesafe/jev-1.13, so the next OpenRouter snapshot bump leaves the published spec out of date. apiKeyis a public property here but private behind a failing getter inJevConfig, andjev.apiKey = ''is handled differently by the two classes.
Could JevConfig declare the scope itself instead? That's how TowerConfig, AwsConfig, WaveConfig and K8sConfig do it: one class is the extension point, with an empty constructor for Nextflow and the (Map, env) constructor for the plugin.
@ScopeName('jev')
@Description('''
The `jev` scope controls how the nf-jev plugin calls a Jev decisions endpoint.
''')
@CompileStatic
class JevConfig implements ConfigScope {
@ConfigOption(types=[String])
@Description('''
The service that answers requests: `typesafe` (default) or `openrouter`.
Inferred from the host of `endpoint` when unset.
''')
final JevProvider provider
@ConfigOption
@Description('''
The credential for the selected provider (default: the `TYPESAFE_API_KEY`
or `OPENROUTER_API_KEY` environment variable, matching the provider).
''')
private final String apiKey
@ConfigOption
@Description('''
The Jev model id (default: the selected provider's current model).
''')
final String model
// endpoint, cacheDir: same pattern
@ConfigOption(types=[Integer])
@Description('''
The request timeout, in seconds (default: `30`).
''')
final Duration timeout
/* required by extension point -- do not remove */
JevConfig() {}
JevConfig(Map opts, Map<String,String> env) {
// unchanged
}
}Then register 'nextflowio.plugin.JevConfig' in extensionPoints, drop JevScope and revert the AGENTS.md/SPEC.md layout changes. JevExtension and JevClient stay as they are.
A few details:
types=[String]/types=[Integer]describe what users actually write for the enum andjava.time.Durationfields.AwsS3Config.s3Acldoes the same for an enum. In 25.10.0 the spec still records the field's Java type and validation only checks that the name exists; newer Nextflow adds thetypesentries.- Please keep
timeoutin whole seconds and don't switch the field tonextflow.util.Duration. That class reads a bare number as milliseconds, so an existingjev.timeout = 30would become 30 ms. - Private fields are fine for
@ConfigOption, because the spec usesgetDeclaredFields. - For the test, check that the
jevscope and its options are in the generatedMETA-INF/spec.json, or at least compareSpecNode.Scope.of(JevConfig, …)with the expected names. Right now nothing fails if theextensionPointsentry is removed.
Drop JevScope. JevConfig is the extension point: an empty constructor for Nextflow, and the existing (Map, env) constructor for the plugin. The spec test reads META-INF/spec.json, so a missing extensionPoints entry fails. Co-authored-by: Edmund Miller <edmundmiller@users.noreply.github.com>
|
Addressed in ebcaa31.
|
Unit tests passed, and guardrail and route passed. label-samples failed while the ENA filereport endpoint was returning 500; it answers 200 again. Co-authored-by: Edmund Miller <edmundmiller@users.noreply.github.com>
pditommaso
left a comment
There was a problem hiding this comment.
Thanks, this addresses the previous review: JevConfig is now the single jev scope and extension point, timeout stays in whole seconds, and the spec test fails if the extensionPoints entry is removed (verified locally). Tests and CI are green.
Minor, non-blocking: the !contains('jev-1.13') check in the spec test only guards one snapshot id and could be dropped. Will squash-merge so the JevScope commit message doesn't land on master.
|
Thanks @edmundmiller, all good. Approved, will merge shortly. |
Issue
Nextflow logs
Unrecognized config optionfor everyjev.*setting. The plugin reads those options, but it never declared a config scope. Flagged on #1 (#1 (review)); it predates that PR.Fix
JevConfigis the scope, the wayTowerConfigandAwsConfigare: it implementsConfigScope, with@ScopeName('jev'),@Description, and a@ConfigOptionon each field it already reads (provider,apiKey,model,endpoint,timeout,cacheDir). The no-arg constructor is empty. The(Map, env)constructor is unchanged. The class is registered inextensionPoints.provideris aJevProviderwithtypes=[String];timeoutstaysjava.time.Durationin whole seconds, withtypes=[Integer].Where
src/main/groovy/nextflowio/plugin/JevConfig.groovybuild.gradle(extensionPoints)src/test/groovy/nextflowio/plugin/JevConfigTest.groovyreads the generatedMETA-INF/spec.jsonand requires thejevscope and its options, so a missingextensionPointsentry fails the testFollowed, at the plugin's Nextflow 25.10.0:
loadPluginScopes)