Skip to content

Ask PiP about a passage, with the session it came from - #271

Merged
4 commits merged into
TannerMidd:mainfrom
vitalNohj:feat/ask-pip-quote
Nov 6, 2026
Merged

4 commits merged into
TannerMidd:mainfrom
vitalNohj:feat/ask-pip-quote

Conversation

@vitalNohj

@vitalNohj vitalNohj commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Select words in one of Pi's replies: next to Reply, PiP's orb (Ask PiP) now asks PiP about them.
I want this so I can quickly tell PiP to route tasks or questions.

What changed

  • The pill (web/quote-reply.js, web/style.css): [↩ Reply | ◉], one tap each. The orb is there only while PiP is on.
  • Two switches in Appearance → Conversation (web/theme.js, web/sheets/appearance.js): Reply to a passage and Ask PiP about a passage (shown while PiP is on), both on by default, per browser. Each turns off only its own button; with both off, no pill shows.
  • PiP's box (web/pip.js): the orb opens PiP with the passage in a quote strip over its box (× drops it) and the box ready to type. The message goes with the passage quoted first (withQuote, as Reply does), and PiP's chat shows it as a quote block. The quote is cleared once sent, kept when a send fails, and dropped when the person or PiP's id changes, together with the draft's files (pip-attachments.js scope() now says when it dropped them). /compact with a quote is refused, as a command with a quote is in a session.
  • Hidden context for PiP (src/server/commands.ts): the submit request takes about: { session }. The server, not the browser, writes a text part after the message: <pocket-context session="…" title="…" folder="…"> and a line that PiP can session_read the session. It is accepted only for a message to PiP, about a listed session (never PiP itself) its person can see. The title goes through hidden.replace and attribute(), so it cannot close the tag.
  • People never see it (CONTEXT_BLOCK in entry-format.ts): the transcript (projection.ts), edit/resend (resend.ts), and PiP's compaction source (pip-compact.ts) leave it out. Anything after the first part counts only if the server put it there: the person's own text is always the first part, so a marker typed into a message shows as typed.
  • The browser sends about only for a session in the list, not for a subagent's conversation or for PiP's own.
  • No orb in PiP's own conversation (opened as a conversation), where Reply already goes to PiP. An open pill follows the switches and PiP turned on or off at once, and each button checks again on tap.

Why

When asked about a passage, PiP should not have to ask "which session do you mean?". Before this, the only way to tell it was to type the session's name or enough context it could find it.

Tested

  • npm run format, npm run check, npm run lint pass. npm test: 1,410 of 1,411 pass. The one that fails, design-lint-pages "25 pages in other styles…", fails on main too.
  • New tests in test/pip.test.ts, which fail without the change: the model gets the hidden part with a safe title; the transcript shows only the quote and the words; about is refused for a non-PiP conversation, PiP itself, an unknown id (a subagent), and a non-number; a typed marker shows as typed; resend and the compaction source leave the part out.
  • By hand, on this branch with a fresh data folder: I selected a reply and tapped the orb. The strip showed and the box had the focus. I asked "which session and folder is this quote from?" and PiP answered with the right session title and folder. The chat showed only the quote and my question.
  • By hand on the live instance: the four switch combinations, switches flipped while a pill shows, and PiP's own conversation (Reply only).
  • Two rounds of independent review; all their findings are fixed.
  • Not tested on a phone. No browser test yet for the pill's switches or PiP's own conversation.

Other than this, lot of PR's incoming.

@vitalNohj
vitalNohj marked this pull request as ready for review November 3, 2026 08:53
TannerMidd added a commit that referenced this pull request Nov 3, 2026
…on it came from

# Conflicts:
#	docs/features.md
#	src/server/projection.ts
#	web/pip.js
#	web/quote-reply.js
#	web/sheets/appearance.js
#	web/style.css
#	web/theme.js
TannerMidd added a commit that referenced this pull request Nov 3, 2026
…haracters

Anyone who can write in a session can name it. Unicode format characters
(tag characters, bidi marks, zero-width spaces) in its title went into the
person's own message to PiP, unseen by people. They are now removed, as
`quoted()` removes them where PiP reads titles elsewhere. Control characters
become spaces. The hidden part's text is split into lines under 100 columns,
and `#mentionedFiles` gets its doc comment back. The test of the refused
`about` values is one table.

Follow-up to #271 by @vitalNohj.
TannerMidd added a commit that referenced this pull request Nov 4, 2026
PiP's quote lived in two slots: pipQuote in the corner, and the session
composer's replyQuote and replyAbout on the board. Every move copied it
from one slot to the other, and each fix of that copy (a move during a
send, a sent quote that came back, a Reply quote with the same words)
left another case.

Now PiP has one quote, pipQuote ({ text, session }), wherever it shows.
The session composer shows and sends PiP's quote while PiP's board is in
the session's place (composerQuote), and the session's own replyQuote
({ text }) otherwise; Reply on PiP's board quotes into PiP's. A move
copies nothing, and a send or a dismiss takes away exactly the quote it
had (dropQuote, by identity), never another one. replyAbout and
quoteSent are gone.

Follow-up to #268 and #271 by @vitalNohj.
TannerMidd added a commit that referenced this pull request Nov 4, 2026
… board steps back

An architecture review of PiP's two places found the rules the one-quote
model still lacked:
- a send takes its quote out of its box as it starts and gives it back
  if it fails and nothing took its place, so PiP's other place never
  offers a quote that is on its way (it went twice);
- closing the board goes back to the history entry it was opened over
  (popRoute), also with Appearance open, so Back no longer opens the
  board again after a move to the corner;
- the session's Reply quote waits under PiP's board while that session
  stays open (openId);
- one showsPip(), from the view's own pip flag or PiP's id, replaces four
  checks that missed PiP's board before its id came after a reload.
Each place keeps its own draft and files; the docs say so.

Follow-up to #268, #271, and #274 by @vitalNohj.
@TannerMidd TannerMidd closed this pull request by merging all changes into TannerMidd:main in 5eb3404 Nov 6, 2026
@TannerMidd

Copy link
Copy Markdown
Owner

Shipped in 0.28.0 through the release branch (#269), so GitHub marked it merged. Thanks @vitalNohj!

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