Skip to content

Releases: BotMakerDev/botmaker-studio

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 17:22

Added

  • A plugin's set of nested classes (contract ofClasses, 2026-10-16): Studio reads a holder of static final class X extends <element> classes, each with its singleton constant, its public final fields and its one-return
    setup method (project/managed/ManagedClasses). A field reference — Screens.MARKET.beerBuy, or MARKET.close
    inside the holder — reads as the plugin's value and is written back as Screens.MARKET.beerBuy. Fields are added,
    renamed, repointed and removed by binding like any set's constants; a class is added with its constant and an
    @Override setup, renamed with its constant (the class follows when it was named from it, FAVORED_SHOP →
    FavoredShop), and removed only while nothing outside it uses the constant, the class or a field. A bare close
    inside the class is not read as a reference yet: write MARKET.close.

  • Project ▸ Migrate… carries the bot over a plugin change by its author's @Migrate rules. Each row is an old
    element the bot still uses, with its uses (double-click one to go to it) and its rule's state. Write rule
    writes the element's signature and a default body into Migrations, marked to be written, and opens it in the
    editor. Preview lists each use before and after. Apply rewrites every use a written rule covers, as one
    version after a safety one. Remove finished rules removes each rule whose element the bot no longer uses,
    and the file when that empties it. A retired type's values still go through Copy values… (the migration
    window). Migrate compares the bot with the classpath the project loaded before its last change: an upgrade, a
    removal, or a dev build rebuilt under the same version. It also opens from a banner above the canvas when that
    change broke something, from a Review tab row, and from the upgrade's question, whose Migrate first moves the
    version and leaves the code for Migrate.

  • migration write (MCP): the assistant sets a seeded rule's body — one value, or one statement for a void
    rule, with the imports it names — checked to compile, and the seed's @Refactor mark goes. edit_code's values
    could not say self.markers(List.of(marker)), so a rule could be seeded and never written over MCP.

  • The assistant's migration tool is Migrate (MCP). list gives Migrate's rows, each element with its first
    uses and its rule, the rules naming nothing, the finished rules and the retired types' values. seed writes an
    element's rule, which the assistant then writes with edit_code. apply previews each use before and after,
    and with confirm writes them. remove_finished removes the finished rules. copy_values copies a retired
    type's values by the bot's own @Migrate method for the pair, and switch_uses and remove_migrated stay as
    they were. read and set, with their mapping lines, are gone: the rule is the mapping. plugins set_version
    takes rulesFirst, the upgrade's Migrate first: only the pom moves, and the answer counts what broke.

  • One migration engine behind @Migrate rules (migrate/). A bot's rule names the
    old method, constructor, field or whole type by its own signature, and Studio finds that element in the jars the
    bot used to compile against. It then rewrites every use in the project through the rule's body, keeping each
    use's own spelling. A chain such as named("home").marker("a").marker("b") comes out whole. Rules with neither
    or both of value and name, rules that match nothing, and two rules for one element are refused with a reason.
    With no rule, nothing is rewritten. A rewrite that would not compile is left as written and its function is
    marked @Refactor. migrate.Broken lists what the new jars break and whether a rule covers each element.

  • The old API survives a plugin change. Each load records the classpath it loaded, and one that differs keeps
    the last as the classpath before (~/.cache/botmaker/api). A -SNAPSHOT jar is recorded as a copy of the bytes
    loaded, so a dev reload can still read what the bot used to call.

  • One finder of uses (nav/Uses): calls, new, this(…)/super(…), method references, field reads and
    writes, case labels, type names and imports, matched by binding. Signature changes (MethodReferences) and
    migrations both use it.

  • The assistant's costly answers show up. tool-times.tsv in Studio's cache now also records how much text and
    how many images each tool call answered, so sort -k5 -n finds the replies that cost the most. A file written
    before these columns is moved aside to tool-times.old.tsv. At connect, the MCP server names the bot's plugins
    that have a guide and points to plugin_guide. It no longer pastes the guides into its instructions, which
    clients cut short.

  • A plugin's assistant tool may take nested values and one of several actions. Studio serves a nested record
    as an object, a list of records as an array of them, and an action tool as one flat object: action, whose
    description says what each action needs and does, and the actions' fields, each naming the actions that take
    it when not all do. No oneOf, which Gemini reads poorly.

  • Studio's own MCP tools are declared as a plugin's are: each an AssistantTool over a parameter record, in
    assist/FileTools, StudioTools, RunTools and ProjectTools; McpTools only serves them. The hand-written
    schemas and the text()/number()/flag() readers, which turned a missing value into "" without a word, are
    gone: a missing or ill-typed argument is refused, REFUSED: <tool>: 'value' is required. add_file's kind
    and set_setting's key are enums, sent as a JSON enum; add_method/edit_signature's params are typed.
    One wire change: each of apply_edits' edits names its kind as action (was op).
    edit_variable's name and type may be left out, as its description always said. An argument a tool does
    not take is refused, where a tool with none ignored it; an answer loses its trailing blank lines.

  • Studio serves 37 MCP tools where it served 58, and a third fewer characters (23,847, was 31,650 —
    McpBudgetTest's ceiling is now 26,000). Families of verbs became one tool of several actions, action
    picking one:

    • edit_code (insert, set, delete, move, add_argument, edit_variable) replaces insert_block, set_slot,
      delete_block, move_block, add_argument, edit_variable and apply_edits; one edit is a list of one;
    • review (list, mark, unmark, undo) replaces list_review, mark_reviewed, remove_mark, undo_change;
    • versions (list, checkpoint, revert), plugins (list, search, add, set_version, remove), migration (list,
      read, set, switch_uses, remove_migrated) and params (list, set_default, reset) replace their 16 tools.

    A field another action takes is refused, naming the action's own. While a plugin moves, plugins list,
    plugins search and versions list still answer. The descriptions are shorter; how a slot's value is spelt is
    said once, in edit_code's. Studio's answers name the new tools (versions revert, plugins list).

  • A plugin's value writes are undone with ↶. Each PluginValues write is one step of the editor's undo, named,
    and a plugin's History.batch makes several one step under its own label; ↶/↷ put every file it wrote back. Before,
    only a Project History safety version could take one back. A batch takes one safety version, not one per write.
    The history moved out of CodeEditorService into services/EditorHistory; plugin/HostHistory is the contract's
    History over it.

  • The assistant's undo and redo take the editor's last step back or do it again, as ↶/↷ do, and say which
    step and what is next each way. undo_change stays: it puts a review item's function back from the versions.

  • A plugin lists the bot's boolean methods and adds one (PluginValues.booleanMethods,
    createBooleanMethod): public static boolean name() { return false; } in the class it names, or a new one.

  • A tool's answer in several text parts reaches the client as one text, the parts a blank line apart.

  • quit_studio closes Studio as its window's close button does, half a second after it answers, so a client
    can restart it with the bridge's start_studio.

  • /mcp-hello proves to a client that it talks to this Studio before the client sends the token: it signs
    the client's nonce with the token (HMAC-SHA256) and says nothing of the token itself. Every other path still
    asks for the token.

