Skip to content

Conversation

@allenhutchison
Copy link
Collaborator

@allenhutchison allenhutchison commented Oct 7, 2025

Summary

Completes the message bus integration by wiring up the UI for ASK_USER policy decisions. When the PolicyEngine decides that a tool requires user confirmation, the system now shows the full legacy confirmation UI instead of blocking or auto-executing.

Changes

Core Infrastructure

  • confirmation-bus/types.ts: Added requiresUserConfirmation flag to ToolConfirmationResponse
  • tools/tools.ts: Updated BaseToolInvocation.handleMessageBusConfirmation() to handle ASK_USER by returning null as a sentinel value
  • core/coreToolScheduler.ts:
    • Subscribe to TOOL_CONFIRMATION_REQUEST messages in constructor (when enableMessageBusIntegration is true)
    • Added handleToolConfirmationRequest() method to respond with requiresUserConfirmation=true for ASK_USER decisions

Integration & Testing

  • tools/web-fetch.ts:
    • Integrated as first end-to-end test of ASK_USER flow
    • Updated shouldConfirmExecute() to check for null return and fall through to legacy confirmation UI
  • tools/web-fetch.test.ts: Added 8 comprehensive message bus integration tests
  • Test mocks: Updated all Config mocks to include getEnableMessageBusIntegration(), getMessageBus(), getPolicyEngine()

Flow

When enableMessageBusIntegration: true in settings:

  1. ALLOW → Tool executes immediately (no UI shown)
  2. DENY → Tool execution blocked with error
  3. ASK_USER → Shows full legacy confirmation UI (the new behavior added in this PR)

ASK_USER Flow Details

Tool.shouldConfirmExecute()
  ↓
BaseToolInvocation publishes TOOL_CONFIRMATION_REQUEST
  ↓
MessageBus → PolicyEngine.check() → ASK_USER
  ↓
MessageBus emits request to CoreToolScheduler
  ↓
CoreToolScheduler responds with requiresUserConfirmation=true
  ↓
BaseToolInvocation receives response → returns null
  ↓
Tool checks for null → falls back to legacy confirmation
  ↓
UI shows full confirmation dialog (diffs, URLs, approval options)

Test Plan

  • All unit tests passing (2502 tests)
  • Message bus integration tests for WebFetchTool (8 new tests)
  • Preflight checks passing (format, lint, build, typecheck)
  • Manual testing with tools.enableMessageBusIntegration: true

Next Steps

This PR enables the ASK_USER flow for WebFetchTool. Follow-up work:

  • Integrate remaining write tools (EditTool, WriteFileTool, ShellTool, etc.)
  • Add policy configuration examples to documentation
  • Consider adding telemetry for policy decisions

Integrates the message bus ASK_USER flow with CoreToolScheduler to show
legacy confirmation UI when policy engine requires user confirmation.

Changes:
- Add `requiresUserConfirmation` flag to ToolConfirmationResponse type
- Update BaseToolInvocation to handle ASK_USER by returning null sentinel
- Wire CoreToolScheduler to subscribe to TOOL_CONFIRMATION_REQUEST events
- Integrate WebFetchTool as first end-to-end test of ASK_USER flow
- Update all test mocks to include new Config methods

Flow:
1. Tool calls shouldConfirmExecute() → publishes TOOL_CONFIRMATION_REQUEST
2. MessageBus checks PolicyEngine → ASK_USER decision
3. CoreToolScheduler receives request → responds with requiresUserConfirmation=true
4. Tool receives null → falls back to legacy confirmation UI
5. User sees full confirmation dialog with diffs, URLs, options

Tested:
- ALLOW policy → auto-executes without UI
- DENY policy → blocks execution with error
- ASK_USER policy → shows full legacy confirmation UI

All preflight checks passing (format, lint, build, typecheck, tests).
@allenhutchison allenhutchison requested a review from a team as a code owner October 7, 2025 03:28
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @allenhutchison, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the tool execution policy system by fully integrating the ASK_USER policy decision with the user interface. It ensures that when a policy engine determines a tool requires user confirmation, the system correctly triggers and displays the existing legacy confirmation UI. This change improves user control and transparency for tool executions governed by policy, providing a consistent and expected user experience for actions requiring explicit approval.

