@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
|
@@ -31,12 +31,45 @@ import { getBrowserCookiesForHosts, getLastBrowserCookieDiagnostic } from "./chr
|
|
|
31
31
|
import { sanitizeInlineDataUris } from "./data-uri-sanitize.ts";
|
|
32
32
|
|
|
33
33
|
const DEFAULT_TIMEOUT_MS = 30000;
|
|
34
|
+
const MAX_CONFIGURED_TIMEOUT_MS = 2_147_483_647;
|
|
34
35
|
const CONCURRENT_LIMIT = 3;
|
|
36
|
+
const WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();
|
|
37
|
+
|
|
38
|
+
function loadFetchTimeoutMs(): number {
|
|
39
|
+
if (!existsSync(WEB_SEARCH_CONFIG_PATH)) return DEFAULT_TIMEOUT_MS;
|
|
40
|
+
|
|
41
|
+
let raw: unknown;
|
|
42
|
+
try {
|
|
43
|
+
raw = JSON.parse(readFileSync(WEB_SEARCH_CONFIG_PATH, "utf-8"));
|
|
44
|
+
} catch (err) {
|
|
45
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
46
|
+
throw new Error(`Failed to parse ${WEB_SEARCH_CONFIG_PATH}: ${message}`);
|
|
47
|
+
}
|
|
48
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
49
|
+
throw new Error(`Invalid config in ${WEB_SEARCH_CONFIG_PATH}: expected a JSON object`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const fetchConfig = (raw as Record<string, unknown>).fetch;
|
|
53
|
+
if (fetchConfig === undefined) return DEFAULT_TIMEOUT_MS;
|
|
54
|
+
if (!fetchConfig || typeof fetchConfig !== "object" || Array.isArray(fetchConfig)) {
|
|
55
|
+
throw new Error(`fetch in ${WEB_SEARCH_CONFIG_PATH} must be an object`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const value = (fetchConfig as Record<string, unknown>).timeout;
|
|
59
|
+
if (value === undefined) return DEFAULT_TIMEOUT_MS;
|
|
60
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
61
|
+
throw new Error(`Invalid fetch.timeout in ${WEB_SEARCH_CONFIG_PATH}: expected a positive finite number of seconds, got ${JSON.stringify(value)}`);
|
|
62
|
+
}
|
|
63
|
+
const timeoutMs = Math.ceil(value * 1000);
|
|
64
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > MAX_CONFIGURED_TIMEOUT_MS) {
|
|
65
|
+
throw new Error(`Invalid fetch.timeout in ${WEB_SEARCH_CONFIG_PATH}: converted timeout must be a finite safe integer from 1 through ${MAX_CONFIGURED_TIMEOUT_MS} milliseconds`);
|
|
66
|
+
}
|
|
67
|
+
return Math.max(1, timeoutMs);
|
|
68
|
+
}
|
|
35
69
|
|
|
36
70
|
const NON_RECOVERABLE_ERRORS = ["Unsupported content type", "Response too large", "PDF extraction is disabled", "Image fetching is disabled"];
|
|
37
71
|
const MIN_USEFUL_CONTENT = 500;
|
|
38
72
|
const SUPPORTED_IMAGE_TYPES = new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
39
|
-
const WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();
|
|
40
73
|
const FETCH_PROVIDERS = ["http", "firecrawl", "jina", "tinyfish", "search1api", "querit", "kagi", "ollama", "parallel", "parallel-mcp", "brightdata", "gemini"] as const;
|
|
41
74
|
type FetchProvider = typeof FETCH_PROVIDERS[number];
|
|
42
75
|
type FetchRouting = { providers: FetchProvider[]; allowRemoteHostedProviders: boolean };
|
|
@@ -51,6 +84,10 @@ function isDefuddleConsoleError(args: Parameters<typeof console.error>): boolean
|
|
|
51
84
|
async function extractWithDefuddle(text: string, url: string): Promise<{ title: string; content: string } | null> {
|
|
52
85
|
const { Defuddle } = await import("defuddle/node");
|
|
53
86
|
const { document } = parseHTML(text);
|
|
87
|
+
Object.defineProperty(document, "location", {
|
|
88
|
+
value: new URL(url),
|
|
89
|
+
configurable: true,
|
|
90
|
+
});
|
|
54
91
|
let processingError: unknown;
|
|
55
92
|
const originalConsoleError = console.error;
|
|
56
93
|
console.error = (...args) => {
|
|
@@ -298,11 +335,16 @@ export interface ExtractOptions {
|
|
|
298
335
|
lookup?: Lookup;
|
|
299
336
|
}
|
|
300
337
|
|
|
338
|
+
/** Resolve the direct HTTP/Jina fetch budget, with a per-call override taking precedence. */
|
|
339
|
+
export function resolveFetchTimeoutMs(options?: Pick<ExtractOptions, "timeoutMs">): number {
|
|
340
|
+
return options?.timeoutMs ?? loadFetchTimeoutMs();
|
|
341
|
+
}
|
|
342
|
+
|
|
301
343
|
const JINA_READER_BASE = "https://r.jina.ai/";
|
|
302
|
-
const JINA_TIMEOUT_MS = 30000;
|
|
303
344
|
|
|
304
345
|
async function extractWithJinaReader(
|
|
305
346
|
url: string,
|
|
347
|
+
timeoutMs: number,
|
|
306
348
|
signal?: AbortSignal,
|
|
307
349
|
lookup?: Lookup,
|
|
308
350
|
): Promise<ExtractedContent | null> {
|
|
@@ -325,7 +367,7 @@ async function extractWithJinaReader(
|
|
|
325
367
|
"X-No-Cache": "true",
|
|
326
368
|
},
|
|
327
369
|
signal: AbortSignal.any([
|
|
328
|
-
AbortSignal.timeout(
|
|
370
|
+
AbortSignal.timeout(timeoutMs),
|
|
329
371
|
...(signal ? [signal] : []),
|
|
330
372
|
]),
|
|
331
373
|
});
|
|
@@ -480,18 +522,14 @@ export async function extractContent(
|
|
|
480
522
|
}
|
|
481
523
|
}
|
|
482
524
|
|
|
483
|
-
if (options?.authFetchProfile) {
|
|
525
|
+
if (options?.authFetchProfile || options?.mode === "raw") {
|
|
484
526
|
try {
|
|
485
|
-
return await extractViaHttp(url, signal, options);
|
|
527
|
+
return await extractViaHttp(url, resolveFetchTimeoutMs(options), signal, options);
|
|
486
528
|
} catch (err) {
|
|
487
529
|
return { url, title: "", content: "", error: errorMessage(err) };
|
|
488
530
|
}
|
|
489
531
|
}
|
|
490
532
|
|
|
491
|
-
if (options?.mode === "raw") {
|
|
492
|
-
return extractViaHttp(url, signal, options);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
533
|
if (options?.frames || options?.timestamp) {
|
|
496
534
|
const disabled = imageGateError();
|
|
497
535
|
if (disabled) return { url, title: "", content: "", error: disabled };
|
|
@@ -703,6 +741,13 @@ export async function extractContent(
|
|
|
703
741
|
|
|
704
742
|
if (signal?.aborted) return abortedResult(url);
|
|
705
743
|
|
|
744
|
+
let fetchTimeoutMs: number;
|
|
745
|
+
try {
|
|
746
|
+
fetchTimeoutMs = resolveFetchTimeoutMs(options);
|
|
747
|
+
} catch (err) {
|
|
748
|
+
return { url, title: "", content: "", error: errorMessage(err) };
|
|
749
|
+
}
|
|
750
|
+
|
|
706
751
|
let fetchRouting: FetchRouting;
|
|
707
752
|
try {
|
|
708
753
|
fetchRouting = loadFetchRouting();
|
|
@@ -731,7 +776,7 @@ export async function extractContent(
|
|
|
731
776
|
? { ...httpResult, error: message }
|
|
732
777
|
: { url, title: "", content: "", error: message };
|
|
733
778
|
const runHttpProvider = async (): Promise<ExtractedContent | null> => {
|
|
734
|
-
const { declaredLinks: discoveredLinks = [], ...result } = await extractViaHttp(url, signal, options);
|
|
779
|
+
const { declaredLinks: discoveredLinks = [], ...result } = await extractViaHttp(url, fetchTimeoutMs, signal, options);
|
|
735
780
|
httpResult = result;
|
|
736
781
|
declaredLinks = discoveredLinks;
|
|
737
782
|
if (signal?.aborted) return abortedResult(url);
|
|
@@ -786,7 +831,7 @@ export async function extractContent(
|
|
|
786
831
|
}
|
|
787
832
|
|
|
788
833
|
if (provider === "jina") {
|
|
789
|
-
const jinaResult = await extractWithJinaReader(url, signal, options?.lookup);
|
|
834
|
+
const jinaResult = await extractWithJinaReader(url, fetchTimeoutMs, signal, options?.lookup);
|
|
790
835
|
if (jinaResult) return withDeclaredLinks(jinaResult);
|
|
791
836
|
continue;
|
|
792
837
|
}
|
|
@@ -1066,10 +1111,10 @@ function responseSizeLimitError(maxBytes: number): Error {
|
|
|
1066
1111
|
|
|
1067
1112
|
async function extractViaHttp(
|
|
1068
1113
|
url: string,
|
|
1114
|
+
timeoutMs: number,
|
|
1069
1115
|
signal?: AbortSignal,
|
|
1070
1116
|
options?: ExtractOptions,
|
|
1071
1117
|
): Promise<HttpExtractedContent> {
|
|
1072
|
-
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1073
1118
|
const activityId = activityMonitor.logStart({ type: "fetch", url });
|
|
1074
1119
|
|
|
1075
1120
|
const controller = new AbortController();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
|
|
1
|
+
import { chmodSync, closeSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
|
|
2
2
|
import { execFile, spawn, type ChildProcess } from "node:child_process";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { basename, dirname, extname, join, resolve as resolvePath, sep as pathSep } from "node:path";
|
|
@@ -59,6 +59,7 @@ interface GitHubCloneConfig {
|
|
|
59
59
|
const cloneCache = new Map<string, CachedClone>();
|
|
60
60
|
|
|
61
61
|
let cachedConfig: GitHubCloneConfig | null = null;
|
|
62
|
+
let cloneRuntime: { parentPath: string; rootPath: string } | null = null;
|
|
62
63
|
|
|
63
64
|
function normalizeEnabled(value: unknown, fallback: boolean): boolean {
|
|
64
65
|
return typeof value === "boolean" ? value : fallback;
|
|
@@ -189,10 +190,48 @@ function cacheKey(owner: string, repo: string, ref?: string): string {
|
|
|
189
190
|
return ref ? `${owner}/${repo}@${ref}` : `${owner}/${repo}`;
|
|
190
191
|
}
|
|
191
192
|
|
|
193
|
+
function removeCloneRuntime(parentPath: string, runtimePath: string): void {
|
|
194
|
+
const normalizedParentPath = resolvePath(parentPath);
|
|
195
|
+
const normalizedRuntimePath = resolvePath(runtimePath);
|
|
196
|
+
if (dirname(normalizedRuntimePath) !== normalizedParentPath || !basename(normalizedRuntimePath).startsWith("runtime-")) return;
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const entry = lstatSync(normalizedRuntimePath);
|
|
200
|
+
if (entry.isSymbolicLink()) unlinkSync(normalizedRuntimePath);
|
|
201
|
+
else rmSync(normalizedRuntimePath, { recursive: true, force: true });
|
|
202
|
+
} catch {
|
|
203
|
+
// The runtime directory may already have been removed externally.
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function getCloneRuntimeRoot(config: GitHubCloneConfig): string | null {
|
|
208
|
+
if (cloneRuntime) return cloneRuntime.rootPath;
|
|
209
|
+
|
|
210
|
+
let parentPath: string | null = null;
|
|
211
|
+
let runtimePath: string | null = null;
|
|
212
|
+
try {
|
|
213
|
+
const configuredPath = resolvePath(config.clonePath);
|
|
214
|
+
mkdirSync(configuredPath, { recursive: true });
|
|
215
|
+
parentPath = realpathSync(configuredPath);
|
|
216
|
+
runtimePath = mkdtempSync(join(parentPath, "runtime-"));
|
|
217
|
+
chmodSync(runtimePath, 0o700);
|
|
218
|
+
const rootPath = realpathSync(runtimePath);
|
|
219
|
+
if (dirname(rootPath) !== parentPath) {
|
|
220
|
+
removeCloneRuntime(parentPath, runtimePath);
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
cloneRuntime = { parentPath, rootPath };
|
|
224
|
+
return rootPath;
|
|
225
|
+
} catch {
|
|
226
|
+
if (parentPath && runtimePath) removeCloneRuntime(parentPath, runtimePath);
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
192
231
|
function cloneDestination(config: GitHubCloneConfig, owner: string, repo: string, ref?: string): CloneDestination | null {
|
|
193
232
|
try {
|
|
194
|
-
|
|
195
|
-
|
|
233
|
+
const rootPath = getCloneRuntimeRoot(config);
|
|
234
|
+
if (!rootPath) return null;
|
|
196
235
|
const digest = createHash("sha256").update(JSON.stringify([owner, repo, ref ?? null])).digest("hex");
|
|
197
236
|
const localPath = resolvePath(rootPath, digest);
|
|
198
237
|
if (dirname(localPath) !== rootPath) return null;
|
|
@@ -742,5 +781,10 @@ export function clearCloneCache(): void {
|
|
|
742
781
|
removeCloneDestination(entry.destination);
|
|
743
782
|
}
|
|
744
783
|
cloneCache.clear();
|
|
784
|
+
|
|
785
|
+
if (cloneRuntime) {
|
|
786
|
+
removeCloneRuntime(cloneRuntime.parentPath, cloneRuntime.rootPath);
|
|
787
|
+
}
|
|
788
|
+
cloneRuntime = null;
|
|
745
789
|
cachedConfig = null;
|
|
746
790
|
}
|
|
@@ -2443,7 +2443,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2443
2443
|
description: "Fetch mode: readable (default extraction), raw (exact textual HTTP body), or answer (answer prompt using only fetched content).",
|
|
2444
2444
|
})),
|
|
2445
2445
|
answerModel: Type.Optional(Type.String({
|
|
2446
|
-
description: "Optional provider/model-id override for mode answer. Defaults to the current Pi model.",
|
|
2446
|
+
description: "Optional provider/model-id override for mode answer. Defaults to fetch.answerProvider + fetch.answerModel when configured, otherwise the current Pi model.",
|
|
2447
2447
|
})),
|
|
2448
2448
|
timestamp: Type.Optional(Type.String({
|
|
2449
2449
|
description: "Extract video frame(s) at a timestamp or time range. Single: '1:23:45', '23:45', or '85' (seconds). Range: '23:41-25:00' extracts evenly-spaced frames across that span (default 6). Use frames with ranges to control density; single+frames uses a fixed 5s interval. YouTube requires yt-dlp + ffmpeg; local videos require ffmpeg. Use a range when you know the approximate area but not the exact moment — you'll get a contact sheet to visually identify the right frame.",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-access",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Exa, Perplexity, Gemini, and Kimi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { complete, type Api, type Message, type Model } from "@earendil-works/pi-ai/compat";
|
|
2
2
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { findModelWithProviderRouting, loadEnabledModelPatterns, modelMatchesEnabledPatterns } from "./summary-model-scope.ts";
|
|
5
|
+
import { getWebSearchConfigPath } from "./utils.ts";
|
|
4
6
|
|
|
5
7
|
const OUTPUT_TOKENS = 2_000;
|
|
6
8
|
const INPUT_CONTEXT_FRACTION = 0.6;
|
|
@@ -16,7 +18,48 @@ export interface PageAnswer {
|
|
|
16
18
|
truncated: boolean;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
interface AnswerModelSelector {
|
|
22
|
+
provider: string;
|
|
23
|
+
id: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function loadConfiguredAnswerModel(): AnswerModelSelector | undefined {
|
|
27
|
+
const configPath = getWebSearchConfigPath();
|
|
28
|
+
if (!existsSync(configPath)) return undefined;
|
|
29
|
+
|
|
30
|
+
let raw: unknown;
|
|
31
|
+
try {
|
|
32
|
+
raw = JSON.parse(readFileSync(configPath, "utf8"));
|
|
33
|
+
} catch (err) {
|
|
34
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
35
|
+
throw new Error(`Failed to parse ${configPath}: ${message}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const root = raw && typeof raw === "object" && !Array.isArray(raw)
|
|
39
|
+
? raw as Record<string, unknown>
|
|
40
|
+
: undefined;
|
|
41
|
+
const fetchConfig = root?.fetch;
|
|
42
|
+
if (!fetchConfig || typeof fetchConfig !== "object" || Array.isArray(fetchConfig)) return undefined;
|
|
43
|
+
const values = fetchConfig as Record<string, unknown>;
|
|
44
|
+
const hasProvider = Object.hasOwn(values, "answerProvider");
|
|
45
|
+
const hasModel = Object.hasOwn(values, "answerModel");
|
|
46
|
+
if (!hasProvider && !hasModel) return undefined;
|
|
47
|
+
|
|
48
|
+
const provider = values.answerProvider;
|
|
49
|
+
const model = values.answerModel;
|
|
50
|
+
if (hasProvider && (typeof provider !== "string" || provider.trim().length === 0)) {
|
|
51
|
+
throw new Error(`fetch.answerProvider in ${configPath} must be a non-empty string`);
|
|
52
|
+
}
|
|
53
|
+
if (hasModel && (typeof model !== "string" || model.trim().length === 0)) {
|
|
54
|
+
throw new Error(`fetch.answerModel in ${configPath} must be a non-empty string`);
|
|
55
|
+
}
|
|
56
|
+
if (!hasProvider || !hasModel) {
|
|
57
|
+
throw new Error(`fetch.answerProvider and fetch.answerModel must be configured together in ${configPath}`);
|
|
58
|
+
}
|
|
59
|
+
return { provider: (provider as string).trim(), id: (model as string).trim() };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function parseModelSelector(value: string): AnswerModelSelector {
|
|
20
63
|
const separator = value.indexOf("/");
|
|
21
64
|
if (separator <= 0 || separator === value.length - 1) {
|
|
22
65
|
throw new Error(`Invalid answerModel: ${value}. Use provider/model-id.`);
|
|
@@ -24,14 +67,20 @@ function parseModelSelector(value: string): { provider: string; id: string } {
|
|
|
24
67
|
return { provider: value.slice(0, separator), id: value.slice(separator + 1) };
|
|
25
68
|
}
|
|
26
69
|
|
|
27
|
-
function resolveModel(ctx: ExtensionContext, override?: string): Model<Api> {
|
|
28
|
-
const
|
|
70
|
+
function resolveModel(ctx: ExtensionContext, override?: string, configured?: AnswerModelSelector): Model<Api> {
|
|
71
|
+
const selector = override ? parseModelSelector(override) : configured;
|
|
72
|
+
const model = selector
|
|
29
73
|
? (() => {
|
|
30
|
-
|
|
31
|
-
return ctx.modelRegistry.find(selector.provider, selector.id);
|
|
74
|
+
return findModelWithProviderRouting(ctx.modelRegistry, selector.provider, selector.id);
|
|
32
75
|
})()
|
|
33
76
|
: ctx.model;
|
|
34
|
-
if (!model)
|
|
77
|
+
if (!model) {
|
|
78
|
+
if (override) throw new Error(`Answer model not found: ${override}`);
|
|
79
|
+
if (configured) {
|
|
80
|
+
throw new Error(`Answer model not found: ${configured.provider}/${configured.id} (from fetch.answerProvider/fetch.answerModel in ${getWebSearchConfigPath()})`);
|
|
81
|
+
}
|
|
82
|
+
throw new Error("No current model available for page answering");
|
|
83
|
+
}
|
|
35
84
|
if (!model.input.includes("text")) throw new Error(`Answer model does not support text input: ${model.provider}/${model.id}`);
|
|
36
85
|
if (!modelMatchesEnabledPatterns(model, loadEnabledModelPatterns(ctx))) {
|
|
37
86
|
throw new Error(`Answer model is not enabled: ${model.provider}/${model.id}`);
|
|
@@ -53,7 +102,11 @@ export async function answerFromPage(
|
|
|
53
102
|
ctx: ExtensionContext,
|
|
54
103
|
signal?: AbortSignal,
|
|
55
104
|
): Promise<PageAnswer> {
|
|
56
|
-
|
|
105
|
+
// Resolve an explicit per-call model first. In particular, do not read a
|
|
106
|
+
// malformed or partial config when the caller has supplied an override.
|
|
107
|
+
const model = input.model
|
|
108
|
+
? resolveModel(ctx, input.model)
|
|
109
|
+
: resolveModel(ctx, undefined, loadConfiguredAnswerModel());
|
|
57
110
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
58
111
|
if (!auth.ok || !auth.apiKey) throw new Error(`No API key available for answer model ${model.provider}/${model.id}`);
|
|
59
112
|
const registry = ctx.modelRegistry as typeof ctx.modelRegistry & { complete?: typeof complete };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-extensions",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.9.0",
|
|
4
4
|
"description": "Aggregate installer for HerbertGao-maintained Pi extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"extensions",
|
|
@@ -37,17 +37,18 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ast-grep/cli": "^0.45.0",
|
|
39
39
|
"@ast-grep/napi": "^0.45.0",
|
|
40
|
-
"@czottmann/pi-automode": "1.
|
|
40
|
+
"@czottmann/pi-automode": "1.15.0",
|
|
41
41
|
"@dietrichgebert/ponytail": "4.9.0",
|
|
42
|
-
"@earendil-works/pi-coding-agent": "^0.84.
|
|
43
|
-
"@earendil-works/pi-tui": "^0.84.
|
|
42
|
+
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
43
|
+
"@earendil-works/pi-tui": "^0.84.4",
|
|
44
44
|
"@effect/platform-node": "4.0.0-beta.103",
|
|
45
45
|
"@effect/platform-node-shared": "4.0.0-beta.103",
|
|
46
|
-
"@herbertgao/pi-
|
|
46
|
+
"@herbertgao/pi-bark": "0.1.0",
|
|
47
|
+
"@herbertgao/pi-cc-extensions": "0.9.0",
|
|
47
48
|
"@herbertgao/pi-subagents": "0.17.1",
|
|
48
49
|
"@herbertgao/resume-from": "0.2.0",
|
|
49
|
-
"@juicesharp/rpiv-ask-user-question": "2.
|
|
50
|
-
"@juicesharp/rpiv-config": "^2.
|
|
50
|
+
"@juicesharp/rpiv-ask-user-question": "2.9.0",
|
|
51
|
+
"@juicesharp/rpiv-config": "^2.9.0",
|
|
51
52
|
"@luxusai/pi-hindsight": "0.12.0",
|
|
52
53
|
"@modelcontextprotocol/client": "2.0.0",
|
|
53
54
|
"@modelcontextprotocol/core": "2.0.0",
|
|
@@ -55,26 +56,27 @@
|
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
56
57
|
"@mozilla/readability": "^0.6.0",
|
|
57
58
|
"@napi-rs/keyring": "^1.3.0",
|
|
58
|
-
"@narumitw/pi-btw": "0.
|
|
59
|
+
"@narumitw/pi-btw": "0.57.0",
|
|
60
|
+
"@narumitw/pi-caffeinate": "0.49.7",
|
|
59
61
|
"@narumitw/pi-tui-kit": "^0.59.0",
|
|
60
62
|
"@noble/ed25519": "^3.1.0",
|
|
61
63
|
"@pi-plugins/fast-mode": "0.1.10",
|
|
62
64
|
"@shikijs/cli": "^4.0.2",
|
|
63
65
|
"@sinclair/typebox": "^0.34.49",
|
|
64
66
|
"@tifan/pi-copy-response": "0.2.6",
|
|
65
|
-
"@tifan/pi-handoff": "2.
|
|
67
|
+
"@tifan/pi-handoff": "2.2.1",
|
|
66
68
|
"@tifan/pi-inline-skills": "1.0.5",
|
|
67
69
|
"@tifan/pi-mermaid-open": "0.2.0",
|
|
68
70
|
"@tifan/pi-preferred-thinking": "1.0.1",
|
|
69
|
-
"@tifan/pi-recap": "0.4.
|
|
70
|
-
"@tifan/pi-rename": "0.
|
|
71
|
-
"@tifan/pi-titlebar-spinner": "0.1.3",
|
|
71
|
+
"@tifan/pi-recap": "0.4.6",
|
|
72
|
+
"@tifan/pi-rename": "0.6.0",
|
|
72
73
|
"@vectorize-io/hindsight-client": "^0.9.0",
|
|
73
74
|
"ajv": "^8.17.1",
|
|
74
75
|
"ajv-formats": "^3.0.1",
|
|
75
76
|
"chalk": "^6.0.0",
|
|
76
77
|
"croner": "^10.0.1",
|
|
77
78
|
"cross-spawn": "^7.0.6",
|
|
79
|
+
"dbus-native": "^0.15.2",
|
|
78
80
|
"defuddle": "0.19.3",
|
|
79
81
|
"effect": "4.0.0-beta.103",
|
|
80
82
|
"gpt-tokenizer": "^3.4.0",
|
|
@@ -88,9 +90,9 @@
|
|
|
88
90
|
"open": "^10.2.0",
|
|
89
91
|
"p-limit": "^6.1.0",
|
|
90
92
|
"pi-footer": "0.5.1",
|
|
91
|
-
"pi-lens": "4.1.
|
|
92
|
-
"pi-mcp-adapter": "2.
|
|
93
|
-
"pi-web-access": "0.
|
|
93
|
+
"pi-lens": "4.1.3",
|
|
94
|
+
"pi-mcp-adapter": "2.32.1",
|
|
95
|
+
"pi-web-access": "0.27.0",
|
|
94
96
|
"pidusage": "^4.0.1",
|
|
95
97
|
"promise.try": "^2.0.1",
|
|
96
98
|
"qrcode-terminal": "^0.12.0",
|
|
@@ -113,12 +115,14 @@
|
|
|
113
115
|
"bundledDependencies": [
|
|
114
116
|
"@czottmann/pi-automode",
|
|
115
117
|
"@dietrichgebert/ponytail",
|
|
118
|
+
"@herbertgao/pi-bark",
|
|
116
119
|
"@herbertgao/pi-cc-extensions",
|
|
117
120
|
"@herbertgao/pi-subagents",
|
|
118
121
|
"@herbertgao/resume-from",
|
|
119
122
|
"@juicesharp/rpiv-ask-user-question",
|
|
120
123
|
"@luxusai/pi-hindsight",
|
|
121
124
|
"@narumitw/pi-btw",
|
|
125
|
+
"@narumitw/pi-caffeinate",
|
|
122
126
|
"@pi-plugins/fast-mode",
|
|
123
127
|
"@tifan/pi-copy-response",
|
|
124
128
|
"@tifan/pi-handoff",
|
|
@@ -127,7 +131,6 @@
|
|
|
127
131
|
"@tifan/pi-preferred-thinking",
|
|
128
132
|
"@tifan/pi-recap",
|
|
129
133
|
"@tifan/pi-rename",
|
|
130
|
-
"@tifan/pi-titlebar-spinner",
|
|
131
134
|
"pi-footer",
|
|
132
135
|
"pi-lens",
|
|
133
136
|
"pi-mcp-adapter",
|
|
@@ -151,10 +154,11 @@
|
|
|
151
154
|
"./node_modules/@tifan/pi-recap/src/index.ts",
|
|
152
155
|
"./node_modules/@tifan/pi-rename/src/index.ts",
|
|
153
156
|
"./node_modules/@herbertgao/pi-subagents/src/index.ts",
|
|
154
|
-
"./node_modules/@tifan/pi-titlebar-spinner/src/index.ts",
|
|
155
157
|
"./node_modules/@juicesharp/rpiv-ask-user-question/index.ts",
|
|
158
|
+
"./node_modules/@herbertgao/pi-bark/src/index.ts",
|
|
156
159
|
"./node_modules/@luxusai/pi-hindsight/extensions/index.ts",
|
|
157
160
|
"./node_modules/@narumitw/pi-btw/dist/index.ts",
|
|
161
|
+
"./node_modules/@narumitw/pi-caffeinate/dist/index.ts",
|
|
158
162
|
"./node_modules/@pi-plugins/fast-mode/dist/index.mjs",
|
|
159
163
|
"./node_modules/pi-mcp-adapter/index.ts",
|
|
160
164
|
"./node_modules/pi-lens/dist/index.js",
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# @tifan/pi-titlebar-spinner
|
|
2
|
-
|
|
3
|
-
Show a braille spinner in the pi titlebar while the agent runs.
|
|
4
|
-
|
|
5
|
-
The spinner starts on `agent_start` and stops when the agent settles or the session shuts down. When it stops, the extension restores the default `π - [session - ]cwd` title.
|
|
6
|
-
|
|
7
|
-
[add image: titlebar spinner while agent runs]
|
|
8
|
-
|
|
9
|
-
- The titlebar while the spinner is active.
|
|
10
|
-
- The restored titlebar after the agent finishes.
|
|
11
|
-
|
|
12
|
-
## Install
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
pi install npm:@tifan/pi-titlebar-spinner
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Release notes
|
|
19
|
-
|
|
20
|
-
See [CHANGELOG.md](CHANGELOG.md)
|
|
21
|
-
|
|
22
|
-
## License
|
|
23
|
-
|
|
24
|
-
[MIT](LICENSE)
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@tifan/pi-titlebar-spinner",
|
|
3
|
-
"version": "0.1.3",
|
|
4
|
-
"description": "Show a spinner in the pi titlebar while the agent runs.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"pi",
|
|
7
|
-
"pi-extension",
|
|
8
|
-
"pi-package",
|
|
9
|
-
"spinner",
|
|
10
|
-
"titlebar"
|
|
11
|
-
],
|
|
12
|
-
"homepage": "https://github.com/tifandotme/pi-extensions/tree/master/packages/pi-titlebar-spinner#readme",
|
|
13
|
-
"bugs": "https://github.com/tifandotme/pi-extensions/issues",
|
|
14
|
-
"license": "MIT",
|
|
15
|
-
"author": "Tifan Dwi Avianto <hi@tifan.me>",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/tifandotme/pi-extensions.git",
|
|
19
|
-
"directory": "packages/pi-titlebar-spinner"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"src/**/*.ts",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"type": "module",
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public",
|
|
29
|
-
"provenance": true
|
|
30
|
-
},
|
|
31
|
-
"engines": {
|
|
32
|
-
"node": ">=20"
|
|
33
|
-
},
|
|
34
|
-
"pi": {
|
|
35
|
-
"extensions": [
|
|
36
|
-
"./src/index.ts"
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import type {
|
|
3
|
-
ExtensionAPI,
|
|
4
|
-
ExtensionContext,
|
|
5
|
-
} from "@earendil-works/pi-coding-agent"
|
|
6
|
-
|
|
7
|
-
const FRAMES = ["⡿", "⣟", "⣯", "⣷", "⣾", "⣽", "⣻", "⢿"]
|
|
8
|
-
const INTERVAL_MS = 70
|
|
9
|
-
|
|
10
|
-
function baseTitle(pi: ExtensionAPI, cwdPath: string): string {
|
|
11
|
-
const cwd = path.basename(cwdPath)
|
|
12
|
-
const session = pi.getSessionName()
|
|
13
|
-
return session ? `π - ${session} - ${cwd}` : `π - ${cwd}`
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default function (pi: ExtensionAPI): void {
|
|
17
|
-
let timer: ReturnType<typeof setInterval> | undefined
|
|
18
|
-
let frameIndex = 0
|
|
19
|
-
|
|
20
|
-
function stop(ctx: ExtensionContext): void {
|
|
21
|
-
if (timer) {
|
|
22
|
-
clearInterval(timer)
|
|
23
|
-
timer = undefined
|
|
24
|
-
}
|
|
25
|
-
frameIndex = 0
|
|
26
|
-
ctx.ui.setTitle(baseTitle(pi, ctx.cwd))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function start(ctx: ExtensionContext): void {
|
|
30
|
-
stop(ctx)
|
|
31
|
-
timer = setInterval(() => {
|
|
32
|
-
const frame = FRAMES[frameIndex % FRAMES.length]
|
|
33
|
-
ctx.ui.setTitle(`${frame} ${baseTitle(pi, ctx.cwd)}`)
|
|
34
|
-
frameIndex++
|
|
35
|
-
}, INTERVAL_MS)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
pi.on("agent_start", async (_event, ctx) => {
|
|
39
|
-
start(ctx)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
pi.on("agent_settled", async (_event, ctx) => {
|
|
43
|
-
stop(ctx)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
pi.on("session_shutdown", async (_event, ctx) => {
|
|
47
|
-
stop(ctx)
|
|
48
|
-
})
|
|
49
|
-
}
|