@vanillagreen/pi-qol 1.0.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.
- package/README.md +104 -0
- package/assets/context-usage.png +0 -0
- package/assets/session-search.png +0 -0
- package/assets/settings-panel.png +0 -0
- package/extensions/qol.ts +4460 -0
- package/package.json +835 -0
package/package.json
ADDED
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vanillagreen/pi-qol",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Pi quality-of-life extension: compact statusline/π prompt, reliable multiline input, styled pasted-image chips, session naming/search/context import, handoff, permission prompts, notifications, custom compaction, and a collapsed-thinking timer.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi",
|
|
9
|
+
"coding-agent",
|
|
10
|
+
"qol",
|
|
11
|
+
"editor"
|
|
12
|
+
],
|
|
13
|
+
"pi": {
|
|
14
|
+
"extensions": [
|
|
15
|
+
"./extensions/qol.ts"
|
|
16
|
+
],
|
|
17
|
+
"image": "https://raw.githubusercontent.com/vanillagreencom/vstack/main/pi-extensions/pi-qol/assets/settings-panel.png"
|
|
18
|
+
},
|
|
19
|
+
"vstack": {
|
|
20
|
+
"extensionManager": {
|
|
21
|
+
"displayName": "QOL",
|
|
22
|
+
"settings": [
|
|
23
|
+
{
|
|
24
|
+
"key": "enabled",
|
|
25
|
+
"label": "Enable QOL editor helpers",
|
|
26
|
+
"description": "Install the QOL editor component and /qol helper command. Disable and reload to leave Pi editor behavior unchanged.",
|
|
27
|
+
"type": "boolean",
|
|
28
|
+
"default": true,
|
|
29
|
+
"category": "General",
|
|
30
|
+
"apply": "reload",
|
|
31
|
+
"requiresReload": true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"key": "replaceFooter",
|
|
35
|
+
"label": "Replace built-in footer",
|
|
36
|
+
"description": "Hide Pi default footer while the compact QOL statusline is active.",
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"default": true,
|
|
39
|
+
"category": "Statusline",
|
|
40
|
+
"apply": "reload",
|
|
41
|
+
"requiresReload": true
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"key": "compactPrompt",
|
|
45
|
+
"label": "Use π prompt editor",
|
|
46
|
+
"description": "Replace the main editor with the compact π prompt editor. Disable to use QOL newline/image helpers with Pi default editor chrome.",
|
|
47
|
+
"type": "boolean",
|
|
48
|
+
"default": true,
|
|
49
|
+
"category": "Statusline",
|
|
50
|
+
"apply": "reload",
|
|
51
|
+
"requiresReload": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"key": "showSessionNameTitle",
|
|
55
|
+
"label": "Show session name title",
|
|
56
|
+
"description": "Show the named session above the prompt. In tmux, update the current pane title to \"π <session>\" and enable a pane border title padded with non-breaking spaces so tmux does not trim it.",
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"default": true,
|
|
59
|
+
"category": "Statusline",
|
|
60
|
+
"apply": "reload",
|
|
61
|
+
"requiresReload": true
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"key": "inputBottomPaddingLines",
|
|
65
|
+
"label": "Input bottom padding",
|
|
66
|
+
"description": "Blank lines below the compact prompt. Default is 0 for no extra space.",
|
|
67
|
+
"type": "number",
|
|
68
|
+
"default": 0,
|
|
69
|
+
"category": "Statusline",
|
|
70
|
+
"apply": "reload",
|
|
71
|
+
"requiresReload": true
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"key": "gitRefreshTimeoutMs",
|
|
75
|
+
"label": "Git refresh timeout",
|
|
76
|
+
"description": "Timeout for each git metadata command used by the statusline.",
|
|
77
|
+
"type": "number",
|
|
78
|
+
"default": 1500,
|
|
79
|
+
"category": "Statusline Git",
|
|
80
|
+
"apply": "live"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"key": "showDirtyMarker",
|
|
84
|
+
"label": "Show dirty marker",
|
|
85
|
+
"description": "Append * to the branch badge when the worktree is dirty.",
|
|
86
|
+
"type": "boolean",
|
|
87
|
+
"default": true,
|
|
88
|
+
"category": "Statusline Git",
|
|
89
|
+
"apply": "live"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"key": "permissionGate.enabled",
|
|
93
|
+
"label": "Prompt before risky bash commands",
|
|
94
|
+
"description": "Ask for confirmation before bash tool calls matching the configured command list. Off by default; enable explicitly if you want this extra prompt.",
|
|
95
|
+
"type": "boolean",
|
|
96
|
+
"default": false,
|
|
97
|
+
"category": "Permission Gate",
|
|
98
|
+
"apply": "live"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"key": "permissionGate.commands",
|
|
102
|
+
"label": "Commands to prompt for",
|
|
103
|
+
"description": "Comma-separated command fragments to confirm before running. Literal entries are case-insensitive and whitespace-tolerant; regex entries may use /pattern/flags. Default prompts only for rm -Rf.",
|
|
104
|
+
"type": "string",
|
|
105
|
+
"default": "rm -Rf",
|
|
106
|
+
"category": "Permission Gate",
|
|
107
|
+
"apply": "live"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"key": "permissionGate.previewLines",
|
|
111
|
+
"label": "Approval preview lines",
|
|
112
|
+
"description": "Maximum command lines rendered in the permission approval prompt. Longer commands show a head/tail preview with an omitted-line marker.",
|
|
113
|
+
"type": "number",
|
|
114
|
+
"default": 12,
|
|
115
|
+
"category": "Permission Gate",
|
|
116
|
+
"apply": "live"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"key": "permissionGate.previewChars",
|
|
120
|
+
"label": "Approval preview characters",
|
|
121
|
+
"description": "Maximum command preview characters rendered in the permission approval prompt to avoid flooding or flickering the terminal.",
|
|
122
|
+
"type": "number",
|
|
123
|
+
"default": 1200,
|
|
124
|
+
"category": "Permission Gate",
|
|
125
|
+
"apply": "live"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"key": "newlineOnShiftEnter",
|
|
129
|
+
"label": "Shift+Enter inserts newline",
|
|
130
|
+
"description": "Intercept distinguishable Shift+Enter/Shift+Return in the prompt editor and insert a newline instead of submitting.",
|
|
131
|
+
"type": "boolean",
|
|
132
|
+
"default": true,
|
|
133
|
+
"category": "Input",
|
|
134
|
+
"apply": "reload",
|
|
135
|
+
"requiresReload": true
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"key": "newlineFallbackKey",
|
|
139
|
+
"label": "Fallback newline key",
|
|
140
|
+
"description": "Alternate newline key for terminals that cannot distinguish Shift+Enter. Alt+Enter is reserved for Pi follow-up messages.",
|
|
141
|
+
"type": "enum",
|
|
142
|
+
"enumValues": [
|
|
143
|
+
"ctrl+j",
|
|
144
|
+
"none"
|
|
145
|
+
],
|
|
146
|
+
"default": "ctrl+j",
|
|
147
|
+
"category": "Input",
|
|
148
|
+
"apply": "reload",
|
|
149
|
+
"requiresReload": true
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"key": "pendingQueue.asciiGreen",
|
|
153
|
+
"label": "Green pending queue preview",
|
|
154
|
+
"description": "Render Pi's built-in steering/follow-up queue preview and Alt+Up hint in ANSI green with a left | queue bar instead of the dim hint color.",
|
|
155
|
+
"type": "boolean",
|
|
156
|
+
"default": true,
|
|
157
|
+
"category": "Input",
|
|
158
|
+
"apply": "live"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"key": "showImageChips",
|
|
162
|
+
"label": "Style image chips",
|
|
163
|
+
"description": "Render [Image #N] placeholders and existing pasted image paths in the editor as visually distinct chips. Pi still owns attachment state.",
|
|
164
|
+
"type": "boolean",
|
|
165
|
+
"default": true,
|
|
166
|
+
"category": "Images",
|
|
167
|
+
"apply": "live"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"key": "showAttachmentCountInStatus",
|
|
171
|
+
"label": "Show attachment count",
|
|
172
|
+
"description": "Show a lightweight status badge when the draft contains image placeholders.",
|
|
173
|
+
"type": "boolean",
|
|
174
|
+
"default": true,
|
|
175
|
+
"category": "Images",
|
|
176
|
+
"apply": "live"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"key": "enableSessionNameCommand",
|
|
180
|
+
"label": "Enable /rename command",
|
|
181
|
+
"description": "Register the /rename command for setting or viewing the current session's friendly name in Pi's session selector.",
|
|
182
|
+
"type": "boolean",
|
|
183
|
+
"default": true,
|
|
184
|
+
"category": "Session",
|
|
185
|
+
"apply": "reload",
|
|
186
|
+
"requiresReload": true
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"key": "sessionAutoRename.enabled",
|
|
190
|
+
"label": "Auto-name new sessions",
|
|
191
|
+
"description": "Automatically generate a friendly session name from the first user prompt when the session does not already have a name.",
|
|
192
|
+
"type": "boolean",
|
|
193
|
+
"default": true,
|
|
194
|
+
"category": "Session Auto-Rename",
|
|
195
|
+
"apply": "live"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"key": "sessionAutoRename.model",
|
|
199
|
+
"label": "Auto-rename model",
|
|
200
|
+
"description": "Model used for title generation. Use provider/model, current, or cheapest. Default is a fast OpenAI Codex model that supports ChatGPT OAuth via /login openai-codex.",
|
|
201
|
+
"type": "string",
|
|
202
|
+
"default": "openai-codex/gpt-5.4-mini",
|
|
203
|
+
"category": "Session Auto-Rename",
|
|
204
|
+
"apply": "live"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"key": "sessionAutoRename.fallbackModel",
|
|
208
|
+
"label": "Auto-rename fallback model",
|
|
209
|
+
"description": "Model to try if the primary model is unavailable. Use current, provider/model, cheapest, none, or off.",
|
|
210
|
+
"type": "string",
|
|
211
|
+
"default": "current",
|
|
212
|
+
"category": "Session Auto-Rename",
|
|
213
|
+
"apply": "live"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"key": "sessionAutoRename.fallback",
|
|
217
|
+
"label": "Deterministic fallback",
|
|
218
|
+
"description": "Fallback naming strategy if all model calls fail: title-case words from the first prompt, a truncated prompt, or none.",
|
|
219
|
+
"type": "enum",
|
|
220
|
+
"enumValues": [
|
|
221
|
+
"words",
|
|
222
|
+
"truncate",
|
|
223
|
+
"none"
|
|
224
|
+
],
|
|
225
|
+
"default": "words",
|
|
226
|
+
"category": "Session Auto-Rename",
|
|
227
|
+
"apply": "live"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"key": "sessionAutoRename.prefix",
|
|
231
|
+
"label": "Auto-rename prefix",
|
|
232
|
+
"description": "Optional static prefix added before generated names, e.g. a project label. Leave empty for no prefix.",
|
|
233
|
+
"type": "string",
|
|
234
|
+
"default": "",
|
|
235
|
+
"category": "Session Auto-Rename",
|
|
236
|
+
"apply": "live"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"key": "sessionAutoRename.maxInputChars",
|
|
240
|
+
"label": "Auto-rename input cap",
|
|
241
|
+
"description": "Maximum first-prompt characters sent to the naming model. Long prompts keep the beginning and end.",
|
|
242
|
+
"type": "number",
|
|
243
|
+
"default": 2000,
|
|
244
|
+
"category": "Session Auto-Rename",
|
|
245
|
+
"apply": "live"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"key": "sessionAutoRename.maxNameChars",
|
|
249
|
+
"label": "Auto-rename title length",
|
|
250
|
+
"description": "Maximum characters for generated session names, including any prefix.",
|
|
251
|
+
"type": "number",
|
|
252
|
+
"default": 80,
|
|
253
|
+
"category": "Session Auto-Rename",
|
|
254
|
+
"apply": "live"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"key": "sessionAutoRename.maxTokens",
|
|
258
|
+
"label": "Auto-rename output tokens",
|
|
259
|
+
"description": "Maximum output tokens requested from the naming model.",
|
|
260
|
+
"type": "number",
|
|
261
|
+
"default": 96,
|
|
262
|
+
"category": "Session Auto-Rename",
|
|
263
|
+
"apply": "live"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"key": "sessionAutoRename.timeoutMs",
|
|
267
|
+
"label": "Auto-rename timeout",
|
|
268
|
+
"description": "Per-model timeout in milliseconds before falling back to the next model or deterministic title.",
|
|
269
|
+
"type": "number",
|
|
270
|
+
"default": 12000,
|
|
271
|
+
"category": "Session Auto-Rename",
|
|
272
|
+
"apply": "live"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"key": "sessionAutoRename.prompt",
|
|
276
|
+
"label": "Auto-rename prompt override",
|
|
277
|
+
"description": "Optional prompt template. Use {{message}} for the first user prompt; when empty, QOL uses its built-in concise title prompt.",
|
|
278
|
+
"type": "string",
|
|
279
|
+
"default": "",
|
|
280
|
+
"category": "Session Auto-Rename Advanced",
|
|
281
|
+
"apply": "live"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"key": "sessionAutoRename.notify",
|
|
285
|
+
"label": "Notify on auto-rename",
|
|
286
|
+
"description": "Show a Pi UI notification when QOL auto-generates a session name. Manual /qol rename always notifies.",
|
|
287
|
+
"type": "boolean",
|
|
288
|
+
"default": false,
|
|
289
|
+
"category": "Session Auto-Rename Advanced",
|
|
290
|
+
"apply": "live"
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"key": "sessionAutoRename.debug",
|
|
294
|
+
"label": "Debug auto-rename",
|
|
295
|
+
"description": "Show model/auth/fallback diagnostics for automatic session naming.",
|
|
296
|
+
"type": "boolean",
|
|
297
|
+
"default": false,
|
|
298
|
+
"category": "Session Auto-Rename Advanced",
|
|
299
|
+
"apply": "live"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"key": "enableHandoffCommand",
|
|
303
|
+
"label": "Enable /handoff command",
|
|
304
|
+
"description": "Register the handoff command to generate a focused prompt and create a new session with the prompt as a draft.",
|
|
305
|
+
"type": "boolean",
|
|
306
|
+
"default": true,
|
|
307
|
+
"category": "Session",
|
|
308
|
+
"apply": "reload",
|
|
309
|
+
"requiresReload": true
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"key": "handoffReviewPrompt",
|
|
313
|
+
"label": "Review handoff prompt",
|
|
314
|
+
"description": "Open an editor to review or edit the generated handoff prompt before creating the new session.",
|
|
315
|
+
"type": "boolean",
|
|
316
|
+
"default": true,
|
|
317
|
+
"category": "Session",
|
|
318
|
+
"apply": "live"
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"key": "enableContextCommand",
|
|
322
|
+
"label": "Enable /context command",
|
|
323
|
+
"description": "Register the /context command to show inline context-window usage with estimated Pi/model category breakdowns.",
|
|
324
|
+
"type": "boolean",
|
|
325
|
+
"default": true,
|
|
326
|
+
"category": "Context",
|
|
327
|
+
"apply": "reload",
|
|
328
|
+
"requiresReload": true
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"key": "sessionSearch.enabled",
|
|
332
|
+
"label": "Enable session search",
|
|
333
|
+
"description": "Register the previous-session search palette, preview, resume, and context-import actions.",
|
|
334
|
+
"type": "boolean",
|
|
335
|
+
"default": true,
|
|
336
|
+
"category": "Session Search",
|
|
337
|
+
"apply": "reload",
|
|
338
|
+
"requiresReload": true
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"key": "sessionSearch.shortcutKey",
|
|
342
|
+
"label": "Session search shortcut",
|
|
343
|
+
"description": "Keyboard shortcut to open the session search overlay. Default f3 avoids Pi's built-in Ctrl+F and Alt+F editor bindings. Set to none to disable.",
|
|
344
|
+
"type": "string",
|
|
345
|
+
"default": "f3",
|
|
346
|
+
"category": "Session Search",
|
|
347
|
+
"apply": "reload",
|
|
348
|
+
"requiresReload": true
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
"key": "sessionSearch.sortMode",
|
|
352
|
+
"label": "Session search sort mode",
|
|
353
|
+
"description": "Sort matches by relevance score or by most recent session modification time.",
|
|
354
|
+
"type": "enum",
|
|
355
|
+
"enumValues": [
|
|
356
|
+
"relevance",
|
|
357
|
+
"recent"
|
|
358
|
+
],
|
|
359
|
+
"default": "relevance",
|
|
360
|
+
"category": "Session Search",
|
|
361
|
+
"apply": "live"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"key": "sessionSearch.resultLimit",
|
|
365
|
+
"label": "Session search result limit",
|
|
366
|
+
"description": "Maximum number of matching sessions returned by the search palette.",
|
|
367
|
+
"type": "number",
|
|
368
|
+
"default": 40,
|
|
369
|
+
"category": "Session Search",
|
|
370
|
+
"apply": "live"
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"key": "sessionSearch.maxVisible",
|
|
374
|
+
"label": "Visible session rows",
|
|
375
|
+
"description": "Maximum number of sessions shown at once in the overlay before scrolling.",
|
|
376
|
+
"type": "number",
|
|
377
|
+
"default": 10,
|
|
378
|
+
"category": "Session Search",
|
|
379
|
+
"apply": "live"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"key": "sessionSearch.previewSnippets",
|
|
383
|
+
"label": "Preview snippets",
|
|
384
|
+
"description": "Maximum matching snippets shown on the selected session preview screen.",
|
|
385
|
+
"type": "number",
|
|
386
|
+
"default": 6,
|
|
387
|
+
"category": "Session Search",
|
|
388
|
+
"apply": "live"
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
"key": "sessionSearch.overlayWidth",
|
|
392
|
+
"label": "Overlay width",
|
|
393
|
+
"description": "Preferred session search overlay width in terminal columns.",
|
|
394
|
+
"type": "number",
|
|
395
|
+
"default": 104,
|
|
396
|
+
"category": "Session Search",
|
|
397
|
+
"apply": "live"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
"key": "sessionSearch.messageMaxVisible",
|
|
401
|
+
"label": "Visible user prompt rows",
|
|
402
|
+
"description": "Maximum number of one-line user prompts shown at once in the session prompt browser before scrolling.",
|
|
403
|
+
"type": "number",
|
|
404
|
+
"default": 12,
|
|
405
|
+
"category": "Session Search",
|
|
406
|
+
"apply": "live"
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"key": "sessionSearch.cacheTtlSeconds",
|
|
410
|
+
"label": "Session cache TTL",
|
|
411
|
+
"description": "Seconds before the in-memory session list is refreshed. Default 0 keeps the cache until you explicitly run /search refresh.",
|
|
412
|
+
"type": "number",
|
|
413
|
+
"default": 0,
|
|
414
|
+
"category": "Session Search",
|
|
415
|
+
"apply": "live"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"key": "sessionSearch.summaryModel",
|
|
419
|
+
"label": "Session summary model",
|
|
420
|
+
"description": "Model used to summarize an imported previous session. Use current, provider/model, or a bare model id. Defaults to current so no extra provider setup is required.",
|
|
421
|
+
"type": "string",
|
|
422
|
+
"default": "current",
|
|
423
|
+
"category": "Session Search Summary",
|
|
424
|
+
"apply": "live"
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
"key": "sessionSearch.summaryMaxTokens",
|
|
428
|
+
"label": "Session summary max output tokens",
|
|
429
|
+
"description": "Maximum tokens requested from the session-search summarizer.",
|
|
430
|
+
"type": "number",
|
|
431
|
+
"default": 4096,
|
|
432
|
+
"category": "Session Search Summary",
|
|
433
|
+
"apply": "live"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"key": "sessionSearch.summaryInputMaxChars",
|
|
437
|
+
"label": "Summary input character cap",
|
|
438
|
+
"description": "Maximum previous-session transcript characters sent to the summarizer; long sessions keep the beginning and end.",
|
|
439
|
+
"type": "number",
|
|
440
|
+
"default": 180000,
|
|
441
|
+
"category": "Session Search Summary",
|
|
442
|
+
"apply": "live"
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
"key": "notification.enabled",
|
|
446
|
+
"label": "Enable notifications",
|
|
447
|
+
"description": "Send terminal/tmux notifications for ready/input-needed, questions, completed task lists, and critical information.",
|
|
448
|
+
"type": "boolean",
|
|
449
|
+
"default": true,
|
|
450
|
+
"category": "Notifications",
|
|
451
|
+
"apply": "live"
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"key": "notification.onAgentReady",
|
|
455
|
+
"label": "Notify when ready",
|
|
456
|
+
"description": "Notify when an agent turn finishes and Pi is ready for input.",
|
|
457
|
+
"type": "boolean",
|
|
458
|
+
"default": true,
|
|
459
|
+
"category": "Notifications Triggers",
|
|
460
|
+
"apply": "live"
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
"key": "notification.onDirectionNeeded",
|
|
464
|
+
"label": "Notify when direction needed",
|
|
465
|
+
"description": "Use stronger notification wording when the last assistant message appears to ask for direction, confirmation, or a choice.",
|
|
466
|
+
"type": "boolean",
|
|
467
|
+
"default": true,
|
|
468
|
+
"category": "Notifications Triggers",
|
|
469
|
+
"apply": "live"
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"key": "notification.onQuestion",
|
|
473
|
+
"label": "Notify for question popups",
|
|
474
|
+
"description": "Notify when pi-questions opens a structured question that requires user input.",
|
|
475
|
+
"type": "boolean",
|
|
476
|
+
"default": true,
|
|
477
|
+
"category": "Notifications Triggers",
|
|
478
|
+
"apply": "live"
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"key": "notification.onTaskComplete",
|
|
482
|
+
"label": "Notify when all tasks complete",
|
|
483
|
+
"description": "Notify after the agent turn ends when tasks_write completes the task panel.",
|
|
484
|
+
"type": "boolean",
|
|
485
|
+
"default": true,
|
|
486
|
+
"category": "Notifications Triggers",
|
|
487
|
+
"apply": "live"
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"key": "notification.onCritical",
|
|
491
|
+
"label": "Notify critical info",
|
|
492
|
+
"description": "Notify for assistant messages containing critical, blocked, security, rate-limit, or cannot-proceed signals. Tool failures are intentionally ignored.",
|
|
493
|
+
"type": "boolean",
|
|
494
|
+
"default": true,
|
|
495
|
+
"category": "Notifications Triggers",
|
|
496
|
+
"apply": "live"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"key": "notification.bell",
|
|
500
|
+
"label": "Terminal bell",
|
|
501
|
+
"description": "Emit BEL (\\u0007) for standard terminal/tmux audible or visual bell behavior.",
|
|
502
|
+
"type": "boolean",
|
|
503
|
+
"default": true,
|
|
504
|
+
"category": "Notifications Channels",
|
|
505
|
+
"apply": "live"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"key": "notification.bellWhenActive",
|
|
509
|
+
"label": "Bell when tmux window active",
|
|
510
|
+
"description": "Also emit BEL when the source tmux window is already active. Disabled by default to avoid noisy bells while you are looking at the Pi window; native terminal notifications still run so Ghostty can decide based on app focus.",
|
|
511
|
+
"type": "boolean",
|
|
512
|
+
"default": false,
|
|
513
|
+
"category": "Notifications Channels",
|
|
514
|
+
"apply": "live"
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"key": "notification.native",
|
|
518
|
+
"label": "Native terminal notification",
|
|
519
|
+
"description": "Send OSC 777/OSC 99 terminal notifications, or Windows toast in Windows Terminal/WSL.",
|
|
520
|
+
"type": "boolean",
|
|
521
|
+
"default": true,
|
|
522
|
+
"category": "Notifications Channels",
|
|
523
|
+
"apply": "live"
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"key": "notification.tmux",
|
|
527
|
+
"label": "tmux display-message",
|
|
528
|
+
"description": "When running inside tmux, also show a transient tmux status-line message. Disabled by default because tmux displays it on the active client, not necessarily as a source-window mark.",
|
|
529
|
+
"type": "boolean",
|
|
530
|
+
"default": false,
|
|
531
|
+
"category": "Notifications Channels",
|
|
532
|
+
"apply": "live"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
"key": "notification.tmuxWindowMark",
|
|
536
|
+
"label": "Mark tmux window",
|
|
537
|
+
"description": "Optionally prefix the source tmux window name when notifying. Disabled by default because BEL should let tmux apply your normal bell styling.",
|
|
538
|
+
"type": "boolean",
|
|
539
|
+
"default": false,
|
|
540
|
+
"category": "Notifications Channels",
|
|
541
|
+
"apply": "live"
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
"key": "notification.tmuxWindowMarkText",
|
|
545
|
+
"label": "tmux window mark text",
|
|
546
|
+
"description": "Prefix used when marking the source tmux window.",
|
|
547
|
+
"type": "string",
|
|
548
|
+
"default": "!",
|
|
549
|
+
"category": "Notifications Tuning",
|
|
550
|
+
"apply": "live"
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
"key": "notification.tmuxWindowMarkDurationMs",
|
|
554
|
+
"label": "tmux window mark duration",
|
|
555
|
+
"description": "Milliseconds before automatically clearing the tmux window mark. 0 keeps it until next input/agent start/reset.",
|
|
556
|
+
"type": "number",
|
|
557
|
+
"default": 0,
|
|
558
|
+
"category": "Notifications Tuning",
|
|
559
|
+
"apply": "live"
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"key": "notification.tmuxNativeClientTty",
|
|
563
|
+
"label": "tmux native via client TTY",
|
|
564
|
+
"description": "When inside tmux, send OSC terminal notifications directly to attached tmux client TTYs so Ghostty/system notifications still appear for inactive source windows.",
|
|
565
|
+
"type": "boolean",
|
|
566
|
+
"default": true,
|
|
567
|
+
"category": "Notifications Channels",
|
|
568
|
+
"apply": "live"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"key": "notification.tmuxPassthrough",
|
|
572
|
+
"label": "tmux OSC passthrough",
|
|
573
|
+
"description": "Wrap OSC terminal notifications in tmux passthrough sequences so supported terminals outside tmux can receive them.",
|
|
574
|
+
"type": "boolean",
|
|
575
|
+
"default": true,
|
|
576
|
+
"category": "Notifications Channels",
|
|
577
|
+
"apply": "live"
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
"key": "notification.piUi",
|
|
581
|
+
"label": "Also show Pi UI notice",
|
|
582
|
+
"description": "Also call ctx.ui.notify for QOL external notifications. Disabled by default to avoid duplicate in-session noise.",
|
|
583
|
+
"type": "boolean",
|
|
584
|
+
"default": false,
|
|
585
|
+
"category": "Notifications Channels",
|
|
586
|
+
"apply": "live"
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
"key": "notification.oscProtocol",
|
|
590
|
+
"label": "Terminal notification protocol",
|
|
591
|
+
"description": "OSC notification protocol. auto uses Kitty OSC 99 when KITTY_WINDOW_ID is present, otherwise OSC 777.",
|
|
592
|
+
"type": "enum",
|
|
593
|
+
"enumValues": [
|
|
594
|
+
"auto",
|
|
595
|
+
"osc777",
|
|
596
|
+
"osc99",
|
|
597
|
+
"off"
|
|
598
|
+
],
|
|
599
|
+
"default": "auto",
|
|
600
|
+
"category": "Notifications Channels",
|
|
601
|
+
"apply": "live"
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"key": "notification.cooldownSeconds",
|
|
605
|
+
"label": "Notification cooldown",
|
|
606
|
+
"description": "Minimum seconds between duplicate notifications of the same kind.",
|
|
607
|
+
"type": "number",
|
|
608
|
+
"default": 8,
|
|
609
|
+
"category": "Notifications Tuning",
|
|
610
|
+
"apply": "live"
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
"key": "notification.title",
|
|
614
|
+
"label": "Notification title",
|
|
615
|
+
"description": "Title used for external terminal notifications.",
|
|
616
|
+
"type": "string",
|
|
617
|
+
"default": "Pi",
|
|
618
|
+
"category": "Notifications Tuning",
|
|
619
|
+
"apply": "live"
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
"key": "notification.readyMessage",
|
|
623
|
+
"label": "Ready message",
|
|
624
|
+
"description": "Body text for normal agent-done notifications.",
|
|
625
|
+
"type": "string",
|
|
626
|
+
"default": "Ready for input",
|
|
627
|
+
"category": "Notifications Tuning",
|
|
628
|
+
"apply": "live"
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
"key": "notification.bodyMaxChars",
|
|
632
|
+
"label": "Notification body length",
|
|
633
|
+
"description": "Maximum body characters for external notifications.",
|
|
634
|
+
"type": "number",
|
|
635
|
+
"default": 240,
|
|
636
|
+
"category": "Notifications Tuning",
|
|
637
|
+
"apply": "live"
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
"key": "notification.tmuxMessageDurationMs",
|
|
641
|
+
"label": "tmux message duration",
|
|
642
|
+
"description": "Milliseconds to display tmux status-line notification messages.",
|
|
643
|
+
"type": "number",
|
|
644
|
+
"default": 5000,
|
|
645
|
+
"category": "Notifications Tuning",
|
|
646
|
+
"apply": "live"
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
"key": "compaction.customEnabled",
|
|
650
|
+
"label": "Custom compaction summaries",
|
|
651
|
+
"description": "Use QOL's custom compaction hook instead of Pi's default summary generation. Manual/auto compaction still uses Pi's normal trigger settings.",
|
|
652
|
+
"type": "boolean",
|
|
653
|
+
"default": false,
|
|
654
|
+
"category": "Compaction",
|
|
655
|
+
"apply": "live"
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
"key": "compaction.model",
|
|
659
|
+
"label": "Compaction model",
|
|
660
|
+
"description": "Summarizer model as provider/model, a bare model id, or current. Default mirrors Pi's custom-compaction example.",
|
|
661
|
+
"type": "string",
|
|
662
|
+
"default": "google/gemini-2.5-flash",
|
|
663
|
+
"category": "Compaction",
|
|
664
|
+
"apply": "live"
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
"key": "compaction.profile",
|
|
668
|
+
"label": "Compaction detail profile",
|
|
669
|
+
"description": "Summary detail level for custom compaction and branch summaries.",
|
|
670
|
+
"type": "enum",
|
|
671
|
+
"enumValues": [
|
|
672
|
+
"concise",
|
|
673
|
+
"balanced",
|
|
674
|
+
"exhaustive"
|
|
675
|
+
],
|
|
676
|
+
"default": "balanced",
|
|
677
|
+
"category": "Compaction",
|
|
678
|
+
"apply": "live"
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
"key": "compaction.maxTokens",
|
|
682
|
+
"label": "Compaction max output tokens",
|
|
683
|
+
"description": "Maximum tokens requested from the custom compaction summarizer.",
|
|
684
|
+
"type": "number",
|
|
685
|
+
"default": 8192,
|
|
686
|
+
"category": "Compaction",
|
|
687
|
+
"apply": "live"
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"key": "compaction.includePreviousSummary",
|
|
691
|
+
"label": "Include previous summary",
|
|
692
|
+
"description": "Pass the previous compaction summary to the custom summarizer for iterative continuity.",
|
|
693
|
+
"type": "boolean",
|
|
694
|
+
"default": true,
|
|
695
|
+
"category": "Compaction",
|
|
696
|
+
"apply": "live"
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
"key": "compaction.fallbackToDefault",
|
|
700
|
+
"label": "Fallback to Pi default compaction",
|
|
701
|
+
"description": "If custom compaction fails, let Pi run its default compaction instead of cancelling the compaction.",
|
|
702
|
+
"type": "boolean",
|
|
703
|
+
"default": true,
|
|
704
|
+
"category": "Compaction",
|
|
705
|
+
"apply": "live"
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
"key": "compaction.notify",
|
|
709
|
+
"label": "Show compaction notifications",
|
|
710
|
+
"description": "Show QOL notifications when custom, remote, branch, or idle compaction starts/fails/completes.",
|
|
711
|
+
"type": "boolean",
|
|
712
|
+
"default": true,
|
|
713
|
+
"category": "Compaction",
|
|
714
|
+
"apply": "live"
|
|
715
|
+
},
|
|
716
|
+
{
|
|
717
|
+
"key": "compaction.remoteEnabled",
|
|
718
|
+
"label": "Remote compaction endpoint",
|
|
719
|
+
"description": "Use a remote HTTP summarization endpoint before falling back to the configured model. Endpoint receives { systemPrompt, prompt, maxTokens } and returns { summary }.",
|
|
720
|
+
"type": "boolean",
|
|
721
|
+
"default": false,
|
|
722
|
+
"category": "Compaction Remote",
|
|
723
|
+
"apply": "live"
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
"key": "compaction.remoteEndpoint",
|
|
727
|
+
"label": "Remote endpoint URL",
|
|
728
|
+
"description": "HTTP endpoint for remote compaction summaries. Leave empty to use the configured compaction model.",
|
|
729
|
+
"type": "string",
|
|
730
|
+
"default": "",
|
|
731
|
+
"category": "Compaction Remote",
|
|
732
|
+
"apply": "live"
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
"key": "compaction.branchSummaryEnabled",
|
|
736
|
+
"label": "Custom branch summaries",
|
|
737
|
+
"description": "When /tree navigation requests a branch summary, generate it through QOL's custom summarizer.",
|
|
738
|
+
"type": "boolean",
|
|
739
|
+
"default": false,
|
|
740
|
+
"category": "Compaction Branching",
|
|
741
|
+
"apply": "live"
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
"key": "compaction.idleEnabled",
|
|
745
|
+
"label": "Idle compaction trigger",
|
|
746
|
+
"description": "Trigger Pi compaction after the session sits idle above the configured token threshold. Inspired by oh-my-pi idle compaction.",
|
|
747
|
+
"type": "boolean",
|
|
748
|
+
"default": false,
|
|
749
|
+
"category": "Compaction Idle",
|
|
750
|
+
"apply": "live"
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
"key": "compaction.idleThresholdTokens",
|
|
754
|
+
"label": "Idle token threshold",
|
|
755
|
+
"description": "Token count above which QOL idle compaction can trigger when thresholdTokens and thresholdPercent are unset.",
|
|
756
|
+
"type": "number",
|
|
757
|
+
"default": 200000,
|
|
758
|
+
"category": "Compaction Idle",
|
|
759
|
+
"apply": "live"
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
"key": "compaction.idleTimeoutSeconds",
|
|
763
|
+
"label": "Idle compaction delay",
|
|
764
|
+
"description": "Seconds to wait idle before triggering QOL idle compaction.",
|
|
765
|
+
"type": "number",
|
|
766
|
+
"default": 300,
|
|
767
|
+
"category": "Compaction Idle",
|
|
768
|
+
"apply": "live"
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"key": "compaction.thresholdTokens",
|
|
772
|
+
"label": "QOL compaction token limit",
|
|
773
|
+
"description": "Optional fixed token limit for QOL idle compaction. Set -1 to use percentage or idle token threshold.",
|
|
774
|
+
"type": "number",
|
|
775
|
+
"default": -1,
|
|
776
|
+
"category": "Compaction Threshold",
|
|
777
|
+
"apply": "live"
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
"key": "compaction.thresholdPercent",
|
|
781
|
+
"label": "QOL compaction percent limit",
|
|
782
|
+
"description": "Optional context-window percentage for QOL idle compaction. Set -1 to use idle token threshold.",
|
|
783
|
+
"type": "number",
|
|
784
|
+
"default": -1,
|
|
785
|
+
"category": "Compaction Threshold",
|
|
786
|
+
"apply": "live"
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
"key": "thinkingLabel.text",
|
|
790
|
+
"label": "Hidden thinking label",
|
|
791
|
+
"description": "Label shown when thinking blocks are hidden. Defaults to a Nerd Font brain icon.",
|
|
792
|
+
"type": "string",
|
|
793
|
+
"default": " ",
|
|
794
|
+
"category": "Thinking",
|
|
795
|
+
"apply": "reload",
|
|
796
|
+
"requiresReload": true
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
"key": "thinkingTimer.enabled",
|
|
800
|
+
"label": "Show thinking timer",
|
|
801
|
+
"description": "Show live elapsed time next to collapsed hidden-thinking labels and leave the final duration after thinking ends. Uses a defensive internal renderer patch and fails back to Pi's default label if Pi internals change.",
|
|
802
|
+
"type": "boolean",
|
|
803
|
+
"default": true,
|
|
804
|
+
"category": "Thinking",
|
|
805
|
+
"apply": "live"
|
|
806
|
+
}
|
|
807
|
+
]
|
|
808
|
+
}
|
|
809
|
+
},
|
|
810
|
+
"peerDependencies": {
|
|
811
|
+
"@mariozechner/pi-agent-core": "*",
|
|
812
|
+
"@mariozechner/pi-ai": "*",
|
|
813
|
+
"@mariozechner/pi-coding-agent": "*",
|
|
814
|
+
"@mariozechner/pi-tui": "*"
|
|
815
|
+
},
|
|
816
|
+
"files": [
|
|
817
|
+
"extensions/",
|
|
818
|
+
"assets/",
|
|
819
|
+
"README.md",
|
|
820
|
+
"package.json"
|
|
821
|
+
],
|
|
822
|
+
"repository": {
|
|
823
|
+
"type": "git",
|
|
824
|
+
"url": "git+https://github.com/vanillagreencom/vstack.git",
|
|
825
|
+
"directory": "pi-extensions/pi-qol"
|
|
826
|
+
},
|
|
827
|
+
"homepage": "https://github.com/vanillagreencom/vstack/tree/main/pi-extensions/pi-qol",
|
|
828
|
+
"bugs": {
|
|
829
|
+
"url": "https://github.com/vanillagreencom/vstack/issues"
|
|
830
|
+
},
|
|
831
|
+
"author": "vanillagreen",
|
|
832
|
+
"publishConfig": {
|
|
833
|
+
"access": "public"
|
|
834
|
+
}
|
|
835
|
+
}
|