Highlights

  • UI Integration for ASK_USER Policy: The system now correctly displays the full legacy confirmation UI when the PolicyEngine determines a tool requires user confirmation via the ASK_USER policy decision, preventing blocking or auto-execution.
  • Confirmation Bus Type Update: The ToolConfirmationResponse interface in confirmation-bus/types.ts has been extended with a requiresUserConfirmation flag to explicitly signal when the legacy UI should be used.
  • BaseToolInvocation Handling: BaseToolInvocation.handleMessageBusConfirmation() has been updated to return null as a sentinel value when an ASK_USER policy decision is received, indicating a fallback to the legacy confirmation UI.
  • CoreToolScheduler Subscription: The CoreToolScheduler now subscribes to TOOL_CONFIRMATION_REQUEST messages in its constructor (when message bus integration is enabled) and responds with requiresUserConfirmation=true for ASK_USER decisions.
  • WebFetchTool Integration & Testing: The WebFetchTool has been integrated as the first end-to-end test for the ASK_USER flow, with its shouldConfirmExecute() method updated to check for the null return from the message bus and fall through to the legacy confirmation UI. Eight new comprehensive message bus integration tests have been added for WebFetchTool.
  • Config Mock Updates: All relevant Config mocks across the codebase have been updated to include getEnableMessageBusIntegration(), getMessageBus(), and getPolicyEngine() for consistent testing of message bus functionality.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully wires up the UI for ASK_USER policy decisions from the message bus. The approach of having the CoreToolScheduler respond to TOOL_CONFIRMATION_REQUEST messages to trigger the legacy confirmation UI in the tool is sound. The changes are well-structured and include comprehensive integration tests for the new flow. My main concern is the use of a type-unsafe null sentinel value in BaseToolInvocation to signal the ASK_USER case to subclasses, which undermines the type system and could be a source of bugs in the future. I've left a specific comment with a suggestion for a safer implementation.

@github-actions
Copy link

github-actions bot commented Oct 7, 2025

Size Change: +1 kB (+0.01%)

Total Size: 17.8 MB

Filename Size Change
./bundle/gemini.js 17.8 MB +1 kB (+0.01%)
ℹ️ View Unchanged
Filename Size
./bundle/sandbox-macos-permissive-closed.sb 1.03 kB
./bundle/sandbox-macos-permissive-open.sb 830 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-closed.sb 3.29 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB

compressed-size-action

Refactors the message bus confirmation flow to avoid using a `null`
sentinel value. Instead, it now uses a string enum (`ALLOW`, `DENY`,
`ASK_USER`) to represent the decision from the message bus.

This change improves the type safety of the interaction between the base
tool invocation and its subclasses.

The following files were updated:
- `packages/core/src/tools/tools.ts`: Updated `BaseToolInvocation` with
  the new `getMessageBusDecision` method.
- `packages/core/src/tools/web-fetch.ts`: Updated
  `WebFetchToolInvocation` to use the new method.
- `packages/core/src/tools/message-bus-integration.test.ts`: Updated
  the tests to reflect the changes in the implementation.
* When true, indicates that policy decision was ASK_USER and the tool should
* show its legacy confirmation UI instead of auto-proceeding.
*/
requiresUserConfirmation?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be optional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way this is written right now is that this only comes into play when the ASK_USER policy decision is set. Otherwise it's null and falls through to the legacy behviour.

override async shouldConfirmExecute(
abortSignal: AbortSignal,
): Promise<false> {
if (this.messageBus) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this conditional always evaluate to true? Can we assert on it instead of making it a conditional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional supports the case where there is no message bus in the test. It's flag guarded so I wanted to test both scenarios. See the test on line 222 for example.

Addresses a comment on the message bus integration test to clarify the
intent of a conditional.

The `shouldConfirmExecute` method in `TestToolInvocation` now includes a
comment explaining why a conditional is used to check for the presence
of the message bus, which is necessary for testing the fallback
behavior when the message bus is not available.

timeoutId = setTimeout(() => {
cleanup();
resolve('ALLOW'); // Default to ALLOW on timeout
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we default to allow for timeout here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I've changed this to ASK_USER.

} else if (response.confirmed) {
resolve('ALLOW');
} else {
reject(new Error('Tool execution denied by policy'));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we reject instead of resolve to DENY here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was left over from an older implementation before I had the status in the promise. I've changed it to resolve to DENY now to be consistent.

This commit addresses feedback on the message bus confirmation flow by
making it more robust and secure.

- The `getMessageBusDecision` method now resolves with `'DENY'` instead of
  rejecting the promise when tool execution is denied or aborted.
- The timeout behavior has been changed to resolve to `'ASK_USER'` as a
  safer default, ensuring user confirmation is requested when the
  message bus times out.
- `console.log` has been changed to `console.debug` for debug-level
  logging.

The tests for `web-fetch` and `message-bus-integration` have been
updated to be consistent with these changes.
Copy link
Collaborator

@abhipatel12 abhipatel12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@allenhutchison allenhutchison added this pull request to the merge queue Oct 15, 2025
Merged via the queue into main with commit b8df8b2 Oct 15, 2025
20 checks passed
@allenhutchison allenhutchison deleted the message-bus-ask-user-ui branch October 15, 2025 17:01
thacio added a commit to thacio/auditaria that referenced this pull request Oct 17, 2025
Millsondylan pushed a commit to Millsondylan/gemini-cli-1 that referenced this pull request Oct 19, 2025
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.

3 participants