pi-ask-popup 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +55 -0
  3. package/docs/adr/0001-fork-rpiv-ask-user-question-as-zero-dep-pi-ask-popup.md +90 -0
  4. package/package.json +48 -0
  5. package/src/ask-user-question.ts +474 -0
  6. package/src/config.ts +250 -0
  7. package/src/events.ts +107 -0
  8. package/src/index.ts +25 -0
  9. package/src/reconcile.ts +31 -0
  10. package/src/rpc-fallback.ts +198 -0
  11. package/src/state/build-questionnaire.ts +346 -0
  12. package/src/state/external-editor.ts +94 -0
  13. package/src/state/key-router.ts +378 -0
  14. package/src/state/questionnaire-session.ts +382 -0
  15. package/src/state/row-intent.ts +156 -0
  16. package/src/state/selectors/contract.ts +40 -0
  17. package/src/state/selectors/derivations.ts +40 -0
  18. package/src/state/selectors/focus.ts +17 -0
  19. package/src/state/selectors/projections.ts +111 -0
  20. package/src/state/state-reducer.ts +421 -0
  21. package/src/state/state.ts +110 -0
  22. package/src/tool/format-answer.ts +28 -0
  23. package/src/tool/response-envelope.ts +123 -0
  24. package/src/tool/types.ts +193 -0
  25. package/src/tool/validate-questionnaire.ts +74 -0
  26. package/src/view/component-binding.ts +51 -0
  27. package/src/view/components/inline-input.ts +66 -0
  28. package/src/view/components/multi-select-view.ts +208 -0
  29. package/src/view/components/option-list-view.ts +77 -0
  30. package/src/view/components/preview/markdown-content-cache.ts +76 -0
  31. package/src/view/components/preview/preview-block-renderer.ts +116 -0
  32. package/src/view/components/preview/preview-box-renderer.ts +88 -0
  33. package/src/view/components/preview/preview-layout-decider.ts +219 -0
  34. package/src/view/components/preview/preview-pane.ts +240 -0
  35. package/src/view/components/submit-picker.ts +66 -0
  36. package/src/view/components/tab-bar.ts +70 -0
  37. package/src/view/components/wrapping-select.ts +313 -0
  38. package/src/view/dialog-builder.ts +325 -0
  39. package/src/view/props-adapter.ts +124 -0
  40. package/src/view/stateful-view.ts +20 -0
  41. package/src/view/tab-components.ts +16 -0
  42. package/src/view/tab-content-strategy.ts +447 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 juicesharp
