@herbertgao/pi-extensions 2026.9.0 → 2026.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +13 -1
- package/node_modules/@czottmann/pi-automode/README.md +20 -0
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +1 -1
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +2 -1
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +3 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +38 -2
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +5 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +11 -3
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/README.md +57 -141
- package/node_modules/@narumitw/pi-btw/dist/index.ts +466 -41
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
- package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
- package/node_modules/@narumitw/pi-btw/package.json +2 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +15 -1
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
- package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
- package/node_modules/@pi-plugins/fast-mode/README.md +5 -3
- package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
- package/node_modules/pi-lens/CHANGELOG.md +1072 -0
- package/node_modules/pi-lens/README.md +3 -0
- package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
- package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -3
- package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -6
- package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -9
- package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +3 -11
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
- package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
- package/node_modules/pi-lens/dist/clients/cache-observability.js +40 -19
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
- package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
- package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
- package/node_modules/pi-lens/dist/clients/config-core/index.js +50 -0
- package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
- package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +164 -0
- package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
- package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
- package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +165 -0
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
- package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
- package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
- package/node_modules/pi-lens/dist/clients/config-schema.js +234 -0
- package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -6
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
- package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
- package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
- package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +15 -5
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -44
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +27 -8
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +383 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +14 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +1 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +4 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -67
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
- package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -10
- package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
- package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
- package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +2 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -2
- package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
- package/node_modules/pi-lens/dist/clients/file-time.js +7 -2
- package/node_modules/pi-lens/dist/clients/file-utils.js +117 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
- package/node_modules/pi-lens/dist/clients/format-service.js +6 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +385 -104
- package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +116 -22
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
- package/node_modules/pi-lens/dist/clients/git-guard.js +6 -1
- package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
- package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
- package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
- package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
- package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +289 -59
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +110 -236
- package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
- package/node_modules/pi-lens/dist/clients/language-profile.js +0 -9
- package/node_modules/pi-lens/dist/clients/language-registry.js +599 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +165 -9
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +34 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +160 -30
- package/node_modules/pi-lens/dist/clients/lens-engine.js +33 -41
- package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +77 -6
- package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -38
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +172 -33
- package/node_modules/pi-lens/dist/clients/lsp/config.js +484 -158
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +18 -5
- package/node_modules/pi-lens/dist/clients/lsp/index.js +892 -96
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -177
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -18
- package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +14 -7
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
- package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
- package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +3 -5
- package/node_modules/pi-lens/dist/clients/module-report.js +21 -46
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
- package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -24
- package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +70 -28
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +5 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
- package/node_modules/pi-lens/dist/clients/path-utils.js +451 -15
- package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
- package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +79 -18
- package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
- package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
- package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +28 -4
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +438 -122
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
- package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
- package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
- package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
- package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +16 -5
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
- package/node_modules/pi-lens/dist/clients/read-guard.js +26 -2
- package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +155 -114
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
- package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
- package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +19 -3
- package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
- package/node_modules/pi-lens/dist/clients/runtime-session.js +184 -32
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +179 -36
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
- package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
- package/node_modules/pi-lens/dist/clients/sanitize.js +7 -12
- package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
- package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
- package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
- package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
- package/node_modules/pi-lens/dist/clients/sgconfig.js +7 -6
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +4 -4
- package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
- package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
- package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +244 -0
- package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
- package/node_modules/pi-lens/dist/clients/tool-policy.js +92 -22
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +87 -100
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
- package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
- package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
- package/node_modules/pi-lens/dist/clients/user-notify.js +6 -6
- package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -9
- package/node_modules/pi-lens/dist/clients/word-index-store.js +23 -12
- package/node_modules/pi-lens/dist/clients/word-index.js +252 -47
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +4 -1
- package/node_modules/pi-lens/dist/index.js +65899 -55340
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
- package/node_modules/pi-lens/dist/mcp/server.js +127 -5
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +96 -25
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +104 -86
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
- package/node_modules/pi-lens/dist/tools/render-compact.js +1 -1
- package/node_modules/pi-lens/dist/tools/shared.js +0 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -2
- package/node_modules/pi-lens/docs/agent-guide.md +64 -1
- package/node_modules/pi-lens/docs/configuration.md +222 -0
- package/node_modules/pi-lens/docs/dependencies.md +3 -3
- package/node_modules/pi-lens/docs/features.md +44 -5
- package/node_modules/pi-lens/docs/globalconfig.md +20 -0
- package/node_modules/pi-lens/docs/language-coverage.md +2 -2
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +33 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +49 -0
- package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
- package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +190 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +7 -3
- package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
- package/node_modules/pi-lens/docs/word-index.md +1 -1
- package/node_modules/pi-lens/package.json +18 -35
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
- package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
- package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
- package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
- package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
- package/node_modules/pi-web-access/CHANGELOG.md +28 -0
- package/node_modules/pi-web-access/README.md +62 -15
- package/node_modules/pi-web-access/curator-page.ts +3 -1
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/gemini-search.ts +8 -4
- package/node_modules/pi-web-access/github-extract.ts +242 -1
- package/node_modules/pi-web-access/index.ts +118 -64
- package/node_modules/pi-web-access/mistral-search.ts +281 -0
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/perplexity.ts +14 -1
- package/node_modules/pi-web-access/utils.ts +23 -6
- package/node_modules/pi-web-access/xai-search.ts +96 -33
- package/package.json +6 -6
|
@@ -2,21 +2,14 @@ import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
3
3
|
import { Array, Cause, Data, Effect, Exit, FileSystem, Inspectable, Match, Order, Path, Predicate, Record, Schema, String, pipe } from "effect";
|
|
4
4
|
//#region ../../tooling/shared/src/run.ts
|
|
5
|
-
const ABORT_MESSAGE = "Operation aborted";
|
|
6
5
|
function causeMessage(cause) {
|
|
7
|
-
if (Cause.hasInterruptsOnly(cause)) return
|
|
6
|
+
if (Cause.hasInterruptsOnly(cause)) return "Operation aborted";
|
|
8
7
|
if (Cause.hasDies(cause)) return Cause.pretty(cause);
|
|
9
8
|
return cause.reasons.filter(Cause.isFailReason).map(({ error }) => {
|
|
10
9
|
if (error instanceof Error) return error.message || error.name;
|
|
11
10
|
return typeof error === "string" ? error : Inspectable.toStringUnknown(error);
|
|
12
11
|
}).join("\n");
|
|
13
12
|
}
|
|
14
|
-
/**
|
|
15
|
-
* For boundaries where pi reports rejections but expected failures should
|
|
16
|
-
* degrade gracefully (event hooks, commands, background work). Expected
|
|
17
|
-
* failures and interrupts never reject. Without `onError` they vanish, while
|
|
18
|
-
* defects rethrow so pi's handler boundary reports the bug.
|
|
19
|
-
*/
|
|
20
13
|
async function runHandler(effect, options) {
|
|
21
14
|
const exit = await Effect.runPromiseExit(effect);
|
|
22
15
|
if (Exit.isSuccess(exit)) return exit.value;
|
|
@@ -26,11 +19,6 @@ async function runHandler(effect, options) {
|
|
|
26
19
|
}
|
|
27
20
|
//#endregion
|
|
28
21
|
//#region ../../tooling/shared/src/config.ts
|
|
29
|
-
/**
|
|
30
|
-
* A missing config file yields `defaults` silently. An unreadable or invalid
|
|
31
|
-
* one warns and yields `defaults`, so a typo downgrades the extension rather
|
|
32
|
-
* than breaking it.
|
|
33
|
-
*/
|
|
34
22
|
const loadExtensionConfig = Effect.fnUntraced(function* (_ctx, schema, name, _defaults) {
|
|
35
23
|
const fs = yield* FileSystem.FileSystem;
|
|
36
24
|
const file = (yield* Path.Path).join(getAgentDir(), "extensions", `${name}.json`);
|
|
@@ -44,44 +32,16 @@ const loadExtensionConfig = Effect.fnUntraced(function* (_ctx, schema, name, _de
|
|
|
44
32
|
//#region ../../tooling/shared/src/statusline.ts
|
|
45
33
|
const WIDGET_KEY = "pi-plugins:statusline";
|
|
46
34
|
const REGISTRY_KEY = Symbol.for("@pi-plugins/statusline-registry");
|
|
47
|
-
function registry() {
|
|
48
|
-
const store = globalThis;
|
|
49
|
-
store[REGISTRY_KEY] ??= /* @__PURE__ */ new Map();
|
|
50
|
-
return store[REGISTRY_KEY];
|
|
51
|
-
}
|
|
52
|
-
const byKey = Order.mapInput(Order.String, ([key]) => key);
|
|
53
35
|
function side(segments, align) {
|
|
54
|
-
return pipe(Array.fromIterable(segments), Array.filter(([, segment]) => segment.align === align), Array.sortBy(
|
|
36
|
+
return pipe(Array.fromIterable(segments), Array.filter(([, segment]) => segment.align === align), Array.sortBy(Order.mapInput(Order.String, ([key]) => key)), Array.map(([, segment]) => segment.text), Array.join(" · "));
|
|
55
37
|
}
|
|
56
|
-
/** Terminal columns of plain text (code points, no ANSI). */
|
|
57
38
|
function textWidth(text) {
|
|
58
39
|
return Array.fromIterable(text).length;
|
|
59
40
|
}
|
|
60
|
-
function truncate(text, columns) {
|
|
61
|
-
return pipe(Array.fromIterable(text), Array.take(columns), Array.join(""));
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Lays out `left ... right` across `width`: left indented one column to match
|
|
65
|
-
* pi's built-in widget rows, right flush against the terminal edge to match
|
|
66
|
-
* pi's footer. Falls back to one truncated `left · right` run when too narrow.
|
|
67
|
-
*/
|
|
68
|
-
function renderLine(segments, width, theme) {
|
|
69
|
-
const left = side(segments, "left");
|
|
70
|
-
const right = side(segments, "right");
|
|
71
|
-
const margin = Math.min(width, 1);
|
|
72
|
-
const inner = width - margin;
|
|
73
|
-
const gap = inner - textWidth(left) - textWidth(right);
|
|
74
|
-
const minGap = String.isNonEmpty(left) && String.isNonEmpty(right) ? 2 : 0;
|
|
75
|
-
const line = String.isNonEmpty(right) && gap >= minGap ? `${left}${" ".repeat(gap)}${right}` : truncate(pipe([left, right], Array.filter(String.isNonEmpty), Array.join(" · ")), Math.max(inner, 0));
|
|
76
|
-
return " ".repeat(margin) + theme.fg("dim", line);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Adds, replaces (`segment`), or removes (`undefined`) a keyed segment on a
|
|
80
|
-
* single status line above the editor shared across pi-plugins extensions,
|
|
81
|
-
* instead of each plugin stacking its own widget row.
|
|
82
|
-
*/
|
|
83
41
|
function setStatuslineSegment(ctx, key, segment) {
|
|
84
|
-
const
|
|
42
|
+
const store = globalThis;
|
|
43
|
+
store[REGISTRY_KEY] ??= /* @__PURE__ */ new Map();
|
|
44
|
+
const segments = store[REGISTRY_KEY];
|
|
85
45
|
if (segment === void 0) segments.delete(key);
|
|
86
46
|
else segments.set(key, segment);
|
|
87
47
|
if (!ctx.hasUI) return;
|
|
@@ -90,8 +50,17 @@ function setStatuslineSegment(ctx, key, segment) {
|
|
|
90
50
|
return;
|
|
91
51
|
}
|
|
92
52
|
ctx.ui.setWidget(WIDGET_KEY, (_tui, theme) => ({
|
|
93
|
-
|
|
94
|
-
|
|
53
|
+
invalidate: () => {},
|
|
54
|
+
render: (width) => {
|
|
55
|
+
const left = side(segments, "left");
|
|
56
|
+
const right = side(segments, "right");
|
|
57
|
+
const margin = Math.min(width, 1);
|
|
58
|
+
const inner = width - margin;
|
|
59
|
+
const gap = inner - textWidth(left) - textWidth(right);
|
|
60
|
+
const minGap = String.isNonEmpty(left) && String.isNonEmpty(right) ? 2 : 0;
|
|
61
|
+
const line = String.isNonEmpty(right) && gap >= minGap ? `${left}${" ".repeat(gap)}${right}` : pipe([left, right], Array.filter(String.isNonEmpty), Array.join(" · "), Array.fromIterable, Array.take(Math.max(inner, 0)), Array.join(""));
|
|
62
|
+
return [" ".repeat(margin) + theme.fg("dim", line)];
|
|
63
|
+
}
|
|
95
64
|
}));
|
|
96
65
|
}
|
|
97
66
|
//#endregion
|
|
@@ -102,30 +71,26 @@ const COMMAND_ARGS = [
|
|
|
102
71
|
"off",
|
|
103
72
|
"status"
|
|
104
73
|
];
|
|
105
|
-
/** Status-line segment shown above the editor while fast mode is active. */
|
|
106
74
|
const SEGMENT_KEY = EXTENSION_ID;
|
|
107
75
|
const SEGMENT_LABEL = "[fast mode]";
|
|
108
76
|
const FastModeConfig = Schema.Struct({
|
|
109
77
|
enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
|
|
110
|
-
/** `provider/model-id` keys that fast mode applies to. */
|
|
111
78
|
models: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(Effect.succeed([
|
|
112
79
|
"openai/gpt-5.4",
|
|
113
80
|
"openai/gpt-5.5",
|
|
114
81
|
"openai/gpt-5.6-sol",
|
|
115
82
|
"openai/gpt-5.6-terra",
|
|
116
83
|
"openai/gpt-5.6-luna",
|
|
84
|
+
"openai/gpt-6-astra",
|
|
117
85
|
"openai-codex/gpt-5.4",
|
|
118
86
|
"openai-codex/gpt-5.5",
|
|
119
87
|
"openai-codex/gpt-5.6-sol",
|
|
120
88
|
"openai-codex/gpt-5.6-terra",
|
|
121
|
-
"openai-codex/gpt-5.6-luna"
|
|
89
|
+
"openai-codex/gpt-5.6-luna",
|
|
90
|
+
"openai-codex/gpt-6-astra"
|
|
122
91
|
]))),
|
|
123
|
-
/** Show a `fast mode` indicator above the editor while active. */
|
|
124
92
|
showStatus: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true)))
|
|
125
93
|
});
|
|
126
|
-
function modelKey(model) {
|
|
127
|
-
return `${model.provider}/${model.id}`;
|
|
128
|
-
}
|
|
129
94
|
const Eligibility = Data.taggedEnum();
|
|
130
95
|
const FAST_APPLICATORS = {
|
|
131
96
|
"openai-responses": applyOpenAIPriorityTier,
|
|
@@ -142,7 +107,7 @@ function fastMode(pi) {
|
|
|
142
107
|
let enabled = false;
|
|
143
108
|
function checkEligibility(model) {
|
|
144
109
|
if (!model) return Eligibility.Ineligible({ message: "no model is selected" });
|
|
145
|
-
const key =
|
|
110
|
+
const key = `${model.provider}/${model.id}`;
|
|
146
111
|
if (!config.models.includes(key)) return Eligibility.Ineligible({ message: `${key} is not in the configured models` });
|
|
147
112
|
const apply = FAST_APPLICATORS[model.api];
|
|
148
113
|
if (!apply) return Eligibility.Ineligible({ message: `the ${model.api} API has no fast-mode support` });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../tooling/shared/src/run.ts","../../../tooling/shared/src/config.ts","../../../tooling/shared/src/statusline.ts","../src/index.ts"],"sourcesContent":["import { Cause, Effect, Exit, Inspectable } from 'effect'\n\n// What pi's own tools throw for a cancelled run, so interrupted plugin runs\n// read like interrupted builtins.\nconst ABORT_MESSAGE = 'Operation aborted'\n\nexport interface RunOptions {\n readonly signal?: AbortSignal | undefined\n}\n\n// Defects keep their stack because they are bugs, and win over failures in a\n// mixed cause.\nfunction causeMessage(cause: Cause.Cause<unknown>): string {\n if (Cause.hasInterruptsOnly(cause)) {\n return ABORT_MESSAGE\n }\n if (Cause.hasDies(cause)) {\n return Cause.pretty(cause)\n }\n return cause.reasons\n .filter(Cause.isFailReason)\n .map(({ error }) => {\n if (error instanceof Error) {\n return error.message || error.name\n }\n return typeof error === 'string' ? error : Inspectable.toStringUnknown(error)\n })\n .join('\\n')\n}\n\n/**\n * Failure rejects with an `Error` whose message is what the model reads back\n * as the tool result, so it is written for the model rather than for a log.\n */\nexport async function runTool<A, E>(\n effect: Effect.Effect<A, E>,\n options?: RunOptions,\n): Promise<A> {\n const exit = await Effect.runPromiseExit(effect, options)\n if (Exit.isFailure(exit)) {\n throw new Error(causeMessage(exit.cause))\n }\n return exit.value\n}\n\nexport interface RunHandlerOptions<B> {\n readonly onError?: (message: string) => B\n}\n\n/**\n * For boundaries where pi reports rejections but expected failures should\n * degrade gracefully (event hooks, commands, background work). Expected\n * failures and interrupts never reject. Without `onError` they vanish, while\n * defects rethrow so pi's handler boundary reports the bug.\n */\nexport async function runHandler<A, E, B = undefined>(\n effect: Effect.Effect<A, E>,\n options?: RunHandlerOptions<B>,\n): Promise<A | B> {\n const exit = await Effect.runPromiseExit(effect)\n if (Exit.isSuccess(exit)) {\n return exit.value\n }\n if (options?.onError) {\n return options.onError(causeMessage(exit.cause))\n }\n const die = exit.cause.reasons.find(Cause.isDieReason)\n if (die !== undefined) {\n throw die.defect\n }\n return undefined as B\n}\n","import type { ExtensionContext } from '@earendil-works/pi-coding-agent'\nimport { getAgentDir } from '@earendil-works/pi-coding-agent'\nimport * as NodeServices from '@effect/platform-node/NodeServices'\nimport { Effect, FileSystem, Path, PlatformError, Schema } from 'effect'\nimport { runHandler } from './run'\n\n/**\n * A missing config file yields `defaults` silently. An unreadable or invalid\n * one warns and yields `defaults`, so a typo downgrades the extension rather\n * than breaking it.\n */\nexport const loadExtensionConfig = Effect.fnUntraced(\n function* <S extends Schema.Codec<unknown>>(\n _ctx: ExtensionContext,\n schema: S,\n name: string,\n _defaults: S['Type'],\n ): Effect.fn.Return<\n S['Type'],\n Schema.SchemaError | PlatformError.PlatformError,\n FileSystem.FileSystem | Path.Path\n > {\n const fs = yield* FileSystem.FileSystem\n const path = yield* Path.Path\n const file = path.join(getAgentDir(), 'extensions', `${name}.json`)\n const contents = yield* fs.readFileString(file)\n return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(contents)\n },\n (load, ctx, _schema, name, defaults) =>\n runHandler(\n load.pipe(\n Effect.catchIf(\n (error) =>\n error._tag === 'PlatformError' && error.reason._tag === 'NotFound',\n () => Effect.succeed(defaults),\n ),\n Effect.provide(NodeServices.layer),\n ),\n {\n onError: (message) => {\n if (ctx.hasUI) {\n ctx.ui.notify(`Ignoring invalid ${name} config: ${message}`, 'warning')\n }\n return defaults\n },\n },\n ),\n)\n","import type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent'\nimport { Array, Order, pipe, String } from 'effect'\n\n/**\n * One entry on the shared status line. `text` must be plain (un-styled) text —\n * the whole row is dimmed uniformly so segments from different plugins share\n * one look.\n */\nexport interface StatuslineSegment {\n readonly text: string\n readonly align: 'left' | 'right'\n}\n\nconst WIDGET_KEY = 'pi-plugins:statusline'\n\n// Each plugin bundles its own copy of this module; `Symbol.for` on\n// `globalThis` gives them all the same registry inside one pi process.\nconst REGISTRY_KEY = Symbol.for('@pi-plugins/statusline-registry')\n\ntype Registry = Map<string, StatuslineSegment>\n\nfunction registry(): Registry {\n const store = globalThis as { [REGISTRY_KEY]?: Registry }\n store[REGISTRY_KEY] ??= new Map()\n return store[REGISTRY_KEY]\n}\n\nconst byKey = Order.mapInput(\n Order.String,\n ([key]: readonly [string, StatuslineSegment]) => key,\n)\n\nfunction side(segments: Registry, align: StatuslineSegment['align']): string {\n return pipe(\n Array.fromIterable(segments),\n Array.filter(([, segment]) => segment.align === align),\n Array.sortBy(byKey),\n Array.map(([, segment]) => segment.text),\n Array.join(' · '),\n )\n}\n\n/** Terminal columns of plain text (code points, no ANSI). */\nfunction textWidth(text: string): number {\n return Array.fromIterable(text).length\n}\n\nfunction truncate(text: string, columns: number): string {\n return pipe(Array.fromIterable(text), Array.take(columns), Array.join(''))\n}\n\n/**\n * Lays out `left ... right` across `width`: left indented one column to match\n * pi's built-in widget rows, right flush against the terminal edge to match\n * pi's footer. Falls back to one truncated `left · right` run when too narrow.\n */\nfunction renderLine(segments: Registry, width: number, theme: Theme): string {\n const left = side(segments, 'left')\n const right = side(segments, 'right')\n\n const margin = Math.min(width, 1)\n const inner = width - margin\n const gap = inner - textWidth(left) - textWidth(right)\n const minGap = String.isNonEmpty(left) && String.isNonEmpty(right) ? 2 : 0\n\n const line =\n String.isNonEmpty(right) && gap >= minGap\n ? `${left}${' '.repeat(gap)}${right}`\n : truncate(\n pipe([left, right], Array.filter(String.isNonEmpty), Array.join(' · ')),\n Math.max(inner, 0),\n )\n\n return ' '.repeat(margin) + theme.fg('dim', line)\n}\n\n/**\n * Adds, replaces (`segment`), or removes (`undefined`) a keyed segment on a\n * single status line above the editor shared across pi-plugins extensions,\n * instead of each plugin stacking its own widget row.\n */\nexport function setStatuslineSegment(\n ctx: ExtensionContext,\n key: string,\n segment: StatuslineSegment | undefined,\n): void {\n const segments = registry()\n if (segment === undefined) {\n segments.delete(key)\n } else {\n segments.set(key, segment)\n }\n\n if (!ctx.hasUI) {\n return\n }\n\n if (segments.size === 0) {\n ctx.ui.setWidget(WIDGET_KEY, undefined)\n return\n }\n\n ctx.ui.setWidget(WIDGET_KEY, (_tui, theme) => ({\n render: (width: number) => [renderLine(segments, width, theme)],\n invalidate: () => {},\n }))\n}\n","import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent'\nimport { loadExtensionConfig } from '@pi-plugins/shared/config'\nimport { setStatuslineSegment } from '@pi-plugins/shared/statusline'\nimport {\n Array,\n Data,\n Effect,\n Match,\n pipe,\n Predicate,\n Record,\n Schema,\n String,\n} from 'effect'\n\nconst EXTENSION_ID = 'fast-mode'\nconst COMMAND_ARGS = ['on', 'off', 'status'] as const\n/** Status-line segment shown above the editor while fast mode is active. */\nconst SEGMENT_KEY = EXTENSION_ID\nconst SEGMENT_LABEL = '[fast mode]'\n\nconst FastModeConfig = Schema.Struct({\n enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),\n /** `provider/model-id` keys that fast mode applies to. */\n models: Schema.Array(Schema.String).pipe(\n Schema.withDecodingDefault(\n Effect.succeed([\n 'openai/gpt-5.4',\n 'openai/gpt-5.5',\n 'openai/gpt-5.6-sol',\n 'openai/gpt-5.6-terra',\n 'openai/gpt-5.6-luna',\n 'openai-codex/gpt-5.4',\n 'openai-codex/gpt-5.5',\n 'openai-codex/gpt-5.6-sol',\n 'openai-codex/gpt-5.6-terra',\n 'openai-codex/gpt-5.6-luna',\n ]),\n ),\n ),\n /** Show a `fast mode` indicator above the editor while active. */\n showStatus: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),\n})\ntype FastModeConfig = typeof FastModeConfig.Type\n\ntype ActiveModel = NonNullable<ExtensionContext['model']>\ntype FastModeApi = 'openai-responses' | 'openai-codex-responses'\n\nfunction modelKey(model: ActiveModel): string {\n return `${model.provider}/${model.id}`\n}\n\n/**\n * Rewrites a provider request payload to ask for fast inference, returning the\n * replacement payload — or `undefined` to leave the request untouched.\n */\ntype Applicator = (\n payload: Record<string, unknown>,\n model: ActiveModel,\n) => Record<string, unknown> | undefined\n\n/** Whether fast mode can apply to the active model. */\ntype Eligibility = Data.TaggedEnum<{\n Eligible: { readonly apply: Applicator }\n Ineligible: { readonly message: string }\n}>\nconst Eligibility = Data.taggedEnum<Eligibility>()\n\nconst FAST_APPLICATORS: Record<string, Applicator> = {\n 'openai-responses': applyOpenAIPriorityTier,\n 'openai-codex-responses': applyOpenAIPriorityTier,\n} satisfies Record<FastModeApi, Applicator>\n\nfunction applyOpenAIPriorityTier(\n payload: Record<string, unknown>,\n): Record<string, unknown> | undefined {\n // If the request already has a `service_tier`, leave it untouched.\n return Record.has(payload, 'service_tier')\n ? undefined\n : { ...payload, service_tier: 'priority' }\n}\n\nexport default function fastMode(pi: ExtensionAPI) {\n let config = Schema.decodeUnknownSync(FastModeConfig)({})\n let enabled = false\n\n function checkEligibility(model: ExtensionContext['model']): Eligibility {\n if (!model) {\n return Eligibility.Ineligible({ message: 'no model is selected' })\n }\n\n const key = modelKey(model)\n if (!config.models.includes(key)) {\n return Eligibility.Ineligible({\n message: `${key} is not in the configured models`,\n })\n }\n\n const apply = FAST_APPLICATORS[model.api]\n if (!apply) {\n return Eligibility.Ineligible({\n message: `the ${model.api} API has no fast-mode support`,\n })\n }\n\n return Eligibility.Eligible({ apply })\n }\n\n function updateStatus(ctx: ExtensionContext): void {\n if (!ctx.hasUI) {\n return\n }\n\n const active =\n config.showStatus &&\n enabled &&\n Eligibility.$is('Eligible')(checkEligibility(ctx.model))\n\n setStatuslineSegment(\n ctx,\n SEGMENT_KEY,\n active ? { text: SEGMENT_LABEL, align: 'right' } : undefined,\n )\n }\n\n function notifyState(ctx: ExtensionContext): void {\n const model = ctx.model\n const name = model?.name ?? '(none)'\n const message = !enabled\n ? `Fast mode is off. Current model: ${name}.`\n : Eligibility.$match(checkEligibility(model), {\n Eligible: () => `Fast mode is on for ${name}.`,\n Ineligible: ({ message: reason }) => {\n const models = config.models.join(', ') || 'none'\n return `Fast mode is on, but inactive: ${reason}. Configured models: ${models}.`\n },\n })\n\n ctx.ui.notify(message, 'info')\n }\n\n pi.on('session_start', async (_event, ctx) => {\n config = await loadExtensionConfig(ctx, FastModeConfig, EXTENSION_ID, config)\n enabled = pi.getFlag('fast') === true || config.enabled\n updateStatus(ctx)\n })\n\n pi.on('model_select', (_event, ctx) => {\n updateStatus(ctx)\n })\n\n pi.on('before_provider_request', (event, ctx) => {\n const model = ctx.model\n if (!enabled || !model) {\n return undefined\n }\n\n const eligibility = checkEligibility(model)\n if (\n Eligibility.$is('Ineligible')(eligibility) ||\n !Predicate.isObject(event.payload) ||\n event.payload['model'] !== model.id\n ) {\n return undefined\n }\n\n return eligibility.apply(event.payload, model)\n })\n\n pi.registerFlag('fast', {\n description: 'Start with fast mode enabled',\n type: 'boolean',\n default: false,\n })\n\n pi.registerCommand('fast', {\n description:\n 'Toggle fast mode (faster, costlier inference) for configured models',\n getArgumentCompletions: (prefix) => {\n const items = pipe(\n COMMAND_ARGS,\n Array.filter(String.startsWith(prefix)),\n Array.map((arg) => ({ value: arg, label: arg })),\n )\n\n return Array.match(items, {\n onNonEmpty: (matched) => [...matched],\n onEmpty: () => null,\n })\n },\n handler: async (args, ctx) => {\n Match.value(args.trim().toLowerCase()).pipe(\n Match.whenOr('', 'on', 'off', (cmd) => {\n enabled = cmd === '' ? !enabled : cmd === 'on'\n updateStatus(ctx)\n notifyState(ctx)\n }),\n Match.when('status', () => notifyState(ctx)),\n Match.orElse(() => ctx.ui.notify('Usage: /fast [on|off|status]', 'warning')),\n )\n },\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../tooling/shared/src/run.ts","../../../tooling/shared/src/config.ts","../../../tooling/shared/src/statusline.ts","../src/index.ts"],"sourcesContent":["import { Cause, Effect, Exit, Inspectable } from 'effect'\n\nexport interface RunOptions {\n readonly signal?: AbortSignal | undefined\n}\n\nfunction causeMessage(cause: Cause.Cause<unknown>): string {\n if (Cause.hasInterruptsOnly(cause)) {\n // What pi's own tools throw for a cancelled run.\n return 'Operation aborted'\n }\n if (Cause.hasDies(cause)) {\n return Cause.pretty(cause)\n }\n return cause.reasons\n .filter(Cause.isFailReason)\n .map(({ error }) => {\n if (error instanceof Error) {\n return error.message || error.name\n }\n return typeof error === 'string' ? error : Inspectable.toStringUnknown(error)\n })\n .join('\\n')\n}\n\n/** The rejection message is what the model reads back as the tool result. */\nexport async function runTool<A, E>(\n effect: Effect.Effect<A, E>,\n options?: RunOptions,\n): Promise<A> {\n const exit = await Effect.runPromiseExit(effect, options)\n if (Exit.isFailure(exit)) {\n throw new Error(causeMessage(exit.cause))\n }\n return exit.value\n}\n\nexport interface RunHandlerOptions<B> {\n readonly onError?: (message: string) => B\n}\n\nexport async function runHandler<A, E, B = undefined>(\n effect: Effect.Effect<A, E>,\n options?: RunHandlerOptions<B>,\n): Promise<A | B> {\n const exit = await Effect.runPromiseExit(effect)\n if (Exit.isSuccess(exit)) {\n return exit.value\n }\n if (options?.onError) {\n return options.onError(causeMessage(exit.cause))\n }\n const die = exit.cause.reasons.find(Cause.isDieReason)\n if (die !== undefined) {\n throw die.defect\n }\n return undefined as B\n}\n","import type { ExtensionContext } from '@earendil-works/pi-coding-agent'\nimport { getAgentDir } from '@earendil-works/pi-coding-agent'\nimport * as NodeServices from '@effect/platform-node/NodeServices'\nimport { Effect, FileSystem, Path, PlatformError, Schema } from 'effect'\nimport { runHandler } from './run'\n\nexport const loadExtensionConfig = Effect.fnUntraced(\n function* <S extends Schema.Codec<unknown>>(\n _ctx: ExtensionContext,\n schema: S,\n name: string,\n _defaults: S['Type'],\n ): Effect.fn.Return<\n S['Type'],\n Schema.SchemaError | PlatformError.PlatformError,\n FileSystem.FileSystem | Path.Path\n > {\n const fs = yield* FileSystem.FileSystem\n const path = yield* Path.Path\n const file = path.join(getAgentDir(), 'extensions', `${name}.json`)\n const contents = yield* fs.readFileString(file)\n return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(contents)\n },\n (load, ctx, _schema, name, defaults) =>\n runHandler(\n load.pipe(\n Effect.catchIf(\n (error) =>\n error._tag === 'PlatformError' && error.reason._tag === 'NotFound',\n () => Effect.succeed(defaults),\n ),\n Effect.provide(NodeServices.layer),\n ),\n {\n onError: (message) => {\n if (ctx.hasUI) {\n ctx.ui.notify(`Ignoring invalid ${name} config: ${message}`, 'warning')\n }\n return defaults\n },\n },\n ),\n)\n","import type { ExtensionContext } from '@earendil-works/pi-coding-agent'\nimport { Array, Order, pipe, String } from 'effect'\n\nexport interface StatuslineSegment {\n /** Plain text: the whole row is dimmed uniformly across plugins. */\n readonly text: string\n readonly align: 'left' | 'right'\n}\n\nconst WIDGET_KEY = 'pi-plugins:statusline'\n\n// Each plugin bundles its own copy of this module, so `Symbol.for` on\n// `globalThis` gives them all the same registry inside one pi process.\nconst REGISTRY_KEY = Symbol.for('@pi-plugins/statusline-registry')\n\ntype Registry = Map<string, StatuslineSegment>\n\nfunction side(segments: Registry, align: StatuslineSegment['align']): string {\n return pipe(\n Array.fromIterable(segments),\n Array.filter(([, segment]) => segment.align === align),\n Array.sortBy(\n Order.mapInput(\n Order.String,\n ([key]: readonly [string, StatuslineSegment]) => key,\n ),\n ),\n Array.map(([, segment]) => segment.text),\n Array.join(' · '),\n )\n}\n\nfunction textWidth(text: string): number {\n return Array.fromIterable(text).length\n}\n\nexport function setStatuslineSegment(\n ctx: ExtensionContext,\n key: string,\n segment: StatuslineSegment | undefined,\n): void {\n const store = globalThis as { [REGISTRY_KEY]?: Registry }\n store[REGISTRY_KEY] ??= new Map()\n const segments = store[REGISTRY_KEY]\n if (segment === undefined) {\n segments.delete(key)\n } else {\n segments.set(key, segment)\n }\n\n if (!ctx.hasUI) {\n return\n }\n\n if (segments.size === 0) {\n ctx.ui.setWidget(WIDGET_KEY, undefined)\n return\n }\n\n ctx.ui.setWidget(WIDGET_KEY, (_tui, theme) => ({\n invalidate: () => {},\n render: (width: number) => {\n const left = side(segments, 'left')\n const right = side(segments, 'right')\n\n // Left indented one column like pi's widget rows, right flush like pi's footer.\n const margin = Math.min(width, 1)\n const inner = width - margin\n const gap = inner - textWidth(left) - textWidth(right)\n const minGap = String.isNonEmpty(left) && String.isNonEmpty(right) ? 2 : 0\n\n const line =\n String.isNonEmpty(right) && gap >= minGap\n ? `${left}${' '.repeat(gap)}${right}`\n : pipe(\n [left, right],\n Array.filter(String.isNonEmpty),\n Array.join(' · '),\n Array.fromIterable,\n Array.take(Math.max(inner, 0)),\n Array.join(''),\n )\n\n return [' '.repeat(margin) + theme.fg('dim', line)]\n },\n }))\n}\n","import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent'\nimport { loadExtensionConfig } from '@pi-plugins/shared/config'\nimport { setStatuslineSegment } from '@pi-plugins/shared/statusline'\nimport {\n Array,\n Data,\n Effect,\n Match,\n pipe,\n Predicate,\n Record,\n Schema,\n String,\n} from 'effect'\n\nconst EXTENSION_ID = 'fast-mode'\nconst COMMAND_ARGS = ['on', 'off', 'status'] as const\nconst SEGMENT_KEY = EXTENSION_ID\nconst SEGMENT_LABEL = '[fast mode]'\n\nconst FastModeConfig = Schema.Struct({\n enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),\n models: Schema.Array(Schema.String).pipe(\n Schema.withDecodingDefault(\n Effect.succeed([\n 'openai/gpt-5.4',\n 'openai/gpt-5.5',\n 'openai/gpt-5.6-sol',\n 'openai/gpt-5.6-terra',\n 'openai/gpt-5.6-luna',\n 'openai/gpt-6-astra',\n 'openai-codex/gpt-5.4',\n 'openai-codex/gpt-5.5',\n 'openai-codex/gpt-5.6-sol',\n 'openai-codex/gpt-5.6-terra',\n 'openai-codex/gpt-5.6-luna',\n 'openai-codex/gpt-6-astra',\n ]),\n ),\n ),\n showStatus: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),\n})\ntype FastModeConfig = typeof FastModeConfig.Type\n\ntype ActiveModel = NonNullable<ExtensionContext['model']>\ntype FastModeApi = 'openai-responses' | 'openai-codex-responses'\n\ntype Applicator = (\n payload: Record<string, unknown>,\n model: ActiveModel,\n) => Record<string, unknown> | undefined\n\ntype Eligibility = Data.TaggedEnum<{\n Eligible: { readonly apply: Applicator }\n Ineligible: { readonly message: string }\n}>\nconst Eligibility = Data.taggedEnum<Eligibility>()\n\nconst FAST_APPLICATORS: Record<string, Applicator> = {\n 'openai-responses': applyOpenAIPriorityTier,\n 'openai-codex-responses': applyOpenAIPriorityTier,\n} satisfies Record<FastModeApi, Applicator>\n\nfunction applyOpenAIPriorityTier(\n payload: Record<string, unknown>,\n): Record<string, unknown> | undefined {\n return Record.has(payload, 'service_tier')\n ? undefined\n : { ...payload, service_tier: 'priority' }\n}\n\nexport default function fastMode(pi: ExtensionAPI) {\n let config = Schema.decodeUnknownSync(FastModeConfig)({})\n let enabled = false\n\n function checkEligibility(model: ExtensionContext['model']): Eligibility {\n if (!model) {\n return Eligibility.Ineligible({ message: 'no model is selected' })\n }\n\n const key = `${model.provider}/${model.id}`\n if (!config.models.includes(key)) {\n return Eligibility.Ineligible({\n message: `${key} is not in the configured models`,\n })\n }\n\n const apply = FAST_APPLICATORS[model.api]\n if (!apply) {\n return Eligibility.Ineligible({\n message: `the ${model.api} API has no fast-mode support`,\n })\n }\n\n return Eligibility.Eligible({ apply })\n }\n\n function updateStatus(ctx: ExtensionContext): void {\n if (!ctx.hasUI) {\n return\n }\n\n const active =\n config.showStatus &&\n enabled &&\n Eligibility.$is('Eligible')(checkEligibility(ctx.model))\n\n setStatuslineSegment(\n ctx,\n SEGMENT_KEY,\n active ? { text: SEGMENT_LABEL, align: 'right' } : undefined,\n )\n }\n\n function notifyState(ctx: ExtensionContext): void {\n const model = ctx.model\n const name = model?.name ?? '(none)'\n const message = !enabled\n ? `Fast mode is off. Current model: ${name}.`\n : Eligibility.$match(checkEligibility(model), {\n Eligible: () => `Fast mode is on for ${name}.`,\n Ineligible: ({ message: reason }) => {\n const models = config.models.join(', ') || 'none'\n return `Fast mode is on, but inactive: ${reason}. Configured models: ${models}.`\n },\n })\n\n ctx.ui.notify(message, 'info')\n }\n\n pi.on('session_start', async (_event, ctx) => {\n config = await loadExtensionConfig(ctx, FastModeConfig, EXTENSION_ID, config)\n enabled = pi.getFlag('fast') === true || config.enabled\n updateStatus(ctx)\n })\n\n pi.on('model_select', (_event, ctx) => {\n updateStatus(ctx)\n })\n\n pi.on('before_provider_request', (event, ctx) => {\n const model = ctx.model\n if (!enabled || !model) {\n return undefined\n }\n\n const eligibility = checkEligibility(model)\n if (\n Eligibility.$is('Ineligible')(eligibility) ||\n !Predicate.isObject(event.payload) ||\n event.payload['model'] !== model.id\n ) {\n return undefined\n }\n\n return eligibility.apply(event.payload, model)\n })\n\n pi.registerFlag('fast', {\n description: 'Start with fast mode enabled',\n type: 'boolean',\n default: false,\n })\n\n pi.registerCommand('fast', {\n description:\n 'Toggle fast mode (faster, costlier inference) for configured models',\n getArgumentCompletions: (prefix) => {\n const items = pipe(\n COMMAND_ARGS,\n Array.filter(String.startsWith(prefix)),\n Array.map((arg) => ({ value: arg, label: arg })),\n )\n\n return Array.match(items, {\n onNonEmpty: (matched) => [...matched],\n onEmpty: () => null,\n })\n },\n handler: async (args, ctx) => {\n Match.value(args.trim().toLowerCase()).pipe(\n Match.whenOr('', 'on', 'off', (cmd) => {\n enabled = cmd === '' ? !enabled : cmd === 'on'\n updateStatus(ctx)\n notifyState(ctx)\n }),\n Match.when('status', () => notifyState(ctx)),\n Match.orElse(() => ctx.ui.notify('Usage: /fast [on|off|status]', 'warning')),\n )\n },\n })\n}\n"],"mappings":"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"}
|