Fixed

  • A fast scroll lagged and showed members being drawn (2026-10-18). Three causes, each fixed in
    EditorCanvas:
    • A scroll's draw ran after the frame that painted the new position, so nearly every frame of a fast scroll
      showed blanks. It now runs before the pulse lays the scene out.
    • Every forced layout called applyCss on the scroll pane. JavaFX restyles every node under a node
      applyCss is called on, clean or not. So each draw restyled every member drawn so far, and every render
      restyled the hidden kept roots too. Now only the new member (MemberPlaceholder.draw) or the new root is
      styled. A switch back went from 11 to 2 ms on the benchmark.
    • Once a render settles (300 ms), the members still blank are drawn about 6 ms per pulse, nearest the
      viewport first, the member at the top kept in place. A fast scroll after that costs about 8 ms a frame
      instead of 70.
  • The file tabs were sometimes hidden (2026-10-18). Since the canvas moved below the tab strip, a canvas
    or viewer asking for more height than the centre column had squeezed the strip to nothing, because a tab
    pane's minimum height is 0. The strip now keeps its height (CenterTabs), and the area below gives way,
    clipped.
  • Each render walked the whole bot again for its parameters and its sets' members (2026-10-18 ...

v1.4.6

Choose a tag to compare

@github-actions github-actions released this 12 Oct 21:19

