Skip to content

Fix/pi ask user submit#1188

Merged
boudra merged 3 commits into
getpaseo:mainfrom
yuruiz:fix/pi-ask-user-submit
May 28, 2026
Merged

Fix/pi ask user submit#1188
boudra merged 3 commits into
getpaseo:mainfrom
yuruiz:fix/pi-ask-user-submit

Conversation

@yuruiz
Copy link
Copy Markdown
Contributor

@yuruiz yuruiz commented May 26, 2026

Linked issue

No issue filed. This was found while manually validating Pi ask_user behavior in the Paseo test app.

Type of change

  • Bug fix
  • New feature (with prior issue + design alignment)
  • Refactor / code improvement
  • Docs

What does this PR do

Fixes the Pi provider's ask_user flow in Paseo when Pi is running in RPC/headless mode.

Problem

Pi's ask_user extension does not expose its rich interactive UI over RPC. In headless/RPC mode it falls back to a sequence of extension UI dialogs:

  1. select for the main answer
  2. optional input for a comment when allowComment: true
  3. optional input for custom/freeform text when allowFreeform: true and the user chooses the freeform sentinel

Before this PR, Paseo bridged each Pi dialog directly as its own permission card. That caused a few user-visible problems:

  • Selecting an option and pressing Submit could immediately show a second permission page, making it look like Submit did not finish the question.
  • The follow-up optional comment prompt could look like another selection step because Pi includes the original prompt and selected option in the follow-up input title.
  • Optional input prompts were rendered like required inputs, so the user had to reason about Dismiss vs completion instead of having an explicit skip/empty path.

Fix

This PR keeps Pi's RPC protocol intact, but changes the Paseo bridge so the UI matches the user's mental model:

  • Standalone optional Pi input prompts are now mapped as skippable question permissions:
    • allowEmpty: true
    • dismissLabel: "Skip"
    • empty submit returns "" instead of treating the prompt as cancelled
  • Pi ask_user calls with allowComment: true and single-select options are presented as one Paseo permission card:
    • the main selection appears in the first question block
    • the optional comment appears in the same card
    • the user submits once
  • After that one UI submit, the Pi provider internally follows Pi's chained RPC flow:
    • replies to Pi's select request with the selected value
    • stores the already-entered comment
    • auto-replies to Pi's follow-up optional input with that comment, or "" if left blank
  • Freeform/custom answers still work with Pi's fallback protocol:
    • Paseo hides Pi's raw freeform sentinel from the visible option list
    • if the user enters a custom answer, the provider first sends Pi's freeform sentinel to the select request
    • then auto-fills Pi's follow-up freeform input with the custom answer
    • then auto-fills the optional comment follow-up if present
  • The question-form parsing/building logic was extracted into question-form-card-core.ts and covered with unit tests so optional empty answers and option-only questions are deterministic.
  • docs/providers.md now documents the Pi RPC ask_user fallback and Paseo's combined-permission behavior.

How did you verify it

Automated checks

Ran formatting and linting:

npm run format
npm run lint

Ran targeted typecheck and tests for the changed server/app logic:

npm run typecheck --workspace=@getpaseo/server
npx vitest run packages/server/src/server/agent/providers/pi/agent.test.ts packages/app/src/components/question-form-card-core.test.ts --bail=1

Result:

  • server typecheck passed
  • targeted Vitest files passed: 24 tests total
  • lint passed with 0 warnings/errors
  • format completed without leaving tracked changes

I also tried the app workspace typecheck locally:

npm run typecheck --workspace=@getpaseo/app

That is currently blocked in my local checkout by unrelated/stale dependency issues after rebasing onto current main:

  • src/terminal/runtime/terminal-emulator-runtime.ts: scrollbar option not present in local xterm typings
  • src/utils/rich-clipboard.ts: missing markdown-it declaration file
  • vitest.config.ts: missing @vitest/browser-playwright

Those errors are outside the files changed by this PR.

Manual web validation

Validated with an isolated dev app/daemon so the main daemon on localhost:6767 was not touched.

Setup used for manual validation:

  • isolated home: PASEO_HOME=/tmp/paseo-dev-manual-verify-home
  • browser URL: http://app.localhost:1355
  • daemon URL: http://daemon.localhost:1355
  • HTTP Portless proxy, not HTTPS, to avoid browser mixed-content websocket issues
  • dev Pi provider configured to use the real global Pi binary: /opt/homebrew/bin/pi

Reproduction before the final fix:

  1. Start the dev app and isolated daemon.
  2. Create a Pi agent that immediately calls ask_user with:
    • options: ["Alpha", "Beta"]
    • allowComment: true
    • allowFreeform: false
  3. Select an option and press Submit.
  4. Paseo showed another pending permission for Pi's follow-up input, so the user had to interact with a second page just to finish the same ask_user request.

Validation after the fix:

  1. Start the dev app and isolated daemon.

  2. Create a Pi validation agent with this prompt:

    Manual validation for Paseo ask_user. Do not edit files. Immediately call ask_user exactly once with question='Manual validation: choose an option; optional comment may be left blank', context='Testing combined Pi ask_user selection/comment UI in Paseo.', options=['Alpha','Beta'], allowComment=true, allowFreeform=false. After the user responds, summarize the selected option and comment.
    
  3. Observed a single pending permission named Pi ask_user.

  4. In the browser, the permission card showed the answer options and optional comment in one form.

  5. Submitted once.

  6. Confirmed there was no second pending permission.

  7. Confirmed the Pi agent completed and summarized both the selected answer and comment.

I also verified the same flow through the CLI permission path by allowing the pending permission with:

{"answers":{"Response":"Beta","Comment":"combined works"}}

Observed result:

  • agent transitioned to idle
  • PendingPermissions became []
  • final agent output included:
    • selected option: Beta
    • comment: combined works

Checklist

  • One focused change. Unrelated cleanups split out.
  • npm run typecheck passes
    • Server typecheck passes; full app typecheck is blocked locally by the unrelated issues listed above.
  • npm run lint passes
  • npm run format ran (Biome)
  • UI changes include screenshots or video for every affected platform
    • Manual web validation was performed; no screenshot/video is attached yet.
  • Tests added or updated where it made sense

@yuruiz yuruiz force-pushed the fix/pi-ask-user-submit branch from a5bff2c to f7123d6 Compare May 26, 2026 14:09
@boudra boudra merged commit 8262fb4 into getpaseo:main May 28, 2026
14 checks passed
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