Skip to content

AI Studio and AI Pilot: fixes and optimizations from three review passes - #126

Merged
oblomov-dev merged 9 commits into
mainfrom
claude/wizardly-ritchie-7sj2br
Oct 7, 2026
Merged

oblomov-dev merged 9 commits into
mainfrom
claude/wizardly-ritchie-7sj2br

Conversation

@oblomov-dev

@oblomov-dev oblomov-dev commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Three review passes over the AI Studio (ai/) and the AI Pilot (pilot/) found a series of problems; each one was traced through the code before it was fixed. The full Chromium suite passes locally, and the new tests below pass as well.

Both chats

  • Tool input is now parsed by the page every 150 ms (followStream( )). The SDK's inputJson re-parsed the input on every delta and ended the stream as soon as one delta was unparsable.
  • Rows of a retried attempt are marked finished.
  • Failed and stopped requests are counted in usage.
  • Stop ends a tool that is still running.
  • A 529 error says what to do.
  • search_samples and find_apps rank partial matches.
  • The log follows the conversation only while the reader is at its end.
  • Safari IME composition is handled.
  • New chat during a running tool is handled.
  • A key error restores the message and its files.
  • Long conversations now clear old tool results on the server (context_management, beta context-management-2025-06-27). This kicks in from 200,000 input tokens; the last ten tool uses are kept and each clear removes at least 60,000 tokens. Before, a Pilot working through a list ended with "the conversation has filled the model's context". The clearing happens on the server, so the history stays append-only and the thinking blocks stay valid. It happens late and in large steps because every clear costs the cache.

AI Studio

  • Linter hints are shown as optional advice.
  • A failed run is marked as failed.
  • A JavaScript error while the app starts is reported as a failed roundtrip.
  • Auto is not restored on the studio's page.
  • Ctrl+Enter sends only.
  • Numbered lists keep their numbers.

AI Pilot

  • The bridge clears the paths the Pilot's request carried. Before, typed values were sent again later.
  • What the reader typed but did not send goes with the Pilot's step and shows in "What Claude sees".
  • restart_app waits for every tab, and stale parked steps are refused.
  • An act whose event cannot be pressed is refused before anything is typed.
  • Told-tracking happens per screen read, and dumps reach the model.
  • A failed open puts the files back.
  • The Run shortcut and opening a draft no longer restart every tab.
  • On a phone the chat comes back; the tab strip is rebuilt only on change.

