@herbertgao/pi-extensions 2026.8.14 → 2026.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -13
- package/THIRD_PARTY_NOTICES.md +26 -1
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +8 -1
- package/node_modules/@czottmann/pi-automode/README.md +4 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +71 -9
- package/node_modules/@czottmann/pi-automode/package.json +1 -1
- package/node_modules/@herbertgao/pi-bark/LICENSE +21 -0
- package/node_modules/@herbertgao/pi-bark/README.md +44 -0
- package/node_modules/@herbertgao/pi-bark/assets/pi-icon.png +0 -0
- package/node_modules/@herbertgao/pi-bark/package.json +53 -0
- package/node_modules/@herbertgao/pi-bark/src/index.ts +178 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +20 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +46 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +6 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +5 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +34 -30
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +129 -88
- package/node_modules/@narumitw/pi-btw/dist/index.ts +283 -59
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +5 -8
- package/node_modules/@narumitw/pi-btw/src/btw.ts +31 -26
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +264 -24
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -2
- package/node_modules/@narumitw/pi-btw/src/settings.ts +16 -0
- package/node_modules/@narumitw/pi-btw/src/text.ts +18 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +5 -16
- package/node_modules/@narumitw/pi-caffeinate/LICENSE +21 -0
- package/node_modules/@narumitw/pi-caffeinate/README.md +224 -0
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +1112 -0
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-caffeinate/package.json +53 -0
- package/node_modules/@narumitw/pi-caffeinate/src/caffeinate.ts +811 -0
- package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +153 -0
- package/node_modules/@narumitw/pi-caffeinate/src/index.ts +1 -0
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitor-process.ts +43 -0
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitors.ts +167 -0
- package/node_modules/@narumitw/pi-caffeinate/src/settings.ts +202 -0
- package/node_modules/@tifan/pi-handoff/README.md +39 -13
- package/node_modules/@tifan/pi-handoff/package.json +2 -2
- package/node_modules/@tifan/pi-handoff/src/index.ts +166 -5
- package/node_modules/@tifan/pi-recap/README.md +1 -1
- package/node_modules/@tifan/pi-recap/package.json +2 -2
- package/node_modules/@tifan/pi-recap/src/index.ts +15 -0
- package/node_modules/@tifan/pi-rename/README.md +42 -21
- package/node_modules/@tifan/pi-rename/package.json +1 -1
- package/node_modules/@tifan/pi-rename/src/index.ts +62 -11
- package/node_modules/@tifan/pi-rename/src/language.ts +18 -0
- package/node_modules/@tifan/pi-rename/src/models.ts +69 -13
- package/node_modules/@tifan/pi-rename/src/naming.ts +36 -7
- package/node_modules/@tifan/pi-rename/src/sanitize.ts +22 -14
- package/node_modules/pi-lens/CHANGELOG.md +320 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +79 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +16 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +13 -6
- package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +12 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +7 -0
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +20 -0
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +56 -19
- package/node_modules/pi-lens/dist/clients/build-identity.js +95 -0
- package/node_modules/pi-lens/dist/clients/bus-publish.js +3 -0
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/cache-observability.js +2 -1
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +15 -1
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +14 -11
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +56 -4
- package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +14 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +20 -3
- package/node_modules/pi-lens/dist/clients/deps/minimatch.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +39 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +150 -9
- package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +231 -9
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +205 -100
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +87 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +21 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +174 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +54 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +37 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +11 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +8 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +76 -25
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +7 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +66 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +157 -7
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +5 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +28 -3
- package/node_modules/pi-lens/dist/clients/git-guard.js +197 -47
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +32 -1
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +5 -1
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +7 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +131 -34
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +3 -1
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +4 -13
- package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +145 -0
- package/node_modules/pi-lens/dist/clients/instance-registry.js +432 -122
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
- package/node_modules/pi-lens/dist/clients/language-profile.js +4 -2
- package/node_modules/pi-lens/dist/clients/latency-logger.js +19 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +3 -1
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +4 -0
- package/node_modules/pi-lens/dist/clients/lsp/client.js +516 -31
- package/node_modules/pi-lens/dist/clients/lsp/config.js +25 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +9 -4
- package/node_modules/pi-lens/dist/clients/lsp/index.js +509 -182
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +5 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +36 -8
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +116 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +142 -13
- package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +99 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +16 -6
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +32 -23
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +16 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +12 -6
- package/node_modules/pi-lens/dist/clients/mcp/session.js +14 -1
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +23 -1
- package/node_modules/pi-lens/dist/clients/message-end-attribution.js +30 -0
- package/node_modules/pi-lens/dist/clients/metrics-history.js +21 -4
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +232 -18
- package/node_modules/pi-lens/dist/clients/package-manager.js +6 -18
- package/node_modules/pi-lens/dist/clients/path-keyed-map.js +14 -1
- package/node_modules/pi-lens/dist/clients/path-utils.js +32 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +0 -8
- package/node_modules/pi-lens/dist/clients/process-singletons.js +210 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +10 -4
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +33 -11
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +24 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +74 -7
- package/node_modules/pi-lens/dist/clients/recent-touches.js +17 -5
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +639 -62
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +5 -1
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +21 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +68 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +30 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +15 -0
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +106 -7
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +242 -27
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +158 -18
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +48 -17
- package/node_modules/pi-lens/dist/clients/session-lifecycle.js +238 -42
- package/node_modules/pi-lens/dist/clients/sg-runner.js +27 -15
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +338 -0
- package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +37 -0
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +15 -1
- package/node_modules/pi-lens/dist/clients/startup-scan.js +6 -7
- package/node_modules/pi-lens/dist/clients/startup-timing.js +69 -4
- package/node_modules/pi-lens/dist/clients/string-utils.js +20 -0
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +419 -88
- package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +11 -5
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +17 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +8 -10
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +13 -1
- package/node_modules/pi-lens/dist/clients/word-index-store.js +448 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +582 -104
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +17 -0
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -6
- package/node_modules/pi-lens/dist/index.js +11243 -6651
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +8 -7
- package/node_modules/pi-lens/dist/mcp/cli.js +3 -1
- package/node_modules/pi-lens/dist/mcp/server.js +6 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +4 -0
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +14 -5
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
- package/node_modules/pi-lens/docs/agent-guide.md +4 -2
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +41 -10
- package/node_modules/pi-lens/docs/astplayground.md +26 -17
- package/node_modules/pi-lens/package.json +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-important.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +42 -0
- package/node_modules/pi-mcp-adapter/README.md +15 -15
- package/node_modules/pi-mcp-adapter/commands.ts +59 -22
- package/node_modules/pi-mcp-adapter/config.ts +18 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +26 -6
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +4 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +13 -4
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +12 -4
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
- package/node_modules/pi-mcp-adapter/error-signal.ts +15 -4
- package/node_modules/pi-mcp-adapter/errors.ts +141 -0
- package/node_modules/pi-mcp-adapter/host-html-template.ts +58 -5
- package/node_modules/pi-mcp-adapter/index.ts +2 -3
- package/node_modules/pi-mcp-adapter/init.ts +5 -0
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +105 -32
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +30 -9
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +66 -28
- package/node_modules/pi-mcp-adapter/mcp-status.ts +2 -0
- package/node_modules/pi-mcp-adapter/package.json +2 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +88 -25
- package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +217 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +343 -6
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +1 -0
- package/node_modules/pi-mcp-adapter/types.ts +19 -4
- package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +18 -2
- package/node_modules/pi-mcp-adapter/ui-server.ts +179 -54
- package/node_modules/pi-mcp-adapter/ui-session.ts +28 -8
- package/node_modules/pi-web-access/CHANGELOG.md +20 -0
- package/node_modules/pi-web-access/README.md +15 -2
- package/node_modules/pi-web-access/extract.ts +57 -12
- package/node_modules/pi-web-access/github-extract.ts +47 -3
- package/node_modules/pi-web-access/index.ts +1 -1
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/pi-web-access/page-query.ts +61 -8
- package/package.json +21 -17
- package/node_modules/@tifan/pi-titlebar-spinner/README.md +0 -24
- package/node_modules/@tifan/pi-titlebar-spinner/package.json +0 -39
- package/node_modules/@tifan/pi-titlebar-spinner/src/index.ts +0 -49
|
@@ -482,8 +482,10 @@ import {
|
|
|
482
482
|
} from "@earendil-works/pi-coding-agent";
|
|
483
483
|
import {
|
|
484
484
|
isKeyRelease,
|
|
485
|
+
isKittyProtocolActive,
|
|
485
486
|
Key as Key2,
|
|
486
487
|
matchesKey as matchesKey2,
|
|
488
|
+
parseKey,
|
|
487
489
|
TuiAltScreen,
|
|
488
490
|
truncateToWidth as truncateToWidth2
|
|
489
491
|
} from "@earendil-works/pi-tui";
|
|
@@ -495,6 +497,18 @@ function sanitizeSingleLine(text) {
|
|
|
495
497
|
return code > 31 && (code < 127 || code > 159);
|
|
496
498
|
}).join("").replace(/ +/gu, " ").trim();
|
|
497
499
|
}
|
|
500
|
+
function formatKeyLabel2(key) {
|
|
501
|
+
const sanitized = sanitizeSingleLine(key);
|
|
502
|
+
if (!sanitized) return "";
|
|
503
|
+
return sanitized.split("+").map((part) => {
|
|
504
|
+
const lower = part.toLowerCase();
|
|
505
|
+
if (lower === "shift") return "Shift";
|
|
506
|
+
if (lower === "ctrl") return "Ctrl";
|
|
507
|
+
if (lower === "alt") return "Alt";
|
|
508
|
+
if (lower === "super") return "Super";
|
|
509
|
+
return part.length === 1 ? part.toUpperCase() : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`;
|
|
510
|
+
}).join("+");
|
|
511
|
+
}
|
|
498
512
|
|
|
499
513
|
// src/fullscreen-ui.ts
|
|
500
514
|
var FullscreenUiDisposedError = class extends Error {
|
|
@@ -503,10 +517,13 @@ var FullscreenUiDisposedError = class extends Error {
|
|
|
503
517
|
this.name = "FullscreenUiDisposedError";
|
|
504
518
|
}
|
|
505
519
|
};
|
|
506
|
-
async function runBtwFullscreen(ctx, run, dependencies = {}) {
|
|
507
|
-
const createTui = dependencies.createTui ?? ((parent, theme) => createBtwFullscreenTui(
|
|
520
|
+
async function runBtwFullscreen(ctx, run, options = {}, dependencies = {}) {
|
|
521
|
+
const createTui = dependencies.createTui ?? ((parent, theme, keybindings, fullscreenOptions) => createBtwFullscreenTui(
|
|
508
522
|
parent,
|
|
509
523
|
theme,
|
|
524
|
+
keybindings,
|
|
525
|
+
fullscreenOptions.copyOnSelect ?? true,
|
|
526
|
+
dependencies.manualSelectionCopySupported ?? hasManualSelectionCopyApi(),
|
|
510
527
|
dependencies.openUrl ?? openUrlInBrowser,
|
|
511
528
|
dependencies.copyToClipboard ?? copyToHostClipboard
|
|
512
529
|
));
|
|
@@ -529,7 +546,8 @@ async function runBtwFullscreen(ctx, run, dependencies = {}) {
|
|
|
529
546
|
}
|
|
530
547
|
done(value);
|
|
531
548
|
},
|
|
532
|
-
createTui
|
|
549
|
+
createTui,
|
|
550
|
+
options
|
|
533
551
|
);
|
|
534
552
|
return host;
|
|
535
553
|
},
|
|
@@ -550,7 +568,7 @@ async function runBtwFullscreen(ctx, run, dependencies = {}) {
|
|
|
550
568
|
var btwInputListeners = /* @__PURE__ */ new WeakMap();
|
|
551
569
|
function dispatchBtwInput(listeners, data) {
|
|
552
570
|
let current = data;
|
|
553
|
-
for (const group of [listeners.beforeViewport, listeners.regular]) {
|
|
571
|
+
for (const group of [listeners.beforeAll, listeners.beforeViewport, listeners.regular]) {
|
|
554
572
|
for (const listener of group) {
|
|
555
573
|
const result = listener(current);
|
|
556
574
|
if (result?.consume) return result;
|
|
@@ -560,10 +578,14 @@ function dispatchBtwInput(listeners, data) {
|
|
|
560
578
|
return current === data ? void 0 : { data: current };
|
|
561
579
|
}
|
|
562
580
|
var BtwTuiAltScreen = class extends TuiAltScreen {
|
|
581
|
+
hasFocusedOverlay() {
|
|
582
|
+
return this.isOverlayFocused();
|
|
583
|
+
}
|
|
563
584
|
addInputListener(listener) {
|
|
564
585
|
let listeners = btwInputListeners.get(this);
|
|
565
586
|
if (!listeners) {
|
|
566
587
|
const registeredListeners = {
|
|
588
|
+
beforeAll: /* @__PURE__ */ new Set(),
|
|
567
589
|
beforeViewport: /* @__PURE__ */ new Set(),
|
|
568
590
|
regular: /* @__PURE__ */ new Set()
|
|
569
591
|
};
|
|
@@ -574,6 +596,12 @@ var BtwTuiAltScreen = class extends TuiAltScreen {
|
|
|
574
596
|
listeners.regular.add(listener);
|
|
575
597
|
return () => listeners.regular.delete(listener);
|
|
576
598
|
}
|
|
599
|
+
addInputListenerBeforeAll(listener) {
|
|
600
|
+
const listeners = btwInputListeners.get(this);
|
|
601
|
+
if (!listeners) return super.addInputListener(listener);
|
|
602
|
+
listeners.beforeAll.add(listener);
|
|
603
|
+
return () => listeners.beforeAll.delete(listener);
|
|
604
|
+
}
|
|
577
605
|
addInputListenerBeforeViewport(listener) {
|
|
578
606
|
const listeners = btwInputListeners.get(this);
|
|
579
607
|
if (!listeners) return super.addInputListener(listener);
|
|
@@ -586,26 +614,165 @@ var BtwTuiAltScreen = class extends TuiAltScreen {
|
|
|
586
614
|
super.removeInputListener(listener);
|
|
587
615
|
return;
|
|
588
616
|
}
|
|
617
|
+
listeners.beforeAll.delete(listener);
|
|
589
618
|
listeners.beforeViewport.delete(listener);
|
|
590
619
|
listeners.regular.delete(listener);
|
|
591
620
|
}
|
|
592
621
|
};
|
|
593
|
-
|
|
622
|
+
var BRACKETED_PASTE_START = "\x1B[200~";
|
|
623
|
+
var BRACKETED_PASTE_END = "\x1B[201~";
|
|
624
|
+
var ALT_SCREEN_ACTIONS_BEFORE_BOTTOM = [
|
|
625
|
+
"tui.altScreen.search",
|
|
626
|
+
"tui.altScreen.searchNext",
|
|
627
|
+
"tui.altScreen.searchPrevious",
|
|
628
|
+
"tui.altScreen.searchClose",
|
|
629
|
+
"tui.altScreen.pageUp",
|
|
630
|
+
"tui.altScreen.pageDown",
|
|
631
|
+
"tui.altScreen.halfPageUp",
|
|
632
|
+
"tui.altScreen.halfPageDown",
|
|
633
|
+
"tui.altScreen.lineUp",
|
|
634
|
+
"tui.altScreen.lineDown",
|
|
635
|
+
"tui.altScreen.previousPrompt",
|
|
636
|
+
"tui.altScreen.nextPrompt",
|
|
637
|
+
"tui.altScreen.top"
|
|
638
|
+
];
|
|
639
|
+
var KEY_MODIFIER_ORDER = ["shift", "ctrl", "alt", "super"];
|
|
640
|
+
var MATCHABLE_SPECIAL_KEYS = /* @__PURE__ */ new Set([
|
|
641
|
+
"space",
|
|
642
|
+
"tab",
|
|
643
|
+
"enter",
|
|
644
|
+
"backspace",
|
|
645
|
+
"delete",
|
|
646
|
+
"insert",
|
|
647
|
+
"home",
|
|
648
|
+
"end",
|
|
649
|
+
"pageup",
|
|
650
|
+
"pagedown",
|
|
651
|
+
"up",
|
|
652
|
+
"down",
|
|
653
|
+
"left",
|
|
654
|
+
"right"
|
|
655
|
+
]);
|
|
656
|
+
var MATCHABLE_SYMBOL_KEYS = new Set("`-=[]\\;',./!@#$%^&*()_+|~{}:<>?");
|
|
657
|
+
function normalizedKeyId(key) {
|
|
658
|
+
const parts = key.toLowerCase().split("+");
|
|
659
|
+
const base = parts.at(-1);
|
|
660
|
+
if (!base) return "";
|
|
661
|
+
const normalizedBase = base === "esc" ? "escape" : base === "return" ? "enter" : base;
|
|
662
|
+
const modifiers = KEY_MODIFIER_ORDER.filter((modifier) => parts.includes(modifier));
|
|
663
|
+
return [...modifiers, normalizedBase].join("+");
|
|
664
|
+
}
|
|
665
|
+
function formatEffectiveKeyLabel(key) {
|
|
666
|
+
const parts = key.split("+");
|
|
667
|
+
const base = parts.at(-1);
|
|
668
|
+
if (base === "pageup") parts[parts.length - 1] = "pageUp";
|
|
669
|
+
if (base === "pagedown") parts[parts.length - 1] = "pageDown";
|
|
670
|
+
return formatKeyLabel2(parts.join("+"));
|
|
671
|
+
}
|
|
672
|
+
function canMatchKeyInput(key) {
|
|
673
|
+
const parts = key.split("+");
|
|
674
|
+
const base = parts.at(-1) ?? "";
|
|
675
|
+
const modifiers = parts.slice(0, -1);
|
|
676
|
+
if (base === "escape") return modifiers.length === 0;
|
|
677
|
+
if (base === "clear") {
|
|
678
|
+
return modifiers.length === 0 || modifiers.length === 1 && (modifiers[0] === "shift" || modifiers[0] === "ctrl");
|
|
679
|
+
}
|
|
680
|
+
if (/^f(?:[1-9]|1[0-2])$/u.test(base)) return modifiers.length === 0;
|
|
681
|
+
return MATCHABLE_SPECIAL_KEYS.has(base) || base.length === 1 && (/^[a-z0-9]$/u.test(base) || MATCHABLE_SYMBOL_KEYS.has(base));
|
|
682
|
+
}
|
|
683
|
+
function rawCtrlInput(base) {
|
|
684
|
+
if (base.length !== 1) return void 0;
|
|
685
|
+
const rawBase = base === "-" ? "_" : base;
|
|
686
|
+
if (!"abcdefghijklmnopqrstuvwxyz[\\]_".includes(rawBase)) return void 0;
|
|
687
|
+
return String.fromCharCode(rawBase.charCodeAt(0) & 31);
|
|
688
|
+
}
|
|
689
|
+
function legacyRawInput(key) {
|
|
690
|
+
const parts = key.split("+");
|
|
691
|
+
const base = parts.at(-1) ?? "";
|
|
692
|
+
if (parts.length === 2 && parts[0] === "ctrl") return rawCtrlInput(base);
|
|
693
|
+
if (isKittyProtocolActive()) return void 0;
|
|
694
|
+
if (parts.length === 2 && parts[0] === "alt" && base.length === 1) return `\x1B${base}`;
|
|
695
|
+
if (parts.length === 3 && parts[0] === "ctrl" && parts[1] === "alt") {
|
|
696
|
+
const input = rawCtrlInput(base);
|
|
697
|
+
return input ? `\x1B${input}` : void 0;
|
|
698
|
+
}
|
|
699
|
+
return void 0;
|
|
700
|
+
}
|
|
701
|
+
function keyInputIdentity(key) {
|
|
702
|
+
const identity = normalizedKeyId(key);
|
|
703
|
+
const input = legacyRawInput(identity);
|
|
704
|
+
return input ? normalizedKeyId(parseKey(input) ?? identity) : identity;
|
|
705
|
+
}
|
|
706
|
+
function hasManualSelectionCopyApi() {
|
|
707
|
+
return typeof TuiAltScreen.prototype.hasActiveSelection === "function" && typeof TuiAltScreen.prototype.copyActiveSelectionToClipboard === "function";
|
|
708
|
+
}
|
|
709
|
+
function createBtwFullscreenTui(parent, theme, keybindings, copyOnSelect, manualSelectionCopySupported, openUrl, copyToClipboard2) {
|
|
710
|
+
if (!copyOnSelect && !manualSelectionCopySupported) {
|
|
711
|
+
throw new Error(
|
|
712
|
+
"Manual fullscreen selection copying is unavailable in this Pi version; update Pi or enable automatic selection copying."
|
|
713
|
+
);
|
|
714
|
+
}
|
|
594
715
|
const styleSearchMatch = (text) => theme.bg("searchMatchBg", theme.fg("searchMatchText", text));
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
716
|
+
const fullscreen = new BtwTuiAltScreen(
|
|
717
|
+
parent.terminal,
|
|
718
|
+
parent.getShowHardwareCursor(),
|
|
719
|
+
void 0,
|
|
720
|
+
{
|
|
721
|
+
mouse: true,
|
|
722
|
+
copyOnSelect,
|
|
723
|
+
searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
|
|
724
|
+
scrollToEndIndicator: () => {
|
|
725
|
+
const unavailableKeyIdentities = /* @__PURE__ */ new Set([keyInputIdentity(Key2.ctrl("c"))]);
|
|
726
|
+
for (const action of ALT_SCREEN_ACTIONS_BEFORE_BOTTOM) {
|
|
727
|
+
for (const actionKey of keybindings.getKeys(action)) {
|
|
728
|
+
unavailableKeyIdentities.add(keyInputIdentity(String(actionKey)));
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (!copyOnSelect) {
|
|
732
|
+
for (const copyKey of keybindings.getKeys("app.message.copy")) {
|
|
733
|
+
unavailableKeyIdentities.add(keyInputIdentity(String(copyKey)));
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
const key = keybindings.getKeys("tui.altScreen.bottom").map((candidate) => keyInputIdentity(String(candidate))).find(
|
|
737
|
+
(identity) => identity && canMatchKeyInput(identity) && !unavailableKeyIdentities.has(identity) && formatEffectiveKeyLabel(identity)
|
|
738
|
+
);
|
|
739
|
+
const label = theme.fg("text", " \u2193 Jump to latest message");
|
|
740
|
+
const shortcut = key ? theme.fg("muted", ` \xB7 ${formatEffectiveKeyLabel(key)}`) : "";
|
|
741
|
+
return theme.bg("selectedBg", `${label}${shortcut} `);
|
|
742
|
+
},
|
|
743
|
+
searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
|
|
744
|
+
openUrl,
|
|
745
|
+
copySelection: async (text) => {
|
|
746
|
+
try {
|
|
747
|
+
await copyToClipboard2(text);
|
|
748
|
+
return true;
|
|
749
|
+
} catch {
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
606
752
|
}
|
|
607
753
|
}
|
|
608
|
-
|
|
754
|
+
);
|
|
755
|
+
if (!copyOnSelect) {
|
|
756
|
+
let isInBracketedPaste = false;
|
|
757
|
+
fullscreen.addInputListenerBeforeViewport((data) => {
|
|
758
|
+
const wasInBracketedPaste = isInBracketedPaste;
|
|
759
|
+
const startsBracketedPaste = data.includes(BRACKETED_PASTE_START);
|
|
760
|
+
if (startsBracketedPaste) isInBracketedPaste = true;
|
|
761
|
+
if (isInBracketedPaste && data.includes(BRACKETED_PASTE_END)) {
|
|
762
|
+
isInBracketedPaste = false;
|
|
763
|
+
}
|
|
764
|
+
if (wasInBracketedPaste || startsBracketedPaste || fullscreen.hasFocusedOverlay() || isKeyRelease(data) || !keybindings.matches(data, "app.message.copy")) {
|
|
765
|
+
return void 0;
|
|
766
|
+
}
|
|
767
|
+
if (!fullscreen.hasActiveSelection()) {
|
|
768
|
+
fullscreen.flash("No selection to copy");
|
|
769
|
+
return { consume: true };
|
|
770
|
+
}
|
|
771
|
+
void fullscreen.copyActiveSelectionToClipboard().catch(() => fullscreen.flash("Copy failed"));
|
|
772
|
+
return { consume: true };
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
return fullscreen;
|
|
609
776
|
}
|
|
610
777
|
function openUrlInBrowser(target) {
|
|
611
778
|
const [command, args] = process.platform === "darwin" ? ["open", [target]] : process.platform === "win32" ? ["rundll32", ["url.dll,FileProtocolHandler", target]] : ["xdg-open", [target]];
|
|
@@ -613,7 +780,7 @@ function openUrlInBrowser(target) {
|
|
|
613
780
|
}).unref();
|
|
614
781
|
}
|
|
615
782
|
var BtwFullscreenHost = class {
|
|
616
|
-
constructor(parent, theme, keybindings, ctx, run, done, createTui) {
|
|
783
|
+
constructor(parent, theme, keybindings, ctx, run, done, createTui, options) {
|
|
617
784
|
this.parent = parent;
|
|
618
785
|
this.theme = theme;
|
|
619
786
|
this.keybindings = keybindings;
|
|
@@ -621,6 +788,7 @@ var BtwFullscreenHost = class {
|
|
|
621
788
|
this.run = run;
|
|
622
789
|
this.done = done;
|
|
623
790
|
this.createTui = createTui;
|
|
791
|
+
this.options = options;
|
|
624
792
|
queueMicrotask(() => void this.start());
|
|
625
793
|
}
|
|
626
794
|
parent;
|
|
@@ -630,6 +798,7 @@ var BtwFullscreenHost = class {
|
|
|
630
798
|
run;
|
|
631
799
|
done;
|
|
632
800
|
createTui;
|
|
801
|
+
options;
|
|
633
802
|
fullscreen;
|
|
634
803
|
parentOverlay;
|
|
635
804
|
cancelActiveCustom;
|
|
@@ -639,9 +808,11 @@ var BtwFullscreenHost = class {
|
|
|
639
808
|
disposed = false;
|
|
640
809
|
finished = false;
|
|
641
810
|
parentStopped = false;
|
|
642
|
-
|
|
811
|
+
parentRestoreAttempted = false;
|
|
643
812
|
fullscreenCreated = false;
|
|
644
813
|
fullscreenStopped = false;
|
|
814
|
+
parentRestoreQueued = false;
|
|
815
|
+
parentRestorePromise;
|
|
645
816
|
cleanupError;
|
|
646
817
|
setParentOverlay(overlay) {
|
|
647
818
|
this.parentOverlay = overlay;
|
|
@@ -665,16 +836,16 @@ var BtwFullscreenHost = class {
|
|
|
665
836
|
this.parent.stop({ preserveScreen: true });
|
|
666
837
|
this.parentStopped = true;
|
|
667
838
|
if (this.disposed) throw new FullscreenUiDisposedError();
|
|
668
|
-
this.fullscreen = this.createTui(this.parent, this.theme);
|
|
839
|
+
this.fullscreen = this.createTui(this.parent, this.theme, this.keybindings, this.options);
|
|
669
840
|
this.fullscreenCreated = true;
|
|
670
841
|
this.fullscreen.start();
|
|
671
|
-
const addHardCancelListener = this.fullscreen.addInputListenerBeforeViewport?.bind(this.fullscreen) ?? this.fullscreen.addInputListener.bind(this.fullscreen);
|
|
842
|
+
const addHardCancelListener = this.fullscreen.addInputListenerBeforeAll?.bind(this.fullscreen) ?? this.fullscreen.addInputListenerBeforeViewport?.bind(this.fullscreen) ?? this.fullscreen.addInputListener.bind(this.fullscreen);
|
|
672
843
|
this.removeHardCancelListener = addHardCancelListener((data) => {
|
|
673
844
|
if (isKeyRelease(data) || !matchesKey2(data, Key2.ctrl("c"))) return void 0;
|
|
674
845
|
try {
|
|
675
846
|
this.hardCancelActiveCustom?.();
|
|
676
847
|
} finally {
|
|
677
|
-
this.
|
|
848
|
+
this.queueParentRestore();
|
|
678
849
|
}
|
|
679
850
|
return { consume: true };
|
|
680
851
|
});
|
|
@@ -687,14 +858,33 @@ var BtwFullscreenHost = class {
|
|
|
687
858
|
} catch (error) {
|
|
688
859
|
this.cleanupError ??= error;
|
|
689
860
|
}
|
|
690
|
-
this.
|
|
861
|
+
if (this.parentRestorePromise) await this.parentRestorePromise;
|
|
862
|
+
else this.restoreParent();
|
|
691
863
|
if (this.cleanupError !== void 0) outcome = { kind: "failed", error: this.cleanupError };
|
|
692
864
|
this.finished = true;
|
|
693
865
|
this.done(outcome);
|
|
694
866
|
}
|
|
867
|
+
queueParentRestore() {
|
|
868
|
+
if (this.parentRestoreQueued || this.parentRestoreAttempted) return;
|
|
869
|
+
this.parentRestoreQueued = true;
|
|
870
|
+
this.parentRestorePromise = Promise.resolve().then(async () => {
|
|
871
|
+
try {
|
|
872
|
+
await this.fullscreen?.terminal.drainInput?.();
|
|
873
|
+
} catch (error) {
|
|
874
|
+
this.cleanupError ??= error;
|
|
875
|
+
}
|
|
876
|
+
this.parentRestoreQueued = false;
|
|
877
|
+
this.restoreParent();
|
|
878
|
+
});
|
|
879
|
+
}
|
|
695
880
|
restoreParent() {
|
|
696
|
-
this.removeHardCancelListener
|
|
881
|
+
const removeHardCancelListener = this.removeHardCancelListener;
|
|
697
882
|
this.removeHardCancelListener = void 0;
|
|
883
|
+
try {
|
|
884
|
+
removeHardCancelListener?.();
|
|
885
|
+
} catch (error) {
|
|
886
|
+
this.cleanupError ??= error;
|
|
887
|
+
}
|
|
698
888
|
if (this.fullscreenCreated && !this.fullscreenStopped) {
|
|
699
889
|
this.fullscreenStopped = true;
|
|
700
890
|
try {
|
|
@@ -703,7 +893,7 @@ var BtwFullscreenHost = class {
|
|
|
703
893
|
this.cleanupError ??= error;
|
|
704
894
|
}
|
|
705
895
|
}
|
|
706
|
-
if (!this.parentStopped || this.
|
|
896
|
+
if (!this.parentStopped || this.parentRestoreAttempted) return;
|
|
707
897
|
const parentOverlay = this.parentOverlay;
|
|
708
898
|
this.parentOverlay = void 0;
|
|
709
899
|
try {
|
|
@@ -712,8 +902,8 @@ var BtwFullscreenHost = class {
|
|
|
712
902
|
this.cleanupError ??= error;
|
|
713
903
|
}
|
|
714
904
|
try {
|
|
905
|
+
this.parentRestoreAttempted = true;
|
|
715
906
|
this.parent.start();
|
|
716
|
-
this.parentRestarted = true;
|
|
717
907
|
this.parent.renderNow(false);
|
|
718
908
|
} catch (error) {
|
|
719
909
|
this.cleanupError ??= error;
|
|
@@ -1020,6 +1210,7 @@ Use the provided conversation context only as background. Answer the user's side
|
|
|
1020
1210
|
|
|
1021
1211
|
// src/settings.ts
|
|
1022
1212
|
var BTW_SETTINGS_FILE = "pi-btw.json";
|
|
1213
|
+
var DEFAULT_FULLSCREEN_COPY_ON_SELECT = true;
|
|
1023
1214
|
var DEFAULT_REMEMBER_THINKING_LEVEL_CHANGES = true;
|
|
1024
1215
|
var MAX_SETTINGS_BYTES = 64 * 1024;
|
|
1025
1216
|
var mutationQueues = /* @__PURE__ */ new Map();
|
|
@@ -1044,6 +1235,11 @@ function normalizeBtwSettings(value) {
|
|
|
1044
1235
|
if (typeof remember !== "boolean") return void 0;
|
|
1045
1236
|
settings.rememberThinkingLevelChanges = remember;
|
|
1046
1237
|
}
|
|
1238
|
+
if (Object.hasOwn(value, "fullscreenCopyOnSelect")) {
|
|
1239
|
+
const copyOnSelect = Reflect.get(value, "fullscreenCopyOnSelect");
|
|
1240
|
+
if (typeof copyOnSelect !== "boolean") return void 0;
|
|
1241
|
+
settings.fullscreenCopyOnSelect = copyOnSelect;
|
|
1242
|
+
}
|
|
1047
1243
|
return settings;
|
|
1048
1244
|
}
|
|
1049
1245
|
function parseBtwModelReference(reference) {
|
|
@@ -1052,6 +1248,9 @@ function parseBtwModelReference(reference) {
|
|
|
1052
1248
|
if (separator <= 0 || separator === reference.length - 1) return void 0;
|
|
1053
1249
|
return { provider: reference.slice(0, separator), modelId: reference.slice(separator + 1) };
|
|
1054
1250
|
}
|
|
1251
|
+
function effectiveFullscreenCopyOnSelect(settings) {
|
|
1252
|
+
return settings.fullscreenCopyOnSelect ?? DEFAULT_FULLSCREEN_COPY_ON_SELECT;
|
|
1253
|
+
}
|
|
1055
1254
|
function effectiveRememberThinkingLevelChanges(settings) {
|
|
1056
1255
|
return settings.rememberThinkingLevelChanges ?? DEFAULT_REMEMBER_THINKING_LEVEL_CHANGES;
|
|
1057
1256
|
}
|
|
@@ -1189,6 +1388,10 @@ function applyBtwSettingsPatch(current, patch) {
|
|
|
1189
1388
|
if (Object.hasOwn(patch, "rememberThinkingLevelChanges")) {
|
|
1190
1389
|
updated.rememberThinkingLevelChanges = patch.rememberThinkingLevelChanges;
|
|
1191
1390
|
}
|
|
1391
|
+
if (Object.hasOwn(patch, "fullscreenCopyOnSelect")) {
|
|
1392
|
+
if (patch.fullscreenCopyOnSelect === void 0) delete updated.fullscreenCopyOnSelect;
|
|
1393
|
+
else updated.fullscreenCopyOnSelect = patch.fullscreenCopyOnSelect;
|
|
1394
|
+
}
|
|
1192
1395
|
return updated;
|
|
1193
1396
|
}
|
|
1194
1397
|
function isSettingsDocument(value) {
|
|
@@ -1246,7 +1449,8 @@ async function showBtwCommandMenu(ctx, options) {
|
|
|
1246
1449
|
kind: "actions",
|
|
1247
1450
|
title: "Pi BTW",
|
|
1248
1451
|
lines: [
|
|
1249
|
-
`Thinking: ${displayThinkingSummary(state.settings)} \xB7 Remember changes: ${displayRememberSummary(state.settings)}
|
|
1452
|
+
`Thinking: ${displayThinkingSummary(state.settings)} \xB7 Remember changes: ${displayRememberSummary(state.settings)}`,
|
|
1453
|
+
`Copy on select: ${effectiveFullscreenCopyOnSelect(state.settings) ? "On" : "Off"}`
|
|
1250
1454
|
],
|
|
1251
1455
|
items: [
|
|
1252
1456
|
{
|
|
@@ -1272,7 +1476,7 @@ async function showBtwCommandMenu(ctx, options) {
|
|
|
1272
1476
|
{
|
|
1273
1477
|
id: "settings",
|
|
1274
1478
|
label: "Settings",
|
|
1275
|
-
description: "Choose
|
|
1479
|
+
description: "Choose thinking, shortcut memory, and selection copying",
|
|
1276
1480
|
to: state.kind === "invalid" ? "invalid" : "settings"
|
|
1277
1481
|
}
|
|
1278
1482
|
],
|
|
@@ -1311,6 +1515,14 @@ async function showBtwCommandMenu(ctx, options) {
|
|
|
1311
1515
|
currentValue: effectiveRememberThinkingLevelChanges(state.settings) ? "On" : "Off",
|
|
1312
1516
|
values: ["On", "Off"],
|
|
1313
1517
|
action: "set-remember"
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
id: "fullscreenCopyOnSelect",
|
|
1521
|
+
label: "Copy selection automatically",
|
|
1522
|
+
description: "Copy mouse selections immediately instead of with the configured copy key.",
|
|
1523
|
+
currentValue: effectiveFullscreenCopyOnSelect(state.settings) ? "On" : "Off",
|
|
1524
|
+
values: ["On", "Off"],
|
|
1525
|
+
action: "set-fullscreen-copy"
|
|
1314
1526
|
}
|
|
1315
1527
|
]
|
|
1316
1528
|
}),
|
|
@@ -1368,6 +1580,21 @@ async function showBtwCommandMenu(ctx, options) {
|
|
|
1368
1580
|
if (!signal.aborted) notifySaveFailure(ctx, error);
|
|
1369
1581
|
return { kind: "rejected" };
|
|
1370
1582
|
}
|
|
1583
|
+
},
|
|
1584
|
+
"set-fullscreen-copy": async ({ value, signal }) => {
|
|
1585
|
+
if (value !== "On" && value !== "Off") return { kind: "rejected" };
|
|
1586
|
+
try {
|
|
1587
|
+
await updateSettings(
|
|
1588
|
+
{ fullscreenCopyOnSelect: value === "On" },
|
|
1589
|
+
{ settingsPath, signal }
|
|
1590
|
+
);
|
|
1591
|
+
if (signal.aborted) return { kind: "rejected" };
|
|
1592
|
+
notifySafely(ctx, `Copy selection automatically: ${value}.`, "info");
|
|
1593
|
+
return { kind: "stay" };
|
|
1594
|
+
} catch (error) {
|
|
1595
|
+
if (!signal.aborted) notifySaveFailure(ctx, error);
|
|
1596
|
+
return { kind: "rejected" };
|
|
1597
|
+
}
|
|
1371
1598
|
}
|
|
1372
1599
|
}
|
|
1373
1600
|
});
|
|
@@ -2264,14 +2491,7 @@ function renderSideThreadHeader(width, theme, thinkingLevel) {
|
|
|
2264
2491
|
return theme.fg("muted", `${title}${"\u2500".repeat(ruleWidth)}`);
|
|
2265
2492
|
}
|
|
2266
2493
|
function thinkingKeyLabel(keybindings) {
|
|
2267
|
-
|
|
2268
|
-
return key.split("+").map((part) => {
|
|
2269
|
-
const lower = part.toLowerCase();
|
|
2270
|
-
if (lower === "shift") return "Shift";
|
|
2271
|
-
if (lower === "ctrl") return "Ctrl";
|
|
2272
|
-
if (lower === "alt") return "Alt";
|
|
2273
|
-
return part.length === 1 ? part.toUpperCase() : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`;
|
|
2274
|
-
}).join("+");
|
|
2494
|
+
return formatKeyLabel2(String(keybindings.getKeys("app.thinking.cycle")[0] ?? "shift+tab")) || "Shift+Tab";
|
|
2275
2495
|
}
|
|
2276
2496
|
function fitComposerLayout(header, contentLines, footer, editorLines, availableRows, statusLines = []) {
|
|
2277
2497
|
const lines = [header, ...contentLines, ...statusLines, footer, ...editorLines];
|
|
@@ -2475,29 +2695,33 @@ function btw(pi, dependencies = {}) {
|
|
|
2475
2695
|
}
|
|
2476
2696
|
const startingTurnCount = state?.thread.turns.length ?? 0;
|
|
2477
2697
|
try {
|
|
2478
|
-
await runFullscreen(
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
state
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2698
|
+
await runFullscreen(
|
|
2699
|
+
ctx,
|
|
2700
|
+
(fullscreenCtx) => {
|
|
2701
|
+
if (!state) {
|
|
2702
|
+
const createdAt = Date.now();
|
|
2703
|
+
state = {
|
|
2704
|
+
id: `btw-${nextThreadNumber}`,
|
|
2705
|
+
thread: createSideThread(
|
|
2706
|
+
selectedConversationContext ?? buildConversationContext(fullscreenCtx.sessionManager.getBranch())
|
|
2707
|
+
),
|
|
2708
|
+
thinkingLevel: settings.thinkingLevel ?? pi.getThinkingLevel(),
|
|
2709
|
+
createdAt,
|
|
2710
|
+
updatedAt: createdAt
|
|
2711
|
+
};
|
|
2712
|
+
nextThreadNumber += 1;
|
|
2713
|
+
}
|
|
2714
|
+
return runThread({
|
|
2715
|
+
initialQuestion: question || void 0,
|
|
2716
|
+
selected: resolution.selected,
|
|
2717
|
+
thinkingLevel: state.thinkingLevel,
|
|
2718
|
+
rememberThinkingLevelChanges: !sameAsMainThinkingLevel && effectiveRememberThinkingLevelChanges(settings),
|
|
2719
|
+
state,
|
|
2720
|
+
ctx: fullscreenCtx
|
|
2721
|
+
});
|
|
2722
|
+
},
|
|
2723
|
+
{ copyOnSelect: effectiveFullscreenCopyOnSelect(settings) }
|
|
2724
|
+
);
|
|
2501
2725
|
} finally {
|
|
2502
2726
|
if (state?.title && state.thread.turns.length > 0) {
|
|
2503
2727
|
if (state.thread.turns.length > startingTurnCount) {
|