@herbertgao/pi-extensions 2026.9.6 → 2026.9.8
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 +3 -8
- package/THIRD_PARTY_NOTICES.md +0 -4
- package/node_modules/@narumitw/pi-btw/README.md +2 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +284 -365
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +52 -53
- package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +494 -547
- package/node_modules/@narumitw/pi-btw/src/btw.ts +814 -856
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +673 -674
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +228 -270
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +309 -318
- package/node_modules/@narumitw/pi-btw/src/menu.ts +416 -454
- package/node_modules/@narumitw/pi-btw/src/settings.ts +203 -219
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +173 -201
- package/node_modules/@narumitw/pi-btw/src/text.ts +21 -23
- package/node_modules/@narumitw/pi-btw/src/transcript-markdown.ts +65 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +611 -662
- package/node_modules/grok-mermaid/CHANGELOG.md +46 -0
- package/node_modules/grok-mermaid/LICENSE +205 -0
- package/node_modules/grok-mermaid/README.md +191 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts +16 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/ansi.js +23 -0
- package/node_modules/grok-mermaid/dist/ansi.js.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.js +366 -0
- package/node_modules/grok-mermaid/dist/canvas.js.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts +74 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.js +91 -0
- package/node_modules/grok-mermaid/dist/graph.js.map +1 -0
- package/node_modules/grok-mermaid/dist/index.d.ts +32 -0
- package/node_modules/grok-mermaid/dist/index.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/index.js +100 -0
- package/node_modules/grok-mermaid/dist/index.js.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts +62 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.js +324 -0
- package/node_modules/grok-mermaid/dist/labels.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts +12 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js +194 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.js +881 -0
- package/node_modules/grok-mermaid/dist/layout.js.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts +83 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.js +1151 -0
- package/node_modules/grok-mermaid/dist/parse.js.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.js +78 -0
- package/node_modules/grok-mermaid/dist/source-box.js.map +1 -0
- package/node_modules/grok-mermaid/dist/types.d.ts +42 -0
- package/node_modules/grok-mermaid/dist/types.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/types.js +1 -0
- package/node_modules/grok-mermaid/dist/types.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts +2 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.js +994 -0
- package/node_modules/grok-mermaid/dist/width-data.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/width.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width.js +76 -0
- package/node_modules/grok-mermaid/dist/width.js.map +1 -0
- package/node_modules/grok-mermaid/package.json +49 -0
- package/node_modules/grok-mermaid/src/ansi.ts +34 -0
- package/node_modules/grok-mermaid/src/canvas.ts +373 -0
- package/node_modules/grok-mermaid/src/graph.ts +142 -0
- package/node_modules/grok-mermaid/src/index.ts +104 -0
- package/node_modules/grok-mermaid/src/labels.ts +326 -0
- package/node_modules/grok-mermaid/src/layout-seq.ts +203 -0
- package/node_modules/grok-mermaid/src/layout.ts +1015 -0
- package/node_modules/grok-mermaid/src/parse.ts +1189 -0
- package/node_modules/grok-mermaid/src/source-box.ts +89 -0
- package/node_modules/grok-mermaid/src/types.ts +43 -0
- package/node_modules/grok-mermaid/src/width-data.ts +993 -0
- package/node_modules/grok-mermaid/src/width.ts +74 -0
- package/node_modules/pi-lens/CHANGELOG.md +239 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +30 -4
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +26 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +403 -35
- package/node_modules/pi-lens/dist/clients/bootstrap.js +6 -1
- package/node_modules/pi-lens/dist/clients/cascade-format.js +200 -4
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +10 -2
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +16 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +12 -1
- package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +65 -0
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +28 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +9 -2
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +222 -0
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +389 -13
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +175 -25
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +62 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +2 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +4 -1
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +1 -0
- package/node_modules/pi-lens/dist/clients/effective-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +26 -1
- package/node_modules/pi-lens/dist/clients/file-role.js +21 -21
- package/node_modules/pi-lens/dist/clients/file-utils.js +156 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +56 -9
- package/node_modules/pi-lens/dist/clients/format-service.js +39 -21
- package/node_modules/pi-lens/dist/clients/formatters.js +60 -13
- package/node_modules/pi-lens/dist/clients/generation-guard.js +2 -2
- package/node_modules/pi-lens/dist/clients/git-guard.js +11 -3
- package/node_modules/pi-lens/dist/clients/indent-retarget.js +78 -8
- package/node_modules/pi-lens/dist/clients/installer/index.js +333 -114
- package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +7 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +20 -10
- package/node_modules/pi-lens/dist/clients/language-profile.js +23 -1
- package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +4 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +12 -3
- package/node_modules/pi-lens/dist/clients/lens-events.js +2 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +79 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +25 -21
- package/node_modules/pi-lens/dist/clients/lsp/config.js +2 -2
- package/node_modules/pi-lens/dist/clients/lsp/index.js +7 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +16 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +5 -3
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +12 -8
- package/node_modules/pi-lens/dist/clients/mcp/session.js +36 -4
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +24 -7
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +40 -2
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +23 -3
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +110 -15
- package/node_modules/pi-lens/dist/clients/path-utils.js +123 -3
- package/node_modules/pi-lens/dist/clients/performance-report.js +5 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +74 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +37 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +145 -18
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +59 -3
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +45 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +70 -11
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +147 -9
- package/node_modules/pi-lens/dist/clients/ruff-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +33 -5
- package/node_modules/pi-lens/dist/clients/runtime-context.js +6 -2
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +77 -7
- package/node_modules/pi-lens/dist/clients/runtime-session.js +21 -2
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +43 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +330 -85
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -17
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +258 -5
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +6 -0
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +50 -5
- package/node_modules/pi-lens/dist/clients/sg-runner.js +23 -11
- package/node_modules/pi-lens/dist/clients/sgconfig.js +79 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +6 -41
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +43 -0
- package/node_modules/pi-lens/dist/clients/tool-agreement.js +423 -0
- package/node_modules/pi-lens/dist/clients/tool-config.js +50 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +47 -76
- package/node_modules/pi-lens/dist/clients/tool-policy.js +163 -7
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +120 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +127 -189
- package/node_modules/pi-lens/dist/clients/widget-state.js +98 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +5 -2
- package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +7 -0
- package/node_modules/pi-lens/dist/index.js +27416 -24153
- package/node_modules/pi-lens/dist/mcp/server.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +7 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +168 -53
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +244 -72
- package/node_modules/pi-lens/docs/audit1.md +5 -5
- package/node_modules/pi-lens/docs/dependencies.md +11 -0
- package/node_modules/pi-lens/docs/dispositions.md +52 -0
- package/node_modules/pi-lens/docs/environment-variables.md +2 -2
- package/node_modules/pi-lens/docs/features.md +4 -4
- package/node_modules/pi-lens/docs/globalconfig.md +3 -1
- package/node_modules/pi-lens/docs/language-coverage.md +1 -0
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +53 -94
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +43 -38
- package/node_modules/pi-lens/docs/pi-lens-retro.md +97 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +53 -66
- package/node_modules/pi-lens/docs/release-qa-baseline.md +22 -0
- package/node_modules/pi-lens/docs/settings.md +7 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +2 -0
- package/node_modules/pi-lens/package.json +1 -1
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +24 -12
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +40 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +15 -0
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +7 -0
- package/package.json +6 -11
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +0 -376
- package/node_modules/@luxusai/pi-hindsight/README.md +0 -92
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +0 -56
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +0 -169
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +0 -107
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +0 -89
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +0 -189
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +0 -54
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +0 -75
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +0 -300
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +0 -158
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +0 -164
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +0 -139
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +0 -74
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +0 -261
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +0 -151
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +0 -18
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +0 -46
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +0 -383
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +0 -240
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +0 -176
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +0 -178
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +0 -41
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +0 -386
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +0 -39
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +0 -34
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +0 -140
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +0 -61
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +0 -925
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +0 -247
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +0 -547
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +0 -480
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +0 -182
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +0 -86
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +0 -1010
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +0 -175
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +0 -425
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +0 -210
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +0 -817
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +0 -25
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +0 -196
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +0 -65
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +0 -260
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +0 -59
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +0 -82
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +0 -331
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +0 -354
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +0 -66
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +0 -132
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +0 -228
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +0 -74
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +0 -16
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +0 -648
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +0 -68
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +0 -71
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +0 -13
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +0 -162
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +0 -131
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +0 -104
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +0 -37
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +0 -893
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +0 -35
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +0 -177
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +0 -7
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +0 -21
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +0 -112
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +0 -111
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +0 -214
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +0 -70
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +0 -392
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +0 -9
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +0 -860
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +0 -299
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +0 -201
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +0 -47
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +0 -239
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +0 -259
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +0 -77
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +0 -534
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +0 -325
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +0 -42
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +0 -56
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +0 -167
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +0 -207
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +0 -120
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +0 -8
- package/node_modules/@luxusai/pi-hindsight/package.json +0 -118
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +0 -75
|
@@ -61,9 +61,11 @@ import { assertInstallAllowed, projectTrustDenialReason, } from "../project-trus
|
|
|
61
61
|
const _installerRequire = createRequire(import.meta.url);
|
|
62
62
|
import { createGunzip } from "node:zlib";
|
|
63
63
|
import { TRANSIENT_MAX_COOLDOWN_MS } from "../dispatch/runners/utils/availability-policy.js";
|
|
64
|
-
import { recordDegradationOnce } from "../degradation-ledger.js";
|
|
64
|
+
import { getDegradationLedgerGeneration, recordDegradationOnce, } from "../degradation-ledger.js";
|
|
65
65
|
import { commitDurableStoreAsync } from "../durable-store.js";
|
|
66
66
|
import { getGlobalPiLensDir } from "../file-utils.js";
|
|
67
|
+
import { createGenerationMap } from "../generation-guard.js";
|
|
68
|
+
import { resolveToolCwd } from "../tool-cwd.js";
|
|
67
69
|
import { allAvailableGlobalBinDirs, installArgs, pmBinary, resolveNodePackageManager, } from "../package-manager.js";
|
|
68
70
|
import { resetSafeSpawnWindowsCommandCache, safeSpawnAsync, } from "../safe-spawn.js";
|
|
69
71
|
import { probeToolAsync } from "../tool-probe.js";
|
|
@@ -267,6 +269,27 @@ function managedGitHubFormatterTool(spec) {
|
|
|
267
269
|
};
|
|
268
270
|
}
|
|
269
271
|
const MANAGED_GITHUB_FORMATTERS = [
|
|
272
|
+
{
|
|
273
|
+
id: "typstyle",
|
|
274
|
+
name: "typstyle",
|
|
275
|
+
owner: "typstyle-rs",
|
|
276
|
+
repo: "typstyle",
|
|
277
|
+
assetPattern: archAssetMatch({
|
|
278
|
+
linux: {
|
|
279
|
+
x64: "typstyle-x86_64-unknown-linux-gnu",
|
|
280
|
+
arm64: "typstyle-aarch64-unknown-linux-gnu",
|
|
281
|
+
},
|
|
282
|
+
darwin: {
|
|
283
|
+
x64: "typstyle-x86_64-apple-darwin",
|
|
284
|
+
arm64: "typstyle-aarch64-apple-darwin",
|
|
285
|
+
},
|
|
286
|
+
win32: {
|
|
287
|
+
x64: "typstyle-x86_64-pc-windows-msvc.exe",
|
|
288
|
+
arm64: "typstyle-aarch64-pc-windows-msvc.exe",
|
|
289
|
+
},
|
|
290
|
+
}),
|
|
291
|
+
kind: "binary",
|
|
292
|
+
},
|
|
270
293
|
{
|
|
271
294
|
id: "stylua",
|
|
272
295
|
name: "StyLua",
|
|
@@ -1054,7 +1077,7 @@ export const TOOLS = [
|
|
|
1054
1077
|
: `${base}/lua-language-server-${version}-win32-x64.zip`;
|
|
1055
1078
|
return undefined;
|
|
1056
1079
|
},
|
|
1057
|
-
kind: "zip",
|
|
1080
|
+
kind: (platform) => (platform === "win32" ? "zip" : "tgz"),
|
|
1058
1081
|
stripComponents: 0,
|
|
1059
1082
|
treeMarker: "bin",
|
|
1060
1083
|
},
|
|
@@ -1432,6 +1455,34 @@ export const TOOLS = [
|
|
|
1432
1455
|
binaryInArchive: "gleam",
|
|
1433
1456
|
},
|
|
1434
1457
|
},
|
|
1458
|
+
{
|
|
1459
|
+
// Tinymist publishes cargo-dist archives containing the `tinymist` binary
|
|
1460
|
+
// for the supported desktop targets. The LSP server uses `tinymist lsp`.
|
|
1461
|
+
id: "tinymist",
|
|
1462
|
+
name: "Tinymist",
|
|
1463
|
+
checkCommand: "tinymist",
|
|
1464
|
+
checkArgs: ["--version"],
|
|
1465
|
+
installStrategy: "github",
|
|
1466
|
+
binaryName: "tinymist",
|
|
1467
|
+
github: {
|
|
1468
|
+
repo: "Myriad-Dreamin/tinymist",
|
|
1469
|
+
assetMatch: archAssetMatch({
|
|
1470
|
+
linux: {
|
|
1471
|
+
x64: "tinymist-x86_64-unknown-linux-gnu.tar.gz",
|
|
1472
|
+
arm64: "tinymist-aarch64-unknown-linux-gnu.tar.gz",
|
|
1473
|
+
},
|
|
1474
|
+
darwin: {
|
|
1475
|
+
x64: "tinymist-x86_64-apple-darwin.tar.gz",
|
|
1476
|
+
arm64: "tinymist-aarch64-apple-darwin.tar.gz",
|
|
1477
|
+
},
|
|
1478
|
+
win32: {
|
|
1479
|
+
x64: "tinymist-x86_64-pc-windows-msvc.zip",
|
|
1480
|
+
arm64: "tinymist-aarch64-pc-windows-msvc.zip",
|
|
1481
|
+
},
|
|
1482
|
+
}),
|
|
1483
|
+
binaryInArchive: "tinymist",
|
|
1484
|
+
},
|
|
1485
|
+
},
|
|
1435
1486
|
{
|
|
1436
1487
|
// marksman ships a single BARE (uncompressed) binary per platform on GitHub
|
|
1437
1488
|
// releases — no archive, so it lands via the bare-binary branch of
|
|
@@ -2678,12 +2729,14 @@ async function getNpmGlobalBinCandidates(onTransient) {
|
|
|
2678
2729
|
return dirs;
|
|
2679
2730
|
}
|
|
2680
2731
|
async function findPipUserToolPath(binaryName, onTransient, verificationArgs = ["--version"], verificationTimeoutMs = 10_000) {
|
|
2681
|
-
const isWindows =
|
|
2682
|
-
const userBaseCandidates =
|
|
2732
|
+
const isWindows = installerPlatform() === "win32";
|
|
2733
|
+
const userBaseCandidates = [
|
|
2734
|
+
path.join(getGlobalPiLensDir(), "pip-tools"),
|
|
2735
|
+
path.join(getGlobalPiLensDir(), "pip-user"),
|
|
2736
|
+
...(await getPythonUserBaseCandidates()),
|
|
2737
|
+
];
|
|
2683
2738
|
for (const userBase of userBaseCandidates) {
|
|
2684
|
-
const scriptDirs = [
|
|
2685
|
-
path.join(userBase, isWindows ? "Scripts" : "bin"),
|
|
2686
|
-
];
|
|
2739
|
+
const scriptDirs = [pipScriptsDir(userBase, installerPlatform())];
|
|
2687
2740
|
if (isWindows) {
|
|
2688
2741
|
try {
|
|
2689
2742
|
const children = await fs.readdir(userBase, { withFileTypes: true });
|
|
@@ -3600,7 +3653,9 @@ async function refreshPackageManagerManagedTool(tool) {
|
|
|
3600
3653
|
const installed = tool.installStrategy === "pip"
|
|
3601
3654
|
? // `-U` is the whole fix: without it pip treats the installed copy as
|
|
3602
3655
|
// satisfying the requirement and the day-one version never moves.
|
|
3603
|
-
await installPipTool(tool.id, tool.packageName,
|
|
3656
|
+
await installPipTool(tool.id, tool.packageName, tool.binaryName ?? tool.id, {
|
|
3657
|
+
upgrade: true,
|
|
3658
|
+
})
|
|
3604
3659
|
: // `gem install` always fetches the newest version that satisfies the
|
|
3605
3660
|
// requirement, so the install command IS the upgrade command.
|
|
3606
3661
|
await installGemTool(tool.id, tool.packageName);
|
|
@@ -3798,9 +3853,35 @@ async function installMavenTool(tool) {
|
|
|
3798
3853
|
* may return `undefined` (unsupported → caller degrades to "unavailable").
|
|
3799
3854
|
* Exported for the tool-registry contract test.
|
|
3800
3855
|
*/
|
|
3801
|
-
export function resolveArchiveUrl(spec, platform =
|
|
3856
|
+
export function resolveArchiveUrl(spec, platform = installerPlatform(), arch = process.arch) {
|
|
3802
3857
|
return typeof spec.url === "function" ? spec.url(platform, arch) : spec.url;
|
|
3803
3858
|
}
|
|
3859
|
+
/** Resolve the archive format independently from the extractor implementation. */
|
|
3860
|
+
export function resolveArchiveKind(spec, platform = installerPlatform(), arch = process.arch) {
|
|
3861
|
+
return typeof spec.kind === "function"
|
|
3862
|
+
? spec.kind(platform, arch)
|
|
3863
|
+
: spec.kind;
|
|
3864
|
+
}
|
|
3865
|
+
function recordArchiveExtractionDegradation(toolId, format, reason) {
|
|
3866
|
+
recordDegradationOnce({
|
|
3867
|
+
kind: "managed-tool-install",
|
|
3868
|
+
subject: `${toolId}:${format}`,
|
|
3869
|
+
reason: `archive extraction ${reason}`,
|
|
3870
|
+
});
|
|
3871
|
+
}
|
|
3872
|
+
async function stripExtractedArchiveRoot(dir, components) {
|
|
3873
|
+
for (let i = 0; i < components; i++) {
|
|
3874
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
3875
|
+
const [entry] = entries;
|
|
3876
|
+
if (entries.length !== 1 || !entry?.isDirectory())
|
|
3877
|
+
return false;
|
|
3878
|
+
const root = path.join(dir, entry.name);
|
|
3879
|
+
for (const child of await fs.readdir(root))
|
|
3880
|
+
await fs.rename(path.join(root, child), path.join(dir, child));
|
|
3881
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
3882
|
+
}
|
|
3883
|
+
return true;
|
|
3884
|
+
}
|
|
3804
3885
|
/**
|
|
3805
3886
|
* Move a verified-good extracted tree into its final, stable location without
|
|
3806
3887
|
* ever leaving `finalDir` empty or missing while a working copy was there
|
|
@@ -3876,8 +3957,10 @@ async function installArchiveTool(tool) {
|
|
|
3876
3957
|
if (!spec)
|
|
3877
3958
|
return undefined;
|
|
3878
3959
|
const binaryName = tool.binaryName ?? tool.id;
|
|
3879
|
-
const
|
|
3880
|
-
const
|
|
3960
|
+
const platform = installerPlatform();
|
|
3961
|
+
const isWindows = platform === "win32";
|
|
3962
|
+
const archiveKind = resolveArchiveKind(spec, platform, process.arch);
|
|
3963
|
+
const url = resolveArchiveUrl(spec, platform, process.arch);
|
|
3881
3964
|
if (!url) {
|
|
3882
3965
|
logSessionStart(`archive-install ${tool.id}: no archive for ${process.platform}/${process.arch} — unsupported, skipping`);
|
|
3883
3966
|
return undefined;
|
|
@@ -3907,7 +3990,7 @@ async function installArchiveTool(tool) {
|
|
|
3907
3990
|
// installed copy is now untouched until the replacement is proven good.
|
|
3908
3991
|
const extractName = tool.id;
|
|
3909
3992
|
const tmpExtractName = `${extractName}.refresh-tmp`;
|
|
3910
|
-
const archiveName = `${tool.id}.download.${
|
|
3993
|
+
const archiveName = `${tool.id}.download.${archiveKind === "zip" ? "zip" : "tgz"}`;
|
|
3911
3994
|
const extractDir = path.join(TOOLS_DIR, extractName);
|
|
3912
3995
|
const tmpExtractDir = path.join(TOOLS_DIR, tmpExtractName);
|
|
3913
3996
|
const tmpArchive = path.join(TOOLS_DIR, archiveName);
|
|
@@ -3925,34 +4008,62 @@ async function installArchiveTool(tool) {
|
|
|
3925
4008
|
// dir — stripping would flatten/merge its sibling module folders — so the
|
|
3926
4009
|
// flag is omitted. bsdtar handles both .tgz and .zip with -xf.
|
|
3927
4010
|
const stripComponents = spec.stripComponents ?? 1;
|
|
3928
|
-
const
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
4011
|
+
const extractionArgs = archiveKind === "zip" && isWindows
|
|
4012
|
+
? [
|
|
4013
|
+
"-NoProfile",
|
|
4014
|
+
"-Command",
|
|
4015
|
+
`Expand-Archive -LiteralPath '${archiveName}' -DestinationPath '${tmpExtractName}' -Force`,
|
|
4016
|
+
]
|
|
4017
|
+
: archiveKind === "zip"
|
|
4018
|
+
? ["-q", "-o", archiveName, "-d", tmpExtractName]
|
|
4019
|
+
: [
|
|
4020
|
+
"-xzf",
|
|
4021
|
+
archiveName,
|
|
4022
|
+
"-C",
|
|
4023
|
+
tmpExtractName,
|
|
4024
|
+
...(stripComponents > 0
|
|
4025
|
+
? [`--strip-components=${stripComponents}`]
|
|
4026
|
+
: []),
|
|
4027
|
+
];
|
|
3935
4028
|
// Resolve `tar` to an absolute path on Windows (System32\tar.exe is the
|
|
3936
4029
|
// bsdtar shipped with Windows 10+) so extraction can't be hijacked via a
|
|
3937
4030
|
// writable PATH entry — same hardening as the taskkill spawn. On POSIX `tar`
|
|
3938
4031
|
// is a trusted coreutil whose absolute path varies by distro, so it stays
|
|
3939
4032
|
// bare (consistent with every other tool spawn).
|
|
3940
|
-
const
|
|
3941
|
-
? `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\
|
|
3942
|
-
: "
|
|
3943
|
-
|
|
4033
|
+
const extractor = archiveKind === "zip" && isWindows
|
|
4034
|
+
? `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`
|
|
4035
|
+
: archiveKind === "zip"
|
|
4036
|
+
? "unzip"
|
|
4037
|
+
: isWindows
|
|
4038
|
+
? `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\tar.exe`
|
|
4039
|
+
: "tar";
|
|
4040
|
+
const extractionResult = await safeSpawnAsync(extractor, extractionArgs, {
|
|
3944
4041
|
cwd: TOOLS_DIR,
|
|
3945
4042
|
timeout: 120_000,
|
|
3946
4043
|
ignoreAmbientSignal: true,
|
|
3947
4044
|
lifetimeCoupled: true,
|
|
3948
4045
|
});
|
|
3949
4046
|
const extracted = {
|
|
3950
|
-
ok:
|
|
3951
|
-
|
|
4047
|
+
ok: extractionResult.status === 0,
|
|
4048
|
+
reason: extractionResult.spawnFailure?.kind === "tool-not-found"
|
|
4049
|
+
? "extractor-unavailable"
|
|
4050
|
+
: extractionResult.spawnFailure
|
|
4051
|
+
? "extractor-error"
|
|
4052
|
+
: "extractor-exit",
|
|
3952
4053
|
};
|
|
3953
4054
|
await fs.rm(tmpArchive, { force: true });
|
|
3954
4055
|
if (!extracted.ok) {
|
|
3955
|
-
|
|
4056
|
+
recordArchiveExtractionDegradation(tool.id, archiveKind, extracted.reason);
|
|
4057
|
+
logSessionStart(`archive-install ${tool.id}: ${archiveKind} extraction failed (${extracted.reason}) — keeping installed version`);
|
|
4058
|
+
await fs
|
|
4059
|
+
.rm(tmpExtractDir, { recursive: true, force: true })
|
|
4060
|
+
.catch(() => { });
|
|
4061
|
+
return undefined;
|
|
4062
|
+
}
|
|
4063
|
+
if (archiveKind === "zip" &&
|
|
4064
|
+
!(await stripExtractedArchiveRoot(tmpExtractDir, stripComponents))) {
|
|
4065
|
+
recordArchiveExtractionDegradation(tool.id, archiveKind, "layout-invalid");
|
|
4066
|
+
logSessionStart(`archive-install ${tool.id}: ${archiveKind} layout invalid — keeping installed version`);
|
|
3956
4067
|
await fs
|
|
3957
4068
|
.rm(tmpExtractDir, { recursive: true, force: true })
|
|
3958
4069
|
.catch(() => { });
|
|
@@ -3970,7 +4081,8 @@ async function installArchiveTool(tool) {
|
|
|
3970
4081
|
await fs.access(tmpMarker);
|
|
3971
4082
|
}
|
|
3972
4083
|
catch {
|
|
3973
|
-
|
|
4084
|
+
recordArchiveExtractionDegradation(tool.id, archiveKind, "marker-missing");
|
|
4085
|
+
logSessionStart(`archive-install ${tool.id}: ${archiveKind} marker missing after extraction — keeping installed version`);
|
|
3974
4086
|
await fs
|
|
3975
4087
|
.rm(tmpExtractDir, { recursive: true, force: true })
|
|
3976
4088
|
.catch(() => { });
|
|
@@ -3992,7 +4104,8 @@ async function installArchiveTool(tool) {
|
|
|
3992
4104
|
await fs.access(tmpResolvedInner);
|
|
3993
4105
|
}
|
|
3994
4106
|
catch {
|
|
3995
|
-
|
|
4107
|
+
recordArchiveExtractionDegradation(tool.id, archiveKind, "launcher-missing");
|
|
4108
|
+
logSessionStart(`archive-install ${tool.id}: ${archiveKind} launcher missing after extraction — keeping installed version`);
|
|
3996
4109
|
await fs
|
|
3997
4110
|
.rm(tmpExtractDir, { recursive: true, force: true })
|
|
3998
4111
|
.catch(() => { });
|
|
@@ -4231,24 +4344,25 @@ export function pipCommandCandidates() {
|
|
|
4231
4344
|
? ["pip", "py", "python"]
|
|
4232
4345
|
: ["pip3", "pip", "python3", "python"];
|
|
4233
4346
|
}
|
|
4347
|
+
/** Resolve the script directory used by a Python installation on each OS. */
|
|
4348
|
+
export function pipScriptsDir(base, platform = installerPlatform()) {
|
|
4349
|
+
return path.join(base, platform === "win32" ? "Scripts" : "bin");
|
|
4350
|
+
}
|
|
4351
|
+
const pipPep668LoggedRefusals = createGenerationMap("installer-pep668-log");
|
|
4234
4352
|
/**
|
|
4235
4353
|
* Install a pip package tool
|
|
4236
4354
|
*/
|
|
4237
|
-
async function installPipTool(toolId, packageName,
|
|
4355
|
+
async function installPipTool(toolId, packageName, binaryName,
|
|
4238
4356
|
/**
|
|
4239
4357
|
* Add `-U`, turning the install into an upgrade. Without it `pip install`
|
|
4240
4358
|
* treats an already-present package as satisfied and leaves the day-one
|
|
4241
4359
|
* version in place forever — the freeze #1747 is about. The flag is the ONLY
|
|
4242
|
-
* difference between install and refresh
|
|
4243
|
-
* `--user` target, so a refresh can never write somewhere the install would
|
|
4244
|
-
* not have.
|
|
4360
|
+
* difference between install and refresh within each selected environment.
|
|
4245
4361
|
*/
|
|
4246
4362
|
options = {}) {
|
|
4247
4363
|
try {
|
|
4248
|
-
const isWindows =
|
|
4249
|
-
const verb = options.upgrade
|
|
4250
|
-
? ["install", "-U", "--user"]
|
|
4251
|
-
: ["install", "--user"];
|
|
4364
|
+
const isWindows = installerPlatform() === "win32";
|
|
4365
|
+
const verb = options.upgrade ? ["install", "-U"] : ["install"];
|
|
4252
4366
|
// Built from `pipCommandCandidates()` — the single source of truth this
|
|
4253
4367
|
// module and any other caller (the tool-smoke lane's toolchain-presence
|
|
4254
4368
|
// probe, #2661 review) share, rather than a second, independently
|
|
@@ -4259,21 +4373,145 @@ options = {}) {
|
|
|
4259
4373
|
? [...verb, packageName]
|
|
4260
4374
|
: ["-m", "pip", ...verb, packageName],
|
|
4261
4375
|
}));
|
|
4262
|
-
const
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4376
|
+
const pep668 = /externally-managed-environment/i;
|
|
4377
|
+
const refuse = (strategy, reason) => {
|
|
4378
|
+
if (!pep668.test(reason))
|
|
4379
|
+
return;
|
|
4380
|
+
const subject = `${toolId}:${strategy}`;
|
|
4381
|
+
recordDegradationOnce({
|
|
4382
|
+
kind: "pip-pep668-strategy-refused",
|
|
4383
|
+
subject,
|
|
4384
|
+
reason,
|
|
4268
4385
|
});
|
|
4269
|
-
const
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4386
|
+
const logKey = `${getDegradationLedgerGeneration()}:${subject}`;
|
|
4387
|
+
if (pipPep668LoggedRefusals.current(logKey) === 0) {
|
|
4388
|
+
pipPep668LoggedRefusals.bump(logKey);
|
|
4389
|
+
logSessionStart(`auto-install pip ${packageName}: ${strategy} refused by PEP 668 (${boundInstallError(reason)})`);
|
|
4390
|
+
}
|
|
4391
|
+
};
|
|
4392
|
+
const succeeded = (strategy, binaryPath) => {
|
|
4393
|
+
recordDegradationOnce({
|
|
4394
|
+
kind: "pip-install-strategy-succeeded",
|
|
4395
|
+
subject: `${toolId}:${strategy}`,
|
|
4396
|
+
reason: binaryPath,
|
|
4397
|
+
});
|
|
4398
|
+
return binaryPath;
|
|
4399
|
+
};
|
|
4400
|
+
const run = (command, args, env) => safeSpawnAsync(command, args, {
|
|
4401
|
+
timeout: 120_000,
|
|
4402
|
+
ignoreAmbientSignal: true,
|
|
4403
|
+
lifetimeCoupled: true,
|
|
4404
|
+
cwd: resolveToolCwd("runner", toolId, getGlobalPiLensDir(), {
|
|
4405
|
+
cwd: getGlobalPiLensDir(),
|
|
4406
|
+
suppressTelemetry: true,
|
|
4407
|
+
}).cwd,
|
|
4408
|
+
...(env ? { env } : {}),
|
|
4409
|
+
});
|
|
4410
|
+
const addBinToPath = async (binDir) => {
|
|
4411
|
+
try {
|
|
4412
|
+
await fs.access(binDir);
|
|
4413
|
+
}
|
|
4414
|
+
catch {
|
|
4415
|
+
return undefined;
|
|
4416
|
+
}
|
|
4417
|
+
const currentPath = process.env.PATH || process.env.Path || "";
|
|
4418
|
+
const separator = isWindows ? ";" : path.delimiter;
|
|
4419
|
+
if (!currentPath
|
|
4420
|
+
.toLowerCase()
|
|
4421
|
+
.split(separator)
|
|
4422
|
+
.includes(binDir.toLowerCase())) {
|
|
4423
|
+
const updatedPath = `${binDir}${separator}${currentPath}`;
|
|
4424
|
+
process.env.PATH = updatedPath;
|
|
4425
|
+
if (isWindows)
|
|
4426
|
+
process.env.Path = updatedPath;
|
|
4427
|
+
}
|
|
4428
|
+
const names = isWindows
|
|
4429
|
+
? [`${binaryName}.exe`, `${binaryName}.cmd`, binaryName]
|
|
4430
|
+
: [binaryName];
|
|
4431
|
+
for (const name of names) {
|
|
4432
|
+
const candidate = path.join(binDir, name);
|
|
4433
|
+
try {
|
|
4434
|
+
await fs.access(candidate);
|
|
4435
|
+
return candidate;
|
|
4436
|
+
}
|
|
4437
|
+
catch {
|
|
4438
|
+
// continue
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
return undefined;
|
|
4442
|
+
};
|
|
4443
|
+
if (await isCommandAvailable("pipx")) {
|
|
4444
|
+
const result = await run("pipx", [
|
|
4445
|
+
options.upgrade ? "upgrade" : "install",
|
|
4446
|
+
packageName,
|
|
4447
|
+
]);
|
|
4448
|
+
const error = (result.error?.message ?? result.stderr).trim();
|
|
4449
|
+
if (result.status === 0) {
|
|
4450
|
+
const location = await run("pipx", [
|
|
4451
|
+
"environment",
|
|
4452
|
+
"--value",
|
|
4453
|
+
"PIPX_BIN_DIR",
|
|
4454
|
+
]);
|
|
4455
|
+
const binDir = location.status === 0 && location.stdout.trim()
|
|
4456
|
+
? location.stdout.trim()
|
|
4457
|
+
: path.join(os.homedir(), ".local", "bin");
|
|
4458
|
+
const binaryPath = await addBinToPath(binDir);
|
|
4459
|
+
if (binaryPath)
|
|
4460
|
+
return succeeded("pipx", binaryPath);
|
|
4461
|
+
throw new Error(`pipx installed ${packageName} but ${binaryName} is not resolvable`);
|
|
4462
|
+
}
|
|
4463
|
+
refuse("pipx", error);
|
|
4464
|
+
}
|
|
4465
|
+
const pythonCandidates = pipCandidates.filter(({ command }) => command === "python3" || command === "python" || command === "py");
|
|
4466
|
+
const pythonAvailability = await Promise.all(pythonCandidates.map(({ command }) => isCommandAvailable(command)));
|
|
4467
|
+
const availablePythonCandidates = pythonCandidates.filter((_, index) => pythonAvailability[index]);
|
|
4468
|
+
const venvRoot = path.join(getGlobalPiLensDir(), "pip-tools");
|
|
4469
|
+
for (const candidate of availablePythonCandidates) {
|
|
4470
|
+
const venvBin = pipScriptsDir(venvRoot, installerPlatform());
|
|
4471
|
+
let venvPip = path.join(venvBin, isWindows ? "pip.exe" : "pip");
|
|
4472
|
+
try {
|
|
4473
|
+
await fs.access(venvPip);
|
|
4474
|
+
}
|
|
4475
|
+
catch {
|
|
4476
|
+
const created = await run(candidate.command, ["-m", "venv", venvRoot]);
|
|
4477
|
+
const error = (created.error?.message ?? created.stderr).trim();
|
|
4478
|
+
if (created.status !== 0) {
|
|
4479
|
+
refuse("venv", error || "python venv module unavailable");
|
|
4480
|
+
continue;
|
|
4481
|
+
}
|
|
4482
|
+
}
|
|
4483
|
+
try {
|
|
4484
|
+
await fs.access(venvPip);
|
|
4485
|
+
}
|
|
4486
|
+
catch {
|
|
4487
|
+
venvPip = path.join(venvBin, isWindows ? "pip.cmd" : "pip3");
|
|
4488
|
+
try {
|
|
4489
|
+
await fs.access(venvPip);
|
|
4490
|
+
}
|
|
4491
|
+
catch {
|
|
4492
|
+
continue;
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4495
|
+
const result = await run(venvPip, [...verb, packageName]);
|
|
4496
|
+
const error = (result.error?.message ?? result.stderr).trim();
|
|
4497
|
+
if (result.status === 0) {
|
|
4498
|
+
const binaryPath = await addBinToPath(venvBin);
|
|
4499
|
+
if (binaryPath)
|
|
4500
|
+
return succeeded("venv", binaryPath);
|
|
4501
|
+
throw new Error(`venv installed ${packageName} but ${binaryName} is not resolvable`);
|
|
4502
|
+
}
|
|
4503
|
+
refuse("venv", error);
|
|
4504
|
+
}
|
|
4505
|
+
const candidateErrors = [];
|
|
4506
|
+
let userRefused = false;
|
|
4507
|
+
for (const candidate of pipCandidates) {
|
|
4508
|
+
const args = candidate.command === "pip" || candidate.command === "pip3"
|
|
4509
|
+
? [...verb, "--user", packageName]
|
|
4510
|
+
: ["-m", "pip", ...verb, "--user", packageName];
|
|
4511
|
+
const result = await run(candidate.command, args);
|
|
4512
|
+
const error = (result.error?.message ?? result.stderr).trim();
|
|
4513
|
+
if (result.status === 0) {
|
|
4514
|
+
const base = await new Promise((resolve) => {
|
|
4277
4515
|
let probe;
|
|
4278
4516
|
try {
|
|
4279
4517
|
probe = spawn(candidate.command, ["-m", "site", "--user-base"], {
|
|
@@ -4282,78 +4520,57 @@ options = {}) {
|
|
|
4282
4520
|
});
|
|
4283
4521
|
}
|
|
4284
4522
|
catch {
|
|
4285
|
-
// SYNCHRONOUS spawn throw (Windows `spawn UNKNOWN`/EINVAL, the
|
|
4286
|
-
// pidusage bug class, #533) — best-effort probe, resolve empty.
|
|
4287
4523
|
resolve("");
|
|
4288
4524
|
return;
|
|
4289
4525
|
}
|
|
4290
4526
|
let stdout = "";
|
|
4291
4527
|
probe.stdout?.on("data", (data) => (stdout += data));
|
|
4292
|
-
probe.on("exit", (code) =>
|
|
4293
|
-
if (code === 0)
|
|
4294
|
-
resolve(stdout.trim());
|
|
4295
|
-
else
|
|
4296
|
-
resolve("");
|
|
4297
|
-
});
|
|
4528
|
+
probe.on("exit", (code) => resolve(code === 0 ? stdout.trim() : ""));
|
|
4298
4529
|
probe.on("error", () => resolve(""));
|
|
4299
4530
|
});
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
"";
|
|
4337
|
-
const updatedPath = `${scriptsDir}${separator}${existingPath}`;
|
|
4338
|
-
process.env.PATH = updatedPath;
|
|
4339
|
-
if (isWindows) {
|
|
4340
|
-
process.env.Path = updatedPath;
|
|
4341
|
-
}
|
|
4342
|
-
debugLog(`Added pip user scripts dir to PATH: ${scriptsDir}`);
|
|
4343
|
-
}
|
|
4344
|
-
}
|
|
4345
|
-
catch {
|
|
4346
|
-
debugLog(`pip user scripts dir not accessible: ${scriptsDir}`);
|
|
4347
|
-
}
|
|
4348
|
-
}
|
|
4349
|
-
}
|
|
4350
|
-
return packageName;
|
|
4531
|
+
const binaryPath = base
|
|
4532
|
+
? await addBinToPath(pipScriptsDir(base, installerPlatform()))
|
|
4533
|
+
: undefined;
|
|
4534
|
+
// Keep the historical normal-user result even when the interpreter's
|
|
4535
|
+
// user-base probe is unavailable. The next availability probe owns
|
|
4536
|
+
// resolution through PATH and its user-base candidates.
|
|
4537
|
+
return succeeded("user", binaryPath ?? packageName);
|
|
4538
|
+
}
|
|
4539
|
+
const candidateError = `${candidate.command} ${args.join(" ")}: ${boundInstallError(error, INSTALL_CANDIDATE_ERROR_LIMIT)}`;
|
|
4540
|
+
candidateErrors.push(candidateError);
|
|
4541
|
+
if (pep668.test(error)) {
|
|
4542
|
+
userRefused = true;
|
|
4543
|
+
refuse("user", error);
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
if (!userRefused)
|
|
4547
|
+
throw new Error(`pip install failed: ${candidateErrors.join(" | ") || "unknown error"}`);
|
|
4548
|
+
const privateBase = path.join(getGlobalPiLensDir(), "pip-user");
|
|
4549
|
+
const privateEnv = { ...process.env, PYTHONUSERBASE: privateBase };
|
|
4550
|
+
for (const candidate of pipCandidates) {
|
|
4551
|
+
const args = candidate.command === "pip" || candidate.command === "pip3"
|
|
4552
|
+
? [...verb, "--user", "--break-system-packages", packageName]
|
|
4553
|
+
: [
|
|
4554
|
+
"-m",
|
|
4555
|
+
"pip",
|
|
4556
|
+
...verb,
|
|
4557
|
+
"--user",
|
|
4558
|
+
"--break-system-packages",
|
|
4559
|
+
packageName,
|
|
4560
|
+
];
|
|
4561
|
+
const result = await run(candidate.command, args, privateEnv);
|
|
4562
|
+
const error = (result.error?.message ?? result.stderr).trim();
|
|
4563
|
+
if (result.status !== 0) {
|
|
4564
|
+
const candidateError = `${candidate.command} ${args.join(" ")}: ${boundInstallError(error, INSTALL_CANDIDATE_ERROR_LIMIT)}`;
|
|
4565
|
+
candidateErrors.push(candidateError);
|
|
4566
|
+
continue;
|
|
4351
4567
|
}
|
|
4352
|
-
const
|
|
4353
|
-
|
|
4354
|
-
|
|
4568
|
+
const binaryPath = await addBinToPath(pipScriptsDir(privateBase, installerPlatform()));
|
|
4569
|
+
if (binaryPath)
|
|
4570
|
+
return succeeded("private-prefix", binaryPath);
|
|
4571
|
+
throw new Error(`private-prefix pip installed ${packageName} but ${binaryName} is not resolvable`);
|
|
4355
4572
|
}
|
|
4356
|
-
throw new Error(`
|
|
4573
|
+
throw new Error(`pip install failed: ${candidateErrors.join(" | ") || "unknown error"}`);
|
|
4357
4574
|
}
|
|
4358
4575
|
catch (err) {
|
|
4359
4576
|
return recordPackageManagerInstallException(toolId, "pip", packageName, err);
|
|
@@ -4493,7 +4710,7 @@ export async function installTool(toolId) {
|
|
|
4493
4710
|
case "pip": {
|
|
4494
4711
|
if (!tool.packageName)
|
|
4495
4712
|
return false;
|
|
4496
|
-
const pipPath = await installPipTool(tool.id, tool.packageName);
|
|
4713
|
+
const pipPath = await installPipTool(tool.id, tool.packageName, tool.binaryName ?? tool.id);
|
|
4497
4714
|
return finishInstallAttempt(tool.id, pipPath !== undefined, startedAt);
|
|
4498
4715
|
}
|
|
4499
4716
|
case "gem": {
|
|
@@ -4871,6 +5088,8 @@ export const GITHUB_TOOLS = [
|
|
|
4871
5088
|
"clojure-lsp",
|
|
4872
5089
|
"cue",
|
|
4873
5090
|
"gleam",
|
|
5091
|
+
"typstyle",
|
|
5092
|
+
"tinymist",
|
|
4874
5093
|
"marksman",
|
|
4875
5094
|
"expert",
|
|
4876
5095
|
];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Directory boundary for the backstop lock and cooldown stamp. Production
|
|
2
|
+
* shares the machine home; the test harness isolates only this state without
|
|
3
|
+
* relocating the registry, installed tools, or other machine-wide stores.
|
|
4
|
+
*/
|
|
5
|
+
export function resolveBackstopStateDir(machineHome) {
|
|
6
|
+
return machineHome;
|
|
7
|
+
}
|