mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
feat(verifier): add SetupAction to walk setup without the seeded root
This commit is contained in:
1 parent
bf983266ed
commit
2dea0e57d4
2 files changed
+42
No files matched your search
@@ -28,6 +28,11 @@ type Verifier struct {
|
||||
// the shared picker (pick.ts) over the shared Pcg.
|
||||
nextActionFn goja.Callable
|
||||
|
||||
// setupActionFn is the bundle-installed __sanderlingSetupAction__, which
|
||||
// walks ONLY the setup generator. The LLM action generator runs it for setup
|
||||
// precedence (e.g. login) without triggering the seeded action root.
|
||||
setupActionFn goja.Callable
|
||||
|
||||
// sampleInputFn is the bundle-installed __sanderlingSampleInput__, which
|
||||
// draws one value from the shared INPUT_CORPUS. The LLM action backend uses
|
||||
// it to fill InputText values, reusing the exact corpus draw rather than
|
||||
@@ -158,6 +163,11 @@ func (v *Verifier) Load(source string) error {
|
||||
v.nextActionFn = callable
|
||||
}
|
||||
}
|
||||
if fn := v.runtime.GlobalObject().Get("__sanderlingSetupAction__"); fn != nil {
|
||||
if callable, ok := goja.AssertFunction(fn); ok {
|
||||
v.setupActionFn = callable
|
||||
}
|
||||
}
|
||||
|
||||
// __sanderlingSampleInput__ draws an InputText value from the shared corpus.
|
||||
// The LLM action backend uses it; a raw-JS fixture without the runtime entry
|
||||
@@ -596,6 +606,28 @@ func (v *Verifier) NextAction() (Action, error) {
|
||||
return DecodeAction(raw)
|
||||
}
|
||||
|
||||
// SetupAction walks ONLY the setup generator (globalThis.setup), returning its
|
||||
// action or ErrNoAction. The LLM action generator runs this for setup
|
||||
// precedence (e.g. login) without triggering the seeded action root, which it
|
||||
// replaces entirely. Mirrors NextAction's decode.
|
||||
func (v *Verifier) SetupAction() (Action, error) {
|
||||
if v.setupActionFn == nil {
|
||||
return Action{}, ErrNoAction
|
||||
}
|
||||
value, err := v.setupActionFn(goja.Undefined())
|
||||
if err != nil {
|
||||
return Action{}, fmt.Errorf("setup action: %w", err)
|
||||
}
|
||||
if value == nil || goja.IsNull(value) || goja.IsUndefined(value) {
|
||||
return Action{}, ErrNoAction
|
||||
}
|
||||
raw, err := json.Marshal(value.Export())
|
||||
if err != nil {
|
||||
return Action{}, fmt.Errorf("marshal action: %w", err)
|
||||
}
|
||||
return DecodeAction(raw)
|
||||
}
|
||||
|
||||
var ErrNoAction = errors.New("verifier: no action available")
|
||||
|
||||
func (v *Verifier) formulaThunk(index int) func() (bool, error) {
|
||||
|
||||
@@ -139,6 +139,16 @@ export function installRuntime(
|
||||
() => INPUT_CORPUS[rng.intN(INPUT_CORPUS.length)] ?? "",
|
||||
);
|
||||
defineLockedGlobal("__sanderlingExtractors__", () => evaluateExtractors());
|
||||
// __sanderlingSetupAction__ walks ONLY the setup generator once, for the LLM
|
||||
// action generator (Go), which drives selection itself and must not run the
|
||||
// seeded action root — but still wants setup's precondition steps (e.g. login)
|
||||
// to run first. Returns null when setup is unset or yields nothing.
|
||||
defineLockedGlobal("__sanderlingSetupAction__", () => {
|
||||
resolveRoot();
|
||||
const setup = resolveSetup();
|
||||
if (!setup) return null;
|
||||
return serializeAction(walk(setup, rng, host));
|
||||
});
|
||||
defineLockedGlobal("__sanderlingNextAction__", () => {
|
||||
// resolveRoot runs first: on web it also resets the per-tick candidate
|
||||
// cache, which setup's walk below must see fresh.
|
||||
|
||||
Reference in new issue
Block a user