AI Pilot, third pass (the bug classes fixed in abap2UI5/mcp-server#48)

  • Stale screens: an event is pressed only on the screen the model saw. Before, two act a1 in one answer pressed NEXT and then the next screen's a1. A click of the reader's while the model was thinking, or during the pause before the press, did the same. Such an act is now refused with the screen as it is, and nothing is typed or pressed.
  • Screen size: screens are fitted to the budget as mcp-server's fitSnapshot does: long values are cut and made read-only, then table rows are dropped from the end. Before, they were cut mid-JSON at 30,000 characters, so a 120 KB TextArea pushed out every action and the app's answer.
  • Message size: the <screen> of one message holds 60,000 characters for all apps together. A dump is at most 2,000 characters and comes after the screen.
  • Unknown arguments: a tool argument the tool does not take is refused. Before, act { value, event } pressed without the values. row and max_rows must be whole numbers, and beside a boolean.
  • Echoed arguments: errors and chat rows repeat at most 80 characters of an argument.
  • Closed tabs: a closed tab's operator is released (it held its mirror for the rest of the chat).

Files

  • Text is decoded via BOM, then UTF-8, then Windows-1252.
  • A docx text box is read once.
  • xlsx row numbers are kept.
  • _xHHHH_ escapes are decoded.
  • New limits: 20 MB per message, 400k characters of text.
  • Empty files are refused.
  • Pastes from Excel and Word stay text.
  • Duplicate files are deduplicated.

Tests and docs

  • New tests in pilot.spec.js and ai.spec.js. Three are for the third pass, and one checks the request shape for context clearing.
  • Fixtures textbox.docx and gaps.xlsx.
  • AGENTS.md updated.

Follow-up after abap2UI5/mcp-server#48 merges: re-vendor src/vendor/agent/ (appclient, snapshot, viewxml). That brings in the client's own fixes: LRU sessions, queued acts, argument echo and linear text handling.

🤖 Generated with Claude Code

https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq

claude added 8 commits October 7, 2026 04:38
…iles as their author saw them

The stream (both chats, followStream( ) in ai-common.mjs):
- The tool input is parsed by the page at most every 150 ms instead of
  through the SDK's inputJson event, which parsed the whole input on every
  delta and ended the stream when one delta left it unparsable.
- The rows of an attempt asked again after an unreadable tool input are
  finished, not left shimmering and then "not finished".
- A failed or stopped request's usage is counted too.

AI Studio (chat.mjs, main.mjs):
- The log follows the answer only while the reader is at its end.
- Enter that commits an IME composition in Safari no longer sends.
- New chat / a new key during a running tool leaves the new chat idle, and
  clears the token counter.
- A key or workspace error puts the typed message and its files back.
- A numbered list goes on with its number after a nested bullet.
- Auto is not restored on the studio's page, where its switch is hidden.

Files (attachments.mjs, attach-ui.mjs):
- Text files decoded by BOM, UTF-8, else Windows-1252 (Excel CSV, SAP GUI).
- A .docx text box once, not four times; w:cr, noBreakHyphen, moveFrom.
- A sheet's CSV line N is its row N; _xHHHH_ escapes; t="s" without <v>.
- 20 MB of PDFs and images per message, 400,000 characters of text across
  all files; an empty file is refused.
- Excel/Word pastes stay text; a duplicate is no longer "left out".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
…long, Restart waits for every tab

- frontend-bridge.js: the Pilot's roundtrip goes around View1.eB, so the
  paths it carried were never cleared - every value the Pilot typed was put
  back over every later answer and sent again with the reader's next click.
  The bridge now notes what the request carries (fill, and pending(true)).
- The reader's unsent typing (no roundtrip, so the mirror never heard of it)
  goes into the session the Pilot acts through and counts as a change for
  the next message's <screen>.
- main.mjs: a step parked for a frame a Run replaced is refused with it,
  never handed to the new document's app start.
- restart_app waits until every tab has started on the new Run before it
  reads a screen.
- An act whose event cannot be pressed is refused before anything is typed.
- An app is marked told when its screen is read, not after every tool round;
  a failed last answer (the reader's click dumped) is in the snapshot.
- Stop ends a running tool in both chats (Pilot and Studio).
- pilot.mjs: the studio's fixes (scroll follow, IME Enter, New chat while a
  tool runs, key error keeps the message); the chat comes back on a phone
  when a turn ends; the tab strip is rebuilt only when it changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
…le catalogue once

- explainError( ): a 529 or an overloaded_error mid-stream says "wait a
  minute, or pick another speed" instead of "The API answered 529"; a 5xx
  says to send again.
- catalogueEntries( ) shapes the ~770 entries once per loaded index rather
  than on every search_samples, read_sample, find_apps and open_app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
…f finding nothing

Every word of the query had to occur, so three keywords with one of them
off ("table filter excel") found nothing and the model spent a whole turn on
"Try one word". rankEntries( ) in ai-common.mjs counts each word that
occurs (title and class twice, a plural also as its singular), puts the
entries with the most words first, and says when none has them all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
…ly sends, hints are advice

- main.mjs addAppFiles( ): a set that does not compile is put back - left
  in, every later open and every Restart failed on it, behind an editor the
  Pilot's page hides, until a reload.
- The Run shortcut (Ctrl+Enter, Ctrl+S) is off on the Pilot's page and in
  the studio's chat: Ctrl+Enter sent the message AND ran, a fresh database
  under every app as the turn began.
- A saved draft picked in the Pilot's samples browser is a pick like any
  other, not a Run that restarted every tab.
- A JavaScript error out of an app's start is listed as a failed roundtrip,
  so the AI's run reads it instead of ten seconds of "none arrived".
- describeRun( ): the linter's hints are listed apart as optional advice;
  the rules no longer say every lint finding is a UI5 1.71 gap. A run that
  did not start is drawn as a failed row, not with a check mark.
- "What Claude sees" shows the reader's unsent typing, as the model's own
  snapshot does, and follows it while open.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
- frontend-bridge.js: pending( ) only reads; the Pilot hands back what its
  session took (carry( )). Carried on every look, a value the session could
  not take was cleared from the frame unsent and lost to the reader's click.
- A tool still running when Stop was pressed: the press after the typed
  values does not follow, and what it does on screen later is not marked as
  told - every screen goes with the next message.
- main.mjs: an app start that throws reaches the Pilot's mirror too, so a
  restart waits no thirty seconds for it.
- A message nothing was answered to is taken out of the conversation in both
  chats (not only on a 400/413 in the Pilot): a 413 of the attachments was
  resent with every later message in the studio, and "send again" after a
  refused key sent it twice.
- Ctrl+S on the Pilot's page and in the studio's chat is still not the
  browser's "save page as".

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

- the tools of one answer run against the screens told before it: an act
  whose app moved on since (an earlier act of the same answer, the
  reader's click while the model thought or during the pause before the
  press) is refused with the screen now - two "act a1" pressed NEXT and
  then the next screen's a1
- screens are fitted as mcp-server's fitSnapshot (long values cut and
  read-only, rows from the end) instead of cut mid-JSON at 30,000; the
  <screen> of a message holds 60,000 together; a dump is 2,000 at most and
  comes after the screen
- a tool argument the tool does not take is refused; row/max_rows are whole
  numbers, beside a boolean; errors and chat rows echo 80 characters
- a closed tab's operator and told state are let go

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
@oblomov-dev oblomov-dev changed the title AI Studio and AI Pilot: 40 fixes and optimizations from two review passes AI Studio and AI Pilot: fixes and optimizations from three review passes Oct 7, 2026
A Pilot working through a list read a screen per act, each resent with
every request, until the conversation filled the model's context. Both
chats now send context_management (beta context-management-2025-06-27):
clear_tool_uses from 200,000 input tokens, the last ten tool uses kept,
at least 60,000 tokens per clear. Server-side, so the history stays
append-only and the thinking blocks valid; late and in large steps,
because each clear costs the cache from that point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nvd2W2zUT5ZyemG91n2oq
@oblomov-dev
oblomov-dev merged commit b50b1e3 into main Oct 7, 2026
4 of 8 checks passed
@oblomov-dev
oblomov-dev deleted the claude/wizardly-ritchie-7sj2br branch October 7, 2026 22:51
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.

2 participants