Skip to content

Release 2.6.58 - #2268

Merged
chsami merged 56 commits into
mainfrom
claude/release-microbot-2.6.58-202611142200
Nov 14, 2026
Merged

chsami merged 56 commits into
mainfrom
claude/release-microbot-2.6.58-202611142200

Conversation

@chsami

@chsami chsami commented Nov 14, 2026 •

Copy link
Copy Markdown
Owner

Release 2.6.58

Client (2.6.57 -> 2.6.58, merged since 2026-11-12)

Hub (merged since 2026-11-12)

The Hub list this PR was generated from was cut off after #874, so older Hub changes merged since 2026-11-12 may be missing here.

Release tree

  • Branched from main at 88a6f9edc623182a6d24186fcd68788a07d1368a
  • 301a749f47 Merge development (a5091a10a4) into the release branch (--no-ff); it carries Backmerge main into development after 2.6.57 release #2250, the backmerge of main after 2.6.57
  • 9eeb9ddac5 Release 2.6.58: microbot.version=2.6.58 in gradle.properties

Test plan

  • ./gradlew :client:shadowJar on the release head 9eeb9ddac5: BUILD SUCCESSFUL in 1m 19s, 22 tasks. Jar runelite-client/build/libs/client-1.13.6-shaded.jar (70.6 MB); its net/runelite/client/runelite.properties has microbot.version=2.6.58.
  • Hub compile against the candidate jar: Microbot-Hub origin/development (8a0cce9195) merged into origin/main (e654169913), ./gradlew compileJava compileTestJava -PmicrobotClientPath=<shaded jar> -PmicrobotClientVersion=2.6.58: BUILD SUCCESSFUL in 3m 58s, 554 tasks, no compile errors (deprecation and unchecked notes only).
  • Live E2E: skipped for this run (skipE2E was set). No live client session was started.
  • Unit tests: run in this PR's CI (full unit test suite), not locally.

E2E summary

Check Result
Live E2E (client login and plugin run) Skipped (skipE2E set)

🤖 Generated with Claude Code

chsami and others added 30 commits November 12, 2026 10:38
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…611121025

Backmerge main into development after 2.6.57 release
A waited walk whose caller went away failed in sendResponseHeaders with
an IOException that isClientDisconnect did not recognise, so it was
logged at error level and the 500 retry threw again on the same
exchange. Classify that message as a disconnect.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…closed-logged-as-error

fix(agentserver): treat closed response stream as client disconnect
Rs2Inventory.combine(int, int) and combine(String, String) pass the
result of get(...) to combine(Rs2ItemModel, Rs2ItemModel), which
dereferenced both arguments. A missing item threw a
NullPointerException on the script thread, and a missing secondary
item left the primary item selected. Return false before any click
when either item is null.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…null-item-npe

fix(inventory): return false from combine when an item is missing
…scatter

The originless-teleport guard only skipped a dispatch when the player stood
less than 3 tiles from the catalog destination, while the wait after a cast
accepts anything within 10 tiles as landed. A cast that scattered the player
3 tiles from the destination was reported as handled and then dispatched
again on the next pass of the same route, spending a second set of runes.

The guard now also skips when the destination is the one the walker just
handled and the player is still inside the landing radius. A teleport that
has not been handled in this walk keeps the previous 3 tile radius.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The report that led to the double cast fix also asked why the walker took
Civitas illa Fortis plus the quetzal instead of Varrock Teleport. The
catalog only offers the plain Varrock destination when varbit 4585 is 0,
but the report carries no value for it, so the cause cannot be proven.

When the transport pass rejects every spell teleport that lands within 64
tiles of the walk target, the walker now logs one line naming each spell,
the rejection reason and the current value of every varbit the row checks.
The line is skipped when a spell teleport near the target is usable and is
not repeated while its content is unchanged.

This does not change which route is chosen.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…leport-skipped

fix(walker): do not recast a teleport that already landed within its scatter
…rted

The Lumbridge Home Teleport branch treated a clicked spell widget as a cast
in progress and waited the full landing window even when the game refused
the spell. Wait a short window for the cast animation (or the landing)
first, log when it never starts and report the transport as not handled so
the dispatch verdict and refusal ledger see the refusal right away.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
A home teleport cast the game refuses is now blocked for the rest of the
walk regardless of the tile the next plan starts from, instead of relying
on the two-strike ledger keyed by the route start tile. The block is
cleared where walk-scoped transport blocks are withdrawn.

