@herbertgao/pi-extensions 2026.8.4 → 2026.8.6
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 +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +106 -34
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
truncateToWidth,
|
|
20
20
|
visibleWidth,
|
|
21
21
|
} from "@earendil-works/pi-tui"
|
|
22
|
-
import { renderAgentName } from "../agent-color.js"
|
|
22
|
+
import { hasAgentBadge, renderAgentName } from "../agent-color.js"
|
|
23
23
|
import type { AgentManager } from "../agent-manager.js"
|
|
24
24
|
import type { AgentRecord } from "../types.js"
|
|
25
25
|
import { getLifetimeTotal } from "../usage.js"
|
|
@@ -476,15 +476,24 @@ export class FleetList {
|
|
|
476
476
|
width: number,
|
|
477
477
|
theme: Theme,
|
|
478
478
|
): string {
|
|
479
|
-
const
|
|
479
|
+
const selected = rosterIndex === sel
|
|
480
|
+
const name = renderAgentName(
|
|
481
|
+
record.type,
|
|
482
|
+
theme,
|
|
483
|
+
selected
|
|
484
|
+
? { fallbackColor: "text", bold: hasAgentBadge(record.type) }
|
|
485
|
+
: { fallbackColor: "muted" },
|
|
486
|
+
)
|
|
487
|
+
const description = selected
|
|
488
|
+
? theme.fg("text", record.description)
|
|
489
|
+
: record.description
|
|
490
|
+
const left = ` ${this.bullet(rosterIndex, sel, theme)} ${name} ${description}`
|
|
480
491
|
const tokens = getLifetimeTotal(
|
|
481
492
|
this.agentActivity.get(record.id)?.lifetimeUsage ?? record.lifetimeUsage,
|
|
482
493
|
)
|
|
483
494
|
const elapsedMs = (record.completedAt ?? Date.now()) - record.startedAt // freezes once finished
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
`${formatFleetElapsed(elapsedMs)} · ${formatFleetTokens(tokens)}`,
|
|
487
|
-
)
|
|
495
|
+
const stats = `${formatFleetElapsed(elapsedMs)} · ${formatFleetTokens(tokens)}`
|
|
496
|
+
const right = selected ? theme.fg("text", stats) : theme.fg("dim", stats)
|
|
488
497
|
return rightAlign(left, right, width)
|
|
489
498
|
}
|
|
490
499
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent"
|
|
12
12
|
import type { SubagentScheduler } from "../schedule.js"
|
|
13
13
|
import type { ScheduledSubagent } from "../types.js"
|
|
14
|
+
import { selectItem } from "./select-item.js"
|
|
14
15
|
|
|
15
16
|
/** Format an ISO timestamp as relative time ("in 4h", "2d ago", "—"). */
|
|
16
17
|
function relTime(iso: string | undefined, now = Date.now()): string {
|
|
@@ -88,16 +89,16 @@ export async function showSchedulesMenu(
|
|
|
88
89
|
return
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
// Numbered + item-paired: two jobs whose names agree in the first 18
|
|
93
|
+
// characters format identically, and matching the returned string back
|
|
94
|
+
// against a parallel label array cancelled whichever came first.
|
|
95
|
+
const job = await selectItem(
|
|
96
|
+
ctx.ui,
|
|
93
97
|
`Scheduled jobs (${jobs.length}) — select to cancel`,
|
|
94
|
-
|
|
98
|
+
jobs,
|
|
99
|
+
(j) => formatJob(j, scheduler),
|
|
95
100
|
)
|
|
96
|
-
if (!
|
|
97
|
-
|
|
98
|
-
const idx = labels.indexOf(choice)
|
|
99
|
-
if (idx < 0) return
|
|
100
|
-
const job = jobs[idx]
|
|
101
|
+
if (!job) return
|
|
101
102
|
|
|
102
103
|
const ok = await ctx.ui.confirm(
|
|
103
104
|
`Cancel "${job.name}"?`,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* select-item.ts — pick an item from a list via `ctx.ui.select`, safely.
|
|
3
|
+
*
|
|
4
|
+
* Pi's dialog API is `select(title, options: string[]) => Promise<string | undefined>`:
|
|
5
|
+
* strings in, string out, with no index or value form. Callers therefore have to
|
|
6
|
+
* map the returned string back to the item it came from, and the obvious way —
|
|
7
|
+
* `labels.indexOf(choice)` over a parallel array — silently resolves to the
|
|
8
|
+
* FIRST match whenever two rows format identically. Row formatters here truncate
|
|
9
|
+
* (job names to 18 chars, agent descriptions to whatever fits), and the text they
|
|
10
|
+
* truncate is LLM-authored, so collisions are ordinary rather than exotic.
|
|
11
|
+
*
|
|
12
|
+
* This numbers every row, which makes the labels unique by construction — no
|
|
13
|
+
* data-dependent branch that only executes in the case nobody exercises — and
|
|
14
|
+
* keeps each label paired with its item so a later edit that sorts or filters
|
|
15
|
+
* between building and resolving cannot desync them.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** Minimal shape of the `ctx.ui` surface this needs. */
|
|
19
|
+
export interface SelectUI {
|
|
20
|
+
select(title: string, options: string[]): Promise<string | undefined>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Show a numbered picker and return the chosen item (not its label).
|
|
25
|
+
*
|
|
26
|
+
* Returns undefined when the user escapes, or when the returned string is not
|
|
27
|
+
* one we offered.
|
|
28
|
+
*/
|
|
29
|
+
export async function selectItem<T>(
|
|
30
|
+
ui: SelectUI,
|
|
31
|
+
title: string,
|
|
32
|
+
items: readonly T[],
|
|
33
|
+
format: (item: T, index: number) => string,
|
|
34
|
+
): Promise<T | undefined> {
|
|
35
|
+
// Pad the number so a 10+ item list keeps its columns aligned.
|
|
36
|
+
const width = String(items.length).length
|
|
37
|
+
const rows = items.map((item, i) => ({
|
|
38
|
+
item,
|
|
39
|
+
label: `${String(i + 1).padStart(width)}. ${format(item, i)}`,
|
|
40
|
+
}))
|
|
41
|
+
|
|
42
|
+
const choice = await ui.select(
|
|
43
|
+
title,
|
|
44
|
+
rows.map((r) => r.label),
|
|
45
|
+
)
|
|
46
|
+
if (!choice) return undefined
|
|
47
|
+
return rows.find((r) => r.label === choice)?.item
|
|
48
|
+
}
|
|
@@ -134,11 +134,15 @@ export function cleanupWorktree(
|
|
|
134
134
|
// Truncate description for commit message (no shell sanitization needed — execFileSync uses argv)
|
|
135
135
|
const safeDesc = agentDescription.slice(0, 200)
|
|
136
136
|
const commitMsg = `pi-agent: ${safeDesc}`
|
|
137
|
-
execFileSync(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
execFileSync(
|
|
138
|
+
"git",
|
|
139
|
+
["commit", "--no-verify", "--no-gpg-sign", "-m", commitMsg],
|
|
140
|
+
{
|
|
141
|
+
cwd: worktree.path,
|
|
142
|
+
stdio: "pipe",
|
|
143
|
+
timeout: 10000,
|
|
144
|
+
},
|
|
145
|
+
)
|
|
142
146
|
} else {
|
|
143
147
|
const currentSha = execFileSync("git", ["rev-parse", "HEAD"], {
|
|
144
148
|
cwd: worktree.path,
|
|
@@ -27,6 +27,8 @@ Nothing to set up — the tool is live as soon as Pi restarts. Hand the model a
|
|
|
27
27
|
|
|
28
28
|
Rather than picking a strategy on your behalf, the model calls `ask_user_question` and a dialog takes over the bottom of your terminal. Move with `↑`/`↓`, choose with `Enter`, press `n` to attach a note, or land on the `Type something.` row to answer in your own words. While typing, `Shift+Enter` adds a line, `Ctrl+G` opens Pi's configured external editor, and `Ctrl+U` clears the draft; browsing another option and returning keeps what you wrote. `Esc` abandons the questionnaire entirely.
|
|
29
29
|
|
|
30
|
+
When the questionnaire begins waiting in an interactive TTY, it emits one standard terminal BEL (`\x07`). Your terminal configuration determines whether that appears as an audible alert, a visual alert, or nothing; redirected and non-TTY output is untouched.
|
|
31
|
+
|
|
30
32
|

|
|
31
33
|
|
|
32
34
|
When the model asks several things at once, `Tab` moves between them and a Submit tab reviews everything before it goes back:
|
|
@@ -61,6 +61,24 @@ const ERROR_SESSION_LOAD_FAILED =
|
|
|
61
61
|
const ERROR_STALE_MODULE_CACHE =
|
|
62
62
|
"Error: the questionnaire UI cannot load — the host's module cache went stale after an earlier failed load (typically dependencies replaced on disk mid-session). This is unrecoverable within the current Pi process. The user never saw the questions — do NOT treat this as a decline. Ask the questions as plain chat text instead, and tell the user to restart Pi to restore this tool.";
|
|
63
63
|
|
|
64
|
+
/** Standard terminal bell — same byte rpiv-warp exports as OSC_TERMINATOR. */
|
|
65
|
+
export const BEL = "\x07";
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Emit one portable terminal attention signal without touching redirected output.
|
|
69
|
+
* Writes to stdout rather than rpiv-warp's `/dev/tty` transport: the `isTTY` gate
|
|
70
|
+
* both proves an interactive terminal owns the coming wait and keeps the byte out
|
|
71
|
+
* of piped RPC transports (VS Code pendant, Zed) — a `/dev/tty` write would ring
|
|
72
|
+
* even when the questionnaire renders in a remote host's own UI.
|
|
73
|
+
*/
|
|
74
|
+
function emitTerminalAttention(): void {
|
|
75
|
+
try {
|
|
76
|
+
if (process.stdout.isTTY) process.stdout.write(BEL);
|
|
77
|
+
} catch {
|
|
78
|
+
// Terminal attention is best effort; the questionnaire must still proceed.
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
/** Delay before the background session-graph pre-warm; mirrors rpiv-workflow's /wf prewarm. */
|
|
65
83
|
export const PREWARM_DELAY_MS = 2000;
|
|
66
84
|
|
|
@@ -173,6 +191,7 @@ Preview content is rendered as markdown in a monospace box. Multi-line text with
|
|
|
173
191
|
if ((ctx as { mode?: string }).mode === "rpc" && hasDialogUI(ctx.ui)) {
|
|
174
192
|
emitAskUserBlockedEvent(pi, true);
|
|
175
193
|
try {
|
|
194
|
+
emitTerminalAttention();
|
|
176
195
|
return buildQuestionnaireResponse(await runRpcQuestionnaire(ctx.ui, typed), typed);
|
|
177
196
|
} finally {
|
|
178
197
|
emitAskUserBlockedEvent(pi, false);
|
|
@@ -232,6 +251,7 @@ Preview content is rendered as markdown in a monospace box. Multi-line text with
|
|
|
232
251
|
|
|
233
252
|
emitAskUserBlockedEvent(pi, true);
|
|
234
253
|
try {
|
|
254
|
+
emitTerminalAttention();
|
|
235
255
|
const result = await ctx.ui.custom<QuestionnaireResult>(
|
|
236
256
|
(tui, theme, keybindings, done) => {
|
|
237
257
|
const session = new QuestionnaireSession({
|
|
@@ -11,6 +11,12 @@ render at all.
|
|
|
11
11
|
| RPC / ACP host (VS Code pendant, Zed, Paseo) | `ask_user_question` in its tool list | A sequence of the host's own native select and input dialogs |
|
|
12
12
|
| Non-interactive run (no UI) | Nothing — the tool is removed | Nothing |
|
|
13
13
|
|
|
14
|
+
### Terminal attention
|
|
15
|
+
|
|
16
|
+
After UI availability and questionnaire validation succeed, the package emits exactly one standard terminal BEL (`\x07`) immediately before the interactive wait begins. The signal is sent to `stdout` only when `process.stdout.isTTY` is true, so redirected output and non-TTY RPC streams stay untouched. A TTY-backed RPC dialog walker receives the same signal as the TUI path.
|
|
17
|
+
|
|
18
|
+
The BEL is best effort: if the synchronous terminal write fails, the questionnaire continues and its existing prompt/blocked lifecycle and result envelope are unchanged. The terminal configuration decides whether the BEL is audible, visual, or ignored. No BEL is emitted for missing UI, invalid questionnaires, or a failed TUI session load.
|
|
19
|
+
|
|
14
20
|
### Non-interactive runs
|
|
15
21
|
|
|
16
22
|
A `before_agent_start` hook reconciles the active tool set against `ctx.hasUI` before every
|
|
@@ -18,6 +18,13 @@ adapts to the size of your terminal.
|
|
|
18
18
|
| `Ctrl+U` | Clear the current custom-answer draft. | `Type something.` input |
|
|
19
19
|
| `Ctrl+]` | Collapse or expand the dialog. Configurable via `collapseKey`. | Everywhere, including while collapsed |
|
|
20
20
|
|
|
21
|
+
The table names the default keys; the dialog actually follows your Pi keybindings.
|
|
22
|
+
Confirm listens to both `tui.select.confirm` and `tui.input.submit`, and a key bound to
|
|
23
|
+
`tui.input.newLine` always inserts a newline even if it also matches confirm. So a
|
|
24
|
+
Slack-style configuration — `enter` folded into `tui.input.newLine`, submit moved to
|
|
25
|
+
`ctrl+enter` — keeps working: `enter` breaks lines, and your submit key confirms
|
|
26
|
+
everywhere `Enter` does.
|
|
27
|
+
|
|
21
28
|
In a multi-select question, `Enter` on a regular row toggles its checkbox exactly like
|
|
22
29
|
`Space` — it does not submit. Committing the question means focusing the `Next` row and
|
|
23
30
|
pressing `Enter`. That is deliberate: it makes `Enter` a zero-cost way to flip boxes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juicesharp/rpiv-ask-user-question",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Pi extension. A structured questionnaire the model can put to you when it would otherwise guess, with typed options instead of free-form replies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@juicesharp/rpiv-config": "^2.
|
|
96
|
+
"@juicesharp/rpiv-config": "^2.6.0",
|
|
97
97
|
"typebox": "^1.1.24"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -130,6 +130,13 @@ class QuestionnaireBuilder {
|
|
|
130
130
|
const textEditorTheme = editorTheme(this.theme);
|
|
131
131
|
this.notesInput = new Editor(this.tui, textEditorTheme);
|
|
132
132
|
this.inlineInput = new Editor(this.tui, textEditorTheme);
|
|
133
|
+
// The key router owns confirm/submit semantics; keys reaching these headless
|
|
134
|
+
// editors are text-editing only. Without this, a `tui.input.submit` match inside
|
|
135
|
+
// Editor.handleInput would run submitValue(), which resets the buffer and
|
|
136
|
+
// silently destroys the draft — no onSubmit is wired here, so the text is
|
|
137
|
+
// unrecoverable (#156).
|
|
138
|
+
this.notesInput.disableSubmit = true;
|
|
139
|
+
this.inlineInput.disableSubmit = true;
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
build(): QuestionnaireBuilt {
|
|
@@ -6,6 +6,7 @@ import type { QuestionnaireRuntime, QuestionnaireState } from "./state.js";
|
|
|
6
6
|
const KEYBIND_UP = "tui.select.up";
|
|
7
7
|
const KEYBIND_DOWN = "tui.select.down";
|
|
8
8
|
const KEYBIND_CONFIRM = "tui.select.confirm";
|
|
9
|
+
const KEYBIND_SUBMIT = "tui.input.submit";
|
|
9
10
|
const KEYBIND_CANCEL = "tui.select.cancel";
|
|
10
11
|
const KEYBIND_NEW_LINE = "tui.input.newLine";
|
|
11
12
|
const KEYBIND_EDITOR_UP = "tui.editor.cursorUp";
|
|
@@ -39,6 +40,16 @@ export interface QuestionnaireKeybindings {
|
|
|
39
40
|
matches(data: string, name: string): boolean;
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
// Confirm has two semantic sources: `tui.select.confirm` (the select-list default)
|
|
44
|
+
// and `tui.input.submit` (the user's "send" key). A Slack-style configuration folds
|
|
45
|
+
// `enter` into `tui.input.newLine` and moves submit elsewhere (e.g. `ctrl+enter`);
|
|
46
|
+
// the newline checks below stay first, so without the submit source every confirm
|
|
47
|
+
// branch would be shadowed by the collision and no key could confirm (#156). With
|
|
48
|
+
// pi defaults both names resolve to `enter`, so matching either is equivalent.
|
|
49
|
+
function isConfirm(kb: QuestionnaireKeybindings, data: string): boolean {
|
|
50
|
+
return kb.matches(data, KEYBIND_CONFIRM) || kb.matches(data, KEYBIND_SUBMIT);
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
export function wrapTab(index: number, total: number): number {
|
|
43
54
|
if (total <= 0) return 0;
|
|
44
55
|
return ((index % total) + total) % total;
|
|
@@ -183,7 +194,7 @@ export function routeKey(data: string, state: QuestionnaireState, runtime: Quest
|
|
|
183
194
|
if (state.notesVisible) {
|
|
184
195
|
if (kb.matches(data, KEYBIND_CANCEL)) return { kind: "notes_exit" };
|
|
185
196
|
if (kb.matches(data, KEYBIND_NEW_LINE)) return { kind: "notes_forward", data };
|
|
186
|
-
if (kb
|
|
197
|
+
if (isConfirm(kb, data)) return { kind: "notes_exit" };
|
|
187
198
|
return { kind: "notes_forward", data };
|
|
188
199
|
}
|
|
189
200
|
|
|
@@ -191,7 +202,7 @@ export function routeKey(data: string, state: QuestionnaireState, runtime: Quest
|
|
|
191
202
|
// Newline takes precedence over confirmation if a user configuration binds
|
|
192
203
|
// the same physical key to both semantic actions.
|
|
193
204
|
if (kb.matches(data, KEYBIND_NEW_LINE)) return { kind: "ignore" };
|
|
194
|
-
if (kb
|
|
205
|
+
if (isConfirm(kb, data)) {
|
|
195
206
|
const answer = buildSingleSelectAnswer(state, runtime);
|
|
196
207
|
if (!answer) return { kind: "ignore" };
|
|
197
208
|
return { kind: "confirm", answer, autoAdvanceTab: computeAutoAdvanceTab(state, runtime) };
|
|
@@ -219,7 +230,7 @@ export function routeKey(data: string, state: QuestionnaireState, runtime: Quest
|
|
|
219
230
|
const next = wrapTab(state.submitChoiceIndex + delta, 2);
|
|
220
231
|
return { kind: "submit_nav", nextIndex: (next === 1 ? 1 : 0) as 0 | 1 };
|
|
221
232
|
}
|
|
222
|
-
if (kb
|
|
233
|
+
if (isConfirm(kb, data)) {
|
|
223
234
|
// D1 (revised): Submit always submits; Cancel always cancels. The warning header
|
|
224
235
|
// is informational only — `allAnswered(state)` no longer gates submission. Partial
|
|
225
236
|
// answers flow through `orderedAnswers()` in the host.
|
|
@@ -265,7 +276,7 @@ export function routeKey(data: string, state: QuestionnaireState, runtime: Quest
|
|
|
265
276
|
if (focusedMeta?.activatesInputMode) return { kind: "ignore" };
|
|
266
277
|
return { kind: "toggle", index: state.optionIndex };
|
|
267
278
|
}
|
|
268
|
-
if (kb
|
|
279
|
+
if (isConfirm(kb, data)) {
|
|
269
280
|
// Enter on the "Type something." row is handled by the inputMode block above
|
|
270
281
|
// (→ confirm kind:"custom"). Defensive: never enter the toggle/multi_confirm
|
|
271
282
|
// path for an inputMode-activating row.
|
|
@@ -289,7 +300,7 @@ export function routeKey(data: string, state: QuestionnaireState, runtime: Quest
|
|
|
289
300
|
return { kind: "ignore" };
|
|
290
301
|
}
|
|
291
302
|
|
|
292
|
-
if (kb
|
|
303
|
+
if (isConfirm(kb, data)) {
|
|
293
304
|
const answer = buildSingleSelectAnswer(state, runtime);
|
|
294
305
|
if (!answer) return { kind: "ignore" };
|
|
295
306
|
return { kind: "confirm", answer, autoAdvanceTab: computeAutoAdvanceTab(state, runtime) };
|
|
@@ -139,7 +139,9 @@ export class QuestionnaireSession {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
private mirrorNotesDraft(s: QuestionnaireState): QuestionnaireState {
|
|
142
|
-
|
|
142
|
+
// Drafts restore through Editor.setText, which clears the backing paste map —
|
|
143
|
+
// read expanded so stored drafts never orphan a paste marker.
|
|
144
|
+
const draft = this.notesInput.getExpandedText?.() ?? this.notesInput.getText();
|
|
143
145
|
return s.notesDraft === draft ? s : { ...s, notesDraft: draft };
|
|
144
146
|
}
|
|
145
147
|
|
|
@@ -202,7 +204,7 @@ export class QuestionnaireSession {
|
|
|
202
204
|
const lastLine = this.inlineInput.getLines().length - 1;
|
|
203
205
|
return {
|
|
204
206
|
keybindings: this.keybindings,
|
|
205
|
-
inputBuffer: this.inlineInput.getText(),
|
|
207
|
+
inputBuffer: this.inlineInput.getExpandedText?.() ?? this.inlineInput.getText(),
|
|
206
208
|
canMoveInputUp: cursor.line > 0,
|
|
207
209
|
canMoveInputDown: cursor.line < lastLine,
|
|
208
210
|
questions: this.questions,
|
|
@@ -18,7 +18,7 @@ Use it when you want to ask a temporary question, inspect context, or get a shor
|
|
|
18
18
|
- Optionally brings the latest answer, a question-to-end suffix, an exact line range, or the entire side thread into the main editor.
|
|
19
19
|
- Uses the current session branch as context.
|
|
20
20
|
- Uses Pi's current model or an independent model selected in `pi-btw.json`.
|
|
21
|
-
- Uses a pi-btw thinking level that can
|
|
21
|
+
- Uses a pi-btw thinking level that can either start from the main thread or use a fixed remembered value.
|
|
22
22
|
- Does not append the side question or answer to the main conversation.
|
|
23
23
|
- Works as an independently installable npm Pi extension package.
|
|
24
24
|
|
|
@@ -58,14 +58,15 @@ Examples:
|
|
|
58
58
|
/btw is this API name idiomatic?
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
Running `/btw` alone opens a menu with **Start side thread** selected first.
|
|
62
|
-
session has non-empty side threads in memory, **Resume side thread** opens a bounded choice list
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
is ordered by the newest recorded answer or visible error.
|
|
66
|
-
new result does not reorder it.
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
Running `/btw` alone opens a menu with **Start side thread** selected first.
|
|
62
|
+
When the current Pi session has non-empty side threads in memory, **Resume side thread** opens a bounded searchable choice list.
|
|
63
|
+
Search matches the displayed first question and question count while returning the thread's raw in-memory ID.
|
|
64
|
+
**Settings** changes the starting thinking level and whether shortcut changes for fixed levels are remembered.
|
|
65
|
+
Each Resume row keeps the first question as its fixed title, shows its question count, and the list is ordered by the newest recorded answer or visible error.
|
|
66
|
+
Opening and closing a thread without a new result does not reorder it.
|
|
67
|
+
`/btw <question>` bypasses this menu and always starts a fresh side thread.
|
|
68
|
+
Its answer opens above the side-thread editor.
|
|
69
|
+
The side thread uses a dedicated full-screen terminal view.
|
|
69
70
|
The main agent continues running in the background, but its screen rendering stays suspended until
|
|
70
71
|
`/btw` closes, so new main-thread output cannot move a mouse selection inside the side thread.
|
|
71
72
|
Drag the primary mouse button across side-thread text to select and copy it through Pi's terminal
|
|
@@ -78,9 +79,11 @@ Previous side questions and answers remain available to the model and visible fo
|
|
|
78
79
|
invocation. The side-thread header shows its current thinking level. Press Pi's configured
|
|
79
80
|
`app.thinking.cycle` shortcut (`Shift+Tab` by default) in the composer to cycle the levels
|
|
80
81
|
supported by the side-thread model; every later question uses the displayed level until it is
|
|
81
|
-
changed again.
|
|
82
|
-
invocation. Turn **Remember thinking level changes** off in
|
|
83
|
-
current side thread.
|
|
82
|
+
changed again. When a fixed thinking level is selected, each shortcut change is also written to
|
|
83
|
+
`pi-btw.json` for the next invocation by default. Turn **Remember thinking level changes** off in
|
|
84
|
+
Settings to keep fixed-level changes local to the current side thread. When **Same as main thread** is
|
|
85
|
+
selected, shortcut changes are always local to the current side thread. Neither path changes the main
|
|
86
|
+
session's thinking level.
|
|
84
87
|
While a response is running, the transcript and composer remain visible above an `Answering…`
|
|
85
88
|
status.
|
|
86
89
|
Type another question and press `Enter` to queue it as `Steering`; queued questions are shown in
|
|
@@ -147,18 +150,23 @@ cannot be found or authenticated, pi-btw warns and falls back to the current ses
|
|
|
147
150
|
If neither model is available, `/btw` reports an error and stops. This selection affects only
|
|
148
151
|
`/btw`; it does not change the main session model.
|
|
149
152
|
|
|
150
|
-
Pi calls its reasoning setting the **thinking level**.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
`
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
A
|
|
153
|
+
Pi calls its reasoning setting the **thinking level**. In Settings, choose **Same as main thread**
|
|
154
|
+
to start each new side thread from the main thread's current thinking level. This is stored by
|
|
155
|
+
omitting `thinkingLevel` from `pi-btw.json`.
|
|
156
|
+
|
|
157
|
+
Set `thinkingLevel` only when you want a fixed pi-btw starting level. Accepted fixed values are
|
|
158
|
+
`off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. The initial value and shortcut cycle
|
|
159
|
+
are clamped to the selected side model's capabilities using Pi's model rules. Resumed side threads
|
|
160
|
+
keep their own local thinking level instead of re-syncing with the main thread. Pi-btw does not read,
|
|
161
|
+
write, or change the main session's `defaultThinkingLevel`.
|
|
162
|
+
|
|
163
|
+
`rememberThinkingLevelChanges` controls only persistence for fixed thinking levels and defaults to
|
|
164
|
+
`true` when omitted. A side-thread shortcut always changes that side thread immediately. When a fixed
|
|
165
|
+
thinking level is selected and remembering is on, the concrete level is written for the next
|
|
166
|
+
invocation; when off, `pi-btw.json` stays unchanged. When **Same as main thread** is selected,
|
|
167
|
+
shortcut changes stay local even when remembering is on. If a shortcut write fails, the local change
|
|
168
|
+
remains active and pi-btw warns that it was not remembered. A failed Settings-screen save instead
|
|
169
|
+
restores the previous displayed value.
|
|
162
170
|
|
|
163
171
|
A missing settings file is a side-effect-free read: pi-btw creates it only after a Settings change
|
|
164
172
|
or a remembered shortcut change. Saves are ordered within the Pi process and published atomically
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-btw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.52.0",
|
|
4
4
|
"description": "Pi extension that adds a /btw side-question command.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"typecheck": "tsc --noEmit"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@biomejs/biome": "2.5.
|
|
35
|
-
"@earendil-works/pi-ai": "0.84.
|
|
36
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
37
|
-
"@earendil-works/pi-tui": "0.84.
|
|
34
|
+
"@biomejs/biome": "2.5.8",
|
|
35
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
36
|
+
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
37
|
+
"@earendil-works/pi-tui": "0.84.2",
|
|
38
38
|
"typescript": "7.0.2"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"directory": "packages/pi-btw"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@narumitw/pi-tui-kit": "^0.
|
|
46
|
+
"@narumitw/pi-tui-kit": "^0.54.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@earendil-works/pi-ai": "*",
|
|
@@ -194,7 +194,7 @@ export async function loadBtwThinkingLevel(
|
|
|
194
194
|
|
|
195
195
|
options.warn?.(
|
|
196
196
|
sanitizeSingleLine(
|
|
197
|
-
`pi-btw settings ignored: ${settings.reason}; expected optional model "provider/model-id", thinkingLevel "${BTW_THINKING_LEVELS.join('" | "')}", and boolean rememberThinkingLevelChanges. Using current Pi thinking level.`,
|
|
197
|
+
`pi-btw settings ignored: ${settings.reason}; expected optional model "provider/model-id", omitted thinkingLevel for Same as main thread or thinkingLevel "${BTW_THINKING_LEVELS.join('" | "')}", and boolean rememberThinkingLevelChanges. Using current Pi thinking level.`,
|
|
198
198
|
),
|
|
199
199
|
);
|
|
200
200
|
return currentThinkingLevel;
|
|
@@ -265,6 +265,7 @@ export default function btw(pi: ExtensionAPI, dependencies: BtwExtensionDependen
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const settings = await loadSettings(ctx);
|
|
268
|
+
const sameAsMainThinkingLevel = settings.thinkingLevel === undefined;
|
|
268
269
|
const resolution = await resolveModel(settings, ctx);
|
|
269
270
|
if (resolution.kind === "cancelled") {
|
|
270
271
|
notifySafely(ctx, "Cancelled", "info");
|
|
@@ -302,7 +303,8 @@ export default function btw(pi: ExtensionAPI, dependencies: BtwExtensionDependen
|
|
|
302
303
|
initialQuestion: question || undefined,
|
|
303
304
|
selected: resolution.selected,
|
|
304
305
|
thinkingLevel: state.thinkingLevel,
|
|
305
|
-
rememberThinkingLevelChanges:
|
|
306
|
+
rememberThinkingLevelChanges:
|
|
307
|
+
!sameAsMainThinkingLevel && effectiveRememberThinkingLevelChanges(settings),
|
|
306
308
|
state,
|
|
307
309
|
ctx: fullscreenCtx,
|
|
308
310
|
});
|
|
@@ -7,6 +7,7 @@ import type { Component, TUI } from "@earendil-works/pi-tui";
|
|
|
7
7
|
import type { MenuContext, RunMenuResult } from "@narumitw/pi-tui-kit";
|
|
8
8
|
import {
|
|
9
9
|
type BtwSettings,
|
|
10
|
+
type BtwSettingsPatch,
|
|
10
11
|
btwSettingsPath,
|
|
11
12
|
effectiveRememberThinkingLevelChanges,
|
|
12
13
|
readBtwSettings,
|
|
@@ -35,7 +36,7 @@ export interface ShowBtwCommandMenuOptions {
|
|
|
35
36
|
settingsPath?: string;
|
|
36
37
|
readSettings?: typeof readBtwSettings;
|
|
37
38
|
updateSettings?: (
|
|
38
|
-
patch:
|
|
39
|
+
patch: BtwSettingsPatch,
|
|
39
40
|
options: UpdateBtwSettingsOptions,
|
|
40
41
|
) => Promise<BtwSettings>;
|
|
41
42
|
}
|
|
@@ -44,6 +45,7 @@ export type BtwCommandMenuResult = "start" | "closed" | { kind: "resume"; thread
|
|
|
44
45
|
|
|
45
46
|
type BtwMenuScreen = "main" | "resume" | "settings" | "invalid";
|
|
46
47
|
type BtwMenuAction = "start" | "resume" | "set-thinking" | "set-remember";
|
|
48
|
+
const SAME_AS_MAIN_THREAD = "Same as main thread";
|
|
47
49
|
type BtwCustomOptions = Parameters<ExtensionCommandContext["ui"]["custom"]>[1];
|
|
48
50
|
|
|
49
51
|
type BtwCustomFactory<T> = (
|
|
@@ -79,8 +81,22 @@ export async function showBtwCommandMenu(
|
|
|
79
81
|
}
|
|
80
82
|
return { kind: "valid", settings: loaded.kind === "loaded" ? loaded.settings : {} };
|
|
81
83
|
};
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
+
const currentMainThinkingLevel = clampToAvailableThinkingLevel(
|
|
85
|
+
options.currentThinkingLevel,
|
|
86
|
+
levels,
|
|
87
|
+
);
|
|
88
|
+
const displayThinkingLevel = (settings: BtwSettings): string =>
|
|
89
|
+
settings.thinkingLevel === undefined
|
|
90
|
+
? SAME_AS_MAIN_THREAD
|
|
91
|
+
: clampToAvailableThinkingLevel(settings.thinkingLevel, levels);
|
|
92
|
+
const displayThinkingSummary = (settings: BtwSettings): string =>
|
|
93
|
+
settings.thinkingLevel === undefined
|
|
94
|
+
? `${SAME_AS_MAIN_THREAD} (currently ${currentMainThinkingLevel})`
|
|
95
|
+
: displayThinkingLevel(settings);
|
|
96
|
+
const displayRememberSummary = (settings: BtwSettings): string => {
|
|
97
|
+
const value = effectiveRememberThinkingLevelChanges(settings) ? "On" : "Off";
|
|
98
|
+
return settings.thinkingLevel === undefined ? `${value} (fixed levels only)` : value;
|
|
99
|
+
};
|
|
84
100
|
|
|
85
101
|
const menu = defineMenu<BtwMenuState, BtwMenuScreen, BtwMenuAction, MenuContext>({
|
|
86
102
|
start: "main",
|
|
@@ -89,7 +105,7 @@ export async function showBtwCommandMenu(
|
|
|
89
105
|
kind: "actions",
|
|
90
106
|
title: "Pi BTW",
|
|
91
107
|
lines: [
|
|
92
|
-
`Thinking: ${
|
|
108
|
+
`Thinking: ${displayThinkingSummary(state.settings)} · Remember changes: ${displayRememberSummary(state.settings)}`,
|
|
93
109
|
],
|
|
94
110
|
items: [
|
|
95
111
|
{
|
|
@@ -111,7 +127,7 @@ export async function showBtwCommandMenu(
|
|
|
111
127
|
{
|
|
112
128
|
id: "settings",
|
|
113
129
|
label: "Settings",
|
|
114
|
-
description: "Choose pi-btw thinking and
|
|
130
|
+
description: "Choose pi-btw thinking level and fixed-level shortcut memory",
|
|
115
131
|
to: state.kind === "invalid" ? "invalid" : "settings",
|
|
116
132
|
},
|
|
117
133
|
],
|
|
@@ -120,6 +136,7 @@ export async function showBtwCommandMenu(
|
|
|
120
136
|
resume: () => ({
|
|
121
137
|
kind: "choice",
|
|
122
138
|
title: "Resume BTW side thread",
|
|
139
|
+
enableSearch: true,
|
|
123
140
|
items: resumeThreads.map((thread) => ({
|
|
124
141
|
id: thread.id,
|
|
125
142
|
label: thread.title,
|
|
@@ -137,15 +154,15 @@ export async function showBtwCommandMenu(
|
|
|
137
154
|
{
|
|
138
155
|
id: "thinkingLevel",
|
|
139
156
|
label: "Thinking level",
|
|
140
|
-
description:
|
|
157
|
+
description: `Set the starting level for future pi-btw side threads. Currently ${currentMainThinkingLevel}.`,
|
|
141
158
|
currentValue: displayThinkingLevel(state.settings),
|
|
142
|
-
values: levels,
|
|
159
|
+
values: [SAME_AS_MAIN_THREAD, ...levels],
|
|
143
160
|
action: "set-thinking",
|
|
144
161
|
},
|
|
145
162
|
{
|
|
146
163
|
id: "rememberThinkingLevelChanges",
|
|
147
164
|
label: "Remember thinking level changes",
|
|
148
|
-
description: "Save
|
|
165
|
+
description: "Save shortcut changes for fixed thinking levels to pi-btw.json.",
|
|
149
166
|
currentValue: effectiveRememberThinkingLevelChanges(state.settings) ? "On" : "Off",
|
|
150
167
|
values: ["On", "Off"],
|
|
151
168
|
action: "set-remember",
|
|
@@ -175,12 +192,16 @@ export async function showBtwCommandMenu(
|
|
|
175
192
|
return { kind: "close" } as const;
|
|
176
193
|
},
|
|
177
194
|
"set-thinking": async ({ value, signal }) => {
|
|
178
|
-
if (!value
|
|
195
|
+
if (!value) return { kind: "rejected" };
|
|
196
|
+
const patch =
|
|
197
|
+
value === SAME_AS_MAIN_THREAD
|
|
198
|
+
? ({ thinkingLevel: undefined } satisfies BtwSettingsPatch)
|
|
199
|
+
: levels.includes(value as BtwThinkingLevel)
|
|
200
|
+
? ({ thinkingLevel: value as BtwThinkingLevel } satisfies BtwSettingsPatch)
|
|
201
|
+
: undefined;
|
|
202
|
+
if (!patch) return { kind: "rejected" };
|
|
179
203
|
try {
|
|
180
|
-
await updateSettings(
|
|
181
|
-
{ thinkingLevel: value as BtwThinkingLevel },
|
|
182
|
-
{ settingsPath, signal },
|
|
183
|
-
);
|
|
204
|
+
await updateSettings(patch, { settingsPath, signal });
|
|
184
205
|
if (signal.aborted) return { kind: "rejected" };
|
|
185
206
|
notifySafely(ctx, `Pi BTW thinking level: ${value}.`, "info");
|
|
186
207
|
return { kind: "stay" };
|