Skip to content

RFC: Input Modality - #634

Open
johnthecat wants to merge 1 commit into
rfc/unified-rendererfrom
rfc/input-modality
Open

RFC: Input Modality#634
johnthecat wants to merge 1 commit into
rfc/unified-rendererfrom
rfc/input-modality

Conversation

@johnthecat

@johnthecat johnthecat commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

RFC: docs/rfcs/input-modality.md, with the matching amendment to docs/rfcs/product-manifest.md.

Last of a four-PR stack: Subscription Typed Interrupt Payload (#631) → Worker Lifecycle (#632) → Unified Renderer (#633) → Input Modality (#634). Based on the unified-renderer branch and uses all three: Input::request ends with a typed interrupt, an open input surface is a worker reference, and a Custom candidate is drawn through Renderer under an InputWidget context.

Why this RFC exists

A view offers the interactions its product designed into it. A product cannot be handed anything: the only way to reach one is to open it, so every input is an entry point. A product cannot answer: it holds state the host cannot see, so a string may mean something to it and to nothing else, and the set of such strings is open. Making input contextual closes both gaps: the screen names its products, and those are the products asked.

What it defines

  • Input is a modality with no screen of its own. The host opens it over the current view, and the products on that screen form the context set that is always asked and ranks first. A host may ask others at its own discretion, ranked below.
  • Registration: the worker manifest's includes.input is an object, { supports: [...] }, listing the input shapes the worker accepts. The Product Manifest Format is amended so includes.input is that object and a boolean is malformed.
  • Data types: RoutedInput (App, Chat, Pocket navigations, or a Query), Query (Text or Attachment), Attachment categorised from the MIME type. Only Query crosses the wire, and Text crosses unmodified.
  • Capture, classify, navigate-or-ask. Input authored outside the host is routed only after the user confirms it.
  • Input::request, host-initiated: the product streams InputResponse items (Candidates or the terminal NotHandled) and ends with Result<(), CallError<GenericError>>. Candidates are Text, Attachment, or Custom; every candidate renders under the answering product's identity.
  • Worker references: an open input surface on every product queried, and a displayed Custom candidate on the product drawing it.

Implementation

Part of this PR. The context set has no producer in the core, so the host passes it in per round.

  • truapi: api/input.rs, v01/input.rs types, versioned envelopes, latest re-exports; RenderContext::InputWidget gains content_type
  • truapi-codegen goldens and generated outputs
  • truapi-server: RoutedInput classification alongside parse_navigate, a round manager that fans Input::request out to a context set and merges candidates, supersession and deadline
  • @parity/truapi: input.onRequest
  • Manifest: includes.input object shape where executable manifests are typed

@pgherveou

pgherveou commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

I find it a bit hard to parse without ascii or figma mockups.
do we have any of that ?

Also same comment as for the other. We should move to the one/two pager rfc format, and focus on high-level approach

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants