Repository navigation
Releases: BotMakerDev/botmaker-studio
Release list
v1.5.0
Added
-
A plugin's set of nested classes (contract
ofClasses, 2026-10-16): Studio reads a holder ofstatic final class X extends <element>classes, each with its singleton constant, itspublic finalfields and its one-return
setup method (project/managed/ManagedClasses). A field reference —Screens.MARKET.beerBuy, orMARKET.close
inside the holder — reads as the plugin's value and is written back asScreens.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
@Overridesetup, 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 bareclose
inside the class is not read as a reference yet: writeMARKET.close. -
Project ▸ Migrate… carries the bot over a plugin change by its author's
@Migraterules. 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 intoMigrations, 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 avoid
rule, with the imports it names — checked to compile, and the seed's@Refactormark goes.edit_code's values
could not sayself.markers(List.of(marker)), so a rule could be seeded and never written over MCP. -
The assistant's
migrationtool is Migrate (MCP).listgives Migrate's rows, each element with its first
uses and its rule, the rules naming nothing, the finished rules and the retired types' values.seedwrites an
element's rule, which the assistant then writes withedit_code.applypreviews each use before and after,
and withconfirmwrites them.remove_finishedremoves the finished rules.copy_valuescopies a retired
type's values by the bot's own@Migratemethod for the pair, andswitch_usesandremove_migratedstay as
they were.readandset, with their mapping lines, are gone: the rule is the mapping.plugins set_version
takesrulesFirst, the upgrade's Migrate first: only the pom moves, and the answer counts what broke. -
One migration engine behind
@Migraterules (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 asnamed("home").marker("a").marker("b")comes out whole. Rules with neither
or both ofvalueandname, 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.Brokenlists 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-SNAPSHOTjar 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,caselabels, type names and imports, matched by binding. Signature changes (MethodReferences) and
migrations both use it. -
The assistant's costly answers show up.
tool-times.tsvin Studio's cache now also records how much text and
how many images each tool call answered, sosort -k5 -nfinds the replies that cost the most. A file written
before these columns is moved aside totool-times.old.tsv. At connect, the MCP server names the bot's plugins
that have a guide and points toplugin_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. NooneOf, which Gemini reads poorly. -
Studio's own MCP tools are declared as a plugin's are: each an
AssistantToolover a parameter record, in
assist/FileTools,StudioTools,RunToolsandProjectTools;McpToolsonly serves them. The hand-written
schemas and thetext()/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'skind
andset_setting'skeyare enums, sent as a JSONenum;add_method/edit_signature'sparamsare typed.
One wire change: each ofapply_edits' edits names its kind asaction(wasop).
edit_variable'snameandtypemay 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) replacesinsert_block,set_slot,
delete_block,move_block,add_argument,edit_variableandapply_edits; one edit is a list of one;review(list, mark, unmark, undo) replaceslist_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) andparams(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 searchandversions liststill answer. The descriptions are shorter; how a slot's value is spelt is
said once, inedit_code's. Studio's answers name the new tools (versions revert,plugins list). -
A plugin's value writes are undone with ↶. Each
PluginValueswrite is one step of the editor's undo, named,
and a plugin'sHistory.batchmakes 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 ofCodeEditorServiceintoservices/EditorHistory;plugin/HostHistoryis the contract's
Historyover it. -
The assistant's
undoandredotake the editor's last step back or do it again, as ↶/↷ do, and say which
step and what is next each way.undo_changestays: 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-helloproves 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
applyCsson the scroll pane. JavaFX restyles every node under a node
applyCssis 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.
- A scroll's draw ran after the frame that painted the new position, so nearly every frame of a fast scroll
- 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
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
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'srequires, 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
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
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
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
Added
- Enum open sets. A plugin's set declared
ofEnumis 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
@Managedis 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()forFLOW_LAYOUT). A bot still marked@Managedis
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-SNAPSHOTversion (the build
mvn installput 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-SNAPSHOTpin, 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
~/.m2at 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.LiQiyeDevandcom.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 oneSdk.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_editsmakes 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_caretand
show_area(the overlay editor's caret and a box on the game),run_bot,run_activity,try_statement,
stop,run_stateandread_trace. Nothing starts while something runs. The plugins' own tools are served
too — with the SDK,sdk_screenshot,sdk_crop_picture,sdk_find_pictureand 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_blockand
add_file;find_usages,rename(every file, one undo step) andopen, 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
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 toActivities)
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
-SNAPSHOTor 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
~/BotMakerProjectswere 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 (themirrorrelease ofbotmaker-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
~/.m2builds 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 itsmain. 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
.gitis 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'soriginis copied to My copy, never renamed, so tools that push toorigin
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
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 ownbotmaker-plugin-basicsentry 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
Added
-
A bot's question is a real dialog. When a bot calls
Ask.choice(…),Ask.yesNo(…)or anotherAsk
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
bringsAsk; a bot on an older SDK that still callsBotMaker.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, orthrew …. 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:
maincallsrun(goHome, Sdk.class); it still named
Sdk.install()andBot.start, both gone from the SDK. - A recorded wait before a click is a
Duration. The recorder hands the wait its timeout in
milliseconds, soImageWaiter.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 ▸ clickandWait ▸ time
wrotenew Point(0, 0)andDuration.ofSeconds(1)without importingPointorDuration; 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,Pointand 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("…")orActivities.next()(SDK 2.0.0).