Files
rs-sdk/learnings/README.md
T
max bittkerandClaude Opus 5.5 df3d8888ae feat(sdk,mcp): cancellable execute_code, bot.mineRock, bounded walkTo
execute_code
- Cancellation now reaches inside the SDK via an AsyncLocalStorage scope:
  timeout, MCP cancel, or a newer call rejects pending waits and blocks
  further action packets, including those inside walkTo().
- One execution per bot: a new call supersedes the running one and starts
  once it has unwound; disconnect_bot does the same.
- Cancelled user code parks on bot/sdk calls instead of throwing, so a
  catch-all loop can't spin and starve the server.
- Console capture is routed per execution, so concurrent bots no longer
  clobber each other's output; leftover logs go to stderr.
- Stale world state warns and still runs, so a stale client can be diagnosed.
- Credentials are redacted from logs, results and launch messages.

SDK
- bot.mineRock() waits for ore plus Mining XP; interactLoc docs note that
  success can mean the action only started.
- walkTo() takes options.timeout (default 120s), refuses stale state, and
  reports the real last position.
- runScript uses the same cancellation scope for timeouts and signals.

Docs trimmed of duplicated or stale execute_code text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:30:19 -04:00

1.7 KiB

Agent learning snippets

Unless a section explicitly says otherwise, snippets in this directory are written for the MCP execute_code environment. That environment provides bot and sdk as globals and accepts TypeScript with top-level await:

const state = sdk.getState();
const result = await bot.walkTo(3222, 3218);
return { result, state: sdk.getState() };

Standalone files under bots/<name>/ use a different wrapper. Import runScript, then destructure the same names once:

import { runScript } from '../../sdk/runner';

await runScript(async ({ bot, sdk }) => {
    await bot.walkTo(3222, 3218);
    return sdk.getState();
});

For a long or background run, execute the standalone file with bun bots/<name>/script.ts. Do not launch a detached bare snippet: runScript owns connection setup, timeout reporting, signal handling, and shutdown. Keep the browser client opened by MCP running: standalone scripts do not start a client.

Action semantics

  • Prefer high-level bot.* helpers. They attempt to observe method-specific evidence. Check the result when a method returns one.
  • Low-level sdk.send* calls confirm browser-client dispatch only. A successful result does not prove that the game server applied the action. Observe the intended state, XP, inventory, dialog, or message change before continuing.
  • Await every method returning Promise, including scanNearbyLocs() and scanGroundItems().
  • getInventory().length counts occupied slots. An InventoryItem.count is the quantity in that slot; findInventoryItem() returns only the first matching slot.

See ../sdk/API.md for exact signatures.