Repository navigation
fix(decision): offer dismiss_keyboard while an on-screen keyboard is showing - #843
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 6 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
Thanks, good catch, and the numbers in the description make the case. One nit: please drop the JSDoc block above For later: the mobile engine already has a measured keyboard state ( |
|
Thanks. The comment block above |
|
Opened the keyboard-state follow-up as #883. On Androids agent-device only measured the keyboard on iOS, and Gboard's tree nodes don't use keyboard/key roles, so also opened callstack/agent-device#3240 to report. #883 will use that once it ships. |
|
@okwasniewski Appreciate your work on this repo! |
|
Thanks! I merged main into this branch and renamed |
|
Thanks for this. #965 just landed and restructured the decision package, so this conflicts now. The change is still wanted: main has no keyboard control yet. Could you rebase onto main and port it? In the new layout it touches:
It comes to about 15 lines, and decision typecheck and tests pass with it. |
…showing
The decision executor's only non-element controls were scroll and back, so
once typing raised a keyboard that covered the next control (an iOS number
pad over a submit button), the decision model had nothing to pick that
could reach it. The runner already exposes dismissKeyboard and the built-in
agent offers it.
dismiss_keyboard is offered when the engine declares the verb and the tree
lists a keyboard or key node, the same probe the mobile engine uses. The
probe stops at hidden subtrees, so a hidden container whose keys carry no
hidden state of their own does not offer it. It dispatches through
perform in dispatch.ts, so the runner authorizes, budgets, and records it
like any other action.
Its criterion states that the keyboard is up and covers controls. Measured
with Jev on an iOS number pad: worded like the built-in tool ("hide the
keyboard when it covers what you need to reach"), Jev never picked it in 23
decisions (p at most 0.20); worded as the fact, it picked it after three
failed taps in both runs and then reached the covered button.
74f003e to
916453d
Compare
|
Rebased onto main and ported to the #965 layout as one commit: |
What and why
scroll_up,scroll_downandbacknext to the element operations, but not the runner'sdismissKeyboard. On a device the keyboard that typing raises can cover the next control, and the tree drops whatever it covers, so the model has nothing that reaches it.packages/decision/src/elements.tsnow addsdismiss_keyboardto the controls when the target declaresdismissKeyboardand the tree lists akeyboardorkeynode outside any hidden subtree. That is the probekeyboardShowinguses inpackages/mobile/src/surface.ts. An iOS number pad lists only its keys.performinpackages/decision/src/dispatch.tsruns it throughctx.actions.dismissKeyboard(), so the runner authorizes, budgets and records it, andCONTROL_LABELSinexecutor.tsnames it "dismiss the keyboard" in turns and history. Web declares no dismiss and is unchanged.packages/decision/src/questions.tsstates the fact: "The on-screen keyboard is up. Controls it covers are missing from the elements; hide it to reach them." With the built-in tool's wording ("when it covers what you need to reach") Jev never picked it in 23 decisions, p at most 0.20.Verified
Ran it locally: yes
elements.test.ts(offered while keys show, not for a hidden keyboard, a hidden subtree, no keyboard, or nodismissKeyboardverb) andexecutor.test.ts(the operation question lists it and choosing it callsdismissKeyboard).e2e run tests/client-workout.e2e.ts --no-cachewith Jev 1.13 through@ai-sdk/typesafe-ai. The step types reps and weight into number-pad fields, then taps "Log set", which the pad covers.APP_UNREACHABLE, then claimsfailedand the check agrees (ACTION_FAILED)dismiss_keyboard, after 3 and after 7 failed taps, then tap "Log set". The logger moves to set 2tap. It sits close totap, so how many taps it takes varies between runs.blockedon the completion check. Run 2 types into set 2 as well, the pad comes back, and Jev taps "Finish" 9 more times before it claimsfailed. That loop is what fix(decision): count failed actions as no progress in the stall guard #844's stall guard is for.Checklist
pnpm changeset) for any change to a published package, or the change is testbed, docs, or CI only.!, the changeset body names what breaks and what replaces it, and the deprecation warning landed a window earlier (stability policy in CONTRIBUTING.md).docs/**/*.mdxpage for the behavior, andskills/e2e/if the skill describes it..d.tsreviewed,tests/types/sdk-types.tsupdated; wire change edits the schema and both fixtures.e2e/engine): changesets fore2e,@e2e-dev/web, and@e2e-dev/mobile.