WidgetActions), the read surfaces (sdk.query, sdk.widgets), and the correctness rules that keep widget code revision-safe.
WidgetActions
WidgetActions (com.n3plugins.Api.actions) clicks interface components: spell icons, dialogue buttons, tab panels, and CS2 components with no named menu action. Every action queues its mouse-click packet before the widget operation, returns InteractionResult, and routes through the pacer.
Click by action name
interact requires a unique action-name match and resolves it to a one-based op index:
onOp listener are invoked through RuneLite’s native CC_OP path so the client listener runs; other named components use the direct widget packet path. The native path uses the shared revision-cached menu dispatcher. Resolution or invocation failure returns PACKET_NOT_QUEUED.
When the component exposes none of the listed actions, interact returns ACTION_NOT_FOUND and queues nothing. Multiple matching action slots also fail closed instead of picking the first. For an action followed by numeric input, use interactThenResumeCount(widget, count, actions).
Click by raw op index
Many components carry no named action, so the name path fails.clickOp fires a one-based op directly:
clickOp guards null or hidden widgets and still applies pacing and click ordering. Confirm the op index against the widget inspector on a live run, and always source the packed ID from a catalog address or a current gameval InterfaceID/ComponentID constant. The correctness audit rejects unreviewed raw production literals.
Sub-menus
subAction reaches a nested menu entry:
WidgetCatalog
WidgetCatalog is the revision-aware name and address index. It loads gameval InterfaceID declarations plus reference WidgetID/WidgetInfo declarations from the bundled widget-mapping snapshot pinned to the current RuneLite and game revision.
Discovery operations: findExact, search, findByPackedId, findAliases, findByViewMode. Resolution: resolveAddress(name) and requireAddress(name) fail closed for ambiguous, incomplete, or reference-only targets. A reference-only or LIVE_PENDING declaration resolves only when its packed target also has a current authoritative actionable mapping.
Packed widget IDs in production code come from a catalog address or from current gameval constants. Never hardcode bitshifted (group << 16) | child expressions and never turn a searchable reference-only raw value into an action target.
WidgetMapping exposes the qualified name, namespace, raw and decomposed values, mapping kind, view mode, authority, aliases, and disposition. WidgetAddress is the complete actionable group/child target with an optional dynamic index.
Typed SDK reads
Thesdk.query classes expose typed reads; writes stay in Api.actions:
ItemEntry is the value type returned by inventory, bank, shop, and GE helpers, carrying itemId, name, quantity, and the backing Widget; interact(actions...) dispatches to that widget.
Read the interface before deciding which result-aware action to queue:
Resolving text to a clickable widget
When visible text belongs to a descriptive child rather than the actionable one, useWidgetInteractionResolver.findByText(root, text, actions). It examines the match and a bounded parent chain, requires exactly one visible named-action owner, and returns explicit resolved, missing, or ambiguous status. It never selects an arbitrary sibling.
Query name predicates strip HTML tags widget-side, so pass bare strings.
Correctness rules
The suite enforces these boundaries with a static audit (auditStageOneCorrectness) and code review:
- Canonical identifiers only. Widget addresses from
WidgetCatalogor current gameval constants. Raw two-argument lookups, packed literals, and removed wrapper classes are findings. - Unique matches.
ActionResolver.findUniqueActionIndex(...)fails closed on zero or multiple matches.hasAction(...)keeps any-match semantics for query filters. - Click before operation. Every widget write queues the mouse-click packet first; a paced or failed click queues no widget packet, and a failed widget packet returns
PACKET_NOT_QUEUEDwithout recording pacing. - Native path for client-owned operations. Listener-backed components select native
CC_OPautomatically;interactViaMenuAction(...)is the explicit native path used by side-tab actions. Bank closing queues a click before the native close operation because it is client-local. - Dispatch is not confirmation.
DISPATCHEDmeans the action was accepted for dispatch;CONFIRMEDmeans the requested postcondition was observed.accepted()includes both;succeeded()is limited to legacy success or observed confirmation, so a dispatched action alone cannot complete a workflow step. - No direct packet calls in modern code. Deprecated named packet facades delegate to
WidgetActions; production callers use the result-aware surface.
PACED and transient results instead of advancing or treating them as terminal.