All four spellbook home teleports share the cast-start wait. The cast
start is an animation observed after the click, so an animation that
ended just before the click no longer counts. An interrupted wait or a
human takeover is no longer logged as a refusal, a landing that never
comes logs one line, and the refusal line names the spell and what
happens next.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ker lambdas

The home teleport refusal change added lambdas to Rs2WalkerTransports, which
shifted the synthetic lambda numbers of 21 existing baseline entries. No new
violations: every removed entry returns under a new number.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ort-refused-wait

fix(walker): notice a refused home teleport and take another route
…n resolves

After an option is pressed the dialogue stays visible until the next game
tick with a placeholder in place of the options. A loop pass in that window
found no quest option and clicked the player tile, which cancelled the
conversation and made the helper talk to the NPC again. The dismiss click now
waits while the option list is not a fresh selectable one, for at most 5s.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The wait that holds back the dismiss click was only cleared right before
a dismiss click, so a chain of option menus less than 3 s apart shared
one 5 s window and the third menu was closed again. Each option press
and every pass without the option menu now clears the window.

The hold also no longer depends only on the placeholder text of the
pressed option: the script remembers when it pressed an option and keeps
the dismiss click back for 1.8 s while the menu is still open. The
status text says the script is waiting while the hold is active.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…gue-walk-click

fix(questhelper): keep the option dialogue open while a pressed option resolves
…cene reload

applyObjectStep wraps a tile object from the step once per iteration. When
the scene reloads mid-iteration that object is stale and its world location
is shifted by the scene base change, so the walker was sent to a tile that
no quest step defines. In the Underground Pass the ledge at 2374,9644
became 2334,9636, a sealed tile, and the route left the dungeon by teleport.

The three walk targets in applyObjectStep now read the object location
through currentStepObjectLocation, which only returns it while the step
still holds that object. Otherwise the iteration ends and the next one
resolves the object again.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…d-pass-teleports-out

fix(questhelper): do not walk to an object the step dropped after a scene reload
…s beside it

The recovery walk asks the walker for a tile within 2 of the object's own
tile. For an object set into a wall the walker never reports arrival, so
the click was refused on every attempt, the can't-reach flag stayed set
and the third to fifth attempt paused all scripts.

When the walk fails but the player is within the recovery distance of the
object, clear the flag and send the click. The attempt count is kept, so
the pause still happens when the game keeps refusing the click itself.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ry-gemcrab-cave

fix(interact): click an object when the can't-reach recovery walk ends beside it
…oldown waits

With Universal Antiban on, an action cooldown paused every script at once but
only counted down while the activity category was not busy. Combat categories
are busy for the whole fight, so scripts stayed paused and could not drink,
eat or re-attack until combat ended. The pause for combat categories now
applies only while the countdown runs, and an activity change no longer
restarts a cooldown that is already active.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The combat release cleared the shared script pause on every tick of a fight, undoing pauses set by break handlers, the agent server and short exclusive sections. The cooldown now remembers whether it applied the pause and lifts only that one.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…-arrival-no-prayer-drink

fix(antiban): keep scripts running during combat while a universal action cooldown waits
Ticking or unticking "Watch folder for changes" is saved in the profile
and restored after the startup scan. Shutdown and a folder change leave
the saved choice alone. A watch that stops on a JAR it cannot load saves
"off", so the next start matches the unticked box.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…nd the cheapest meeting

The backward half of the two-directional search could not step onto a
blocked transport tile such as a fairy ring, so it dead-ended at every
ring. getReverseNeighbors now mirrors the forward special case: a blocked
tile that is a transport origin accepts its cardinal walking predecessors.

runBidirectional returned the chain of whichever frontier popped the
opposite endpoint first, even when a cheaper meeting was already recorded.
It now keeps the recorded meeting when that is cheaper.

Grand Exchange to Kalphite Lair planned a spirit tree, glider and Lumbridge
cellar detour instead of the fairy ring next to the start.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…air-lumbridge-cellar-detour

fix(walker): let long surface-to-underground routes use fairy rings and the cheapest meeting
…der-watch

fix(live-plugins): remember the watch-folder choice across restarts
…yer's choice

The Mouse tab checkbox "Use Natural Mouse" promised to switch human-like
mouse movement off, but the trajectory has been unconditional in
VirtualMouse since the detection hardening work, and every script antiban
template plus the script-side settings reset ticked the box again.

- Relabel the checkbox to "Aim Clicks From Cursor" with a tooltip that says
  what the flag does and that mouse movement is always human-like; use the
  same wording in the diagnostics line.
- Antiban setup templates no longer write the flag, so a value set by hand
  survives a script start.