Fixed

  • A plugin installs at its newest release. New Project, Browse and Installed offered the SDK at v1.4.2,
    the registry's verified version, while v1.4.4 was out: the registry's update for it never merged. Studio now
    asks JitPack for each plugin's newest build, and Installed marks it (newest).
  • A template whose pom has a self-referencing property no longer exhausts Studio's memory in New Project:
    property substitution stops after 32 replacements.

v1.4.5

Choose a tag to compare

@github-actions github-actions released this 12 Oct 20:36

Fixed

  • New Project copies a template's newest release. A template's gallery entry is vetted at one release, and
    New Project installed that one: gamebot v0.2.0 with v0.2.6 out. A template now installs its newest release,
    vetted or not; an ordinary vetted bot still installs its vetted one.
  • New Project shows the plugin versions the copied template pins, read off the pom of the release it copies.
    It showed the gallery entry's requires, written when the template was last published: SDK 1.2.3 for a
    gamebot pinning 1.4.4.

Changed

  • Publishing writes no requires, and the Publish sheet has no Requires row; a gallery card no longer shows
    one. The gallery stores the repository, and an installed release's pom says what it needs.

v1.4.4

Choose a tag to compare

@github-actions github-actions released this 12 Oct 17:21

Fixed

  • A new project's SDK is 1.4.4. SDK 1.4.3 never built on JitPack (it pinned a shared tag that never built), so
    1.4.3's fallback SDK version named a release no bot could resolve. Studio 1.4.4 is 1.4.3 otherwise.

v1.4.2

Choose a tag to compare

@github-actions github-actions released this 10 Oct 15:59

No source changes since v1.4.1; re-released for updated upstream pins.

No changes since v1.4.0 but the SDK it falls back to: v1.4.0 named SDK v1.4.0, which never built on JitPack,
so a project created by it could not resolve its SDK. This one names SDK v1.4.1.

v1.4.1

Choose a tag to compare

@github-actions github-actions released this 10 Oct 14:42

No changes since v1.4.0 but the SDK it falls back to: v1.4.0 named SDK v1.4.0, which never built on JitPack,
so a project created by it could not resolve its SDK. This one names SDK v1.4.1.

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 10 Oct 14:36

Added

  • Enum open sets. A plugin's set declared ofEnum is an enum in the bot: its members are the enum's
    constants, and adding one writes a bare constant after the last. Rename, repoint and remove work by binding as
    they do for a class's fields. A missing holder is written as an empty enum carrying the plugin's mark and
    implementing the element type. A reference to a constant reads as the value the plugin makes of its name, and
    a value equal to one is written as that constant (ManagedSets, ManagedConstants, ManagedHolders). A
    marked enum is locked like a marked class (LockResolver).
  • Values written as named chains. A type its plugin declares with withers is written as its factory call
    followed by a link for each part that differs from what the factory makes —
    Flow.activity(COLLECT, Collect::body).described("…").goesHome() — and read back with the links in any
    order, a link left out reading as the factory's. A chain setting one part twice, or a link no declaration
    has, stays as written. The Parameters window labels a wither's field by the wither's name.

