pi-ui-extend 1.0.41 → 1.0.45
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 +50 -13
- package/dist/app/app.d.ts +13 -0
- package/dist/app/app.js +158 -8
- package/dist/app/cli/install.js +2 -2
- package/dist/app/commands/command-controller.d.ts +4 -0
- package/dist/app/commands/command-controller.js +11 -0
- package/dist/app/commands/command-git-actions.d.ts +25 -0
- package/dist/app/commands/command-git-actions.js +381 -0
- package/dist/app/commands/command-host.d.ts +4 -0
- package/dist/app/commands/command-host.js +5 -2
- package/dist/app/commands/command-model-actions.d.ts +1 -0
- package/dist/app/commands/command-model-actions.js +57 -35
- package/dist/app/commands/command-navigation-actions.d.ts +1 -0
- package/dist/app/commands/command-navigation-actions.js +16 -3
- package/dist/app/commands/command-registry.d.ts +2 -0
- package/dist/app/commands/command-registry.js +15 -1
- package/dist/app/commands/command-session-actions.js +9 -3
- package/dist/app/commands/reload-context-inventory.d.ts +11 -0
- package/dist/app/commands/reload-context-inventory.js +70 -0
- package/dist/app/extensions/extension-actions-controller.d.ts +1 -0
- package/dist/app/extensions/extension-actions-controller.js +6 -0
- package/dist/app/extensions/subagent-catalog-state.d.ts +9 -0
- package/dist/app/extensions/subagent-catalog-state.js +23 -0
- package/dist/app/input/autocomplete-controller.js +61 -34
- package/dist/app/input/input-action-controller.d.ts +2 -0
- package/dist/app/input/input-action-controller.js +8 -1
- package/dist/app/input/input-controller.d.ts +2 -1
- package/dist/app/input/input-controller.js +7 -2
- package/dist/app/input/prompt-enhancer-controller.js +53 -35
- package/dist/app/input/voice-controller.d.ts +41 -45
- package/dist/app/input/voice-controller.js +351 -419
- package/dist/app/model/model-usage-controller.js +17 -7
- package/dist/app/model/model-usage-status.d.ts +4 -1
- package/dist/app/model/model-usage-status.js +270 -46
- package/dist/app/popup/menu-items-controller.d.ts +13 -3
- package/dist/app/popup/menu-items-controller.js +37 -21
- package/dist/app/popup/popup-action-controller.d.ts +12 -2
- package/dist/app/popup/popup-action-controller.js +77 -24
- package/dist/app/popup/popup-menu-controller.d.ts +36 -14
- package/dist/app/popup/popup-menu-controller.js +239 -69
- package/dist/app/rendering/dcp-stats.d.ts +9 -4
- package/dist/app/rendering/dcp-stats.js +40 -425
- package/dist/app/rendering/editor-panels.js +10 -4
- package/dist/app/rendering/popup-menu-renderer.d.ts +3 -5
- package/dist/app/rendering/popup-menu-renderer.js +42 -37
- package/dist/app/rendering/render-controller.js +23 -2
- package/dist/app/rendering/status-line-renderer.d.ts +5 -0
- package/dist/app/rendering/status-line-renderer.js +41 -5
- package/dist/app/rendering/tab-line-renderer.js +26 -20
- package/dist/app/runtime.d.ts +12 -1
- package/dist/app/runtime.js +120 -12
- package/dist/app/screen/mouse-controller.d.ts +2 -0
- package/dist/app/screen/mouse-controller.js +17 -7
- package/dist/app/screen/status-controller.d.ts +4 -0
- package/dist/app/screen/status-controller.js +5 -0
- package/dist/app/session/lazy-session-manager.js +34 -0
- package/dist/app/session/session-event-controller.d.ts +1 -0
- package/dist/app/session/session-event-controller.js +10 -1
- package/dist/app/session/session-history.d.ts +1 -0
- package/dist/app/session/session-history.js +12 -1
- package/dist/app/session/session-lifecycle-controller.d.ts +7 -1
- package/dist/app/session/session-lifecycle-controller.js +16 -1
- package/dist/app/session/tabs-controller.d.ts +26 -1
- package/dist/app/session/tabs-controller.js +454 -147
- package/dist/app/subagents/subagents-files.js +60 -1
- package/dist/app/subagents/subagents-model.d.ts +1 -0
- package/dist/app/subagents/subagents-model.js +18 -2
- package/dist/app/subagents/subagents-widget-controller.d.ts +1 -0
- package/dist/app/subagents/subagents-widget-controller.js +6 -0
- package/dist/app/types.d.ts +16 -1
- package/dist/app/workspace/workspace-actions-controller.js +10 -2
- package/dist/app/workspace/workspace-undo.d.ts +1 -0
- package/dist/app/workspace/workspace-undo.js +1 -0
- package/dist/bundled-extensions/question/index.js +9 -1
- package/dist/bundled-extensions/question/remote.d.ts +4 -0
- package/dist/bundled-extensions/question/remote.js +33 -0
- package/dist/bundled-extensions/telegram-connector/bot.d.ts +43 -0
- package/dist/bundled-extensions/telegram-connector/bot.js +166 -0
- package/dist/bundled-extensions/telegram-connector/config.d.ts +8 -0
- package/dist/bundled-extensions/telegram-connector/config.js +87 -0
- package/dist/bundled-extensions/telegram-connector/coordinator.d.ts +66 -0
- package/dist/bundled-extensions/telegram-connector/coordinator.js +413 -0
- package/dist/bundled-extensions/telegram-connector/index.d.ts +3 -0
- package/dist/bundled-extensions/telegram-connector/index.js +195 -0
- package/dist/bundled-extensions/terminal-bell/index.d.ts +0 -8
- package/dist/bundled-extensions/terminal-bell/index.js +0 -76
- package/dist/bundled-extensions/workspace-undo/index.d.ts +26 -0
- package/dist/bundled-extensions/workspace-undo/index.js +191 -0
- package/dist/config.d.ts +21 -2
- package/dist/config.js +159 -32
- package/dist/default-pix-config.js +25 -5
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/pi-tools-suite-schema.d.ts +88 -62
- package/dist/schemas/pi-tools-suite-schema.js +54 -83
- package/dist/schemas/pix-schema.d.ts +19 -2
- package/dist/schemas/pix-schema.js +47 -5
- package/dist/schemas/tasks-schema.d.ts +18 -0
- package/dist/schemas/tasks-schema.js +41 -0
- package/docs/concurrency.md +9 -1
- package/docs/desktop-mvp.md +22 -6
- package/docs/desktop-task-manager.md +148 -84
- package/docs/release.md +30 -6
- package/external/pi-tools-suite/README.md +197 -84
- package/external/pi-tools-suite/docs/evals.md +1 -1
- package/external/pi-tools-suite/docs/session-recovery.md +47 -14
- package/external/pi-tools-suite/docs/subagent-model-pools.md +48 -30
- package/external/pi-tools-suite/docs/ui-qa-subagent.md +440 -0
- package/external/pi-tools-suite/package.json +6 -1
- package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +2 -1
- package/external/pi-tools-suite/src/antigravity-auth/constants.ts +9 -3
- package/external/pi-tools-suite/src/antigravity-auth/headers.ts +41 -3
- package/external/pi-tools-suite/src/antigravity-auth/models.ts +94 -21
- package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +5 -17
- package/external/pi-tools-suite/src/antigravity-auth/payload.ts +72 -7
- package/external/pi-tools-suite/src/antigravity-auth/stream.ts +13 -1
- package/external/pi-tools-suite/src/async-subagents/agents/frontier-review.md +23 -0
- package/external/pi-tools-suite/src/async-subagents/agents/implement.md +1 -1
- package/external/pi-tools-suite/src/async-subagents/agents/presets.jsonc +16 -0
- package/external/pi-tools-suite/src/async-subagents/agents/research.md +5 -3
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/browser.mjs +346 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/desktop.mjs +1038 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/tui.mjs +759 -0
- package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/scripts/browser-qa-runner.mjs +32 -23
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/chrome-devtools/chrome-devtools-provider.mjs +895 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/linux/linux-atspi.py +494 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/macos/macos-accessibility.swift +1085 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/bridge-client.mjs +50 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/native-terminal-host.mjs +501 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/windows/windows-uia.ps1 +454 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-auth.md +114 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-chrome-devtools.md +91 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-playwright.md +145 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser.md +82 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-linux.md +26 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-macos.md +29 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-windows.md +23 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop.md +54 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-native-terminal.md +59 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-pty.md +37 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui.md +60 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/scripts/ui-qa-runner.mjs +535 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa.md +75 -0
- package/external/pi-tools-suite/src/async-subagents/commands.ts +15 -71
- package/external/pi-tools-suite/src/async-subagents/core/activity.ts +33 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +5 -4
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +1 -1
- package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +8 -5
- package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +16 -2
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +160 -327
- package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +2 -1
- package/external/pi-tools-suite/src/async-subagents/core/registry.ts +158 -33
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +21 -5
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +40 -26
- package/external/pi-tools-suite/src/async-subagents/core/state.ts +40 -0
- package/external/pi-tools-suite/src/async-subagents/core/types.ts +7 -0
- package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +51 -45
- package/external/pi-tools-suite/src/async-subagents/index.ts +69 -5
- package/external/pi-tools-suite/src/async-subagents/lib.ts +16 -9
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +8 -5
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +5 -4
- package/external/pi-tools-suite/src/async-subagents/types.ts +1 -0
- package/external/pi-tools-suite/src/coding-discipline/index.ts +90 -59
- package/external/pi-tools-suite/src/config.ts +55 -1
- package/external/pi-tools-suite/src/context-gateway/accounting-log.ts +282 -0
- package/external/pi-tools-suite/src/context-gateway/config.ts +77 -3
- package/external/pi-tools-suite/src/context-gateway/efficiency.ts +414 -0
- package/external/pi-tools-suite/src/context-gateway/enforcement.ts +222 -0
- package/external/pi-tools-suite/src/context-gateway/index.ts +206 -19
- package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +7 -7
- package/external/pi-tools-suite/src/context-gateway/telemetry.ts +101 -28
- package/external/pi-tools-suite/src/context-gateway/types.ts +16 -3
- package/external/pi-tools-suite/src/context-inventory.ts +99 -0
- package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +39 -4
- package/external/pi-tools-suite/src/dcp/auto-compress.ts +128 -49
- package/external/pi-tools-suite/src/dcp/commands.ts +32 -156
- package/external/pi-tools-suite/src/dcp/compress-tool.ts +177 -46
- package/external/pi-tools-suite/src/dcp/compression-blocks.ts +6 -58
- package/external/pi-tools-suite/src/dcp/compression-preview.ts +9 -0
- package/external/pi-tools-suite/src/dcp/compression-progress.ts +22 -0
- package/external/pi-tools-suite/src/dcp/config.ts +114 -17
- package/external/pi-tools-suite/src/dcp/conversation-index.ts +36 -9
- package/external/pi-tools-suite/src/dcp/diagnostics.ts +41 -0
- package/external/pi-tools-suite/src/dcp/fresh-tool-results.ts +38 -0
- package/external/pi-tools-suite/src/dcp/index.ts +338 -66
- package/external/pi-tools-suite/src/dcp/journal.ts +126 -4
- package/external/pi-tools-suite/src/dcp/progress-controller.ts +2 -1
- package/external/pi-tools-suite/src/dcp/prompts.ts +83 -192
- package/external/pi-tools-suite/src/dcp/protected-continuity.ts +175 -0
- package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +93 -3
- package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +6 -10
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +36 -33
- package/external/pi-tools-suite/src/dcp/pruner-tools.ts +6 -3
- package/external/pi-tools-suite/src/dcp/pruner.ts +1 -0
- package/external/pi-tools-suite/src/dcp/routine-pressure.ts +86 -0
- package/external/pi-tools-suite/src/dcp/state.ts +9 -0
- package/external/pi-tools-suite/src/dcp/statistics.d.ts +8 -0
- package/external/pi-tools-suite/src/dcp/statistics.js +156 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +78 -22
- package/external/pi-tools-suite/src/index.ts +7 -1
- package/external/pi-tools-suite/src/lib/project.ts +36 -1
- package/external/pi-tools-suite/src/model-tools/index.ts +10 -7
- package/external/pi-tools-suite/src/repo-discovery/index.ts +304 -4
- package/external/pi-tools-suite/src/resource-registry/index.ts +2551 -0
- package/external/pi-tools-suite/src/session-recovery/index.ts +17 -0
- package/external/pi-tools-suite/src/shell-command-policy.ts +219 -0
- package/external/pi-tools-suite/src/todo/index.ts +21 -0
- package/external/pi-tools-suite/src/todo/todo.ts +19 -1
- package/external/pi-tools-suite/src/tool-descriptions.ts +47 -19
- package/package.json +10 -9
- package/schemas/pi-tools-suite.json +466 -287
- package/schemas/pix.json +129 -11
- package/schemas/tasks.json +131 -0
- package/skills/simplify/SKILL.md +33 -5
- package/docs/desktop-markdown-media.md +0 -77
- package/external/pi-tools-suite/docs/browser-qa-subagent.md +0 -177
- package/external/pi-tools-suite/docs/dcp-emergency-current-turn.md +0 -102
- package/external/pi-tools-suite/src/async-subagents/agents/browser-qa.md +0 -598
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +0 -54
- package/external/pi-tools-suite/src/skill-installer/index.ts +0 -333
- package/skills/playwright-cli/SKILL.md +0 -420
- package/skills/playwright-cli/references/element-attributes.md +0 -23
- package/skills/playwright-cli/references/playwright-tests.md +0 -50
- package/skills/playwright-cli/references/request-mocking.md +0 -87
- package/skills/playwright-cli/references/running-code.md +0 -241
- package/skills/playwright-cli/references/session-management.md +0 -273
- package/skills/playwright-cli/references/spec-driven-testing.md +0 -311
- package/skills/playwright-cli/references/storage-state.md +0 -290
- package/skills/playwright-cli/references/test-generation.md +0 -142
- package/skills/playwright-cli/references/tracing.md +0 -154
- package/skills/playwright-cli/references/video-recording.md +0 -147
- package/skills/spec-lite/SKILL.md +0 -140
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-auth.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-flow.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.LICENSE +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.mjs +0 -0
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ Pi provides the agent runtime, models, tools, skills, extensions, and persistent
|
|
|
34
34
|
- **Keep projects organized.** Tabs are scoped to the working directory and survive restarts. Search, resume, fork, clone, jump through, import, export, share, or delete sessions without leaving the terminal.
|
|
35
35
|
- **Stay in flow.** Run quick commands with `!`, open a raw interactive terminal with `!!`, paste images, follow file links, dictate in English or Russian, and improve a prompt before sending it.
|
|
36
36
|
- **Know what the agent is doing.** The status area exposes model, thinking level, context, usage, workspace, todos, sub-agents, voice state, and prompt actions — with mouse targets where useful.
|
|
37
|
-
- **Bring a serious toolkit.** Pix ships with `pi-tools-suite`:
|
|
37
|
+
- **Bring a serious toolkit.** Pix ships with `pi-tools-suite`: 21 integrated modules for indexed repository discovery, AST edits, LSP diagnostics, parallel agents, durable todos, context compression, web access, provider accounts, and more.
|
|
38
38
|
- **Use the models you want.** Pix runs on Pi's provider ecosystem and supports model switching, scoped model lists, per-model thinking levels, usage views, autocomplete, and fallback-aware helper workflows.
|
|
39
39
|
|
|
40
40
|
Pix is not a separate agent protocol or an RPC wrapper around Pi. It runs on the Pi SDK, so the runtime, session format, extensions, skills, prompts, and tools remain part of the same ecosystem.
|
|
@@ -95,8 +95,10 @@ On startup, Pix tries to link the bundled suite into the active Pi agent directo
|
|
|
95
95
|
| Context control | `dcp` | Explicit compression and context pruning for long sessions, including sidecar state. |
|
|
96
96
|
| Local web access | `web-search` | Web search and page extraction through a local Ollama instance. |
|
|
97
97
|
| Providers and quotas | `antigravity-auth`, `opencode-import`, `usage` | Antigravity OAuth/account failover, OpenCode credential import, and multi-provider usage views. |
|
|
98
|
-
| Reusable workflows | `prompt-commands`, `
|
|
98
|
+
| Reusable workflows | `prompt-commands`, `resource-registry`, `session-name` | Prompt-command CRUD, private Git-backed skill/agent install/update/push/remote-remove/local-uninstall with reload-on-change, project-scoped `.pi/tasks.jsonc` + `.pi/plans/` + `.pi/TODO.md` sync, a Desktop Registry sidebar for status/actions/configuration, and session naming. |
|
|
99
99
|
| Model compatibility | `coding-discipline`, `model-tools`, `codex-reasoning-fix` | Model-specific discipline and vision lookup, compatibility aliases, and a Codex reasoning payload workaround. |
|
|
100
|
+
| Agent session context | `session-recovery` | Bounded session overview/search/section tools so agents can recover prior context. |
|
|
101
|
+
| Payload hygiene | `context-gateway`, `truncation-metadata-normalizer`, `credential-firewall` | Observe-only result-chain gateway, opt-in truncation-metadata cleanup, and an opt-in secret firewall. |
|
|
100
102
|
|
|
101
103
|
Every module can be disabled. Optional integrations only activate when their requirements are available — for example, repository tools require an index, web tools require local Ollama web search, and LSP servers must be configured and trusted.
|
|
102
104
|
|
|
@@ -136,8 +138,8 @@ Recommended:
|
|
|
136
138
|
|
|
137
139
|
Optional:
|
|
138
140
|
|
|
139
|
-
-
|
|
140
|
-
- an audio recorder for dictation: SoX (`rec`/`sox`), `ffmpeg`, or `arecord` on Linux
|
|
141
|
+
- a Deepgram API key in `dictation.apiKey` inside `~/.config/pi/pix.jsonc` for voice input; `DEEPGRAM_API_KEY` remains supported as a fallback
|
|
142
|
+
- an audio recorder for terminal dictation: SoX (`rec`/`sox`), `ffmpeg`, or `arecord` on Linux
|
|
141
143
|
- `tmux` and `rsvg-convert` only if you want to regenerate README screenshots
|
|
142
144
|
- Ollama with web search enabled for the bundled `web_search` and `web_fetch` tools
|
|
143
145
|
- language servers for the LSP module (see [LSP setup](external/pi-tools-suite/README.md#lsp-setup) for install commands and ready-to-paste configs for popular servers, including Svelte, Vue, Go, clangd, Lua, and bash)
|
|
@@ -210,7 +212,7 @@ Pix uses Pi's model and authentication stores. Environment-based API keys and cr
|
|
|
210
212
|
| Model-backed helpers | No | Review `promptEnhancer`, `autocomplete`, and `sessionTitle` in `pix.jsonc` | Each configured helper model needs credentials for its own provider; it need not use the main session provider. |
|
|
211
213
|
| Ollama/Tavily web access | No | Use local Ollama without a cloud key, set `OLLAMA_API_KEY`/`TAVILY_API_KEY`, or run `/web-credentials` | Stored keys live in `~/.config/pi/pi-tools-suite-credentials.json` with mode `0600`. |
|
|
212
214
|
| Context7 documentation skill | No | Export `CONTEXT7_API_KEY` | The skill fails before making a network request when the variable is absent. |
|
|
213
|
-
| Telegram
|
|
215
|
+
| Telegram task connector | No | Configure `telegramConnector.botToken` + `telegramConnector.chatId`, or `PIX_TELEGRAM_BOT_TOKEN` + `PIX_TELEGRAM_CHAT_ID` | Completion/question notifications; reply to continue the exact live session, or use `/new <task>` for a fresh session. |
|
|
214
216
|
|
|
215
217
|
`pix install` reports whether these sources appear configured, but never displays, copies, or overwrites token values.
|
|
216
218
|
|
|
@@ -267,6 +269,12 @@ Pix can provide inline, model-backed autocomplete with configurable debounce, ti
|
|
|
267
269
|
- While it runs, submit editor text to its stdin; use `Ctrl-C` to interrupt.
|
|
268
270
|
- `!!command` opens a raw interactive terminal for REPLs, TUIs, debuggers, and development servers. Exit it to return to Pix.
|
|
269
271
|
|
|
272
|
+
### Git helpers
|
|
273
|
+
|
|
274
|
+
- `/code-review` reviews staged, unstaged, and untracked Git changes with the configured review model and prints the findings locally in the TUI.
|
|
275
|
+
- `/commit-message` generates a message from staged changes, shows the full message, and asks for confirmation before running `git commit`. If the staged diff changes before confirmation completes, Pix refuses the commit and asks you to regenerate the message.
|
|
276
|
+
- These helpers use the existing `desktop.git.reviewModelRef` / `reviewFallbackModels` and `desktop.git.commitMessageModelRef` / `commitMessageFallbackModels` settings for compatibility. `/commit-message` never stages changes or bypasses Git hooks.
|
|
277
|
+
|
|
270
278
|
### Images, clipboard, and files
|
|
271
279
|
|
|
272
280
|
- Paste an image from the clipboard with `Ctrl+V`/`Cmd+V` in supported terminals.
|
|
@@ -274,14 +282,25 @@ Pix can provide inline, model-backed autocomplete with configurable debounce, ti
|
|
|
274
282
|
- `/copy` copies the last assistant message.
|
|
275
283
|
- Pix integrates with the native clipboard on macOS and Windows and common Wayland/X11 helpers on Linux.
|
|
276
284
|
|
|
277
|
-
###
|
|
285
|
+
### Voice input
|
|
286
|
+
|
|
287
|
+
Put the Deepgram key in the user Pix config:
|
|
288
|
+
|
|
289
|
+
```jsonc
|
|
290
|
+
{
|
|
291
|
+
"dictation": {
|
|
292
|
+
"apiKey": "your-deepgram-api-key"
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The file is `~/.config/pi/pix.jsonc`. Keep the key in this user config rather than a project `.pi/pix.jsonc`; project config is intentionally not allowed to override the secret. `DEEPGRAM_API_KEY` remains supported as a compatibility fallback when `dictation.apiKey` is not set.
|
|
278
298
|
|
|
279
|
-
|
|
299
|
+
Then press `Ctrl+G` or click the microphone in the terminal status area to start/stop dictation. Pix streams microphone audio to Deepgram Nova-3 and inserts finalized text into the editor so you can review it before sending. The default dictation languages are English and Russian and can be changed with the existing language control.
|
|
280
300
|
|
|
281
|
-
-
|
|
282
|
-
- Russian: `vosk-model-small-ru-0.22`
|
|
301
|
+
Pix Desktop exposes the same voice-input action directly in the message composer. The desktop client uses Nova-3 and respects `dictation.language` plus the selected language's `deepgramLanguage` value from the user Pix config. It requests a short-lived Deepgram token from the local Tauri backend; the permanent API key is read from the user Pix config (or the environment fallback) by Rust and is never exposed to the WebView. The Settings UI also exposes `Dictation · Api Key` as a sensitive field because it is generated from the Pix schema.
|
|
283
302
|
|
|
284
|
-
|
|
303
|
+
Voice audio is sent to Deepgram while recording. Pix no longer downloads or installs local speech-recognition models.
|
|
285
304
|
|
|
286
305
|
### Workspace undo
|
|
287
306
|
|
|
@@ -312,12 +331,13 @@ Type `/` for the live, searchable list. Extensions can add more commands than th
|
|
|
312
331
|
| Models | `/model`, `/default-model`, `/scoped-models`, `/thinking`, `/default-thinking`, `/autocomplete` |
|
|
313
332
|
| Project context | `/no-context-files`, `/compact` |
|
|
314
333
|
| Prompt workflow | `/enhance`, `/queue`, `/copy` |
|
|
334
|
+
| Git | `/code-review`, `/commit-message` |
|
|
315
335
|
| Sessions | `/new`, `/new_tab`, `/resume`, `/name`, `/session`, `/search`, `/history`, `/jump`, `/tree` |
|
|
316
336
|
| Branching and files | `/fork`, `/clone`, `/delete`, `/export`, `/import`, `/share` |
|
|
317
337
|
| Status | `/usage` |
|
|
318
338
|
| Process | `/quit`, `/exit` |
|
|
319
339
|
|
|
320
|
-
Useful suite commands include `/todos`, `/todos-persist`, `/todos-scope`, `/sub-status`, `/sub-stop`, `/ultrawork`, `/hyperplan`, `/subagent-preset`, `/usage`, `/dcp`, `/idx-init`, `/idx-update`, `/opencode-import`, `/antigravity-add-account`,
|
|
340
|
+
Useful suite commands include `/todos`, `/todos-persist`, `/todos-scope`, `/sub-status`, `/sub-stop`, `/ultrawork`, `/hyperplan`, `/subagent-preset`, `/usage`, `/dcp`, `/idx-init`, `/idx-update`, `/opencode-import`, `/antigravity-add-account`, and `/registry`.
|
|
321
341
|
|
|
322
342
|
### Keyboard and mouse
|
|
323
343
|
|
|
@@ -361,6 +381,7 @@ Both support the published schema:
|
|
|
361
381
|
"$schema": "https://unpkg.com/pi-ui-extend/schemas/pix.json",
|
|
362
382
|
"defaultModel": {
|
|
363
383
|
"modelRef": "openai-codex/gpt-5.6-sol",
|
|
384
|
+
"fallbackModels": [],
|
|
364
385
|
"thinking": "medium"
|
|
365
386
|
},
|
|
366
387
|
"toolRenderer": {
|
|
@@ -371,9 +392,10 @@ Both support the published schema:
|
|
|
371
392
|
"apply_patch": { "defaultExpanded": true }
|
|
372
393
|
}
|
|
373
394
|
},
|
|
374
|
-
"promptEnhancer": { "modelRef": "openai-codex/gpt-5.6-luna" },
|
|
395
|
+
"promptEnhancer": { "modelRef": "openai-codex/gpt-5.6-luna", "fallbackModels": [] },
|
|
375
396
|
"autocomplete": {
|
|
376
397
|
"modelRef": "zai/glm-5-turbo",
|
|
398
|
+
"fallbackModels": [],
|
|
377
399
|
"debounceMs": 350,
|
|
378
400
|
"timeoutMs": 3000
|
|
379
401
|
},
|
|
@@ -387,6 +409,12 @@ Both support the published schema:
|
|
|
387
409
|
}
|
|
388
410
|
```
|
|
389
411
|
|
|
412
|
+
Singular model selectors resolve with an explicit ordered fallback array, even
|
|
413
|
+
when it is empty. Existing configs that omit the array remain compatible and
|
|
414
|
+
normalize to `[]`. Pix uses `fallbackModels` for object selectors; Desktop Git
|
|
415
|
+
uses `reviewFallbackModels` and `commitMessageFallbackModels` beside the
|
|
416
|
+
corresponding primary model refs.
|
|
417
|
+
|
|
390
418
|
Configurable areas include:
|
|
391
419
|
|
|
392
420
|
- default model and thinking level;
|
|
@@ -449,7 +477,7 @@ Install `wl-clipboard` on Wayland or `xclip`/`xsel` on X11, then run `pix instal
|
|
|
449
477
|
|
|
450
478
|
### Voice input is unavailable
|
|
451
479
|
|
|
452
|
-
Ensure the
|
|
480
|
+
Ensure `dictation.apiKey` is set in `~/.config/pi/pix.jsonc`, or set the compatibility fallback `DEEPGRAM_API_KEY` in the environment that launches Pix. Terminal voice input also needs an audio recorder: SoX (`rec`/`sox`), `ffmpeg`, or `arecord` on Linux. Pix Desktop additionally needs microphone permission from the operating system. Voice support can be omitted without affecting the rest of Pix.
|
|
453
481
|
|
|
454
482
|
### A provider login dialog is missing
|
|
455
483
|
|
|
@@ -500,8 +528,17 @@ npm run test:tools-suite
|
|
|
500
528
|
|
|
501
529
|
# Build the publishable renderer
|
|
502
530
|
npm run build:pix
|
|
531
|
+
|
|
532
|
+
# Watch Pix, ACP, the bundled suite, and Desktop
|
|
533
|
+
npm run watch:all
|
|
503
534
|
```
|
|
504
535
|
|
|
536
|
+
`watch:all` rebuilds only the affected project parts. It keeps the last working
|
|
537
|
+
Desktop process alive while changes compile, then replaces it only after the
|
|
538
|
+
entire queued build succeeds. A failed build is reported without replacing the
|
|
539
|
+
running Desktop. Desktop web changes rebuild the Vite bundle first and then
|
|
540
|
+
invalidate the native Tauri asset embedding before the replacement app starts.
|
|
541
|
+
|
|
505
542
|
Regenerate the README screenshots without accounts or live model traffic:
|
|
506
543
|
|
|
507
544
|
```bash
|
package/dist/app/app.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export declare class PiUiExtendApp {
|
|
|
51
51
|
* for one tab never reaches another tab's extensions.
|
|
52
52
|
*/
|
|
53
53
|
private readonly extensionEventBusByRuntime;
|
|
54
|
+
private readonly subagentCatalogBySessionId;
|
|
54
55
|
private readonly inputEditor;
|
|
55
56
|
private lastInputEditorContentVersion;
|
|
56
57
|
private readonly requestHistory;
|
|
@@ -67,9 +68,18 @@ export declare class PiUiExtendApp {
|
|
|
67
68
|
private voicePartialText;
|
|
68
69
|
private resumeSessions;
|
|
69
70
|
private resumeLoading;
|
|
71
|
+
private draftModels;
|
|
72
|
+
private draftModelRef;
|
|
73
|
+
private draftThinkingLevel;
|
|
74
|
+
private draftModelOverrideRef;
|
|
70
75
|
constructor(options: AppOptions);
|
|
71
76
|
private createRuntime;
|
|
72
77
|
private loadStartupConfig;
|
|
78
|
+
private refreshDraftModelCatalog;
|
|
79
|
+
private resetDraftModelSelection;
|
|
80
|
+
private selectDraftModel;
|
|
81
|
+
private draftModelState;
|
|
82
|
+
private draftModelStatus;
|
|
73
83
|
private applyPixConfig;
|
|
74
84
|
private updateOutputFilters;
|
|
75
85
|
start(): Promise<void>;
|
|
@@ -77,7 +87,10 @@ export declare class PiUiExtendApp {
|
|
|
77
87
|
private bindCurrentSession;
|
|
78
88
|
private awaitCurrentSessionExtensions;
|
|
79
89
|
private activateRuntime;
|
|
90
|
+
private deactivateRuntimeForDraft;
|
|
80
91
|
private createExtensionEventBus;
|
|
92
|
+
private subagentTypesForRuntime;
|
|
93
|
+
private contextInventoryText;
|
|
81
94
|
private handleTerminalBellAttention;
|
|
82
95
|
private afterSessionReplacement;
|
|
83
96
|
private requireRuntime;
|
package/dist/app/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { THEMES } from "../theme.js";
|
|
2
2
|
import { InputEditor } from "../input-editor.js";
|
|
3
|
-
import { compileOutputFilterPatterns, defaultPixConfig, loadPixConfig, resolveToolRule, } from "../config.js";
|
|
3
|
+
import { compileOutputFilterPatterns, defaultPixConfig, loadPixConfig, resolveDefaultModelRef, resolveToolRule, savePixThinkingLevelForModel, savePixVisibleModels, } from "../config.js";
|
|
4
4
|
import { AppCommandController } from "./commands/command-controller.js";
|
|
5
5
|
import { ConversationViewport } from "./rendering/conversation-viewport.js";
|
|
6
6
|
import { renderRegisteredExtensionEntry } from "./rendering/extension-entry-renderer.js";
|
|
@@ -23,7 +23,8 @@ import { AppAutocompleteController } from "./input/autocomplete-controller.js";
|
|
|
23
23
|
import { AppQueuedMessageController } from "./session/queued-message-controller.js";
|
|
24
24
|
import { AppRequestHistory } from "./session/request-history.js";
|
|
25
25
|
import { AppRenderController } from "./rendering/render-controller.js";
|
|
26
|
-
import { createPixRuntime } from "./runtime.js";
|
|
26
|
+
import { createPixDraftModelCatalog, createPixRuntime } from "./runtime.js";
|
|
27
|
+
import { parseModelRef } from "./model/model-ref.js";
|
|
27
28
|
import { ScreenStyler } from "./screen/screen-styler.js";
|
|
28
29
|
import { AppScrollController } from "./screen/scroll-controller.js";
|
|
29
30
|
import { searchResultScrollNeedles, searchResultTargetEntry } from "./session/session-search.js";
|
|
@@ -47,6 +48,8 @@ import { checkPiUpdate, checkPixUpdate, formatPixStartupUpdateDialog, formatPiSt
|
|
|
47
48
|
import { checkAndUpdateIdxOnStartup, formatIdxStartupUpdateNotice } from "./cli/startup-checks.js";
|
|
48
49
|
import { AppVoiceController } from "./input/voice-controller.js";
|
|
49
50
|
import { createIsolatedExtensionEventBus } from "./extensions/extension-event-bus.js";
|
|
51
|
+
import { parseSubagentCatalogState, SUBAGENTS_CATALOG_STATE_EVENT, } from "./extensions/subagent-catalog-state.js";
|
|
52
|
+
import { createReloadContextInventory, formatReloadContextInventory } from "./commands/reload-context-inventory.js";
|
|
50
53
|
import { setAppIconTheme } from "./icons.js";
|
|
51
54
|
const TERMINAL_BELL_ATTENTION_EVENT = "pix:terminal-bell:attention";
|
|
52
55
|
function normalizeJumpTargetText(text) {
|
|
@@ -123,6 +126,7 @@ export class PiUiExtendApp {
|
|
|
123
126
|
* for one tab never reaches another tab's extensions.
|
|
124
127
|
*/
|
|
125
128
|
extensionEventBusByRuntime = new WeakMap();
|
|
129
|
+
subagentCatalogBySessionId = new Map();
|
|
126
130
|
inputEditor = new InputEditor();
|
|
127
131
|
lastInputEditorContentVersion = this.inputEditor.contentVersion;
|
|
128
132
|
requestHistory;
|
|
@@ -139,6 +143,10 @@ export class PiUiExtendApp {
|
|
|
139
143
|
voicePartialText;
|
|
140
144
|
resumeSessions = [];
|
|
141
145
|
resumeLoading = false;
|
|
146
|
+
draftModels = [];
|
|
147
|
+
draftModelRef;
|
|
148
|
+
draftThinkingLevel = "off";
|
|
149
|
+
draftModelOverrideRef;
|
|
142
150
|
constructor(options) {
|
|
143
151
|
this.options = options;
|
|
144
152
|
this.theme = THEMES[options.themeName];
|
|
@@ -167,6 +175,7 @@ export class PiUiExtendApp {
|
|
|
167
175
|
theme: this.theme,
|
|
168
176
|
blinkController: this.blinkController,
|
|
169
177
|
runtimeSession: () => this.runtime?.session,
|
|
178
|
+
draftModelStatus: () => this.draftModelStatus(),
|
|
170
179
|
render: () => this.scheduleRender(),
|
|
171
180
|
});
|
|
172
181
|
this.agentPauseController = new AgentPauseController({
|
|
@@ -183,7 +192,7 @@ export class PiUiExtendApp {
|
|
|
183
192
|
maxProjectSessions: () => this.pixConfig.maxProjectSessions,
|
|
184
193
|
blinkController: this.blinkController,
|
|
185
194
|
runtime: () => this.runtime,
|
|
186
|
-
createRuntimeForNewSession: () => this.createRuntime(
|
|
195
|
+
createRuntimeForNewSession: (modelRef) => this.createRuntime(
|
|
187
196
|
// Never reuse services across tabs. The SDK ties the extension
|
|
188
197
|
// runtime (resourceLoader.getExtensions().runtime) to the
|
|
189
198
|
// resourceLoader, and that runtime is shared by every session
|
|
@@ -194,12 +203,18 @@ export class PiUiExtendApp {
|
|
|
194
203
|
// then throw "ctx is stale after session replacement or reload".
|
|
195
204
|
// Fresh services per session = fresh extension runtime = no
|
|
196
205
|
// cross-session invalidation.
|
|
197
|
-
|
|
206
|
+
{
|
|
207
|
+
...newTabRuntimeOptions(this.options),
|
|
208
|
+
...(modelRef ? { modelRef } : {}),
|
|
209
|
+
}),
|
|
198
210
|
createRuntimeForSession: (sessionPath) => this.createRuntime({
|
|
199
211
|
...this.options,
|
|
200
212
|
noSession: false,
|
|
201
213
|
sessionPath,
|
|
202
214
|
}),
|
|
215
|
+
draftModelOverrideRef: () => this.draftModelOverrideRef,
|
|
216
|
+
resetDraftModelSelection: () => this.resetDraftModelSelection(),
|
|
217
|
+
deactivateRuntimeForDraft: () => this.deactivateRuntimeForDraft(),
|
|
203
218
|
awaitCurrentSessionExtensions: (runtime) => this.awaitCurrentSessionExtensions(runtime),
|
|
204
219
|
activateRuntime: (runtime, options) => this.activateRuntime(runtime, options),
|
|
205
220
|
disposeRuntime: (runtime) => this.terminalController.disposeRuntime(runtime),
|
|
@@ -221,6 +236,13 @@ export class PiUiExtendApp {
|
|
|
221
236
|
restoreAutoUserMessages: (messages) => this.queuedMessages.restoreAutoUserMessages(messages),
|
|
222
237
|
captureDeferredUserMessages: () => this.queuedMessages.captureDeferredUserMessages(),
|
|
223
238
|
restoreDeferredUserMessages: (messages) => this.queuedMessages.restoreDeferredUserMessages(messages),
|
|
239
|
+
openDraftSessionSelector: () => {
|
|
240
|
+
void this.commandController.runDraftSessionSelector();
|
|
241
|
+
},
|
|
242
|
+
closeDraftSessionSelector: () => {
|
|
243
|
+
this.popupMenus.closeDraftSessionSelectorForTabLifecycle();
|
|
244
|
+
},
|
|
245
|
+
contextInventoryText: (runtime, heading) => this.contextInventoryText(runtime, heading),
|
|
224
246
|
addEntry: (entry) => this.addEntry(entry),
|
|
225
247
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
226
248
|
render: () => this.render(),
|
|
@@ -258,9 +280,12 @@ export class PiUiExtendApp {
|
|
|
258
280
|
}, this.pixConfig.dictation);
|
|
259
281
|
this.menuItems = new AppMenuItemsController({
|
|
260
282
|
runtime: () => this.runtime,
|
|
283
|
+
draftModelState: () => this.draftModelState(),
|
|
284
|
+
visibleModels: () => this.pixConfig.visibleModels,
|
|
261
285
|
getBuiltinSlashCommands: () => this.slashCommands,
|
|
262
286
|
getEntries: () => this.entries,
|
|
263
287
|
getResumeSessions: () => this.resumeSessions,
|
|
288
|
+
getOpenSessionPaths: () => this.tabsController.openSessionPaths(),
|
|
264
289
|
});
|
|
265
290
|
const popupMenuRenderer = new PopupMenuRenderer({
|
|
266
291
|
theme: this.theme,
|
|
@@ -275,6 +300,8 @@ export class PiUiExtendApp {
|
|
|
275
300
|
this.popupMenus = new AppPopupMenuController({
|
|
276
301
|
get entries() { return app.entries; },
|
|
277
302
|
get session() { return app.runtime?.session; },
|
|
303
|
+
currentThinkingLevel: () => this.runtime?.session.thinkingLevel ?? this.draftModelState()?.thinkingLevel,
|
|
304
|
+
rememberedThinkingLevel: (modelRef) => this.pixConfig.thinkingByModel?.[modelRef],
|
|
278
305
|
get resumeLoading() { return app.resumeLoading; },
|
|
279
306
|
get resumeSessionCount() { return app.resumeSessions.length; },
|
|
280
307
|
isRunning: () => this.running,
|
|
@@ -282,9 +309,9 @@ export class PiUiExtendApp {
|
|
|
282
309
|
setInput: (value) => this.setInput(value),
|
|
283
310
|
parseSlashInput: (text) => this.menuItems.parseSlashInput(text),
|
|
284
311
|
getSlashCommandMenuItems: (query) => this.menuItems.getSlashCommandMenuItems(query),
|
|
285
|
-
getModelMenuItems: (query) => this.menuItems.getModelMenuItems(query),
|
|
312
|
+
getModelMenuItems: (query, includeHidden) => this.menuItems.getModelMenuItems(query, includeHidden),
|
|
286
313
|
getThinkingMenuItems: (query) => this.menuItems.getThinkingMenuItems(query),
|
|
287
|
-
getResumeMenuItems: (query, limit) => this.menuItems.getResumeMenuItems(query, limit),
|
|
314
|
+
getResumeMenuItems: (query, limit, options) => this.menuItems.getResumeMenuItems(query, limit, options),
|
|
288
315
|
getUserMessageMenuItems: () => this.menuItems.getUserMessageMenuItems(),
|
|
289
316
|
getUserMessageJumpMenuItems: (query) => this.menuItems.getUserMessageJumpMenuItems(query),
|
|
290
317
|
getQueueMessageMenuItems: () => this.menuItems.getQueueMessageMenuItems(),
|
|
@@ -298,6 +325,7 @@ export class PiUiExtendApp {
|
|
|
298
325
|
theme: this.theme,
|
|
299
326
|
screenStyler: this.screenStyler,
|
|
300
327
|
get session() { return app.runtime?.session; },
|
|
328
|
+
draftModelStatus: () => this.draftModelStatus(),
|
|
301
329
|
modelColors: this.pixConfig.modelColors,
|
|
302
330
|
get sessionActivity() { return app.statusController.sessionActivity; },
|
|
303
331
|
get statusDotBright() { return app.statusController.statusDotBright; },
|
|
@@ -358,6 +386,7 @@ export class PiUiExtendApp {
|
|
|
358
386
|
this.extensionActions = new AppExtensionActionsController({
|
|
359
387
|
isRunning: () => this.running,
|
|
360
388
|
runtime: () => this.runtime,
|
|
389
|
+
subagentTypes: (runtime) => this.subagentTypesForRuntime(runtime),
|
|
361
390
|
getInput: () => this.input,
|
|
362
391
|
setInput: (value) => this.setInput(value),
|
|
363
392
|
awaitCurrentSessionExtensions: (runtime) => this.awaitCurrentSessionExtensions(runtime),
|
|
@@ -372,6 +401,7 @@ export class PiUiExtendApp {
|
|
|
372
401
|
});
|
|
373
402
|
this.subagentsWidgetController = new AppSubagentsWidgetController({
|
|
374
403
|
cwd: this.options.cwd,
|
|
404
|
+
hasActiveRuntime: () => this.runtime !== undefined,
|
|
375
405
|
sessionFile: () => this.runtime?.session.sessionFile,
|
|
376
406
|
isRunning: () => this.running,
|
|
377
407
|
render: () => this.scheduleRender(),
|
|
@@ -508,6 +538,8 @@ export class PiUiExtendApp {
|
|
|
508
538
|
this.commandController = new AppCommandController({
|
|
509
539
|
options: this.options,
|
|
510
540
|
runtime: () => this.runtime,
|
|
541
|
+
inputScopeKey: () => this.tabsController.activeInputTabId(),
|
|
542
|
+
subagentTypes: (runtime) => this.subagentTypesForRuntime(runtime),
|
|
511
543
|
requestHistory: () => this.requestHistory,
|
|
512
544
|
getInput: () => this.input,
|
|
513
545
|
setInput: (value) => this.setInput(value),
|
|
@@ -552,6 +584,7 @@ export class PiUiExtendApp {
|
|
|
552
584
|
setDirectPopupMenuQuery: (query) => {
|
|
553
585
|
this.popupMenus.setDirectQuery(query);
|
|
554
586
|
},
|
|
587
|
+
setResumeMenuMode: (mode) => this.popupMenus.setResumeMenuMode(mode),
|
|
555
588
|
refreshUserMessageJumpMenuItems: () => this.menuItems.refreshUserMessageJumpMenuItems(),
|
|
556
589
|
getResumeLoading: () => this.resumeLoading,
|
|
557
590
|
getResumeSessions: () => this.resumeSessions,
|
|
@@ -570,6 +603,10 @@ export class PiUiExtendApp {
|
|
|
570
603
|
});
|
|
571
604
|
this.popupActions = new AppPopupActionController({
|
|
572
605
|
runtime: () => this.runtime,
|
|
606
|
+
inputScopeKey: () => this.tabsController.activeInputTabId(),
|
|
607
|
+
isDraftTabActive: () => this.tabsController.isDraftTabActive(),
|
|
608
|
+
materializeDraftSession: () => this.tabsController.materializeActiveDraftTab(),
|
|
609
|
+
selectDraftModel: (model, thinkingLevel) => this.selectDraftModel(model, thinkingLevel),
|
|
573
610
|
getBuiltinSlashCommands: () => this.slashCommands,
|
|
574
611
|
isRunning: () => this.running,
|
|
575
612
|
setInput: (value) => this.setInput(value),
|
|
@@ -577,9 +614,20 @@ export class PiUiExtendApp {
|
|
|
577
614
|
setStatus: (status) => this.setStatus(status),
|
|
578
615
|
setSessionStatus: (session) => this.setSessionStatus(session),
|
|
579
616
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
617
|
+
visibleModels: () => this.pixConfig.visibleModels,
|
|
618
|
+
saveVisibleModels: (modelRefs) => {
|
|
619
|
+
const saved = savePixVisibleModels(modelRefs);
|
|
620
|
+
this.pixConfig.visibleModels = [...saved];
|
|
621
|
+
return saved;
|
|
622
|
+
},
|
|
623
|
+
saveThinkingLevelForModel: (modelRef, thinkingLevel) => {
|
|
624
|
+
const saved = savePixThinkingLevelForModel(modelRef, thinkingLevel);
|
|
625
|
+
this.pixConfig.thinkingByModel = { ...saved };
|
|
626
|
+
},
|
|
580
627
|
render: () => this.render(),
|
|
581
628
|
awaitCurrentSessionExtensions: (runtime) => this.awaitCurrentSessionExtensions(runtime),
|
|
582
629
|
afterSessionReplacement: (message) => this.afterSessionReplacement(message),
|
|
630
|
+
openSessionInActiveDraftTab: (sessionPath) => this.tabsController.openSessionInActiveDraftTab(sessionPath),
|
|
583
631
|
scrollToConversationEntry: (entryId) => this.scrollController.scrollToConversationEntry(entryId),
|
|
584
632
|
scrollToUserMessageJumpTarget: (target) => this.scrollToUserMessageJumpTarget(target),
|
|
585
633
|
}, this.popupMenus, this.commandController, this.menuItems, this.queuedMessages, this.workspaceActions);
|
|
@@ -691,6 +739,8 @@ export class PiUiExtendApp {
|
|
|
691
739
|
this.inputActions = new AppInputActionController({
|
|
692
740
|
runtime: () => this.runtime,
|
|
693
741
|
inputScopeKey: () => this.tabsController.activeInputTabId(),
|
|
742
|
+
isDraftTabActive: () => this.tabsController.isDraftTabActive(),
|
|
743
|
+
materializeDraftSession: () => this.tabsController.materializeActiveDraftTab(),
|
|
694
744
|
isRunning: () => this.running,
|
|
695
745
|
isSessionSwitching: () => this.tabsController.isSwitching(),
|
|
696
746
|
inputEditor: () => this.inputEditor,
|
|
@@ -730,6 +780,7 @@ export class PiUiExtendApp {
|
|
|
730
780
|
resetInputMenuDismissals: () => this.popupMenus.resetInputMenuDismissals(),
|
|
731
781
|
render: () => this.render(),
|
|
732
782
|
moveActivePopupMenuSelection: (delta) => this.popupMenus.moveActivePopupMenuSelection(delta),
|
|
783
|
+
moveActiveModelThinkingLevel: (delta) => this.popupMenus.moveActiveModelThinkingLevel(delta),
|
|
733
784
|
navigateRequestHistory: (delta) => this.requestHistory.navigate(delta),
|
|
734
785
|
scrollByLines: (delta) => this.scrollController.scrollByLines(delta),
|
|
735
786
|
scrollByPage: (delta) => this.scrollController.scrollByPage(delta),
|
|
@@ -738,8 +789,8 @@ export class PiUiExtendApp {
|
|
|
738
789
|
handleInterrupt: () => this.inputActions.handleInterrupt(),
|
|
739
790
|
handleEscape: () => this.inputActions.handleEscape(),
|
|
740
791
|
handleDirectPopupInput: (char) => this.popupMenus.handleDirectPopupInput(char),
|
|
792
|
+
toggleModelVisibilityMode: () => this.popupMenus.toggleModelVisibilityMode(),
|
|
741
793
|
autocompleteModel: () => this.popupMenus.autocompleteModel(),
|
|
742
|
-
autocompleteThinking: () => this.popupMenus.autocompleteThinking(),
|
|
743
794
|
acceptAutocompleteSuggestion: () => this.autocompleteController.acceptSuggestion(),
|
|
744
795
|
autocompleteSlashCommand: () => this.popupMenus.autocompleteSlashCommand(),
|
|
745
796
|
toggleVoiceRecording: () => {
|
|
@@ -774,7 +825,10 @@ export class PiUiExtendApp {
|
|
|
774
825
|
});
|
|
775
826
|
this.sessionLifecycle = new AppSessionLifecycleController({
|
|
776
827
|
options: this.options,
|
|
777
|
-
|
|
828
|
+
prepareStartupRuntime: () => this.tabsController.prepareStartupRuntime(),
|
|
829
|
+
createRuntime: (startup) => this.createRuntime(startup?.sessionPath
|
|
830
|
+
? { ...this.options, noSession: false, sessionPath: startup.sessionPath }
|
|
831
|
+
: this.options),
|
|
778
832
|
entries: this.entries,
|
|
779
833
|
runtime: () => this.runtime,
|
|
780
834
|
setRuntime: (runtime) => {
|
|
@@ -800,6 +854,7 @@ export class PiUiExtendApp {
|
|
|
800
854
|
handleExtensionError: (error) => this.extensionActions.handleExtensionError(error),
|
|
801
855
|
handleSessionEvent: (event) => this.handleSessionEvent(event),
|
|
802
856
|
bindAgentPause: (session) => this.agentPauseController.bind(session),
|
|
857
|
+
contextInventoryText: (runtime, heading) => this.contextInventoryText(runtime, heading),
|
|
803
858
|
addEntry: (entry) => this.addEntry(entry),
|
|
804
859
|
setStatus: (status) => this.setStatus(status),
|
|
805
860
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
@@ -856,6 +911,59 @@ export class PiUiExtendApp {
|
|
|
856
911
|
async loadStartupConfig() {
|
|
857
912
|
await yieldToEventLoop();
|
|
858
913
|
this.applyPixConfig(loadPixConfig(this.options.cwd));
|
|
914
|
+
await this.refreshDraftModelCatalog();
|
|
915
|
+
}
|
|
916
|
+
async refreshDraftModelCatalog() {
|
|
917
|
+
try {
|
|
918
|
+
this.draftModels = await createPixDraftModelCatalog({ cwd: this.options.cwd });
|
|
919
|
+
}
|
|
920
|
+
catch {
|
|
921
|
+
this.draftModels = [];
|
|
922
|
+
}
|
|
923
|
+
this.resetDraftModelSelection();
|
|
924
|
+
}
|
|
925
|
+
resetDraftModelSelection() {
|
|
926
|
+
this.draftModelOverrideRef = undefined;
|
|
927
|
+
const configuredRef = this.options.modelRef ?? resolveDefaultModelRef(this.pixConfig);
|
|
928
|
+
if (configuredRef) {
|
|
929
|
+
try {
|
|
930
|
+
const parsed = parseModelRef(configuredRef);
|
|
931
|
+
this.draftModelRef = `${parsed.provider}/${parsed.modelId}`;
|
|
932
|
+
this.draftThinkingLevel = parsed.thinkingLevel ?? "off";
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
catch {
|
|
936
|
+
// Runtime creation will surface an invalid configured model. Keep the
|
|
937
|
+
// draft picker usable so the user can select a valid model first.
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
const first = this.draftModels[0];
|
|
941
|
+
this.draftModelRef = first ? `${first.provider}/${first.id}` : undefined;
|
|
942
|
+
this.draftThinkingLevel = "off";
|
|
943
|
+
}
|
|
944
|
+
selectDraftModel(model, thinkingLevel) {
|
|
945
|
+
if (!this.tabsController.isDraftTabActive())
|
|
946
|
+
return;
|
|
947
|
+
const ref = `${model.provider}/${model.id}`;
|
|
948
|
+
this.draftModelRef = ref;
|
|
949
|
+
this.draftThinkingLevel = thinkingLevel;
|
|
950
|
+
this.draftModelOverrideRef = `${ref}:${thinkingLevel}`;
|
|
951
|
+
this.setStatus("new conversation");
|
|
952
|
+
}
|
|
953
|
+
draftModelState() {
|
|
954
|
+
if (!this.tabsController.isDraftTabActive())
|
|
955
|
+
return undefined;
|
|
956
|
+
return {
|
|
957
|
+
models: this.draftModels,
|
|
958
|
+
...(this.draftModelRef ? { modelRef: this.draftModelRef } : {}),
|
|
959
|
+
thinkingLevel: this.draftThinkingLevel,
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
draftModelStatus() {
|
|
963
|
+
const state = this.draftModelState();
|
|
964
|
+
if (!state?.modelRef)
|
|
965
|
+
return undefined;
|
|
966
|
+
return { modelLabel: state.modelRef, thinkingLabel: state.thinkingLevel };
|
|
859
967
|
}
|
|
860
968
|
applyPixConfig(config) {
|
|
861
969
|
replaceRecord(this.pixConfig.toolRenderer, config.toolRenderer);
|
|
@@ -869,6 +977,14 @@ export class PiUiExtendApp {
|
|
|
869
977
|
delete this.pixConfig.defaultModel;
|
|
870
978
|
else
|
|
871
979
|
this.pixConfig.defaultModel = { ...config.defaultModel };
|
|
980
|
+
if (config.visibleModels === undefined)
|
|
981
|
+
delete this.pixConfig.visibleModels;
|
|
982
|
+
else
|
|
983
|
+
this.pixConfig.visibleModels = [...config.visibleModels];
|
|
984
|
+
if (config.thinkingByModel === undefined)
|
|
985
|
+
delete this.pixConfig.thinkingByModel;
|
|
986
|
+
else
|
|
987
|
+
this.pixConfig.thinkingByModel = { ...config.thinkingByModel };
|
|
872
988
|
this.pixConfig.ignoreContextFiles = config.ignoreContextFiles;
|
|
873
989
|
this.pixConfig.maxProjectSessions = config.maxProjectSessions;
|
|
874
990
|
this.updateOutputFilters();
|
|
@@ -939,16 +1055,49 @@ export class PiUiExtendApp {
|
|
|
939
1055
|
});
|
|
940
1056
|
await this.bindCurrentSession(options);
|
|
941
1057
|
}
|
|
1058
|
+
deactivateRuntimeForDraft() {
|
|
1059
|
+
const runtime = this.runtime;
|
|
1060
|
+
if (!runtime)
|
|
1061
|
+
return;
|
|
1062
|
+
const scopeKey = this.activeExtensionUiScope();
|
|
1063
|
+
// Clear the visible runtime before any UI cleanup. cancelCustomUi() can
|
|
1064
|
+
// synchronously render; leaving the old runtime attached during that render
|
|
1065
|
+
// lets tab synchronization incorrectly reactivate the previous real tab.
|
|
1066
|
+
this.runtime = undefined;
|
|
1067
|
+
this.extensionUiController.cancelCustomUi(scopeKey);
|
|
1068
|
+
this.extensionUiController.clearWidgets(scopeKey, { cancelCustomUi: false });
|
|
1069
|
+
void this.voiceController.stopRecording();
|
|
1070
|
+
this.sessionLifecycle.unsubscribeSession();
|
|
1071
|
+
}
|
|
942
1072
|
createExtensionEventBus() {
|
|
943
1073
|
return createIsolatedExtensionEventBus((channel, data) => {
|
|
944
1074
|
if (channel === TERMINAL_BELL_ATTENTION_EVENT)
|
|
945
1075
|
this.handleTerminalBellAttention(data);
|
|
946
1076
|
if (channel === SUBAGENTS_LIVE_STATE_EVENT)
|
|
947
1077
|
this.subagentsWidgetController.observeLiveState(data);
|
|
1078
|
+
if (channel === SUBAGENTS_CATALOG_STATE_EVENT) {
|
|
1079
|
+
const catalog = parseSubagentCatalogState(data);
|
|
1080
|
+
if (catalog?.sessionId)
|
|
1081
|
+
this.subagentCatalogBySessionId.set(catalog.sessionId, catalog);
|
|
1082
|
+
}
|
|
948
1083
|
if (channel === TODO_STATE_EVENT)
|
|
949
1084
|
this.todoWidgetController.observeLiveState(data);
|
|
950
1085
|
});
|
|
951
1086
|
}
|
|
1087
|
+
subagentTypesForRuntime(runtime) {
|
|
1088
|
+
const sessionId = runtime.session.sessionManager.getSessionId();
|
|
1089
|
+
const catalog = this.subagentCatalogBySessionId.get(sessionId);
|
|
1090
|
+
if (!catalog)
|
|
1091
|
+
return undefined;
|
|
1092
|
+
const model = runtime.session.model;
|
|
1093
|
+
const currentModelRef = model ? `${model.provider}/${model.id}` : undefined;
|
|
1094
|
+
if (catalog.model && currentModelRef && catalog.model !== currentModelRef)
|
|
1095
|
+
return undefined;
|
|
1096
|
+
return catalog.types;
|
|
1097
|
+
}
|
|
1098
|
+
contextInventoryText(runtime, heading) {
|
|
1099
|
+
return formatReloadContextInventory(createReloadContextInventory(runtime, this.subagentTypesForRuntime(runtime)), heading);
|
|
1100
|
+
}
|
|
952
1101
|
handleTerminalBellAttention(data) {
|
|
953
1102
|
const sessionFile = isRecord(data) && typeof data.sessionFile === "string" ? data.sessionFile : undefined;
|
|
954
1103
|
this.tabsController.markTerminalBellAttention(sessionFile);
|
|
@@ -1250,6 +1399,7 @@ export class PiUiExtendApp {
|
|
|
1250
1399
|
if (contentVersion === this.lastInputEditorContentVersion)
|
|
1251
1400
|
return;
|
|
1252
1401
|
this.lastInputEditorContentVersion = contentVersion;
|
|
1402
|
+
this.tabsController.noteActiveDraftInputChanged();
|
|
1253
1403
|
this.scrollController.scrollToBottom();
|
|
1254
1404
|
}
|
|
1255
1405
|
conversationQuickScrollDirections() {
|
package/dist/app/cli/install.js
CHANGED
|
@@ -59,7 +59,7 @@ export function inspectPixOnboarding(homeDir = homedir(), env = process.env) {
|
|
|
59
59
|
opencodeAntigravityExists: pixInstallDeps.existsSync(join(opencodeConfigDir, "antigravity-accounts.json")),
|
|
60
60
|
webCredentialsConfigured: Boolean(env.OLLAMA_API_KEY?.trim() || env.TAVILY_API_KEY?.trim()) || jsonObjectHasEntries(webCredentialPath),
|
|
61
61
|
context7Configured: Boolean(env.CONTEXT7_API_KEY?.trim()),
|
|
62
|
-
telegramConfigured: Boolean(env.
|
|
62
|
+
telegramConfigured: Boolean(env.PIX_TELEGRAM_BOT_TOKEN?.trim() && env.PIX_TELEGRAM_CHAT_ID?.trim()),
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
export function ensurePixSetupFiles(homeDir = homedir()) {
|
|
@@ -106,7 +106,7 @@ export function formatPixInstallNextSteps(homeDir = homedir(), state = inspectPi
|
|
|
106
106
|
"Optional integrations:",
|
|
107
107
|
` ${state.webCredentialsConfigured ? "✓ Web credentials detected." : "○ Web search: use local Ollama without a key, or run /web-credentials for Ollama Cloud/Tavily."}`,
|
|
108
108
|
` ${state.context7Configured ? "✓ Context7 API key detected." : "○ Context7 docs skill: export CONTEXT7_API_KEY."}`,
|
|
109
|
-
` ${state.telegramConfigured ? "✓ Telegram
|
|
109
|
+
` ${state.telegramConfigured ? "✓ Telegram connector credentials detected in the environment." : "○ Telegram connector: set telegramConnector in tools config or PIX_TELEGRAM_BOT_TOKEN plus PIX_TELEGRAM_CHAT_ID."}`,
|
|
110
110
|
" ○ Model-backed helpers: review promptEnhancer, autocomplete, and sessionTitle model refs; each provider needs its own credentials.",
|
|
111
111
|
" ○ Voice: set dictation.language in Pix config. LSP: configure and trust servers under lsp.servers in tools config.",
|
|
112
112
|
"",
|
|
@@ -4,14 +4,18 @@ export declare class AppCommandController {
|
|
|
4
4
|
private readonly host;
|
|
5
5
|
readonly slashCommands: readonly SlashCommand[];
|
|
6
6
|
private readonly modelActions;
|
|
7
|
+
private readonly gitActions;
|
|
7
8
|
private readonly sessionActions;
|
|
8
9
|
private readonly navigationActions;
|
|
9
10
|
constructor(host: CommandControllerHost);
|
|
10
11
|
runResumeCommand(queryOrOptions?: string | {
|
|
11
12
|
preserveStatus?: boolean;
|
|
12
13
|
placement?: PopupMenuPlacement;
|
|
14
|
+
draft?: boolean;
|
|
13
15
|
}): Promise<void>;
|
|
16
|
+
runDraftSessionSelector(): Promise<void>;
|
|
14
17
|
runModelCommand(model: SessionModel): Promise<void>;
|
|
18
|
+
runModelThinkingCommand(model: SessionModel, level: ThinkingLevel): Promise<void>;
|
|
15
19
|
runThinkingCommand(level: ThinkingLevel): Promise<void>;
|
|
16
20
|
private registryActions;
|
|
17
21
|
}
|