- The non-forced settings reset that scripts run on stop restores the flag
  from the saved profile settings instead of forcing it on. The panel's
  reset button still restores the default.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…log and debug overlay

The tooltip now says what the box does when on and when off, the dev-debug hover log names the checkbox to change, and the Humanizer overlay line uses the same name as the panel and the diagnostics report.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ouse-toggle-ignored

fix(antiban): rename the natural mouse checkbox to what it does and keep the player's choice
chsami and others added 26 commits November 14, 2026 13:27
…trike out failing teleport items

The worn Hunter cape has no equipment op or sub-op named after the
destination, so the walker asked for an op that does not exist, logged an
error and retried the same teleport on every attempt.

- Treat the Hunter cape as a destination-choice teleport item, worn and in
  the inventory: invoke Teleport, then pick the destination.
- Count a teleport item handler failure in the normal dispatch path, so the
  transport is blocked for the walk after repeated failures and the route
  is replanned.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…l the player

A teleport item works from any tile, but its strike-out was keyed on the
route-step tile, so the same failing teleport could be picked again after
the replan moved the player. A struck-out transport without a catalog
origin is now also blocked by name for the rest of the walk, and the
status and one plain log line name the teleport that was dropped.

Also restores seven unrelated test lines to their original form.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ldip-subaction-loop

fix(walker): stop the worn Hunter cape teleport failing in a loop
…e client thread

GET /varbit passed any parsed id straight to Rs2PlayerStateCache, whose
client-thread read only caught NullPointerException. An id missing from
the varbit table made client.getVarbitValue throw
IndexOutOfBoundsException, which ClientThread logged as an error.

Rs2PlayerStateCache now treats an unknown varbit as 0 without caching,
and exposes isValidVarbitId so VarbitHandler answers 400 for an unknown
or negative id and 503 when the client thread is unavailable, matching
VarpHandler.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…own-varbit-ioobe

fix(agentserver): reject unknown varbit ids instead of throwing on the client thread
…e matches

When an option dialogue had no highlighted choice, QuestScript closed it
with a walk click and talked to the NPC again, forever. It now closes
such a dialogue at most three times per step, then leaves it open and
asks the player to choose through the status line. A pressed option or a
new step restores the attempts.

Tai Bwo Wannai Trio: pick the first Lubufu choice, and buy the Karamjan
rum from Zembo through the same dialogue choice and shop highlight that
Pirate's Treasure uses.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… Microbot account

The Mouse Macro Recorder now records every mouse move, button, scroll and
game key (typed characters are never stored, player names in menu targets
become <player>), with game context: ticks, position and instance template,
camera, hovered and opened menus, menu actions marked human or not, the
player's animations, XP and the content being done (Tithe Farm, combat by
NPC, skilling). It records only real input: events dispatched by scripts
(BotEventGuard) are dropped, and recording pauses while any script runs, on
the login screen, the bank PIN, a chatbox prompt or without focus. Chunks of
30 s are gzipped off the client thread and uploaded to /api/input with the
client link token; nothing is written to disk any more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2jMX72L53891CRTE9AXZp
…e player once

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… explain retries

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…hlighted-dialog-option-click-out

fix(questhelper): stop clicking away option dialogues no step choice matches
After picking a destination on the charter map the walker pressed an
option only when its text was exactly "Yes", ignored whether anything was
pressed, and reported the transport as handled. With the prompt still
open the 12 s landing wait timed out and the next walk clicked Charter
again.

The prompt is now waited for up to 5 s and answered with the affirmative
option (Yes / Okay wording, otherwise the first option that is not a
refusal), re-checked every tick until it closes. handleCharterShip
returns false when the prompt was shown but never closed.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ear status

Review fixes for the Input Recorder:
- Upload needs the new "Upload my input" switch (off by default), so users
  of the old local recorder never start uploading without opting in.
- Bot activity pauses recording for 30 s: any script input (BotEventGuard now
  stamps its last dispatch, which also covers Quest Helper, the walker and the
  agent server), a menu action not preceded by the user's own click or key, a
  script start, or a running Hub script. Enabled but idle plugins (Break
  Handler, utilities) no longer pause it. Microbot.targetMenu is read before
  MicrobotPlugin clears it.
- Menu targets keep their name only for NPC, object, ground-item and item
  entries; friends, chat, clan and lookup names are blanked. Non-game keys are
  not sent at all, and recording pauses while chat input is non-empty or a
  RuneLite chatbox input or prompt is open. Pause checks run every client tick.
- Content segments end on pause; content names are cleaned to the API's
  characters and length.
