@herbertgao/pi-extensions 2026.8.11 → 2026.8.13
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 +23 -10
- package/{node_modules/@herbertgao/pi-mermaid-open/LICENSE → THIRD_PARTY_NOTICES.md} +19 -1
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +15 -0
- package/node_modules/@czottmann/pi-automode/README.md +5 -3
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +2 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +60 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +1 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +4 -4
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +20 -4
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +1 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +692 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +181 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +4 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +143 -36
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +103 -148
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +32 -6
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +344 -22
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +1 -0
- package/node_modules/@czottmann/pi-automode/package.json +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +4 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +21 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +19 -19
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +4 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +10 -2
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +21 -15
- package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +11 -8
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +184 -106
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +31 -11
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +9 -1
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +156 -31
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +17 -0
- package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +14 -0
- package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +8 -0
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +32 -1
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +17 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +23 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +259 -24
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +376 -0
- package/node_modules/@luxusai/pi-hindsight/README.md +92 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +56 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +169 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +107 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +89 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +189 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +54 -0
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +75 -0
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +300 -0
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +158 -0
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +164 -0
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +139 -0
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +74 -0
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +261 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +151 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +18 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +46 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +383 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +240 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +176 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +178 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +41 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +386 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +39 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +34 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +140 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +61 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +925 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +247 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +547 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +480 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +182 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +86 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +1010 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +175 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +425 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +210 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +817 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +25 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +319 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +196 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +189 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +65 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +260 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +244 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +59 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +82 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +45 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +331 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +354 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +66 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +132 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +228 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +74 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +16 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +648 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +105 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +68 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +71 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +13 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +162 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +131 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +104 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +37 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +893 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +35 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +177 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +7 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +21 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +112 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +111 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +214 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +70 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +392 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +45 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +9 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +860 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +105 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +189 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +299 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +201 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +47 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +239 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +50 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +259 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +77 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +534 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +319 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +325 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +42 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +244 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +56 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +50 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +167 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +207 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +120 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +8 -0
- package/node_modules/@luxusai/pi-hindsight/package.json +118 -0
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +75 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -46
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +136 -22
- package/node_modules/{@herbertgao → @tifan}/pi-copy-response/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-copy-response/package.json +5 -15
- package/node_modules/{@herbertgao → @tifan}/pi-handoff/README.md +4 -6
- package/node_modules/@tifan/pi-handoff/package.json +43 -0
- package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/index.ts +1 -1
- package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/package.json +5 -15
- package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/README.md +5 -7
- package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/package.json +5 -19
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/README.md +4 -6
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/package.json +6 -16
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/src/index.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-recap/README.md +4 -6
- package/node_modules/@tifan/pi-recap/package.json +42 -0
- package/node_modules/{@herbertgao → @tifan}/pi-recap/src/models.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-rename/README.md +13 -8
- package/node_modules/@tifan/pi-rename/package.json +47 -0
- package/node_modules/@tifan/pi-rename/src/herdr-label.ts +4 -0
- package/node_modules/{@herbertgao → @tifan}/pi-rename/src/index.ts +4 -16
- package/node_modules/{@herbertgao → @tifan}/pi-rename/src/models.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/package.json +5 -15
- package/node_modules/pi-lens/CHANGELOG.md +96 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +14 -5
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +48 -18
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +16 -4
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +3 -1
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +21 -8
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +24 -8
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +4 -3
- package/node_modules/pi-lens/dist/clients/cache-manager.js +6 -7
- package/node_modules/pi-lens/dist/clients/cache-observability.js +461 -66
- package/node_modules/pi-lens/dist/clients/call-graph.js +238 -63
- package/node_modules/pi-lens/dist/clients/codebase-model.js +13 -5
- package/node_modules/pi-lens/dist/clients/complexity-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -8
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +1 -2
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +3 -1
- package/node_modules/pi-lens/dist/clients/debug-heap.js +8 -1
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +1 -1
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +11 -7
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -2
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +13 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -4
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +6 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +31 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +5 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +10 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +25 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +25 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +28 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +212 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +8 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +23 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +7 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +5 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +17 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +7 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +24 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +6 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +5 -3
- package/node_modules/pi-lens/dist/clients/feature-hints.js +8 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +34 -129
- package/node_modules/pi-lens/dist/clients/file-utils.js +17 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +57 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +144 -27
- package/node_modules/pi-lens/dist/clients/freshness.js +38 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +43 -13
- package/node_modules/pi-lens/dist/clients/go-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/grammar-source.js +1 -1
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +30 -4
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +1 -3
- package/node_modules/pi-lens/dist/clients/install-diagnostics.js +4 -2
- package/node_modules/pi-lens/dist/clients/installer/index.js +86 -77
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +5 -2
- package/node_modules/pi-lens/dist/clients/instance-registry.js +4 -2
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
- package/node_modules/pi-lens/dist/clients/knip-client.js +29 -15
- package/node_modules/pi-lens/dist/clients/language-profile.js +4 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +13 -2
- package/node_modules/pi-lens/dist/clients/lens-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-map.js +8 -3
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/config.js +4 -6
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +119 -32
- package/node_modules/pi-lens/dist/clients/lsp/index.js +94 -35
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +4 -1
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +11 -3
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +152 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -7
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +10 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +9 -4
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -3
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +10 -20
- package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +1 -1
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +73 -7
- package/node_modules/pi-lens/dist/clients/metrics-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +8 -3
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +7 -1
- package/node_modules/pi-lens/dist/clients/module-report.js +14 -17
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +3 -5
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +220 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +6 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +57 -9
- package/node_modules/pi-lens/dist/clients/project-conventions.js +2 -8
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +10 -7
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +2 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +13 -9
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +3 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -2
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +12 -5
- package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +48 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +15 -1
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +472 -66
- package/node_modules/pi-lens/dist/clients/read-expansion.js +12 -2
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +5 -4
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +5 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +1 -1
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +6 -5
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +42 -17
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +8 -2
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +10 -1
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +4 -2
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +2 -2
- package/node_modules/pi-lens/dist/clients/ruff-client.js +6 -5
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +63 -31
- package/node_modules/pi-lens/dist/clients/runtime-context.js +12 -4
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +83 -4
- package/node_modules/pi-lens/dist/clients/runtime-session.js +14 -0
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +59 -3
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +148 -34
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -6
- package/node_modules/pi-lens/dist/clients/rust-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +150 -11
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/session-summary.js +3 -1
- package/node_modules/pi-lens/dist/clients/sg-runner.js +1 -3
- package/node_modules/pi-lens/dist/clients/source-filter.js +10 -6
- package/node_modules/pi-lens/dist/clients/source-walker.js +1 -1
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +96 -0
- package/node_modules/pi-lens/dist/clients/startup-scan.js +4 -1
- package/node_modules/pi-lens/dist/clients/tool-definition.js +7 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +26 -11
- package/node_modules/pi-lens/dist/clients/tool-render.js +2 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +10 -4
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +12 -5
- package/node_modules/pi-lens/dist/clients/warm-attach.js +12 -5
- package/node_modules/pi-lens/dist/clients/widget-state.js +27 -11
- package/node_modules/pi-lens/dist/clients/word-index.js +3 -1
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -2
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +9 -1
- package/node_modules/pi-lens/dist/i18n.js +13 -5
- package/node_modules/pi-lens/dist/index.js +10797 -8627
- package/node_modules/pi-lens/dist/mcp/server.js +3 -1
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +68 -12
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +21 -7
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +164 -35
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +24 -7
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
- package/node_modules/pi-lens/dist/tools/module-report.js +1 -1
- package/node_modules/pi-lens/dist/tools/project-report.js +1 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +5 -2
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +1 -1
- package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
- package/node_modules/pi-lens/package.json +160 -156
- package/node_modules/pi-lens/rules/typos/_typos.toml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +31 -13
- package/node_modules/pi-lens/scripts/download-grammars.js +9 -3
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +30 -9
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +47 -0
- package/node_modules/pi-mcp-adapter/README.md +42 -13
- package/node_modules/pi-mcp-adapter/commands.ts +4 -2
- package/node_modules/pi-mcp-adapter/config.ts +45 -5
- package/node_modules/pi-mcp-adapter/direct-tools.ts +103 -92
- package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +10 -0
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js +63 -0
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +8 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +356 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +123 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +1087 -0
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +19 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +319 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +156 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +1 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js +15 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +564 -0
- package/node_modules/pi-mcp-adapter/dist/types.js +287 -0
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +37 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +104 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +59 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +4 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +27 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +32 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js +338 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -0
- package/node_modules/pi-mcp-adapter/failure-backoff.ts +23 -0
- package/node_modules/pi-mcp-adapter/index.ts +204 -82
- package/node_modules/pi-mcp-adapter/init.ts +41 -30
- package/node_modules/pi-mcp-adapter/lifecycle.ts +16 -8
- package/node_modules/pi-mcp-adapter/mcp-code.ts +2 -0
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +66 -16
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +95 -7
- package/node_modules/pi-mcp-adapter/mcp-probe.ts +18 -4
- package/node_modules/pi-mcp-adapter/mcp-references.ts +368 -0
- package/node_modules/pi-mcp-adapter/mcp-status.ts +8 -19
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +20 -12
- package/node_modules/pi-mcp-adapter/namespace-tools.ts +276 -0
- package/node_modules/pi-mcp-adapter/package.json +24 -6
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -10
- package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +63 -12
- package/node_modules/pi-mcp-adapter/state.ts +1 -3
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +16 -2
- package/node_modules/pi-mcp-adapter/types.ts +48 -1
- package/node_modules/pi-mcp-adapter/ui-server.ts +3 -19
- package/node_modules/pi-mcp-adapter/ui-session.ts +2 -1
- package/node_modules/pi-mcp-adapter/utils.ts +21 -19
- package/node_modules/pi-web-access/CHANGELOG.md +26 -0
- package/node_modules/pi-web-access/README.md +71 -14
- package/node_modules/pi-web-access/chrome-cookies.ts +115 -35
- package/node_modules/pi-web-access/credential-source.ts +6 -2
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +89 -9
- package/node_modules/pi-web-access/fetch-params.ts +13 -0
- package/node_modules/pi-web-access/gemini-adc.ts +298 -0
- package/node_modules/pi-web-access/gemini-api.ts +59 -15
- package/node_modules/pi-web-access/gemini-search.ts +58 -18
- package/node_modules/pi-web-access/gemini-url-context.ts +3 -2
- package/node_modules/pi-web-access/gemini-web-config.ts +57 -7
- package/node_modules/pi-web-access/gemini-web.ts +9 -3
- package/node_modules/pi-web-access/github-api.ts +5 -4
- package/node_modules/pi-web-access/github-issue-pr.ts +700 -0
- package/node_modules/pi-web-access/index.ts +403 -297
- package/node_modules/pi-web-access/kimi-search.ts +234 -0
- package/node_modules/pi-web-access/openai-search.ts +118 -21
- package/node_modules/pi-web-access/package.json +3 -2
- package/node_modules/pi-web-access/ssrf-protection.ts +4 -1
- package/node_modules/pi-web-access/utils.ts +307 -1
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +46 -37
- package/node_modules/@herbertgao/pi-copy-response/CHANGELOG.md +0 -49
- package/node_modules/@herbertgao/pi-copy-response/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +0 -83
- package/node_modules/@herbertgao/pi-handoff/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-handoff/package.json +0 -60
- package/node_modules/@herbertgao/pi-inline-skills/CHANGELOG.md +0 -57
- package/node_modules/@herbertgao/pi-inline-skills/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +0 -39
- package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +0 -63
- package/node_modules/@herbertgao/pi-preferred-thinking/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +0 -101
- package/node_modules/@herbertgao/pi-recap/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-recap/package.json +0 -55
- package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +0 -49
- package/node_modules/@herbertgao/pi-rename/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-rename/package.json +0 -63
- package/node_modules/@herbertgao/pi-titlebar-spinner/CHANGELOG.md +0 -25
- package/node_modules/@herbertgao/pi-titlebar-spinner/LICENSE +0 -22
- /package/node_modules/{@herbertgao → @tifan}/pi-copy-response/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/complete-text.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/session-query.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/viewer.mjs +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/model-picker.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/sanitize.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/tui.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/model-picker.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/naming.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/sanitize.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/src/index.ts +0 -0
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { hasCredentialSource, redactCredential, resolveCredential } from "./credential-source.ts";
|
|
3
3
|
import { getWebSearchConfigPath } from "./utils.ts";
|
|
4
|
+
import {
|
|
5
|
+
isGeminiAdcAvailable,
|
|
6
|
+
getAdcAccessToken,
|
|
7
|
+
getAdcProject,
|
|
8
|
+
getAdcLocation,
|
|
9
|
+
getVertexApiBase,
|
|
10
|
+
isVertexHost,
|
|
11
|
+
} from "./gemini-adc.ts";
|
|
4
12
|
|
|
5
13
|
const DEFAULT_API_HOST = "https://generativelanguage.googleapis.com";
|
|
6
14
|
const API_VERSION = "v1beta";
|
|
@@ -72,6 +80,11 @@ export function getApiHost(): string {
|
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
export function getVersionedApiBase(): string {
|
|
83
|
+
const project = getAdcProject();
|
|
84
|
+
const location = getAdcLocation();
|
|
85
|
+
if (isGeminiAdcAvailable() && project && location) {
|
|
86
|
+
return getVertexApiBase(project, location);
|
|
87
|
+
}
|
|
75
88
|
return `${getApiHost()}/${API_VERSION}`;
|
|
76
89
|
}
|
|
77
90
|
|
|
@@ -109,18 +122,21 @@ export function buildAuthHeaders(apiKey: string | null = null, cloudflareApiKey:
|
|
|
109
122
|
return cloudflareApiKey ? { "cf-aig-authorization": `Bearer ${cloudflareApiKey}` } : {};
|
|
110
123
|
}
|
|
111
124
|
|
|
112
|
-
function redactGeminiCredentials(text: string, apiKey: string | null | undefined, cloudflareApiKey: string | null | undefined): string {
|
|
113
|
-
|
|
125
|
+
function redactGeminiCredentials(text: string, apiKey: string | null | undefined, cloudflareApiKey: string | null | undefined, adcToken?: string | null): string {
|
|
126
|
+
let out = redactCredential(redactCredential(text, apiKey), cloudflareApiKey);
|
|
127
|
+
if (adcToken) out = redactCredential(out, adcToken);
|
|
128
|
+
return out;
|
|
114
129
|
}
|
|
115
130
|
|
|
116
131
|
const responseCredentials = new WeakMap<Response, {
|
|
117
132
|
apiKey: string | null | undefined;
|
|
118
133
|
cloudflareApiKey: string | null | undefined;
|
|
134
|
+
adcToken?: string | null;
|
|
119
135
|
}>();
|
|
120
136
|
|
|
121
|
-
export function redactGeminiApiResponse(response: Response, text: string, apiKey?: string | null): string {
|
|
137
|
+
export function redactGeminiApiResponse(response: Response, text: string, apiKey?: string | null, adcToken?: string | null): string {
|
|
122
138
|
const credentials = responseCredentials.get(response);
|
|
123
|
-
return redactGeminiCredentials(text, credentials?.apiKey ?? apiKey, credentials?.cloudflareApiKey);
|
|
139
|
+
return redactGeminiCredentials(text, credentials?.apiKey ?? apiKey, credentials?.cloudflareApiKey, credentials?.adcToken ?? adcToken);
|
|
124
140
|
}
|
|
125
141
|
|
|
126
142
|
export async function fetchGeminiApi(
|
|
@@ -134,28 +150,42 @@ export async function fetchGeminiApi(
|
|
|
134
150
|
throw new Error("Gemini API credential query parameters are not allowed");
|
|
135
151
|
}
|
|
136
152
|
}
|
|
137
|
-
const
|
|
153
|
+
const project = getAdcProject();
|
|
154
|
+
const location = getAdcLocation();
|
|
155
|
+
const adcMode = isGeminiAdcAvailable() && !!project && !!location && isVertexHost(parsedUrl.origin);
|
|
156
|
+
let adcToken: string | null = null;
|
|
157
|
+
if (adcMode) {
|
|
158
|
+
adcToken = await getAdcAccessToken(init.signal ?? undefined);
|
|
159
|
+
}
|
|
160
|
+
const resolvedApiKey = adcMode ? null : (apiKey === undefined ? await getApiKey(init.signal ?? undefined) : apiKey);
|
|
138
161
|
const cloudflareApiKey = isCloudflareGateway() ? await resolveCloudflareApiKey(init.signal ?? undefined) : null;
|
|
139
162
|
const allowedOrigins = new Set([
|
|
140
163
|
new URL(getApiHost()).origin,
|
|
141
164
|
new URL(DEFAULT_API_HOST).origin,
|
|
165
|
+
...(adcMode ? [parsedUrl.origin] : []),
|
|
142
166
|
]);
|
|
143
|
-
|
|
167
|
+
const needsAuth = resolvedApiKey || isGatewayConfigured() || adcMode;
|
|
168
|
+
if (needsAuth && !allowedOrigins.has(parsedUrl.origin)) {
|
|
144
169
|
throw new Error("Gemini API request host is not allowed");
|
|
145
170
|
}
|
|
146
171
|
const headers = new Headers(init.headers);
|
|
147
172
|
headers.delete("x-goog-api-key");
|
|
148
173
|
headers.delete("cf-aig-authorization");
|
|
149
|
-
|
|
150
|
-
|
|
174
|
+
headers.delete("authorization");
|
|
175
|
+
if (adcMode && adcToken) {
|
|
176
|
+
headers.set("Authorization", `Bearer ${adcToken}`);
|
|
177
|
+
} else {
|
|
178
|
+
for (const [name, value] of Object.entries(buildAuthHeaders(resolvedApiKey, cloudflareApiKey))) {
|
|
179
|
+
headers.set(name, value);
|
|
180
|
+
}
|
|
151
181
|
}
|
|
152
182
|
try {
|
|
153
183
|
const response = await fetch(parsedUrl, { ...init, headers });
|
|
154
|
-
responseCredentials.set(response, { apiKey: resolvedApiKey, cloudflareApiKey });
|
|
184
|
+
responseCredentials.set(response, { apiKey: resolvedApiKey, cloudflareApiKey, adcToken });
|
|
155
185
|
return response;
|
|
156
186
|
} catch (error) {
|
|
157
187
|
const message = error instanceof Error ? error.message : String(error);
|
|
158
|
-
const redactedMessage = redactGeminiCredentials(message, resolvedApiKey, cloudflareApiKey);
|
|
188
|
+
const redactedMessage = redactGeminiCredentials(message, resolvedApiKey, cloudflareApiKey, adcToken);
|
|
159
189
|
if (redactedMessage === message) throw error;
|
|
160
190
|
const redactedError = new Error(redactedMessage);
|
|
161
191
|
if (error instanceof Error) redactedError.name = error.name;
|
|
@@ -163,12 +193,25 @@ export async function fetchGeminiApi(
|
|
|
163
193
|
}
|
|
164
194
|
}
|
|
165
195
|
|
|
166
|
-
|
|
196
|
+
function hasGeminiApiKeySource(): boolean {
|
|
167
197
|
return hasCredentialSource({
|
|
168
198
|
provider: "Gemini",
|
|
169
199
|
configuredValue: loadConfig().geminiApiKey,
|
|
170
200
|
environmentValue: process.env.GEMINI_API_KEY,
|
|
171
|
-
})
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function isGeminiApiAvailable(): boolean {
|
|
205
|
+
return isGeminiAdcAvailable() || hasGeminiApiKeySource() || isGatewayConfigured();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Whether the Gemini Files-API paths (YouTube and local video analysis) can
|
|
210
|
+
* authenticate. These use the Gemini Files API and metadata endpoints, which do
|
|
211
|
+
* not support ADC, so they still require an API key or a Cloudflare gateway.
|
|
212
|
+
*/
|
|
213
|
+
export function isGeminiApiAvailableWithVideo(): boolean {
|
|
214
|
+
return hasGeminiApiKeySource() || isGatewayConfigured();
|
|
172
215
|
}
|
|
173
216
|
|
|
174
217
|
export interface GeminiApiOptions {
|
|
@@ -192,12 +235,13 @@ export async function queryGeminiApiWithInlineData(
|
|
|
192
235
|
options: GeminiApiOptions = {},
|
|
193
236
|
): Promise<GeminiGenerateContentResult> {
|
|
194
237
|
const signal = withTimeout(options.signal, options.timeoutMs ?? 120000);
|
|
195
|
-
const apiKey = options.apiKey ?? await getApiKey(signal);
|
|
196
|
-
if (!apiKey && !isGatewayConfigured()) {
|
|
238
|
+
const apiKey = isGeminiAdcAvailable() ? null : (options.apiKey ?? await getApiKey(signal));
|
|
239
|
+
if (!apiKey && !isGatewayConfigured() && !isGeminiAdcAvailable()) {
|
|
197
240
|
throw new Error(
|
|
198
241
|
"Gemini API not configured. Either:\n" +
|
|
199
242
|
` 1. Configure geminiApiKey in ${CONFIG_PATH} or set GEMINI_API_KEY\n` +
|
|
200
|
-
" 2. Set GOOGLE_GEMINI_BASE_URL + CLOUDFLARE_API_KEY for Cloudflare AI Gateway routing"
|
|
243
|
+
" 2. Set GOOGLE_GEMINI_BASE_URL + CLOUDFLARE_API_KEY for Cloudflare AI Gateway routing\n" +
|
|
244
|
+
" 3. Set geminiAuth to \"adc\" with a Google Cloud ADC (GOOGLE_APPLICATION_CREDENTIALS) + project/location"
|
|
201
245
|
);
|
|
202
246
|
}
|
|
203
247
|
|
|
@@ -3,11 +3,17 @@ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import { activityMonitor } from "./activity.ts";
|
|
4
4
|
import { CredentialResolutionError } from "./credential-source.ts";
|
|
5
5
|
import { getApiKey, getVersionedApiBase, fetchGeminiApi, isGatewayConfigured, isGeminiApiAvailable, redactGeminiApiResponse } from "./gemini-api.ts";
|
|
6
|
+
import { isGeminiAdcAvailable } from "./gemini-adc.ts";
|
|
6
7
|
import { getGeminiWebAvailabilityDiagnostic, isGeminiWebAvailable, queryWithCookies } from "./gemini-web.ts";
|
|
7
8
|
import { isPerplexityAvailable, searchWithPerplexity, type SearchResult, type SearchResponse, type SearchOptions } from "./perplexity.ts";
|
|
8
9
|
import { isExaAvailable, searchWithExa } from "./exa.ts";
|
|
9
10
|
import { isBraveAvailable, searchWithBrave } from "./brave.ts";
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
isCurrentModelHostedSearchEligible,
|
|
13
|
+
isOpenAISearchAvailable,
|
|
14
|
+
searchWithCurrentModelOpenAI,
|
|
15
|
+
searchWithOpenAI,
|
|
16
|
+
} from "./openai-search.ts";
|
|
11
17
|
import { isParallelAvailable, searchWithParallel } from "./parallel.ts";
|
|
12
18
|
import { isParallelMcpAvailable, searchWithParallelMcp } from "./parallel-mcp.ts";
|
|
13
19
|
import { isTinyFishAvailable, searchWithTinyFish } from "./tinyfish.ts";
|
|
@@ -29,9 +35,10 @@ import { isBrightDataAvailable, searchWithBrightData } from "./brightdata.ts";
|
|
|
29
35
|
import { isSerpBaseAvailable, searchWithSerpBase } from "./serpbase.ts";
|
|
30
36
|
import { isSerperAvailable, searchWithSerper } from "./serper.ts";
|
|
31
37
|
import { isValyuAvailable, searchWithValyu } from "./valyu.ts";
|
|
38
|
+
import { isKimiSearchAvailable, searchWithKimi } from "./kimi-search.ts";
|
|
32
39
|
import { getWebSearchConfigPath } from "./utils.ts";
|
|
33
40
|
|
|
34
|
-
export const RESOLVED_SEARCH_PROVIDERS = ["openai", "brave", "parallel", "parallel-mcp", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "searxng", "duckduckgo", "perplexity", "gemini", "exa", "serpdive", "kagi", "ollama", "anysearch", "xai", "brightdata", "serpbase", "serper", "valyu", "bocha"] as const;
|
|
41
|
+
export const RESOLVED_SEARCH_PROVIDERS = ["openai", "brave", "parallel", "parallel-mcp", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "searxng", "duckduckgo", "perplexity", "gemini", "kimi", "exa", "serpdive", "kagi", "ollama", "anysearch", "xai", "brightdata", "serpbase", "serper", "valyu", "bocha"] as const;
|
|
35
42
|
export const SEARCH_PROVIDERS = ["auto", "all", ...RESOLVED_SEARCH_PROVIDERS] as const;
|
|
36
43
|
|
|
37
44
|
export type ResolvedSearchProvider = typeof RESOLVED_SEARCH_PROVIDERS[number];
|
|
@@ -46,12 +53,14 @@ export type SearchProviderErrorKind =
|
|
|
46
53
|
| "auth"
|
|
47
54
|
| "invalid-request"
|
|
48
55
|
| "invalid-response"
|
|
56
|
+
| "unsupported"
|
|
49
57
|
| "aborted"
|
|
50
58
|
| "unknown";
|
|
51
59
|
|
|
52
60
|
export interface SearchRoutingConfig {
|
|
53
61
|
providers: ResolvedSearchProvider[];
|
|
54
|
-
|
|
62
|
+
useCurrentModel?: boolean;
|
|
63
|
+
fallbackOn: Array<Extract<SearchProviderErrorKind, "transient" | "quota" | "network" | "invalid-response" | "unsupported">>;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
export class SearchProviderError extends Error {
|
|
@@ -93,10 +102,10 @@ export interface AttributedSearchResponse extends SearchResponse {
|
|
|
93
102
|
|
|
94
103
|
const CONFIG_PATH = getWebSearchConfigPath();
|
|
95
104
|
const DEFAULT_SEARCH_MODEL = "gemini-3.6-flash";
|
|
96
|
-
// Explicit-only providers (Parallel MCP, DuckDuckGo, AnySearch, xAI, Bright Data, SerpBase, Serper, Valyu) are deliberately absent:
|
|
105
|
+
// Explicit-only providers (Parallel MCP, DuckDuckGo, Kimi, AnySearch, xAI, Bright Data, SerpBase, Serper, Valyu) are deliberately absent:
|
|
97
106
|
// `all` must never fan out to an opt-in or paid provider without the user asking for it.
|
|
98
107
|
const ALL_SEARCH_PROVIDERS: ResolvedSearchProvider[] = ["searxng", "openai", "exa", "brave", "parallel", "tinyfish", "search1api", "searchinfinity", "querit", "tavily", "firecrawl", "jina", "serpdive", "kagi", "ollama", "perplexity", "gemini", "bocha"];
|
|
99
|
-
const VALID_ROUTING_KINDS = ["transient", "quota", "network", "invalid-response"] as const;
|
|
108
|
+
const VALID_ROUTING_KINDS = ["transient", "quota", "network", "invalid-response", "unsupported"] as const;
|
|
100
109
|
|
|
101
110
|
type SearchConfig = {
|
|
102
111
|
searchProvider: SearchProviderSelection;
|
|
@@ -144,19 +153,27 @@ function normalizeSearchRouting(value: unknown): SearchRoutingConfig {
|
|
|
144
153
|
}
|
|
145
154
|
const raw = value as Record<string, unknown>;
|
|
146
155
|
const providers = normalizeResolvedProviderList(raw.providers, `searchRouting.providers in ${CONFIG_PATH}`);
|
|
156
|
+
const useCurrentModel = raw.useCurrentModel;
|
|
157
|
+
if (useCurrentModel !== undefined && typeof useCurrentModel !== "boolean") {
|
|
158
|
+
throw new Error(`searchRouting.useCurrentModel in ${CONFIG_PATH} must be a boolean`);
|
|
159
|
+
}
|
|
147
160
|
if (!Array.isArray(raw.fallbackOn) || raw.fallbackOn.length === 0) {
|
|
148
161
|
throw new Error(`searchRouting.fallbackOn in ${CONFIG_PATH} must be a non-empty array`);
|
|
149
162
|
}
|
|
150
163
|
const fallbackOn: SearchRoutingConfig["fallbackOn"] = [];
|
|
151
164
|
for (const kind of raw.fallbackOn) {
|
|
152
165
|
if (typeof kind !== "string" || !VALID_ROUTING_KINDS.includes(kind as typeof VALID_ROUTING_KINDS[number])) {
|
|
153
|
-
throw new Error(`searchRouting.fallbackOn in ${CONFIG_PATH} may only contain transient, quota, network,
|
|
166
|
+
throw new Error(`searchRouting.fallbackOn in ${CONFIG_PATH} may only contain transient, quota, network, invalid-response, or unsupported`);
|
|
154
167
|
}
|
|
155
168
|
if (!fallbackOn.includes(kind as SearchRoutingConfig["fallbackOn"][number])) {
|
|
156
169
|
fallbackOn.push(kind as SearchRoutingConfig["fallbackOn"][number]);
|
|
157
170
|
}
|
|
158
171
|
}
|
|
159
|
-
return {
|
|
172
|
+
return {
|
|
173
|
+
providers,
|
|
174
|
+
...(useCurrentModel !== undefined ? { useCurrentModel: useCurrentModel as boolean } : {}),
|
|
175
|
+
fallbackOn,
|
|
176
|
+
};
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
export function getConfiguredSearchRouting(): SearchRoutingConfig | undefined {
|
|
@@ -278,6 +295,7 @@ function classifyProviderError(provider: ResolvedSearchProvider, err: unknown):
|
|
|
278
295
|
const lower = message.toLowerCase();
|
|
279
296
|
const status = providerErrorStatus(message);
|
|
280
297
|
let kind: SearchProviderErrorKind = "unknown";
|
|
298
|
+
const mentionsUnsupportedWebSearch = /(?:web[_ -]?search|web[_ -]?search_preview|(?:the )?tool)\b.*\b(?:unsupported|not supported|does not support|doesn't support|unknown|unrecognized|unavailable|not found)|\b(?:unsupported|not supported|does not support|doesn't support|unknown|unrecognized|unavailable|not found)\b.*\b(?:web[_ -]?search|web[_ -]?search_preview|(?:the )?tool)/i.test(lower);
|
|
281
299
|
if (err instanceof CredentialResolutionError || /(?:api )?key (?:not found|missing)|credential resolution/.test(lower)) {
|
|
282
300
|
kind = "credential";
|
|
283
301
|
} else if (isAbortError(err)) {
|
|
@@ -286,6 +304,8 @@ function classifyProviderError(provider: ResolvedSearchProvider, err: unknown):
|
|
|
286
304
|
kind = "quota";
|
|
287
305
|
} else if (status === 401 || status === 403) {
|
|
288
306
|
kind = "auth";
|
|
307
|
+
} else if (provider === "openai" && (status === 400 || status === 422) && mentionsUnsupportedWebSearch) {
|
|
308
|
+
kind = "unsupported";
|
|
289
309
|
} else if (status === 400 || status === 422) {
|
|
290
310
|
kind = "invalid-request";
|
|
291
311
|
} else if (status === 402 || status === 429) {
|
|
@@ -298,7 +318,7 @@ function classifyProviderError(provider: ResolvedSearchProvider, err: unknown):
|
|
|
298
318
|
kind = "auth";
|
|
299
319
|
} else if (/bad request|invalid request/.test(lower)) {
|
|
300
320
|
kind = "invalid-request";
|
|
301
|
-
} else if (/invalid json|no parseable response|no parseable results|invalid response|returned empty response/.test(lower)) {
|
|
321
|
+
} else if (/invalid json|no parseable response|no parseable results|invalid response|returned empty response|no web_search_call/.test(lower)) {
|
|
302
322
|
kind = "invalid-response";
|
|
303
323
|
} else if (/temporar|service unavailable|server error/.test(lower)) {
|
|
304
324
|
kind = "transient";
|
|
@@ -314,9 +334,12 @@ async function searchWithResolvedProvider(
|
|
|
314
334
|
provider: ResolvedSearchProvider,
|
|
315
335
|
query: string,
|
|
316
336
|
options: FullSearchOptions,
|
|
337
|
+
useCurrentModel = false,
|
|
317
338
|
): Promise<AttributedSearchResponse> {
|
|
318
339
|
if (provider === "openai") {
|
|
319
|
-
const result =
|
|
340
|
+
const result = useCurrentModel
|
|
341
|
+
? await searchWithCurrentModelOpenAI(query, options, options.extensionContext)
|
|
342
|
+
: await searchWithOpenAI(query, options, options.extensionContext);
|
|
320
343
|
return { ...result, provider };
|
|
321
344
|
}
|
|
322
345
|
if (provider === "brave") return { ...(await searchWithBrave(query, options)), provider };
|
|
@@ -342,6 +365,7 @@ async function searchWithResolvedProvider(
|
|
|
342
365
|
if (provider === "perplexity") return { ...(await searchWithPerplexity(query, options)), provider };
|
|
343
366
|
if (provider === "searxng") return { ...(await searchWithSearXNG(query, options)), provider };
|
|
344
367
|
if (provider === "duckduckgo") return { ...(await searchWithDuckDuckGo(query, options)), provider };
|
|
368
|
+
if (provider === "kimi") return { ...(await searchWithKimi(query, options, options.extensionContext)), provider };
|
|
345
369
|
if (provider === "gemini") {
|
|
346
370
|
const result = await searchWithGemini(query, options, true);
|
|
347
371
|
if (result) return { ...result, provider };
|
|
@@ -349,7 +373,8 @@ async function searchWithResolvedProvider(
|
|
|
349
373
|
"Gemini search unavailable. Either:\n" +
|
|
350
374
|
` 1. Configure geminiApiKey in ${CONFIG_PATH} or set GEMINI_API_KEY\n` +
|
|
351
375
|
" 2. Set GOOGLE_GEMINI_BASE_URL + CLOUDFLARE_API_KEY for Cloudflare AI Gateway routing\n" +
|
|
352
|
-
" 3.
|
|
376
|
+
" 3. Set geminiAuth to \"adc\" in web-search.json with a Google Cloud ADC + project/location\n" +
|
|
377
|
+
" 4. Sign into gemini.google.com in a supported Chromium-based browser",
|
|
353
378
|
);
|
|
354
379
|
}
|
|
355
380
|
const result = await searchWithExa(query, options);
|
|
@@ -357,8 +382,12 @@ async function searchWithResolvedProvider(
|
|
|
357
382
|
throw new Error("Exa search returned no results.");
|
|
358
383
|
}
|
|
359
384
|
|
|
360
|
-
async function isResolvedProviderAvailable(provider: ResolvedSearchProvider, options: FullSearchOptions): Promise<boolean> {
|
|
361
|
-
if (provider === "openai")
|
|
385
|
+
async function isResolvedProviderAvailable(provider: ResolvedSearchProvider, options: FullSearchOptions, useCurrentModel = false): Promise<boolean> {
|
|
386
|
+
if (provider === "openai") {
|
|
387
|
+
return useCurrentModel
|
|
388
|
+
? isCurrentModelHostedSearchEligible(options.extensionContext)
|
|
389
|
+
: isOpenAISearchAvailable(options.extensionContext);
|
|
390
|
+
}
|
|
362
391
|
if (provider === "brave") return isBraveAvailable();
|
|
363
392
|
if (provider === "parallel") return isParallelAvailable();
|
|
364
393
|
if (provider === "parallel-mcp") return isParallelMcpAvailable();
|
|
@@ -382,10 +411,19 @@ async function isResolvedProviderAvailable(provider: ResolvedSearchProvider, opt
|
|
|
382
411
|
if (provider === "perplexity") return isPerplexityAvailable();
|
|
383
412
|
if (provider === "searxng") return isSearXNGAvailable();
|
|
384
413
|
if (provider === "duckduckgo") return isDuckDuckGoAvailable();
|
|
385
|
-
if (provider === "gemini") return isGeminiApiAvailable() ||
|
|
414
|
+
if (provider === "gemini") return isGeminiApiAvailable() || await isGeminiWebOptionallyAvailable();
|
|
415
|
+
if (provider === "kimi") return isKimiSearchAvailable(options.extensionContext);
|
|
386
416
|
return isExaAvailable();
|
|
387
417
|
}
|
|
388
418
|
|
|
419
|
+
async function isGeminiWebOptionallyAvailable(): Promise<boolean> {
|
|
420
|
+
try {
|
|
421
|
+
return !!(await isGeminiWebAvailable());
|
|
422
|
+
} catch {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
389
427
|
function providerLabel(provider: ResolvedSearchProvider): string {
|
|
390
428
|
if (provider === "openai") return "OpenAI";
|
|
391
429
|
if (provider === "parallel-mcp") return "Parallel MCP";
|
|
@@ -399,6 +437,7 @@ function providerLabel(provider: ResolvedSearchProvider): string {
|
|
|
399
437
|
if (provider === "duckduckgo") return "DuckDuckGo";
|
|
400
438
|
if (provider === "kagi") return "Kagi";
|
|
401
439
|
if (provider === "bocha") return "Bocha";
|
|
440
|
+
if (provider === "kimi") return "Kimi";
|
|
402
441
|
if (provider === "ollama") return "Ollama";
|
|
403
442
|
if (provider === "xai") return "xAI";
|
|
404
443
|
if (provider === "brightdata") return "Bright Data";
|
|
@@ -431,7 +470,7 @@ async function searchWithProviders(
|
|
|
431
470
|
: await isResolvedProviderAvailable(provider, options),
|
|
432
471
|
})))).filter((entry) => entry.available).map((entry) => entry.provider);
|
|
433
472
|
if (providers.length === 0) {
|
|
434
|
-
throw new Error("No configured search provider available for provider \"all\". Parallel MCP, AnySearch, xAI, Bright Data, SerpBase, Serper, and Valyu are excluded.");
|
|
473
|
+
throw new Error("No configured search provider available for provider \"all\". Parallel MCP, DuckDuckGo, Kimi, AnySearch, xAI, Bright Data, SerpBase, Serper, and Valyu are excluded.");
|
|
435
474
|
}
|
|
436
475
|
|
|
437
476
|
const settled = await Promise.allSettled(
|
|
@@ -499,12 +538,13 @@ async function searchWithConfiguredRouting(
|
|
|
499
538
|
): Promise<AttributedSearchResponse> {
|
|
500
539
|
const diagnostics: string[] = [];
|
|
501
540
|
for (const provider of routing.providers) {
|
|
502
|
-
|
|
541
|
+
const useCurrentModel = provider === "openai" && routing.useCurrentModel === true;
|
|
542
|
+
if (!(await isResolvedProviderAvailable(provider, options, useCurrentModel))) {
|
|
503
543
|
diagnostics.push(`${provider}: unavailable`);
|
|
504
544
|
continue;
|
|
505
545
|
}
|
|
506
546
|
try {
|
|
507
|
-
return await searchWithResolvedProvider(provider, query, options);
|
|
547
|
+
return await searchWithResolvedProvider(provider, query, options, useCurrentModel);
|
|
508
548
|
} catch (err) {
|
|
509
549
|
const classified = classifyProviderError(provider, err);
|
|
510
550
|
diagnostics.push(`${provider} [${classified.kind}]: ${errorMessage(err)}`);
|
|
@@ -732,8 +772,8 @@ async function searchWithGeminiApi(query: string, options: SearchOptions = {}):
|
|
|
732
772
|
AbortSignal.timeout(120000),
|
|
733
773
|
...(options.signal ? [options.signal] : []),
|
|
734
774
|
]);
|
|
735
|
-
const apiKey = await getApiKey(requestSignal);
|
|
736
|
-
if (!apiKey && !isGatewayConfigured()) return null;
|
|
775
|
+
const apiKey = isGeminiAdcAvailable() ? null : await getApiKey(requestSignal);
|
|
776
|
+
if (!apiKey && !isGatewayConfigured() && !isGeminiAdcAvailable()) return null;
|
|
737
777
|
|
|
738
778
|
const activityId = activityMonitor.logStart({ type: "api", query });
|
|
739
779
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { activityMonitor } from "./activity.ts";
|
|
2
2
|
import { CredentialResolutionError } from "./credential-source.ts";
|
|
3
3
|
import { getApiKey, getVersionedApiBase, fetchGeminiApi, isGatewayConfigured, DEFAULT_MODEL } from "./gemini-api.ts";
|
|
4
|
+
import { isGeminiAdcAvailable } from "./gemini-adc.ts";
|
|
4
5
|
import { isGeminiWebAvailable, queryWithCookies } from "./gemini-web.ts";
|
|
5
6
|
import { extractHeadingTitle, type ExtractedContent } from "./extract.ts";
|
|
6
7
|
|
|
@@ -23,8 +24,8 @@ export async function extractWithUrlContext(
|
|
|
23
24
|
AbortSignal.timeout(60000),
|
|
24
25
|
...(signal ? [signal] : []),
|
|
25
26
|
]);
|
|
26
|
-
const apiKey = await getApiKey(requestSignal);
|
|
27
|
-
if (!apiKey && !isGatewayConfigured()) return null;
|
|
27
|
+
const apiKey = isGeminiAdcAvailable() ? null : await getApiKey(requestSignal);
|
|
28
|
+
if (!apiKey && !isGatewayConfigured() && !isGeminiAdcAvailable()) return null;
|
|
28
29
|
|
|
29
30
|
const activityId = activityMonitor.logStart({ type: "api", query: `url_context: ${url}` });
|
|
30
31
|
|
|
@@ -4,10 +4,18 @@ import { getWebSearchConfigPath } from "./utils.ts";
|
|
|
4
4
|
const CONFIG_PATH = getWebSearchConfigPath();
|
|
5
5
|
|
|
6
6
|
interface GeminiWebConfig {
|
|
7
|
-
|
|
7
|
+
browserCookies?: BrowserCookieSelection;
|
|
8
8
|
allowBrowserCookies?: boolean;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
const BROWSER_COOKIE_PRESETS = ["helium", "chrome", "brave", "arc", "chromium", "edge"] as const;
|
|
12
|
+
export type BrowserCookiePreset = typeof BROWSER_COOKIE_PRESETS[number];
|
|
13
|
+
|
|
14
|
+
export interface BrowserCookieSelection {
|
|
15
|
+
browser?: BrowserCookiePreset;
|
|
16
|
+
profile?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
let cachedConfig: GeminiWebConfig | null = null;
|
|
12
20
|
|
|
13
21
|
export function normalizeChromeProfile(value: unknown): string | undefined {
|
|
@@ -16,6 +24,35 @@ export function normalizeChromeProfile(value: unknown): string | undefined {
|
|
|
16
24
|
return normalized.length > 0 ? normalized : undefined;
|
|
17
25
|
}
|
|
18
26
|
|
|
27
|
+
function parseBrowserCookies(value: unknown): BrowserCookieSelection | undefined {
|
|
28
|
+
if (value === undefined) return undefined;
|
|
29
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
30
|
+
throw new Error(`browserCookies in ${CONFIG_PATH} must be an object`);
|
|
31
|
+
}
|
|
32
|
+
const raw = value as Record<string, unknown>;
|
|
33
|
+
if ("profilePath" in raw) {
|
|
34
|
+
throw new Error(`browserCookies.profilePath is not supported; use a browser preset and profile directory name in ${CONFIG_PATH}`);
|
|
35
|
+
}
|
|
36
|
+
let browser: BrowserCookiePreset | undefined;
|
|
37
|
+
if (raw.browser !== undefined) {
|
|
38
|
+
if (typeof raw.browser !== "string") throw new Error(`browserCookies.browser in ${CONFIG_PATH} must be a supported browser name`);
|
|
39
|
+
const normalized = raw.browser.trim().toLowerCase();
|
|
40
|
+
const preset = BROWSER_COOKIE_PRESETS.find((candidate) => candidate === normalized);
|
|
41
|
+
if (!preset) {
|
|
42
|
+
throw new Error(`Unsupported browserCookies.browser ${JSON.stringify(raw.browser)} in ${CONFIG_PATH}`);
|
|
43
|
+
}
|
|
44
|
+
browser = preset;
|
|
45
|
+
}
|
|
46
|
+
if (raw.profile !== undefined && typeof raw.profile !== "string") {
|
|
47
|
+
throw new Error(`browserCookies.profile in ${CONFIG_PATH} must be a profile directory name`);
|
|
48
|
+
}
|
|
49
|
+
const profile = normalizeChromeProfile(raw.profile);
|
|
50
|
+
if (profile && (profile === "." || profile === ".." || profile.includes("/") || profile.includes("\\"))) {
|
|
51
|
+
throw new Error(`browserCookies.profile in ${CONFIG_PATH} must be a profile directory name, not a path`);
|
|
52
|
+
}
|
|
53
|
+
return { ...(browser ? { browser } : {}), ...(profile ? { profile } : {}) };
|
|
54
|
+
}
|
|
55
|
+
|
|
19
56
|
function loadConfig(): GeminiWebConfig {
|
|
20
57
|
if (cachedConfig) return cachedConfig;
|
|
21
58
|
if (!existsSync(CONFIG_PATH)) {
|
|
@@ -24,28 +61,41 @@ function loadConfig(): GeminiWebConfig {
|
|
|
24
61
|
}
|
|
25
62
|
|
|
26
63
|
const rawText = readFileSync(CONFIG_PATH, "utf-8");
|
|
27
|
-
let raw: { chromeProfile?: unknown; allowBrowserCookies?: unknown };
|
|
64
|
+
let raw: { chromeProfile?: unknown; browserCookies?: unknown; allowBrowserCookies?: unknown };
|
|
28
65
|
try {
|
|
29
|
-
raw = JSON.parse(rawText) as { chromeProfile?: unknown; allowBrowserCookies?: unknown };
|
|
66
|
+
raw = JSON.parse(rawText) as { chromeProfile?: unknown; browserCookies?: unknown; allowBrowserCookies?: unknown };
|
|
30
67
|
} catch (err) {
|
|
31
68
|
const message = err instanceof Error ? err.message : String(err);
|
|
32
69
|
throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
|
|
33
70
|
}
|
|
34
71
|
|
|
72
|
+
if (raw.chromeProfile !== undefined) {
|
|
73
|
+
throw new Error(`chromeProfile in ${CONFIG_PATH} is no longer supported; use browserCookies.profile`);
|
|
74
|
+
}
|
|
35
75
|
cachedConfig = {
|
|
36
|
-
|
|
76
|
+
browserCookies: parseBrowserCookies(raw.browserCookies),
|
|
37
77
|
allowBrowserCookies: raw.allowBrowserCookies === true,
|
|
38
78
|
};
|
|
39
79
|
return cachedConfig;
|
|
40
80
|
}
|
|
41
81
|
|
|
42
|
-
export function
|
|
43
|
-
return loadConfig().
|
|
82
|
+
export function getBrowserCookieSelectionFromConfig(): BrowserCookieSelection {
|
|
83
|
+
return { ...loadConfig().browserCookies };
|
|
44
84
|
}
|
|
45
85
|
|
|
46
86
|
export function isBrowserCookieAccessAllowed(): boolean {
|
|
47
87
|
if (process.env.PI_ALLOW_BROWSER_COOKIES === "1" || process.env.FEYNMAN_ALLOW_BROWSER_COOKIES === "1") {
|
|
48
88
|
return true;
|
|
49
89
|
}
|
|
50
|
-
|
|
90
|
+
if (!existsSync(CONFIG_PATH)) return false;
|
|
91
|
+
|
|
92
|
+
const rawText = readFileSync(CONFIG_PATH, "utf-8");
|
|
93
|
+
let raw: { allowBrowserCookies?: unknown };
|
|
94
|
+
try {
|
|
95
|
+
raw = JSON.parse(rawText) as { allowBrowserCookies?: unknown };
|
|
96
|
+
} catch (err) {
|
|
97
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
98
|
+
throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
|
|
99
|
+
}
|
|
100
|
+
return raw.allowBrowserCookies === true;
|
|
51
101
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { basename } from "node:path";
|
|
3
|
-
import { getLastGoogleCookieDiagnostic, type CookieMap, getGoogleCookies } from "./chrome-cookies.ts";
|
|
4
|
-
import {
|
|
3
|
+
import { getLastGoogleCookieDiagnostic, getLastGoogleCookieDiagnosticDetails, type BrowserCookieDiagnosticDetails, type CookieMap, getGoogleCookies } from "./chrome-cookies.ts";
|
|
4
|
+
import { getBrowserCookieSelectionFromConfig, isBrowserCookieAccessAllowed, normalizeChromeProfile } from "./gemini-web-config.ts";
|
|
5
5
|
|
|
6
6
|
const GEMINI_APP_URL = "https://gemini.google.com/app";
|
|
7
7
|
const GEMINI_STREAM_GENERATE_URL =
|
|
@@ -100,8 +100,10 @@ export interface GeminiWebOptions {
|
|
|
100
100
|
export async function isGeminiWebAvailable(chromeProfile?: string): Promise<CookieMap | null> {
|
|
101
101
|
if (!isBrowserCookieAccessAllowed()) return null;
|
|
102
102
|
|
|
103
|
+
const configured = getBrowserCookieSelectionFromConfig();
|
|
103
104
|
const result = await getGoogleCookies({
|
|
104
|
-
|
|
105
|
+
browser: configured.browser,
|
|
106
|
+
profile: normalizeChromeProfile(chromeProfile) ?? configured.profile,
|
|
105
107
|
requiredCookies: REQUIRED_COOKIES,
|
|
106
108
|
});
|
|
107
109
|
if (!result) return null;
|
|
@@ -112,6 +114,10 @@ export function getGeminiWebAvailabilityDiagnostic(): string | null {
|
|
|
112
114
|
return isBrowserCookieAccessAllowed() ? getLastGoogleCookieDiagnostic() : null;
|
|
113
115
|
}
|
|
114
116
|
|
|
117
|
+
export function getGeminiWebAvailabilityDiagnosticDetails(): BrowserCookieDiagnosticDetails | null {
|
|
118
|
+
return isBrowserCookieAccessAllowed() ? getLastGoogleCookieDiagnosticDetails() : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
115
121
|
export async function getActiveGoogleEmail(cookies: CookieMap): Promise<string | null> {
|
|
116
122
|
const cookieHeader = buildCookieHeader(cookies);
|
|
117
123
|
if (!cookieHeader) return null;
|
|
@@ -8,13 +8,14 @@ const MAX_INLINE_FILE_CHARS = 100_000;
|
|
|
8
8
|
let ghAvailable: boolean | null = null;
|
|
9
9
|
let ghHintShown = false;
|
|
10
10
|
|
|
11
|
-
export async function checkGhAvailable(): Promise<boolean> {
|
|
11
|
+
export async function checkGhAvailable(signal?: AbortSignal): Promise<boolean> {
|
|
12
12
|
if (ghAvailable !== null) return ghAvailable;
|
|
13
13
|
|
|
14
14
|
return new Promise((resolve) => {
|
|
15
|
-
execFile("gh", ["--version"], { timeout: 5000 }, (err) => {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
execFile("gh", ["--version"], { timeout: 5000, ...(signal ? { signal } : {}) }, (err) => {
|
|
16
|
+
const available = !err;
|
|
17
|
+
if (!signal?.aborted) ghAvailable = available;
|
|
18
|
+
resolve(available);
|
|
18
19
|
});
|
|
19
20
|
});
|
|
20
21
|
}
|