@rol1n/pi-kit 0.1.0 → 0.1.2

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 (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -50
  3. package/README_zh.md +136 -0
  4. package/ask-u-questions/README.md +26 -0
  5. package/{extensions/ask-u-questions → ask-u-questions}/dialog-ui.ts +23 -0
  6. package/{extensions/ask-u-questions → ask-u-questions}/index.ts +9 -5
  7. package/{extensions/ask-u-questions → ask-u-questions}/multi-choice.ts +1 -3
  8. package/{extensions/ask-u-questions → ask-u-questions}/single-choice.ts +1 -3
  9. package/{extensions/ask-u-questions → ask-u-questions}/tool-renderers.ts +1 -3
  10. package/ask-u-questions/types.ts +192 -0
  11. package/continue-signal/README.md +20 -0
  12. package/{extensions/continue-signal → continue-signal}/index.ts +21 -3
  13. package/custom-providers/README.md +20 -0
  14. package/{extensions/custom-providers → custom-providers}/index.ts +16 -2
  15. package/image-generate/README.md +25 -0
  16. package/{extensions/image-generate → image-generate}/index.ts +22 -2
  17. package/{extensions/image-generate → image-generate}/model-selector.ts +1 -1
  18. package/memory-log/README.md +121 -0
  19. package/{extensions/memory-log → memory-log}/config.ts +1 -1
  20. package/{extensions/memory-log → memory-log}/hooks/compaction-hook.ts +58 -15
  21. package/memory-log/hooks/compaction-trigger.ts +87 -0
  22. package/{extensions/memory-log → memory-log}/hooks/observer-trigger.ts +2 -1
  23. package/{extensions/memory-log → memory-log}/index.ts +4 -0
  24. package/{extensions/memory-log → memory-log}/ledger/index.ts +1 -0
  25. package/memory-log/ledger/recall.ts +111 -0
  26. package/{extensions/memory-log → memory-log}/ledger/render.ts +3 -1
  27. package/{extensions/memory-log → memory-log}/ledger/serialize.ts +2 -4
  28. package/{extensions/memory-log → memory-log}/ledger/types.ts +4 -1
  29. package/{extensions/memory-log → memory-log}/runtime.ts +0 -5
  30. package/memory-log/tools/recall.ts +60 -0
  31. package/model-vision/README.md +22 -0
  32. package/{extensions/multi-harness → multi-harness}/README.md +3 -3
  33. package/oai-subquota/README.md +22 -0
  34. package/{extensions/oai-subquota → oai-subquota}/index.ts +16 -6
  35. package/{extensions/oai-subquota → oai-subquota}/snapshot.ts +127 -1
  36. package/{extensions/oai-subquota → oai-subquota}/ui.ts +1 -1
  37. package/package.json +46 -46
  38. package/prompt-snipaste/README.md +27 -0
  39. package/{extensions/prompt-snipaste → prompt-snipaste}/renderers.ts +0 -1
  40. package/{extensions/prompt-snipaste → prompt-snipaste}/snippets.ts +5 -2
  41. package/{extensions/prompt-snipaste → prompt-snipaste}/types.ts +0 -1
  42. package/screenshot/README.md +14 -0
  43. package/srp-theme/README.md +18 -0
  44. package/{extensions/srp-theme → srp-theme}/footer.ts +0 -1
  45. package/{extensions/srp-theme → srp-theme}/tps-meter.ts +0 -1
  46. package/{extensions/subagent → subagent}/README.md +1 -1
  47. package/tui-asr/README.md +21 -0
  48. package/{extensions/tui-asr → tui-asr}/dictation.ts +70 -3
  49. package/{extensions/tui-asr → tui-asr}/index.ts +2 -2
  50. package/{extensions/tui-asr → tui-asr}/input.ts +30 -1
  51. package/{extensions/tui-asr → tui-asr}/model-selector.ts +1 -1
  52. package/web-reach/README.md +19 -0
  53. package/windows-wheel-fix/README.md +12 -0
  54. package/extensions/ask-u-questions/README.md +0 -32
  55. package/extensions/ask-u-questions/answers.ts +0 -53
  56. package/extensions/ask-u-questions/results.ts +0 -83
  57. package/extensions/ask-u-questions/schema.ts +0 -17
  58. package/extensions/ask-u-questions/types.ts +0 -45
  59. package/extensions/ask-u-questions/ui-lock.ts +0 -24
  60. package/extensions/continue-signal/README.md +0 -28
  61. package/extensions/continue-signal/renderer.ts +0 -21
  62. package/extensions/custom-providers/README.md +0 -28
  63. package/extensions/image-generate/README.md +0 -29
  64. package/extensions/image-generate/models.ts +0 -19
  65. package/extensions/memory-log/README.md +0 -54
  66. package/extensions/memory-log/hooks/compaction-trigger.ts +0 -160
  67. package/extensions/model-vision/README.md +0 -28
  68. package/extensions/oai-subquota/README.md +0 -30
  69. package/extensions/oai-subquota/api.ts +0 -27
  70. package/extensions/oai-subquota/auth.ts +0 -34
  71. package/extensions/oai-subquota/cache.ts +0 -30
  72. package/extensions/oai-subquota/types.ts +0 -40
  73. package/extensions/prompt-snipaste/README.md +0 -33
  74. package/extensions/screenshot/README.md +0 -25
  75. package/extensions/srp-theme/README.md +0 -24
  76. package/extensions/subagent/skills/subagent/SKILL.md +0 -70
  77. package/extensions/tui-asr/README.md +0 -28
  78. package/extensions/tui-asr/audio.ts +0 -40
  79. package/extensions/tui-asr/clipboard.ts +0 -30
  80. package/extensions/tui-asr/providers.ts +0 -25
  81. package/extensions/web-reach/README.md +0 -37
  82. package/extensions/web-reach/html.ts +0 -83
  83. package/extensions/web-reach/index.ts +0 -82
  84. package/extensions/web-reach/page.ts +0 -132
  85. package/extensions/web-reach/pdf.ts +0 -42
  86. package/extensions/web-reach/reader.ts +0 -42
  87. package/extensions/web-reach/rsc.ts +0 -161
  88. package/extensions/web-reach/search.ts +0 -85
  89. package/extensions/web-reach/transport.ts +0 -35
  90. package/extensions/windows-wheel-fix/README.md +0 -21
  91. /package/{extensions/custom-providers → custom-providers}/asr/handlers/dashscope.ts +0 -0
  92. /package/{extensions/custom-providers → custom-providers}/asr/index.ts +0 -0
  93. /package/{extensions/custom-providers → custom-providers}/asr/models.ts +0 -0
  94. /package/{extensions/custom-providers → custom-providers}/asr/types.ts +0 -0
  95. /package/{extensions/custom-providers → custom-providers}/chat/index.ts +0 -0
  96. /package/{extensions/custom-providers → custom-providers}/chat/magpie.ts +0 -0
  97. /package/{extensions/custom-providers → custom-providers}/chat/models.ts +0 -0
  98. /package/{extensions/custom-providers → custom-providers}/classifier/index.ts +0 -0
  99. /package/{extensions/custom-providers → custom-providers}/classifier/models.ts +0 -0
  100. /package/{extensions/custom-providers → custom-providers}/image/handlers/dashscope.ts +0 -0
  101. /package/{extensions/custom-providers → custom-providers}/image/handlers/openrouter.ts +0 -0
  102. /package/{extensions/custom-providers → custom-providers}/image/index.ts +0 -0
  103. /package/{extensions/custom-providers → custom-providers}/image/models.ts +0 -0
  104. /package/{extensions/custom-providers → custom-providers}/image/types.ts +0 -0
  105. /package/{extensions/custom-providers → custom-providers}/types.ts +0 -0
  106. /package/{extensions/image-generate → image-generate}/files.ts +0 -0
  107. /package/{extensions/memory-log → memory-log}/agent/consolidator/prompt.ts +0 -0
  108. /package/{extensions/memory-log → memory-log}/agent/consolidator/tools.ts +0 -0
  109. /package/{extensions/memory-log → memory-log}/agent/cost.ts +0 -0
  110. /package/{extensions/memory-log → memory-log}/agent/index.ts +0 -0
  111. /package/{extensions/memory-log → memory-log}/agent/observer/prompt.ts +0 -0
  112. /package/{extensions/memory-log → memory-log}/agent/observer/tool.ts +0 -0
  113. /package/{extensions/memory-log → memory-log}/commands/compact.ts +0 -0
  114. /package/{extensions/memory-log → memory-log}/commands/consolidate.ts +0 -0
  115. /package/{extensions/memory-log → memory-log}/commands/status.ts +0 -0
  116. /package/{extensions/memory-log → memory-log}/debug-log.ts +0 -0
  117. /package/{extensions/memory-log → memory-log}/hooks/consolidator-trigger.ts +0 -0
  118. /package/{extensions/memory-log → memory-log}/ids.ts +0 -0
  119. /package/{extensions/memory-log → memory-log}/ledger/fold.ts +0 -0
  120. /package/{extensions/memory-log → memory-log}/ledger/pool.ts +0 -0
  121. /package/{extensions/memory-log → memory-log}/ledger/progress.ts +0 -0
  122. /package/{extensions/memory-log → memory-log}/ledger/projection.ts +0 -0
  123. /package/{extensions/memory-log → memory-log}/memory/index-render.ts +0 -0
  124. /package/{extensions/memory-log → memory-log}/memory/paths.ts +0 -0
  125. /package/{extensions/memory-log → memory-log}/memory/session.ts +0 -0
  126. /package/{extensions/memory-log → memory-log}/spawn/launch.ts +0 -0
  127. /package/{extensions/memory-log → memory-log}/spawn/runs.ts +0 -0
  128. /package/{extensions/memory-log → memory-log}/tokens.ts +0 -0
  129. /package/{extensions/memory-log → memory-log}/ui/status-controller.ts +0 -0
  130. /package/{extensions/memory-log → memory-log}/ui/timeline.ts +0 -0
  131. /package/{extensions/multi-harness → multi-harness}/adapters.mjs +0 -0
  132. /package/{extensions/multi-harness → multi-harness}/harness-done.mjs +0 -0
  133. /package/{extensions/multi-harness → multi-harness}/index.ts +0 -0
  134. /package/{extensions/multi-harness → multi-harness}/ipc.mjs +0 -0
  135. /package/{extensions/multi-harness → multi-harness}/opencode-plugin.mjs +0 -0
  136. /package/{extensions/multi-harness → multi-harness}/process-runner.mjs +0 -0
  137. /package/{extensions/multi-harness → multi-harness}/turn-hook.mjs +0 -0
  138. /package/{extensions/multi-harness → multi-harness}/worker-bridge.ts +0 -0
  139. /package/{extensions/prompt-snipaste → prompt-snipaste}/index.ts +0 -0
  140. /package/{extensions/prompt-snipaste → prompt-snipaste}/menu.ts +0 -0
  141. /package/{prompts → prompt-snipaste/prompts}/ask-questions.md +0 -0
  142. /package/{prompts → prompt-snipaste/prompts}/delegate-exploration.md +0 -0
  143. /package/{prompts → prompt-snipaste/prompts}/diagnose-report.md +0 -0
  144. /package/{prompts → prompt-snipaste/prompts}/frontend-tech-preset.md +0 -0
  145. /package/{prompts → prompt-snipaste/prompts}/orchestrator-mode.md +0 -0
  146. /package/{prompts → prompt-snipaste/prompts}/session-kickoff.md +0 -0
  147. /package/{prompts → prompt-snipaste/prompts}/verify-not-assume.md +0 -0
  148. /package/{extensions/srp-theme → srp-theme}/index.ts +0 -0
  149. /package/{extensions/subagent → subagent}/bridge.ts +0 -0
  150. /package/{extensions/subagent → subagent}/index.ts +0 -0
  151. /package/{extensions/subagent → subagent}/mux.ts +0 -0
  152. /package/{extensions/subagent → subagent}/session.ts +0 -0
  153. /package/{extensions/subagent → subagent}/ui.ts +0 -0
  154. /package/{extensions/tui-asr → tui-asr}/status.ts +0 -0
  155. /package/{extensions/windows-wheel-fix → windows-wheel-fix}/index.ts +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RoL1n_SrP
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,99 +1,136 @@
1
1
  # pi-kit
2
2
 
3
- Pi extensions and prompt templates, published together as **`@rol1n/pi-kit`** or as individual extension packages. Each extension's README describes its commands, settings, platform support, and dependencies.
3
+ > Modular extensions and prompt templates for the [Pi Coding Agent](https://pi.dev), published as the **`@rol1n/pi-kit`** bundle and as standalone **`@rol1n/<extension>`** packages.
4
+
5
+ <p align="left">
6
+ <b>English</b> •
7
+ <a href="README_zh.md"><b>中文说明</b></a>
8
+ </p>
9
+
10
+ [![npm version](https://img.shields.io/npm/v/@rol1n/pi-kit?style=flat-square&logo=npm)](https://www.npmjs.com/package/@rol1n/pi-kit)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
12
+
13
+ ---
4
14
 
5
15
  ## Install
6
16
 
17
+ Install the default bundle:
18
+
7
19
  ```sh
8
20
  pi install npm:@rol1n/pi-kit
9
21
  ```
10
22
 
23
+ Or install any standalone extension individually:
24
+
25
+ ```sh
26
+ pi install npm:@rol1n/memory-log
27
+ pi install npm:@rol1n/subagent
28
+ pi install npm:@rol1n/multi-harness
29
+ ```
30
+
11
31
  Install from GitHub or a local checkout during development:
12
32
 
13
33
  ```sh
14
- pi install git:git@github.com:RolinShmily/pi-kit.git
34
+ pi install https://github.com/RolinShmily/pi-kit
15
35
  pi install /absolute/path/to/pi-kit
16
36
  ```
17
37
 
18
- Update an installed package with `pi update npm:@rol1n/pi-kit`, or update all Pi packages with `pi update --extensions`.
38
+ Update installed packages:
39
+
40
+ ```sh
41
+ pi update npm:@rol1n/pi-kit
42
+ pi update --extensions
43
+ ```
44
+
45
+ ---
19
46
 
20
47
  ## Extensions
21
48
 
22
- | Package and documentation | Purpose | Included in the kit |
23
- |---|---|---|
24
- | [ask-u-questions](extensions/ask-u-questions/README.md) | Interactive questions | Yes |
25
- | [continue-signal](extensions/continue-signal/README.md) | Resume an idle agent | Yes |
26
- | [custom-providers](extensions/custom-providers/README.md) | Additional model providers and gateway configuration | Yes |
27
- | [image-generate](extensions/image-generate/README.md) | Image generation and model selection | Yes |
28
- | [memory-log](extensions/memory-log/README.md) | Background observational memory | Yes |
29
- | [model-vision](extensions/model-vision/README.md) | Image understanding and OCR | No |
30
- | [multi-harness](extensions/multi-harness/README.md) | Delegate to Pi, Codex, Claude, and OpenCode | Yes |
31
- | [oai-subquota](extensions/oai-subquota/README.md) | Codex subscription quota | Yes |
32
- | [prompt-snipaste](extensions/prompt-snipaste/README.md) | Select snippets for the next user message | Yes |
33
- | [screenshot](extensions/screenshot/README.md) | Reference the latest Windows/WSL screenshot | No |
34
- | [srp-theme](extensions/srp-theme/README.md) | Footer, prompt preview, and throughput display | Yes |
35
- | [subagent](extensions/subagent/README.md) | Delegate to asynchronous Pi workers | Yes |
36
- | [tui-asr](extensions/tui-asr/README.md) | Streaming voice dictation | Yes |
37
- | [web-reach](extensions/web-reach/README.md) | Web search and page extraction | Yes |
38
- | [windows-wheel-fix](extensions/windows-wheel-fix/README.md) | Windows ConPTY/Zellij mouse reporting | Yes, active only on Windows |
39
-
40
- Independent package names use the `@rol1n/<name>` scope, such as `@rol1n/memory-log` or `@rol1n/multi-harness`. Each package has its own release version and README; the implementation is shared with the kit.
41
-
42
- Every extension uses the same directory layout:
43
-
44
- ```text
45
- extensions/<name>/
46
- ├── index.ts # Pi entrypoint and registration
47
- ├── README.md # Package documentation
48
- └── ... # Modules grouped by responsibility
49
- ```
49
+ Each top-level directory is a self-contained extension (`<name>/index.ts` + `README.md`). Detailed commands, parameters, and settings are documented in each extension's README:
50
+
51
+ | Extension | Description | In `@rol1n/pi-kit` | Standalone Package |
52
+ | :--- | :--- | :---: | :--- |
53
+ | [ask-u-questions](ask-u-questions/README.md) | Interactive single-choice, multi-choice, and text dialogs | Yes | `@rol1n/ask-u-questions` |
54
+ | [continue-signal](continue-signal/README.md) | Resume an idle agent via `/continue` or `Alt+C` | Yes | `@rol1n/continue-signal` |
55
+ | [custom-providers](custom-providers/README.md) | Additional model providers and gateway registration | Yes | `@rol1n/custom-providers` |
56
+ | [image-generate](image-generate/README.md) | Image generation tool and `/image-generate` model selector | Yes | `@rol1n/image-generate` |
57
+ | [memory-log](memory-log/README.md) | Tiered asynchronous observational memory and instant compaction | Yes | `@rol1n/memory-log` |
58
+ | [model-vision](model-vision/README.md) | Image understanding and OCR tool (`model_vision`) | No | `@rol1n/model-vision` |
59
+ | [multi-harness](multi-harness/README.md) | Delegate tasks across `pi`, `codex`, `claude`, and `opencode` | Yes | `@rol1n/multi-harness` |
60
+ | [oai-subquota](oai-subquota/README.md) | OpenAI Codex subscription quota monitor and statusline | Yes | `@rol1n/oai-subquota` |
61
+ | [prompt-snipaste](prompt-snipaste/README.md) | Prompt snippet selector (`/snipaste`, `Alt+S`) with 7 built-in prompts | Yes | `@rol1n/prompt-snipaste` |
62
+ | [screenshot](screenshot/README.md) | Insert the latest Windows/WSL screenshot path (`/screenshot`) | No | `@rol1n/screenshot` |
63
+ | [srp-theme](srp-theme/README.md) | Last-prompt preview widget and real-time streaming TPS meter | Yes | `@rol1n/srp-theme` |
64
+ | [subagent](subagent/README.md) | Delegate tasks to parallel Pi workers in tmux/Zellij or background processes | Yes | `@rol1n/subagent` |
65
+ | [tui-asr](tui-asr/README.md) | Streaming voice dictation via Aliyun DashScope ASR (`/asr`, `Alt+M`) | Yes | `@rol1n/tui-asr` |
66
+ | [web-reach](web-reach/README.md) | Keyless Exa MCP web search and multi-tier page extraction | No | `@rol1n/web-reach` |
67
+ | [windows-wheel-fix](windows-wheel-fix/README.md) | Windows ConPTY / Zellij mouse-wheel reporting fix | Yes (Windows) | `@rol1n/windows-wheel-fix` |
50
68
 
51
- UI, transport, parsing, and storage helpers live beside the entrypoint as needed. Small extensions can remain a single cohesive `index.ts`.
69
+ > Standalone packages with cross-extension dependencies (`tui-asr` / `image-generate` -> `@rol1n/custom-providers`, `multi-harness` -> `@rol1n/subagent`) declare standard npm `dependencies` and resolve them automatically on install.
52
70
 
53
- ## Resource selection
71
+ ---
54
72
 
55
- The kit currently exposes 13 extension entrypoints and the seven templates in [prompts](prompts/). Personal skills, provider credentials, MCP servers, and keybindings remain normal Pi configuration.
73
+ ## Resource Selection
56
74
 
57
- Use `pi config` or narrow package resources in personal/project settings:
75
+ `@rol1n/pi-kit` exposes 12 extension entrypoints and the 7 prompt templates bundled in [prompt-snipaste/prompts](prompt-snipaste/prompts/). Use `pi config` or filter loaded resources in `settings.json`:
58
76
 
59
77
  ```json
60
78
  {
61
79
  "packages": [
62
80
  {
63
81
  "source": "npm:@rol1n/pi-kit",
64
- "extensions": ["extensions/**", "!extensions/tui-asr/**"],
65
- "prompts": ["prompts/diagnose-report.md"]
82
+ "extensions": ["**/*.ts", "!tui-asr/**"],
83
+ "prompts": ["prompt-snipaste/prompts/diagnose-report.md"]
66
84
  }
67
85
  ]
68
86
  }
69
87
  ```
70
88
 
71
- Omit a resource field to load the package defaults; use `[]` to disable that resource type. Filters select resources already exposed by the package. When also installing an independent extension package, exclude its entry from the kit to avoid loading the same feature twice.
89
+ ---
90
+
91
+ ## Development & Publishing
72
92
 
73
- ## Build and publish
93
+ [kit.config.json](kit.config.json) controls bundle selection (`bundle`), inter-extension dependencies (`deps`), and release versions. The top-level `version` belongs to `@rol1n/pi-kit`; each extension can set its own `version`, otherwise it inherits the top-level version. Set explicit extension versions to release the kit and standalone packages independently.
74
94
 
75
- From a source checkout, edit [kit.config.json](https://github.com/RolinShmily/pi-kit/blob/main/kit.config.json) to choose each extension's `bundle` flag, package name, version, entrypoint, runtime files, and README. Then synchronize and inspect the aggregate release:
95
+ ### Automated releases
96
+
97
+ 1. Update the code and bump the relevant version(s) in `kit.config.json`.
98
+ 2. Push to `main` with changes to `kit.config.json` or `package.json`, or manually run **Publish to npm** in GitHub Actions. Changes to the packaging script or workflow also trigger a release run.
99
+ 3. CI runs the same pipeline for both triggers:
76
100
 
77
101
  ```sh
78
102
  npm run manifest
79
103
  npm run check
80
- npm pack --dry-run --ignore-scripts
81
- npm publish --access public
104
+ npm run publish:ci -- all
82
105
  ```
83
106
 
84
- Prepare an independent release from the same source:
107
+ The workflow in [`.github/workflows/publish.yml`](.github/workflows/publish.yml) generates `package.json`, validates the layout, then publishes all standalone extensions in dependency order, followed by the kit. Already-published versions are skipped; versions are never bumped automatically. `bundle: false` excludes an extension from the kit, not from standalone publishing. Publishing runs do not overlap, and a new run does not cancel an active release. Code-only pushes do not trigger publishing.
108
+
109
+ You do not need to run `manifest` or publish locally for an npm release. CI generates the manifest only in its checkout and does not commit it back. For local or Git installs, run `npm run manifest` and commit the generated `package.json` when changing bundle selection or versions so the repository manifest stays in sync.
110
+
111
+ ### Local development and manual publishing
85
112
 
86
113
  ```sh
114
+ # Sync the local manifest and validate all extensions
115
+ npm run manifest
116
+ npm run check
117
+
118
+ # Stage a standalone package into dist/<id>
87
119
  npm run prepare:extension -- memory-log
88
- cd dist/extensions/memory-log
89
- npm pack --dry-run --ignore-scripts
90
- npm publish --access public
120
+
121
+ # Optional local release; also accepts extensions, kit, or a single extension ID
122
+ npm run publish:ci -- all
91
123
  ```
92
124
 
93
- The preparation command copies that extension's README to the package root and includes shared implementation files where needed. Add new runtime assets to its `files` list. Names and versions are configured independently; use an available npm name and a new version for each publication. Preparation does not install dependencies or publish anything.
125
+ ---
126
+
127
+ ## Acknowledgements
128
+
129
+ - [elpapi42/pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) — Observational memory architecture and inspiration for [`memory-log`](memory-log/README.md).
130
+ - [earendil-works/pi](https://github.com/earendil-works/pi) — The Pi coding agent harness and SDK.
94
131
 
95
- All packages link to [RolinShmily/pi-kit](https://github.com/RolinShmily/pi-kit). The `pi-package` keyword makes each published package eligible for the Pi gallery; indexing can take time. Pi supplies the host libraries declared as peer dependencies.
132
+ ---
96
133
 
97
- ## Attribution
134
+ ## License
98
135
 
99
- Existing author and copyright notices remain with their source files. Upstream issue references and integration details are linked from the individual extension READMEs, including the [Windows terminal workaround](extensions/windows-wheel-fix/README.md).
136
+ [MIT](LICENSE) © RoL1n_SrP
package/README_zh.md ADDED
@@ -0,0 +1,136 @@
1
+ # pi-kit
2
+
3
+ > 面向 [Pi Coding Agent](https://pi.dev) 的模块化扩展与提示词模板套件,支持作为 **`@rol1n/pi-kit`** 聚合包或 **`@rol1n/<extension>`** 独立包安装。
4
+
5
+ <p align="left">
6
+ <a href="README.md"><b>English</b></a> •
7
+ <b>中文说明</b>
8
+ </p>
9
+
10
+ [![npm version](https://img.shields.io/npm/v/@rol1n/pi-kit?style=flat-square&logo=npm)](https://www.npmjs.com/package/@rol1n/pi-kit)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
12
+
13
+ ---
14
+
15
+ ## 安装
16
+
17
+ 安装默认聚合包:
18
+
19
+ ```sh
20
+ pi install npm:@rol1n/pi-kit
21
+ ```
22
+
23
+ 或按需安装任意独立扩展包:
24
+
25
+ ```sh
26
+ pi install npm:@rol1n/memory-log
27
+ pi install npm:@rol1n/subagent
28
+ pi install npm:@rol1n/multi-harness
29
+ ```
30
+
31
+ 开发期间也可直接从 GitHub 或本地目录安装:
32
+
33
+ ```sh
34
+ pi install https://github.com/RolinShmily/pi-kit
35
+ pi install /absolute/path/to/pi-kit
36
+ ```
37
+
38
+ 更新已安装的包:
39
+
40
+ ```sh
41
+ pi update npm:@rol1n/pi-kit
42
+ pi update --extensions
43
+ ```
44
+
45
+ ---
46
+
47
+ ## 扩展列表
48
+
49
+ 仓库根目录下每个文件夹均为自包含扩展(`<name>/index.ts` + `README.md`)。各扩展的详细命令、参数与配置说明请参阅对应目录的 README:
50
+
51
+ | 扩展目录 | 功能简介 | 默认纳入 `pi-kit` | 独立 npm 包名 |
52
+ | :--- | :--- | :---: | :--- |
53
+ | [ask-u-questions](ask-u-questions/README.md) | 交互式单选、多选与自由文本提问弹窗(共享 UI 锁) | Yes | `@rol1n/ask-u-questions` |
54
+ | [continue-signal](continue-signal/README.md) | 通过 `/continue` 或 `Alt+C` 唤醒空闲智能体继续未完成任务 | Yes | `@rol1n/continue-signal` |
55
+ | [custom-providers](custom-providers/README.md) | 自定义模型服务商与网关(Magpie、智谱、阿里百炼等)注册 | Yes | `@rol1n/custom-providers` |
56
+ | [image-generate](image-generate/README.md) | OpenRouter / 百炼文生图与参考图生图工具及 `/image-generate` 模型选择器 | Yes | `@rol1n/image-generate` |
57
+ | [memory-log](memory-log/README.md) | 分层异步观察记忆系统与零模型阻塞的确定性秒级压缩 | Yes | `@rol1n/memory-log` |
58
+ | [model-vision](model-vision/README.md) | 本地与远程图片视觉理解、OCR 与 UI 诊断工具(`model_vision`) | No | `@rol1n/model-vision` |
59
+ | [multi-harness](multi-harness/README.md) | 跨 `pi`、`codex`、`claude`、`opencode` 的多 CLI 协同委派运行时 | Yes | `@rol1n/multi-harness` |
60
+ | [oai-subquota](oai-subquota/README.md) | OpenAI Codex 订阅额度(5h / 7d 窗口与重置时间)状态栏监控 | Yes | `@rol1n/oai-subquota` |
61
+ | [prompt-snipaste](prompt-snipaste/README.md) | 提示词片段选择器(`/snipaste`、`Alt+S`),内置 7 个常用提示词模板 | Yes | `@rol1n/prompt-snipaste` |
62
+ | [screenshot](screenshot/README.md) | 一键将最新 Windows / WSL 系统截图路径插入编辑器(`/screenshot`) | No | `@rol1n/screenshot` |
63
+ | [srp-theme](srp-theme/README.md) | 编辑器下方最近提问预览组件与实时流式 TPS 速率仪表 | Yes | `@rol1n/srp-theme` |
64
+ | [subagent](subagent/README.md) | 基于 tmux / Zellij 分屏或后台进程的并发 Pi 子智能体工具 | Yes | `@rol1n/subagent` |
65
+ | [tui-asr](tui-asr/README.md) | 基于阿里百炼 Paraformer 的终端实时流式语音听写(`/asr`、`Alt+M`) | Yes | `@rol1n/tui-asr` |
66
+ | [web-reach](web-reach/README.md) | 免 Key Exa MCP 网页搜索与多级网页正文提取(RSC / HTML / PDF / Jina) | No | `@rol1n/web-reach` |
67
+ | [windows-wheel-fix](windows-wheel-fix/README.md) | 修复 Windows ConPTY / Zellij 下鼠标滚轮被误转为上下方向键的问题 | Yes (仅 Windows) | `@rol1n/windows-wheel-fix` |
68
+
69
+ > 带有跨扩展依赖的独立包(`tui-asr` / `image-generate` 依赖 `@rol1n/custom-providers`,`multi-harness` 依赖 `@rol1n/subagent`)已声明标准 npm `dependencies`,单独安装时会自动拉取补全并激活所需依赖。
70
+
71
+ ---
72
+
73
+ ## 资源按需筛选
74
+
75
+ `@rol1n/pi-kit` 默认导出 12 个扩展入口与 [prompt-snipaste/prompts](prompt-snipaste/prompts/) 下的 7 个提示词模板。可通过 `pi config` 或在 `settings.json` 中按需过滤:
76
+
77
+ ```json
78
+ {
79
+ "packages": [
80
+ {
81
+ "source": "npm:@rol1n/pi-kit",
82
+ "extensions": ["**/*.ts", "!tui-asr/**"],
83
+ "prompts": ["prompt-snipaste/prompts/diagnose-report.md"]
84
+ }
85
+ ]
86
+ }
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 构建与发布
92
+
93
+ [kit.config.json](kit.config.json) 统一管理聚合包选择(`bundle`)、扩展间的依赖关系(`deps`)与发布版本。顶层 `version` 属于 `@rol1n/pi-kit`;各扩展可以单独设置 `version`,未设置时继承顶层版本。为每个扩展显式设置版本即可让聚合包与独立包分别升级。
94
+
95
+ ### 自动发布
96
+
97
+ 1. 修改代码,并在 `kit.config.json` 中提升需要发布的包的版本。
98
+ 2. 将包含 `kit.config.json` 或 `package.json` 变更的提交推送到 `main`,或在 GitHub Actions 手动运行 **Publish to npm**。修改打包脚本或工作流本身也会触发发布流程。
99
+ 3. 自动和手动触发均执行同一条流水线:
100
+
101
+ ```sh
102
+ npm run manifest
103
+ npm run check
104
+ npm run publish:ci -- all
105
+ ```
106
+
107
+ [`.github/workflows/publish.yml`](.github/workflows/publish.yml) 会生成 `package.json`、校验扩展布局,再按依赖顺序发布所有独立扩展,最后发布聚合包。已存在的版本自动跳过,不会自动提升版本号。`bundle: false` 只表示不纳入聚合包,不影响独立发布。发布流程不会并行执行,新触发的流程也不会取消正在进行的发布。仅修改扩展代码不会触发发布。
108
+
109
+ 发布 npm 包无需本地运行 `manifest` 或 `publish`。CI 只在运行目录中生成清单,不会自动提交回仓库。若使用本地或 Git 安装,调整聚合包选择或版本后仍应运行 `npm run manifest` 并提交生成的 `package.json`,保持仓库清单同步。
110
+
111
+ ### 本地开发与手动发布
112
+
113
+ ```sh
114
+ # 同步本地清单并校验所有扩展
115
+ npm run manifest
116
+ npm run check
117
+
118
+ # 将单个扩展构建到 dist/<id>
119
+ npm run prepare:extension -- memory-log
120
+
121
+ # 可选的本地发布,也支持 extensions、kit 或单个扩展 ID
122
+ npm run publish:ci -- all
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 致谢
128
+
129
+ - [elpapi42/pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) — [`memory-log`](memory-log/README.md) 的观察记忆架构灵感与上游基础。
130
+ - [earendil-works/pi](https://github.com/earendil-works/pi) — Pi Coding Agent 运行时与 SDK。
131
+
132
+ ---
133
+
134
+ ## 许可证
135
+
136
+ [MIT](LICENSE) © RoL1n_SrP
@@ -0,0 +1,26 @@
1
+ # ask-u-questions
2
+
3
+ Interactive single-choice, multiple-choice, and free-text questions for Pi. Registers the `ask_user_question` tool and serializes dialogs through a shared UI lock.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pi install npm:@rol1n/ask-u-questions
9
+ ```
10
+
11
+ Also included in `@rol1n/pi-kit`.
12
+
13
+ ## Use
14
+
15
+ ```json
16
+ {
17
+ "question": "Which output format should I use?",
18
+ "options": [
19
+ { "label": "Markdown (Recommended)", "value": "markdown" },
20
+ { "label": "JSON", "value": "json" }
21
+ ],
22
+ "multiSelect": false
23
+ }
24
+ ```
25
+
26
+ Omit `options` or pass `[]` for free-text input. Set `multiSelect: true` only when multiple choices are expected. `details` adds supporting context, and an `Other` option is provided automatically for choice questions.
@@ -55,3 +55,26 @@ export function addWrapped(
55
55
  }
56
56
  }
57
57
 
58
+ const SHARED_UI_LOCK_KEY = "__piSharedUiLock";
59
+ function getSharedUiLock(): { withLock<T>(fn: () => T | Promise<T>): Promise<T> } {
60
+ const g = globalThis as any;
61
+ if (!g[SHARED_UI_LOCK_KEY]) {
62
+ let chain: Promise<void> = Promise.resolve();
63
+ g[SHARED_UI_LOCK_KEY] = {
64
+ withLock<T>(fn: () => T | Promise<T>): Promise<T> {
65
+ const prev = chain;
66
+ let release: () => void;
67
+ chain = new Promise<void>((r) => {
68
+ release = r;
69
+ });
70
+ return prev.then(fn).finally(() => release!());
71
+ },
72
+ };
73
+ }
74
+ return g[SHARED_UI_LOCK_KEY];
75
+ }
76
+ const sharedUiLock = getSharedUiLock();
77
+
78
+ export function withUILock<T>(fn: () => Promise<T>): Promise<T> {
79
+ return sharedUiLock.withLock(fn);
80
+ }
@@ -1,12 +1,16 @@
1
1
  /** Interactive questions, serialized through the shared dialog lock. */
2
2
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
- import type { AskUserQuestionMode } from "./types.ts";
4
- import { AskUserQuestionParams } from "./schema.ts";
5
- import { normalizeOptions } from "./answers.ts";
6
- import { buildResult, cancelledResult, unavailableResult } from "./results.ts";
3
+ import {
4
+ AskUserQuestionParams,
5
+ buildResult,
6
+ cancelledResult,
7
+ normalizeOptions,
8
+ unavailableResult,
9
+ type AskUserQuestionMode,
10
+ } from "./types.ts";
11
+ import { withUILock } from "./dialog-ui.ts";
7
12
  import { askSingleChoice } from "./single-choice.ts";
8
13
  import { askMultiChoice } from "./multi-choice.ts";
9
- import { withUILock } from "./ui-lock.ts";
10
14
  import { questionRenderers } from "./tool-renderers.ts";
11
15
 
12
16
  export type { AskOption, TextAnswer, OptionAnswer, OtherAnswer, AskAnswer, AskUserQuestionStatus, AskUserQuestionMode, AskUserQuestionResultDetails } from "./types.ts";
@@ -1,7 +1,6 @@
1
1
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { Editor, Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
3
- import type { AskAnswer, AskOption, DisplayOption } from "./types.ts";
4
- import { getOtherLabel, isChineseContext, sortAnswers } from "./answers.ts";
3
+ import { getOtherLabel, isChineseContext, sortAnswers, type AskAnswer, type AskOption, type DisplayOption } from "./types.ts";
5
4
  import { addWrapped, createEditorTheme } from "./dialog-ui.ts";
6
5
 
7
6
  export async function askMultiChoice(
@@ -257,4 +256,3 @@ export async function askMultiChoice(
257
256
  },
258
257
  );
259
258
  }
260
-
@@ -1,7 +1,6 @@
1
1
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { Editor, Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
3
- import type { AskAnswer, AskOption, DisplayOption } from "./types.ts";
4
- import { getOtherLabel, isChineseContext } from "./answers.ts";
3
+ import { getOtherLabel, isChineseContext, type AskAnswer, type AskOption, type DisplayOption } from "./types.ts";
5
4
  import { addWrapped, createEditorTheme } from "./dialog-ui.ts";
6
5
 
7
6
  export async function askSingleChoice(
@@ -179,4 +178,3 @@ export async function askSingleChoice(
179
178
  },
180
179
  );
181
180
  }
182
-
@@ -1,8 +1,6 @@
1
1
  import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
2
2
  import { Text } from "@earendil-works/pi-tui";
3
- import type { AskUserQuestionParams } from "./schema.ts";
4
- import type { AskUserQuestionResultDetails } from "./types.ts";
5
- import { getOtherLabel, isChineseContext, normalizeOptions } from "./answers.ts";
3
+ import { AskUserQuestionParams, getOtherLabel, isChineseContext, normalizeOptions, type AskUserQuestionResultDetails } from "./types.ts";
6
4
 
7
5
  export const questionRenderers: Pick<ToolDefinition<typeof AskUserQuestionParams, AskUserQuestionResultDetails>, "renderCall" | "renderResult"> = {
8
6
  renderCall(args, theme, context) {
@@ -0,0 +1,192 @@
1
+ import { Type } from "typebox";
2
+
3
+ const OptionSchema = Type.Object({
4
+ label: Type.String({ description: 'Option label. Put a recommended option first and append "(Recommended)".' }),
5
+ value: Type.Optional(Type.String({ description: "Machine-readable value; defaults to the label." })),
6
+ description: Type.Optional(Type.String({ description: "Additional context shown below the option." })),
7
+ });
8
+
9
+ export const AskUserQuestionParams = Type.Object({
10
+ question: Type.String({ description: "The question to ask. Ask only one question per call." }),
11
+ details: Type.Optional(Type.String({ description: "Background or instructions shown below the question." })),
12
+ options: Type.Optional(Type.Array(OptionSchema, {
13
+ description: "Choices for selection. Omit or pass an empty array for free-text input. An Other choice is always available.",
14
+ })),
15
+ multiSelect: Type.Optional(Type.Boolean({ description: "Allow selecting multiple options when true." })),
16
+ });
17
+
18
+ export interface AskOption {
19
+ label: string;
20
+ value: string;
21
+ description?: string;
22
+ }
23
+
24
+ export interface DisplayOption extends AskOption {
25
+ id: string;
26
+ index?: number;
27
+ isOther?: boolean;
28
+ isSubmit?: boolean;
29
+ }
30
+
31
+ export interface TextAnswer {
32
+ type: "text";
33
+ label: string;
34
+ value: string;
35
+ }
36
+
37
+ export interface OptionAnswer {
38
+ type: "option";
39
+ label: string;
40
+ value: string;
41
+ index: number;
42
+ }
43
+
44
+ export interface OtherAnswer {
45
+ type: "other";
46
+ label: string;
47
+ value: string;
48
+ }
49
+
50
+ export type AskAnswer = TextAnswer | OptionAnswer | OtherAnswer;
51
+ export type AskUserQuestionStatus = "answered" | "cancelled" | "unavailable";
52
+ export type AskUserQuestionMode = "text" | "single-select" | "multi-select";
53
+
54
+ export interface AskUserQuestionResultDetails {
55
+ status: AskUserQuestionStatus;
56
+ question: string;
57
+ context?: string;
58
+ mode: AskUserQuestionMode;
59
+ answers: AskAnswer[];
60
+ message?: string;
61
+ }
62
+
63
+ export function normalizeOptions(
64
+ options: Array<{ label: string; value?: string; description?: string }> | undefined,
65
+ ): AskOption[] {
66
+ return (options || [])
67
+ .map((option) => ({
68
+ label: option.label.trim(),
69
+ value: option.value?.trim() || option.label.trim(),
70
+ description: option.description?.trim() || undefined,
71
+ }))
72
+ .filter((option) => option.label.length > 0);
73
+ }
74
+
75
+ export function isChineseContext(
76
+ question: string,
77
+ options?: Array<{ label?: string; description?: string }>,
78
+ context?: string,
79
+ ): boolean {
80
+ if (/[\u4e00-\u9fa5]/.test(question)) return true;
81
+ if (context && /[\u4e00-\u9fa5]/.test(context)) return true;
82
+ if (options && options.some((o) => (o.label && /[\u4e00-\u9fa5]/.test(o.label)) || (o.description && /[\u4e00-\u9fa5]/.test(o.description)))) {
83
+ return true;
84
+ }
85
+ return false;
86
+ }
87
+
88
+ export function getOtherLabel(options: AskOption[], isZh = false): string {
89
+ if (isZh) {
90
+ return options.some((option) => option.label === "其他(自定义输入)")
91
+ ? "自定义输入"
92
+ : "其他(自定义输入)";
93
+ }
94
+ return options.some((option) => option.label === "Other (custom input)")
95
+ ? "Custom input"
96
+ : "Other (custom input)";
97
+ }
98
+
99
+ function answerSortRank(answer: AskAnswer): number {
100
+ switch (answer.type) {
101
+ case "option":
102
+ return answer.index;
103
+ case "other":
104
+ return Number.MAX_SAFE_INTEGER - 1;
105
+ case "text":
106
+ return Number.MAX_SAFE_INTEGER;
107
+ }
108
+ }
109
+
110
+ export function sortAnswers(answers: AskAnswer[]): AskAnswer[] {
111
+ return [...answers].sort((a, b) => answerSortRank(a) - answerSortRank(b));
112
+ }
113
+
114
+ function formatAnswerForModel(answer: AskAnswer): string {
115
+ switch (answer.type) {
116
+ case "text":
117
+ return answer.label;
118
+ case "other":
119
+ return `Other: ${answer.label}`;
120
+ case "option":
121
+ return `${answer.index}. ${answer.label}`;
122
+ }
123
+ }
124
+
125
+ function buildStructuredResult(
126
+ status: AskUserQuestionStatus,
127
+ question: string,
128
+ mode: AskUserQuestionMode,
129
+ answers: AskAnswer[],
130
+ context?: string,
131
+ message?: string,
132
+ ): AskUserQuestionResultDetails {
133
+ return {
134
+ status,
135
+ question,
136
+ context,
137
+ mode,
138
+ answers,
139
+ message,
140
+ };
141
+ }
142
+
143
+ export function cancelledResult(question: string, mode: AskUserQuestionMode, context?: string) {
144
+ const isZh = isChineseContext(question, undefined, context);
145
+ const message = isZh ? "用户取消了本次提问" : "User cancelled the question.";
146
+ return {
147
+ content: [{ type: "text" as const, text: message }],
148
+ details: buildStructuredResult("cancelled", question, mode, [], context, message),
149
+ };
150
+ }
151
+
152
+ export function unavailableResult(question: string, mode: AskUserQuestionMode, message: string, context?: string) {
153
+ return {
154
+ content: [{ type: "text" as const, text: message }],
155
+ details: buildStructuredResult("unavailable", question, mode, [], context, message),
156
+ };
157
+ }
158
+
159
+ export function buildResult(
160
+ question: string,
161
+ context: string | undefined,
162
+ mode: AskUserQuestionMode,
163
+ answers: AskAnswer[],
164
+ ) {
165
+ const isZh = isChineseContext(question, answers, context);
166
+ let text: string;
167
+ if (mode === "text") {
168
+ const answer = answers[0];
169
+ if (isZh) {
170
+ text = answer.label.trim().length > 0
171
+ ? `用户输入回答: ${answer.label}`
172
+ : "用户提交了空回答";
173
+ } else {
174
+ text = answer.label.trim().length > 0
175
+ ? `User answered: ${answer.label}`
176
+ : "User submitted an empty answer";
177
+ }
178
+ } else if (mode === "single-select") {
179
+ text = isZh
180
+ ? `用户选择项: ${formatAnswerForModel(answers[0])}`
181
+ : `User selected: ${formatAnswerForModel(answers[0])}`;
182
+ } else {
183
+ text = isZh
184
+ ? `用户选择多项:\n${answers.map((answer) => `- ${formatAnswerForModel(answer)}`).join("\n")}`
185
+ : `User selected multiple:\n${answers.map((answer) => `- ${formatAnswerForModel(answer)}`).join("\n")}`;
186
+ }
187
+
188
+ return {
189
+ content: [{ type: "text" as const, text }],
190
+ details: buildStructuredResult("answered", question, mode, answers, context),
191
+ };
192
+ }