Skip to content

feat: Gemini Enterprise Demo Generator v11.91-public - #3056

Open
ryotat7 wants to merge 5 commits into
GoogleCloudPlatform:mainfrom
ryotat7:feat/port-v11.89
Open

feat: Gemini Enterprise Demo Generator v11.91-public#3056
ryotat7 wants to merge 5 commits into
GoogleCloudPlatform:mainfrom
ryotat7:feat/port-v11.89

Conversation

@ryotat7

@ryotat7 ryotat7 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Description

Ports the Gemini Enterprise Demo Generator sample forward from v11.62-public
to v11.91-public. One new file (test_press_retire.py), no layout change —
the same sample, updated.

The largest change is a client scroll behaviour that made every A2UI button
press throw the reader backwards, and what the agent can do about it.

A2UI press landing

On a press, Gemini Enterprise scrolls to the element of the user's PREVIOUS
press.
The test that settled it changed nothing in the agent: press a button
in the newest turn, then scroll up and press one in a much older turn, and the
view jumps down, onto the surface pressed a moment earlier. Direction is the
tell — no rule about "the nearest surface above the pressed one" can scroll
downward, so the earlier readings are withdrawn.

  • That target is client state, and nothing the agent emits during the turn can
    move it. What it can do is delete what the target points at:
    _pressed_surface_delete_parts() reads userAction.surfaceId off the press
    payload and appends a deleteSurface as the last part of the artifact, so the
    anchor the next press would aim at no longer exists. Live-verified on a
    deployed demo: the backwards jump stops.
  • The choice stays visible — a press also carries query.text, which the client
    renders as the user's own message. A surface the same turn is rendering is
    never deleted, and A2UI_KEEP_PRESSED_SURFACE=1 restores the old behaviour.
  • test_press_retire.py exercises the helper off-line (chip, gate and welcome
    presses, the re-render guard, typed messages, malformed payloads, the kill
    switch), because the helper deletes a surface the user can see.
  • Buttons still go in a trailing, card-rooted surface of their own — not as a
    scroll fix any more, but because next actions below the answer card is the
    layout the demos want. The server-built gate cards keep their prose in the
    card and move their input fields out together with the buttons: a
    {"path": ...} binding only resolves inside the surface the button lives in,
    so the fields cannot stay behind. Compose, confirmation and what-if cards keep
    their buttons inside, and so does the welcome card.
  • Eight few-shot examples move their follow-up row out to the trailing surface,
    and the prompt no longer asks every card for a footer action row.
  • Component properties the v0.9 composite catalog does not declare
    (MaterialRow.ariaLabel and friends) are removed: the renderer is strict where
    draft-07 validation is not, and one foreign property drops the whole surface.
  • AGENTS.md section 2.6 records the rule, the test that pinned it, and the
    dead ends (an anchor surface before the card, an invisible trailing landing).

Registration survives a broken authorization

The setup script warned when the authorization write failed and then handed
$AUTH_ID to register_agent.py anyway. That is worse than it sounds:
Discovery Engine resolves authorizationConfig.agentAuthorization at create
time and rejects the whole registration with 404 NOT_FOUND when it names
nothing — so a broken authorization did not cost the demo its Workspace tools,
it cost the demo its agent and its direct chat link.

  • Read the authorization back. A 200 on the POST or PATCH is not proof the
    resource is readable, and only the read answers the question the registration
    actually asks. Not readable → clear $AUTH_ID, register without it, and say
    plainly what was lost.
  • Retry the registration once without it. Reading back fine is still no
    guarantee the registration accepts it (bound to another agent, wrong project
    number). A registered agent with degraded Workspace tools beats no agent at
    all.
  • Both call sites — the single-app branch and the pick-an-app branch — now go
    through one register_ge_agent_with_fallback, so the two copies cannot drift
    apart again.

Prompt cost

  • The setup script prunes the seven Workspace few-shot examples when Workspace
    MCP is off. a2ui globs the examples directory, so they were prefilled on every
    turn — about 5.5k tokens teaching an agent to compose a Gmail draft it has no
    tool to send. A2UI_KEEP_ALL_EXAMPLES=1 keeps them.
  • The BigQuery toolset is filtered to the three tools the instruction actually
    uses, and the routing block is rewritten so a figure question is one
    execute_sql call instead of a metadata expedition in front of it.

Hardening in the generated demo

  • Auth-token fingerprints in the logs instead of token prefixes, in both the
    agent and the A2A runtime.
  • sha256 for the idempotency key. Task failures and the viewer app's error
    responses return a generic message and log the detail — these run on public
    Cloud Run URLs and the exception text carries Firestore paths and project
    identifiers.
  • Record and task ids are restricted to identifier characters before they reach
    an inline handler, the goal preview escapes its markdown input, and the two
    version-pinned CDN scripts carry subresource integrity hashes.

Sample data and defaults

  • The few-shot business data is genericized: no real company names, English
    throughout, so the examples do not steer the agent's output language.
  • Default agent model moves to Gemini 3.7 Flash.

Validation

  • All 26 A2UI example JSONs parse and validate against the v0.9 composite
    catalog (validate_examples.py), and the 9 template Python files compile.
  • python3 test_press_retire.py — 9 cases, all passing.
  • node --check on Code.gs; bash -n on all six renders of the setup script
    (managed-agent × Workspace-MCP × Workspace-auth), with the authorization
    read-back present in exactly the four Workspace combos and the registration
    fallback used at both call sites in all six.
  • Nine words added to .github/actions/spelling/allow.txt.

