Skip to content

feat(agent): hold modifier keys on tap, double tap, and right click - #957

Merged
okwasniewski merged 5 commits into
tester-army:mainfrom
zichen0116:fix/mcp-tap-modifiers
Oct 15, 2026
Merged

okwasniewski merged 5 commits into
tester-army:mainfrom
zichen0116:fix/mcp-tap-modifiers

Conversation

@zichen0116

@zichen0116 zichen0116 commented Oct 7, 2026 •

Copy link
Copy Markdown

The agent's tap, double_tap, and right_click tools take an optional modifiers list when the target's engine declares tapModifiers, in both agent.act and the MCP server. An agent can now Shift-click or Ctrl-click the way the test API's tap({ modifiers }) can since #626.

{ tool: 'tap', args: { target: 'n42', modifiers: ['Shift'] } }
  • ctx.target.tapModifiers tells executors whether the target can hold keys for a click. The grammar tools read it, so agent.act, MCP, and custom executors use the same flag. Engines without it get the same schema as before.
  • ctx.actions.tap, doubleTap, and secondaryTap take { modifiers }. Bad values fail with INVALID_ARGUMENT. An engine that doesn't declare tapModifiers refuses them with UNSUPPORTED_CAPABILITY.
  • Held keys are recorded with the action (tap button "Save" with Shift held) and replayed from the cache. The trace reader rejects an entry whose modifiers are malformed or sit on a verb that can't hold them.
  • Docs: reference/agent.mdx, executors.mdx, reference/mcp.mdx, skills/e2e/references/mcp.md. Changeset: e2e patch.

Closes #953

Verified

Ran it locally: yes, on the testbed /controls page with a temporary click-log button that records event.shiftKey and the other modifier flags.

MCP, built server, driven with an MCP client:

>> tap {"target":"n6062","modifiers":["Shift"]}            Tapped #n6062.
>> tap {"target":"n6062"}                                  Tapped #n6062.
>> double_tap {"target":"n6062","modifiers":["Alt"]}       Double-tapped #n6062.
>> right_click {"target":"n6062","modifiers":["ControlOrMeta"]}  Right-clicked #n6062.
>> tap {"target":"n6062","modifiers":["Bogus"]}   INVALID_ARGUMENT: call tap: modifiers.0: Invalid option ...
>> hover {"target":"n6062","modifiers":["Shift"]} INVALID_ARGUMENT: call hover: Unrecognized key: "modifiers"
status "Click log" text="click[shiftKey] click[] click[altKey] click[altKey] dblclick[altKey] contextmenu[metaKey]"

agent.act('click the "Click log target" button once while holding Shift') with toHaveText('click[shiftKey]'), live and then from the cache:

✓ the agent shift-clicks 5.52s ai 9.6k tokens · 2 model calls   Cache 1 missed
✓ the agent shift-clicks 331ms                                  Cache 1 replayed

The recorded entry: { "name": "tap", "summary": "tap button \"Click log target\" with Shift held", "modifiers": ["Shift"] }.

Unit: agent-tap-modifiers.test.ts (7 tests, including trace rejection), full e2e unit suite 2663 passed, decision 157 passed. pnpm typecheck and oxlint are clean.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 12 files

Reply to a comment to ask cubic a question or push back. It learns from your replies.

Turn on auto-fix | Re-trigger cubic

Comment thread packages/e2e/src/agent/executor.ts Outdated
Comment thread packages/e2e/src/cache/trace.ts Outdated
…iers

- ctx.target.tapModifiers replaces the MCP-only grammar option
- executor tap family takes modifiers only, not timeout
- trace reader rejects malformed modifiers or modifiers on non-tap verbs
- one isTapActionName helper for the tap family
- docs + changeset
@okwasniewski okwasniewski changed the title feat(mcp): hold modifier keys on tap, double tap, and right click feat(agent): hold modifier keys on tap, double tap, and right click Oct 15, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 14 files (changes from recent commits).

Tip: Get a Slack DM when cubic finishes reviewing your PRs. Connect Slack

View guided diff | Re-trigger cubic

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".changeset/agent-tap-modifiers.md">

<violation number="1" location=".changeset/agent-tap-modifiers.md:5">
P3: The changeset has a grammatical error in its cache description: change `replay` to `replayed` so it says the held keys are recorded and replayed from the cache.</violation>
</file>

Comment thread .changeset/agent-tap-modifiers.md Outdated

@okwasniewski okwasniewski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@okwasniewski
okwasniewski merged commit b1646e2 into tester-army:main Oct 15, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP server: tap cannot hold modifier keys (Shift-click, Ctrl-click, Cmd-click)

2 participants