- Uploader: sessions are bound to the token that created them (no upload into
  another account), refused chunks are removed by identity, chunks are gzipped
  as soon as they are queued, a malformed 201 backs off, close without parts
  sends no finalSeq, a 401 rejects the shared link token, the daily limit is
  retried every 30 minutes, and stopping the plugin never blocks the UI thread
  (the client's exit waits for the last upload).
- Overlay tells the player what to do: where to link, telemetry off, link
  removed, retrying, the limit retry time, which script pauses it, and lost
  input in minutes. The plugin is now listed as "Input Recorder" (2.0.0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2jMX72L53891CRTE9AXZp
…allback answers

Log one warning per failed attempt naming the destination and the option
texts on screen, log the option chosen when no Yes/Okay option exists, and
stop waiting for the prompt once a continue dialog shows or the player has
already left. Guardrail baseline updated for the shifted lambda index.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ip-confirm-dialog

fix(walker): answer the charter ship fare prompt before waiting to land
…link, keep sessions over loading screens

Second review: a refused link stays "Link removed" instead of falling back to
"Not linked"; a session only starts when recording would not be paused, so a
hopping bot creates no sessions; each session is bound to the link token it
started with, so relinking before the first upload never sends it to the new
account; loading screens skip the tick instead of ending the session (only
the login screen and world hops end it); a real mouse release counts as the
user's input (hold-and-release menu picks); upload being switched off is
re-checked inside session start, the due chunk is drained under the lock,
and the not-uploaded counter resets per session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2jMX72L53891CRTE9AXZp
…logue

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… the wait status

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ene-teleport-tablet

fix(questhelper): wait out cutscenes that move the player after a dialogue
The EventBus requires subscriber methods to be named on<Event>, so a second
MenuOptionClicked handler on the plugin stopped it from starting. The
priority-1 check now lives in a small inner subscriber registered next to the
plugin, and a test registers both on a real EventBus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2jMX72L53891CRTE9AXZp
Typing, a chatbox prompt, the bank PIN or losing focus split one Tithe Farm
run into six segments. Only a script pause ends the segment now; the other
pauses stay visible as pause and resume events inside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2jMX72L53891CRTE9AXZp
The plugin now runs idle for everyone and asks GET /api/input/access once
per link (again every 6 hours or when the link changes). It appears in the
Microbot plugin list and records only after a yes, remembered between
restarts, and hides itself again when the API answers 403 not-available
for the check or for an upload. The API enforces the same rule on every
input route, so a modified client still cannot upload or read anything.

Plugins can now hide themselves from the Microbot plugin list by
implementing ConditionallyListed and posting PluginListingChanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwwsPumKzuGjss5QHRrRfC
- Always on: the plugin only checks access and stays idle until "Upload my
  input" is on, so an old "off" setting from Mouse Macro Recorder can no
  longer hide it from an admin for good.
- Notice a new link within 10 s instead of 60.
- Show the pause reason when a session cannot start yet (script running,
  window not focused) instead of showing nothing.
- Recover from "Link removed" once the client is linked again.
- Turning upload off drops what was recorded but not sent yet.
- Skip the Hub script scan while not recording; clamp event times at 0.
- Break Handler V2 lists the plugin as Input Recorder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwwsPumKzuGjss5QHRrRfC
feat(mouserecorder): upload your own mouse and game-key input to your Microbot account
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Walkthrough

The pull request replaces local mouse recording with filtered, session-based input collection and upload. It also changes walker transport handling and route planning, quest helper dialogue and object-step behavior, antiban cooldown and preference handling, and live-plugin folder-watch persistence. Additional changes validate varbit IDs, handle a closed agent-server response stream, reject missing inventory items during combination, update documentation, and change the configured version to 2.6.58.

Severity of issue fixed: Medium

Pre-merge checks: Passed 2

Check name Status Explanation
Title check Passed The title "Release 2.6.58" names the version bump, which is the change in gradle.properties and the release branch. It does not describe the main functional changes, but it is related to the changeset…
Description check Passed The description lists the client and Hub changes in the release, the release branch base, the version commit, and a test plan. It directly describes the changes in this PR, so it is related to the cha…
Full details: Title check

Explanation

The title "Release 2.6.58" names the version bump, which is the change in gradle.properties and the release branch. It does not describe the main functional changes, but it is related to the changeset and is not off-topic. It is short and specific enough to identify the release.

Full details: Description check

Explanation

The description lists the client and Hub changes in the release, the release branch base, the version commit, and a test plan. It directly describes the changes in this PR, so it is related to the changeset.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@chsami
chsami merged commit e3c0844 into main Nov 14, 2026
2 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.

1 participant