Checklist

  • Follow the CONTRIBUTING Guide.
  • Ensure the tests and linter pass.
  • Appropriate docs were updated (AGENTS.md).
  • The author is listed in CODEOWNERS for these files.

Ports the sample forward from v11.62-public. The largest change is where an
A2UI button is allowed to sit, which turned out to decide where Gemini
Enterprise leaves the reader after a press.

A2UI press landing
- A press scrolls to the nearest surface ABOVE the pressed one whose root
  renders as a card, crossing the turn boundary only when the pressed
  button's own turn has no earlier card-rooted surface. A button in the
  first card of a turn therefore scrolls the reader back into the previous
  answer. Buttons now go in a trailing, card-rooted surface of their own,
  and the server-built gate cards keep their prose in the card while their
  input fields and buttons move out together - a {"path": ...} binding only
  resolves inside the surface the button lives in, so the fields cannot stay
  behind. Compose, confirmation and what-if cards keep their buttons inside,
  and so does the welcome card. AGENTS.md section 2.6 records the rule.
- Eight few-shot examples move their follow-up row out to the trailing
  surface, and the prompt no longer asks every card for a footer action row.
- Drop component properties the v0.9 composite catalog does not declare
  (MaterialRow.ariaLabel and friends): the renderer is strict where draft-07
  validation is not, and one foreign property drops the whole surface.

Prompt cost
- The setup script prunes the seven Workspace few-shot examples when
  Workspace MCP is off. a2ui globs the examples directory, so they were
  prefilled on every turn - about 5.5k tokens teaching an agent to compose a
  Gmail draft it has no tool to send. A2UI_KEEP_ALL_EXAMPLES=1 keeps them.
- Trim the BigQuery toolset and the routing block so a figure question is one
  execute_sql call instead of a metadata expedition in front of it.

Hardening in the generated demo
- Log an auth-token fingerprint instead of a token prefix, in both the agent
  and the A2A runtime.
- sha256 for the idempotency key; a generic message for task failures and for
  the viewer app's error responses, with the detail going to the log - these
  run on public Cloud Run URLs and the exception text carries Firestore paths
  and project identifiers.
- Restrict record and task ids to identifier characters before they reach an
  inline handler, escape the goal preview's markdown input, and pin subresource
  integrity hashes on the two version-pinned CDN scripts.

Sample data and defaults
- Genericize the few-shot business data: no real company names, and English
  throughout, so the examples do not steer the agent's output language.
- Default agent model moves to Gemini 3.7 Flash.
@ryotat7
ryotat7 requested a review from a team as a code owner August 24, 2026 02:14
….90-public)

A live test that changed nothing in the agent finally pinned the press-scroll
defect: press a button in the newest turn, then scroll up and press one in a
much older turn, and the view jumps DOWN - onto the surface pressed a moment
earlier. Direction is the tell. No rule phrased as "the nearest surface above
the pressed one" can scroll downward, so the reading this sample has carried
since v11.83, including v11.89's, is withdrawn. The rule is:

    on a press, Gemini Enterprise scrolls to the element of the PREVIOUS press.

That target is client state and no arrangement of surfaces can move it. The one
lever left is that a deleted surface cannot be scrolled to, so a press-initiated
turn now retires the surface its button lived in - exactly the anchor the next
press would aim at. Live-verified: the backwards jump stops. The choice stays
visible, because a press arrives with query.text, which the client renders as
the user's message. A surface this turn is also rendering is never deleted, and
A2UI_KEEP_PRESSED_SURFACE=1 restores the old behaviour.

The v11.87 chip wrapper and the v11.89 trailing action surface both stay. Their
scroll rationale is dead, but next actions below the answer card is the layout
that was asked for and it reads better. The comments, AGENTS.md section 2.6 and
the two prompt sentences that asserted the refuted rule are corrected, which
also trims the prompt.

test_press_retire.py covers the helper off-line: chip, gate and welcome presses,
the re-render guard, typed messages, malformed payloads and the kill switch.
@ryotat7 ryotat7 changed the title feat: Gemini Enterprise Demo Generator v11.89-public feat: Gemini Enterprise Demo Generator v11.90-public Aug 24, 2026
The welcome-card exception in the agent instruction still explained itself with
"there is nothing above it to jump to", which is the reading v11.90 withdrew.
The exception itself stands - the welcome card's buttons are its own content -
so only the justification goes.
…91-public)

The generated setup script warned when the authorization write failed and then
handed $AUTH_ID to register_agent.py anyway. Discovery Engine resolves
authorizationConfig.agentAuthorization at create time and rejects the WHOLE
registration with 404 NOT_FOUND when it names nothing, so a broken
authorization did not cost the demo its Workspace tools - it cost the demo its
agent and its direct chat link.

Two guards:

- read the authorization back with a GET after the write. A 200 on the POST or
  PATCH is not proof the resource is readable, and only the read answers the
  question the registration actually asks. Not readable -> clear $AUTH_ID and
  say what was lost.
- retry the registration once without the authorization. Reading back fine is
  still no guarantee the registration accepts it. A registered agent with
  degraded Workspace tools beats no agent at all.

Both registration call sites - single app and pick-an-app - now go through one
register_ge_agent_with_fallback, so the two branches cannot drift again.
@ryotat7 ryotat7 changed the title feat: Gemini Enterprise Demo Generator v11.90-public feat: Gemini Enterprise Demo Generator v11.91-public Aug 24, 2026
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