4
+ Copyright (c) 2026 derangga
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # pi-ask-popup
2
+
3
+ Let the model ask you instead of guessing. This Pi extension registers one tool,
4
+ `ask_user_question`, that opens a terminal dialog of up to four questions with
5
+ written-out options, and hands your choices back as structured data.
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ pi install npm:pi-ask-popup
11
+ ```
12
+
13
+ ## What it does
14
+
15
+ - **Typed options, not a wall of prose.** Each question carries 2-4 authored
16
+ choices, and every choice explains what it means or what it costs you.
17
+ - **You can always answer in your own words.** A `Type something.` row is
18
+ appended to every question and widens to the full pane while you type.
19
+ - **Compare artifacts, not labels.** An option can carry a markdown `preview`
20
+ that renders in a bordered box beside the option list.
21
+ - **One interruption, not five.** Up to four questions arrive in a single tabbed
22
+ dialog, and a Submit tab names anything still blank before you commit.
23
+ - **Notes on any answer, or on all of them.** `n` opens a note editor on any
24
+ question tab, and on the Submit tab it writes one note covering everything.
25
+ A written note stays on its tab, dimmed, and the tab bar marks which tabs
26
+ carry one. A note on a question you never answer still reaches the model.
27
+ - **Read the transcript behind it.** `Ctrl+]` collapses the dialog and brings it
28
+ back with your answers intact.
29
+ - **A timeout that is not a decline.** Auto-dismiss returns a distinct
30
+ `timed_out` result, so the model never mistakes a clock for a refusal.
31
+ - **Works outside the terminal.** RPC and ACP hosts such as Zed or the VS Code
32
+ pendant walk the host's native dialogs instead.
33
+
34
+ ## Requirements
35
+
36
+ - Node.js 22 or newer
37
+ - Pi Agent 0.80 or newer, with an interactive terminal or an RPC/ACP host
38
+ - A terminal at least 100 columns wide for side-by-side previews
39
+
40
+ No runtime dependencies, no build step, no API keys. The extension makes no
41
+ model calls of its own.
42
+
43
+ ## Credits
44
+
45
+ Derived from [`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono/tree/main/packages/rpiv-ask-user-question)
46
+ by juicesharp, MIT licensed. This fork strips the `rpiv-config` and `rpiv-i18n`
47
+ dependencies, targets Pi 0.80+, and adds a timeout.
48
+
49
+ If you want something smaller, [`pi-ask-user`](https://www.npmjs.com/package/pi-ask-user)
50
+ by Enzo Lucchesi does a comparable job in a fraction of the code, with a
51
+ searchable split-pane selector instead of tabs and previews. Pick whichever fits.
52
+
53
+ ## License
54
+
55
+ MIT. See [LICENSE](LICENSE) for both copyright holders.
@@ -0,0 +1,90 @@
1
+ # 0001 Fork rpiv-ask-user-question as the zero-dependency pi-ask-popup
2
+
3
+ Pi had no Claude-Code-style questionnaire dialog, and the closest existing
4
+ package, `pi-ask-user`, takes a different shape (a searchable split-pane
5
+ selector, no tabs, no previews). We fork juicesharp's
6
+ `@juicesharp/rpiv-ask-user-question`, strip it to zero runtime dependencies,
7
+ and publish it as `pi-ask-popup` 0.1.0. These decisions were settled before any
8
+ code was ported, so the notes below record the evidence behind them.
9
+
10
+ ## Identity
11
+
12
+ - npm `pi-ask-popup`, unscoped, starting at 0.1.0. The name was verified free
13
+ on npm; `pi-ask-user` is taken by the similar package noted above.
14
+ - The package lives at `packages/pi-ask-popup/` in this workspaces monorepo.
15
+ Shared tooling (tsconfig base, oxlint, oxfmt, vitest config) sits at the
16
+ root, and root scripts are scoped to `packages/` so the vendored reference
17
+ clones never get linted, formatted or tested. Pi peer dependencies are also
18
+ root devDependencies pinned at one exact version, so every package
19
+ typechecks against the same Pi while peering the wider range.
20
+ - Author `derangga <derangga1011@gmail.com>`. The LICENSE is MIT carrying
21
+ juicesharp's original copyright line plus derangga's, as the MIT terms
22
+ require of a fork.
23
+ - Ships raw TypeScript. Pi resolves `"pi": { "extensions": ["./src/index.ts"] }`
24
+ and loads it through jiti. No build step, no `dist/`. Layout is `src/` plus
25
+ `test/`.
26
+
27
+ ## Dependencies
28
+
29
+ Zero runtime dependencies. Peers only: `@earendil-works/pi-coding-agent
30
+ >=0.80`,`@earendil-works/pi-tui >=0.80`,`typebox *`.
31
+
32
+ The peer is `typebox`, never `@sinclair/typebox`. Pi 0.84.4 depends on
33
+ `typebox@1.3.7`; the old name is a different package that Pi never loads, so
34
+ peering it would silently resolve to something unused.
35
+
36
+ ## Considered options
37
+
38
+ **Effect, rejected.** `effect@3.22.1` is 27 MB unpacked, larger than Pi's own
39
+ coding agent, against a zero-dep goal and a 114 kB competitor. Effect v4,
40
+ which the house style targets, is still a release candidate with no stable
41
+ release. The ported code has three async edges in total, so failure is
42
+ modeled as tagged unions instead: Effect-shaped, no import.
43
+
44
+ **rpiv-config and rpiv-i18n, dropped.** The fork drops both dependencies, the
45
+ i18n bridge, all nine locale files, and their tests. The 2-second prewarm
46
+ timer goes with them.
47
+
48
+ **Kept.** The pure reducer and key router, the tabbed multi-question dialog,
49
+ the Submit review tab, side-by-side markdown previews, multi-select with the
50
+ `Next` row, the appended `Type something.` row, per-question and global
51
+ notes, collapse mode on `Ctrl+]`, the RPC/ACP dialog walker, the `no_ui`,
52
+ `no_custom_ui`, `session_load_failed` and `stale_module_cache` envelopes, and
53
+ every test covering a surviving feature.
54
+
55
+ ## Pi compatibility
56
+
57
+ Verified by diffing the published `.d.ts` of Pi 0.80.6 and 0.84.4:
58
+
59
+ - `ui.select`, `ui.input`, `ui.custom`, `ui.onTerminalInput`, `ctx.mode` and
60
+ `ctx.hasUI` are identical in both versions.
61
+ - `OverlayHandle` (hide/setHidden/isHidden/focus/unfocus) is byte-identical at
62
+ the same line numbers in pi-tui 0.80.6 and 0.84.4, so collapse mode ports
63
+ untouched.
64
+ - 137 lines changed elsewhere in `core/extensions/types.d.ts` between the
65
+ versions; none are in the surface this package uses. The `>=0.80` peer
66
+ range is therefore safe.
67
+ - `ExtensionUIDialogOptions` already carries `timeout?: number`, documented
68
+ as auto-dismissing with a live countdown display, in both versions. The RPC
69
+ path passes timeout through; only the TUI overlay needs a hand-built clock.
70
+
71
+ ## Added
72
+
73
+ `timeout`, with a distinct `timed_out` result that is never folded into
74
+ `cancelled`. The reasoning matches why `no_custom_ui` is its own envelope: a
75
+ timeout is not a decline, and the model must not read it as one.
76
+
77
+ ## Consequences
78
+
79
+ The two load-failure envelopes stay even though the prewarm timer goes. jiti
80
+ is pinned at 2.7.0 in both Pi versions, so the cache-poisoning bug they guard
81
+ against is still live: a failed import stays registered in the module graph
82
+ cache and poisons every later import for the process lifetime.
83
+
84
+ Out of scope: no searchable option filter (the schema caps options at four),
85
+ no cross-session answer memory, no CI, no changesets, no built `dist/`, and
86
+ no raised caps on questions or options.
87
+
88
+ One question is deliberately deferred. The `"Other"` label stays in the
89
+ reserved-label list purely because Claude Code conditions models to reach for
90
+ it. It is worth keeping only as long as tool-name parity is the goal.
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "pi-ask-popup",
3
+ "version": "0.1.0",
4
+ "description": "Pi extension. A tabbed terminal questionnaire the model can put to you when it would otherwise guess, with typed options, markdown previews and notes instead of free-form replies.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "derangga <derangga1011@gmail.com>",
8
+ "keywords": [
9
+ "pi-package",
10
+ "pi-extension",
11
+ "pi",
12
+ "pi-coding-agent",
13
+ "ask",
14
+ "ask-user-question",
15
+ "questionnaire",
16
+ "dialog",
17
+ "tui"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "pi": {
23
+ "extensions": [
24
+ "./src/index.ts"
25
+ ]
26
+ },
27
+ "exports": {
28
+ ".": "./src/index.ts",
29
+ "./events": "./src/events.ts"
30
+ },
31
+ "files": [
32
+ "src/",
33
+ "docs/",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "engines": {
38
+ "node": ">=22"
39
+ },
40
+ "scripts": {
41
+ "typecheck": "tsc --noEmit"
42
+ },
43
+ "peerDependencies": {
44
+ "@earendil-works/pi-coding-agent": ">=0.80",
45
+ "@earendil-works/pi-tui": ">=0.80",
46
+ "typebox": "*"
47
+ }
48
+ }