Changed

  • A plugin's typed marker is a managed value's mark, and @Managed is no longer read. Studio reads a
    plugin's own annotation marked @ManagedMarker — @SdkValue(SdkValue.Id.FLOW) — as the value it names, on
    a method or on an open set's class: the plugin's window opens and rewrites it, the canvas locks it, ▶ Try
    names its holder, and its pill reads as a plugin's. A missing holder is written with the plugin's annotation
    and a method named after the constant (flowLayout() for FLOW_LAYOUT). A bot still marked @Managed is
    ordinary code until it moves to its plugin's annotation.
  • A file whose open-set constants were read before its plugin was bound is read again once the plugin is, so
    the constants are found.
  • Adding a constant to an open set that two classes carry is refused, naming both, instead of going into
    whichever was found first.
  • A plugin's toolbar button that shows a run property refreshes when the plugin sets it: Runs.setProperty
    announces the change as every other settings write does. The SDK's 🎮 game button needs this.

Removed

  • The unused global list of recent launch targets in the preferences file (recentLaunchTargets). Nothing
    wrote it since the launch-target dialog moved to the SDK plugin, whose game dialog keeps its recents per
    computer in the run properties. An older preferences file still reads.

Added

  • Installing Studio installs gamescope and Xephyr too, the two servers a bot's private display runs on. The
    rpm and the deb recommend them (Recommends:), so dnf and apt install them by default and you can remove
    them afterwards.
  • Dev mode: try a plugin before it is released. Project ▸ Plugins & Libraries has a Dev mode box, per
    project and only on this computer. While it is on, plugins pinned at a -SNAPSHOT version (the build
    mvn install put in ~/.m2) load. Reload plugins picks up each rebuild, and a banner above the canvas
    names what is loaded. A plugin refused outside dev mode offers Use dev mode on its row. A Studio run from
    source gives a dev-mode project its own unreleased contract. Publish still refuses a -SNAPSHOT pin, and
    turning dev mode off moves the contract entry back to the released one.
  • Dev mode offers your local builds. In a dev-mode project, Browse lists every plugin built into
    ~/.m2 at a -SNAPSHOT, marked (local build). That includes your own and, from the umbrella, the SDK,
    plugin-basics and the rest. Each Installed row's version list offers its local build too, the SDK's
    included, through the usual checked pass.
  • A plugin declared twice is one row, and Studio loads one copy. A pom naming a plugin under both
    com.github.LiQiyeDev and com.github.BotMakerDev (the SDK pinned before the move, then installed again)
    had both jars on one loader, so Studio ran a mix of the two versions. Studio now loads the new groupId's
    copy and its tree, or the old one's when the new one is a dev build outside dev mode. Installed shows one
    row flagged Declared twice, with Keep for each copy. Browse no longer offers to install a
    plugin the pom already declares under the old groupId.
  • Installed says what each plugin loaded. A Loaded column names the jar each plugin came from,
    (dev build) included, or not loaded with the reason. Plugins another plugin brings (plugin-basics with
    the SDK) are listed read-only, comes with another plugin. Browse's Included is now Installed with
    another plugin — view…
    .
  • Installed: one button per row. A row opens on its installed version. Its button reads Upgrade to X
    when a newer release is known, or Switch to X once another version is picked in the menu, a downgrade
    included. One click runs that row alone. Upgrade all moves every row that has an upgrade, in one pass.
    The Check button, the report under the table, Snapshot, repair & switch and Pin released versions are
    gone; a pass still saves a version first and repairs the bot's calls. A dev build in a dev-mode project
    shows Dev build and is never offered an upgrade.
  • An upgrade asks a fix for every place it breaks, before writing anything. When a move breaks calls,
    a list opens with each place in source order and the fixes for it as buttons: Studio's suggestion, each
    member a split one became, a default value marked for review, or deleting the call. A type the bot writes
    that is gone is listed to acknowledge. Picking a fix moves to the next one; Use the suggested fix for the N
    left
    answers the rest. Upgrade stays disabled until every place has a fix, and Cancel changes nothing.
  • Remove asks in a window that fits. One sentence counts the calls and types it changes, the plugin's
    files are a scrolling list with one checkbox, and the buttons stay at the bottom. It replaces an alert that
    could open taller or wider than the screen.
  • Libraries points to Installed and marks unneeded editor dependencies. A link says how many plugins are on
    the Installed tab. A library only an absent plugin lists as an editor dependency is marked not needed.
  • The overlay editor docks beside the game. ⧉ Overlay opens a panel beside the window your bot watches —
    with the SDK, the one Sdk.captureSource() names — without asking; ⇄ Change picks another. It follows the
    window, drags off to float (⇲ docks it again) and resizes from either edge. Chips across the top are your
    activities: pick one and its file opens in the editor and the caret goes inside it. The script below has one
    ⋮ per row (configure, move, delete); ▲▼ always move the caret. The tabs at the bottom are the plugins' tools —
    with the SDK, Picture cuts a picture off the game and can insert a click on it, Point inserts a click at
    a spot, Flow opens 🔀 Activity Flow — then Actions (the plugins' overlay buttons) and Blocks. While the
    bot runs, its stop, pause and trace sit in the panel's header instead of a second window.
  • The overlay editor shows what each row would do now. A row whose call a plugin can check — with the SDK,
    finding, waiting for or clicking a picture — gets ✓, ✗ or ? (hover for found 0.94 at 412,230). The row the
    caret is on is checked twice a second and its match is boxed on the game, orange where a click would land;
    ⟳ checks every row, and so does the end of a run. Nothing is clicked. A bot that watches its private
    display session is checked on the session's own pixels, and the box is drawn on the window showing it.
  • ▶ Try one statement, or run one activity. Right-click a block on the canvas, or open an overlay row's ⋮,
    and pick ▶ Try this statement: it runs on its own against the screen as it is now, as a run — Stop, the
    run bar, the Run and Trace tabs — and the Run tab says what it found or returned. Values it reads from earlier
    lines are taken from the last debug pause, computed again when they only look (a picture search), or asked
    for with the type's own editor. A static method that takes nothing — an activity's body — offers ▶ Run …
    on its own
    , and so does the overlay's ▶ Run ▸ Run this activity. Needs a plugin with a trial entry (the
    SDK's); nothing is written into the bot.
  • The assistant works on the whole bot, and runs it. Over MCP, every file tool takes a file, so Claude
    edits the activity it is automating rather than only the open file — an edit to another file opens it in the
    editor first, as one undo step there. apply_edits makes several inserts, slot sets and deletes in one call,
    kept all together as one undo step or not at all. A slot takes one of the bot's constants by name
    (Pictures.ORE). New tools: list_files, list_methods, list_targets, set_target, move_caret and
    show_area (the overlay editor's caret and a box on the game), run_bot, run_activity, try_statement,
    stop, run_state and read_trace. Nothing starts while something runs. The plugins' own tools are served
    too — with the SDK, sdk_screenshot, sdk_crop_picture, sdk_find_picture and the rest, pictures coming
    back as images. The game is still touched only by running the bot's code; there is no click or key tool.
  • The assistant shapes the code, not just the blocks. add_method (types Studio offers, by name),
    edit_signature (the file's calls follow; refused when another file's call would break), move_block and
    add_file; find_usages, rename (every file, one undo step) and open, each naming a declaration as
    Collect.body; and the Review list — list_review, mark_reviewed, remove_mark, undo_change.
  • The overlay editor sees what the bot sees. With a plugin that grabs its own frames (the SDK), the
    probes, the tool tabs and the assistant's screenshots read the bot's capture source itself: a bot narrowed
    to a regio ...

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 16:01

Changed

  • New Project opens on the templates, not on Blank: it shows the gallery's last list at once, and Create
    waits until the gallery confirms it. On a first run it says it is loading; Blank is offered only when the
    gallery cannot be reached.
  • The theme styles the contract's new text roles (text-strong, -warning, -error, -ok, -muted,
    -small, -mono) in every theme, so a plugin's status lines read in the dark themes.
  • New Project's plugin checklist names each plugin's version: the template's pin for its own plugins, the
    registry's verified release for the rest.
  • A value a plugin's editor hands over that Studio has no Java for is no longer dropped without a word: the
    field keeps what it had and the status line says why. A plugin can ask itself through the contract's new
    ValueContext.write.
  • A plugin adding a constant to one of its open sets (a picture to Pictures, an activity to Activities)
    is refused, with both classes named, when the value is not the kind the set declares holding.
  • Studio loads released plugins only. A plugin pinned to a dev build (-SNAPSHOT) is not loaded; the
    editor says so, and Project ▸ Plugins & Libraries ▸ Installed offers Pin released versions, which
    moves each one to a release through the usual checked upgrade.
  • A Studio built from source gives a new project the latest released plugin contract instead of
    0.0.0-SNAPSHOT.
  • The getting-started text describes activities and outcomes as constants (Outcomes.BAG_FULL,
    Outcome.NEXT), matching the SDK's typed flow names.
  • Publish refuses a bot whose pom pins a -SNAPSHOT or an undefined ${property}, naming each one: the
    release would compile on this computer and nowhere else.
  • The plugin upgrade report opens with one line saying what the move costs ("Studio repairs 4 calls · you
    finish 1 removed type · nothing else changes", or "Nothing breaks"). The "What breaks in this bot" list
    is gone: it repeated the repair card and the finish-yourself list. The repair card now lists where each
    repaired call is.
  • The welcome screen's project list is one list, sorted as chosen. Projects opened from outside
    ~/BotMakerProjects were always listed last under their own header, whatever the sort; they now carry an
    Elsewhere tag instead. Newest first reads when Studio last opened a project, or its folder's date when
    that is later, so the project you just opened is on top.

Added

  • A gallery bot whose author deleted its repository still installs, from the copy of its releases the gallery
    keeps (the mirror release of botmaker-gallery). A template unpacks from the same copy, and the newest
    release is read from it. The installed bot has its own history and no original to update from, and Browse
    Bots says so: "author removed the repository · no updates".

Removed

  • Local ~/.m2 builds of plugins and the SDK are no longer offered in Plugins & Libraries, Browse or New
    Project, and the (local build) labels are gone. Pin a local build in the pom by hand to try it.

Fixed

  • A project opened a second time drew its function-call blocks as nothing, logging "Classpath element is not
    known for this classpath element" on every redraw. The library index is reloaded from its cache then, and
    the class dropdown asked ClassGraph which jar each class came from, which a cached class cannot answer; the
    index now keeps that itself.
  • Studio takes no automatic version (before a run, a debug, an AI session, a rewrite) in a git submodule,
    whose history is also the umbrella's releases. A "Run" version had swept an old Studio's leftover files
    into the gamebot template, one push from its main. Versions you save, updates and upgrades are still
    written there.
  • An old Studio's src/main/resources/botmaker-project.properties, which nothing reads since 2026-09-27, is
    kept out of every version (.git/info/exclude); it is never deleted, and a project that tracks it keeps it.
  • A push GitHub refuses as "git-receive-pack not permitted" says what it usually means on an organization's
    repository: the organization has not granted BotMaker Studio access, with where an owner approves it.
  • A project checked out as a git submodule (its .git is a file) has its history again. Studio read it as
    "no history" and Publish failed with "Creating directories for …/.git failed".
  • An SSH remote (git@github.com:owner/repo) counts as a GitHub repository, so a project cloned by hand reads
    as published. A submodule's origin is copied to My copy, never renamed, so tools that push to origin
    keep working.
  • Publishing a project whose copy lives under an organization you can push to (the BotMakerDev templates)
    publishes there: the last release, the listing and its Vetted tier are read under that owner, instead of
    under your account, where the bot looked never published. Studio still creates repositories only on your
    own account.
  • A provenance file naming the project's own repository (written by an earlier publish, or before the
    repository moved to an organization) no longer links that repository as somebody else's original.
  • The plugin version picker starts on the installed version, and offers the registry's verified one only
    as a move up. A bot on SDK 1.2.3 opened on 1.1.7 and, when JitPack's list came back empty, offered
    nothing else. Both are labelled in the list, and JitPack gets 20 seconds instead of 8.
  • A plugin pinned as ${property} resolves its jar in the plugins window, so it is recognised as a plugin
    and its type names count when two plugins clash.

v1.2.3

Choose a tag to compare

@github-actions github-actions released this 01 Oct 17:24

Added

  • Pick plugins when you create a project, whatever you start from. New Project lists the same plugins as
    Plugins & Libraries ▸ Browse; tick any to have them in the project's first version. The chosen template's
    own plugins are shown ticked and locked. With no network the list is empty and creating still works.

Fixed

  • A project pinning a plugin as ${property} loads it. Both templates pin their plugin that way
    (${botmaker.sdk.version}, ${botmaker.basics.version}); Studio handed the placeholder text to the
    resolver, which found no such version, so the plugin did not load. The property's value is used now.
  • Installing a plugin that brings another plugin you already declare removes the redundant entry. Adding
    the SDK to a project made from the Base template left the template's own botmaker-plugin-basics entry in
    the pom, which pinned a basics version the SDK was not built against. The entry is now removed, and the
    status line says so.

v1.2.2

Choose a tag to compare

@github-actions github-actions released this 01 Oct 14:07

Added

  • A bot's question is a real dialog. When a bot calls Ask.choice(…), Ask.yesNo(…) or another Ask
    question, Studio shows the prompt with a list of the choices, Yes and No buttons, or a text field, and sends
    the answer back on the run's telemetry channel. Closing the dialog cancels the question. This replaces the
    generic "The bot is waiting for input" box, which could not show what was asked. Needs the SDK release that
    brings Ask; a bot on an older SDK that still calls BotMaker.readLine() gets no prompt.

  • The Trace tab shows every call your bot makes into a plugin, with no trace code in the plugin:
    [ImageFinder] find(ORE) → Match[…] 12 ms, or threw …. Studio starts each Run and Debug with a small
    agent that rewrites the bot's own calls into the plugins' offered classes as they load. A call repeated in a
    loop is one line and a count. A plugin can leave a member out with the contract's @Untraced.

  • Writers lists the traced classes before they write anything. Untick a class or a method and its calls
    are not traced at all from the next run.

Fixed

  • The run diagram describes today's entry point: main calls run(goHome, Sdk.class); it still named
    Sdk.install() and Bot.start, both gone from the SDK.
  • A recorded wait before a click is a Duration. The recorder hands the wait its timeout in
    milliseconds, so ImageWaiter.waitFor(Pictures.ORE, Duration.ofMillis(6000L)) is written; the SDK's
    whole-seconds shape it used to fill is gone.
  • A plugin call from the statement menu no longer lands unresolved. Mouse ▸ click and Wait ▸ time
    wrote new Point(0, 0) and Duration.ofSeconds(1) without importing Point or Duration; each seeded
    argument's type is now imported with the call.
  • Set Variable asks which variable first. It is a submenu of the variables in scope where the block goes;
    it assigned the first one and let you change it afterwards, and with none in scope it inserted nothing.
    With no variable it now says so.

Changed

  • The class dropdown lists only what a plugin offers. ActivityContext, Debug, Point and every other
    value or plumbing type left it; "Java & Libraries" and the expression menu's "Library (static)" leave out
    every class of a plugin's jar, and a plugin class its palette does not reach offers no members. Plugin
    classes are listed alphabetically.
  • A slot editor can ask which of the bot's methods it sits in (Owner::method), for the outcome picker.
  • The Workflow guide describes an activity body as public static Outcome body() returning
    Activities.outcome("…") or Activities.next() (SDK 2.0.0).