@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.
Files changed (476) hide show
  1. package/README.md +23 -10
  2. package/{node_modules/@herbertgao/pi-mermaid-open/LICENSE → THIRD_PARTY_NOTICES.md} +19 -1
  3. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +15 -0
  4. package/node_modules/@czottmann/pi-automode/README.md +5 -3
  5. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +2 -0
  6. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +60 -0
  7. package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +1 -0
  8. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +4 -4
  9. package/node_modules/@czottmann/pi-automode/docs/configuration.md +20 -4
  10. package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +1 -1
  11. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +692 -0
  12. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +181 -3
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +4 -1
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +143 -36
  15. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +103 -148
  16. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +32 -6
  17. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +344 -22
  18. package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +1 -0
  19. package/node_modules/@czottmann/pi-automode/package.json +4 -1
  20. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -1
  21. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -1
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +4 -0
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +21 -1
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +1 -1
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +19 -19
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +4 -2
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +2 -1
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +10 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  30. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
  31. package/node_modules/@herbertgao/pi-subagents/README.md +21 -15
  32. package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
  33. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +11 -8
  34. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +184 -106
  35. package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +31 -11
  36. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +9 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/index.ts +156 -31
  38. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +17 -0
  39. package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +14 -0
  40. package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +8 -0
  41. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +32 -1
  42. package/node_modules/@herbertgao/pi-subagents/src/types.ts +17 -2
  43. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +23 -2
  44. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +259 -24
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  46. package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +376 -0
  47. package/node_modules/@luxusai/pi-hindsight/README.md +92 -0
  48. package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +56 -0
  49. package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +169 -0
  50. package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +107 -0
  51. package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +89 -0
  52. package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +189 -0
  53. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
  54. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
  55. package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +54 -0
  56. package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +75 -0
  57. package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +300 -0
  58. package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +158 -0
  59. package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +164 -0
  60. package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +139 -0
  61. package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +74 -0
  62. package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +261 -0
  63. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +151 -0
  64. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +18 -0
  65. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +46 -0
  66. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +383 -0
  67. package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +240 -0
  68. package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +176 -0
  69. package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +178 -0
  70. package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +41 -0
  71. package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +386 -0
  72. package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +39 -0
  73. package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +34 -0
  74. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +140 -0
  75. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +61 -0
  76. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +925 -0
  77. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +247 -0
  78. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +547 -0
  79. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +480 -0
  80. package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +182 -0
  81. package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +86 -0
  82. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +1010 -0
  83. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +175 -0
  84. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +425 -0
  85. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +210 -0
  86. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +817 -0
  87. package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +25 -0
  88. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +319 -0
  89. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +196 -0
  90. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +189 -0
  91. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +65 -0
  92. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +260 -0
  93. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +244 -0
  94. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +59 -0
  95. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +82 -0
  96. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +45 -0
  97. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +331 -0
  98. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +354 -0
  99. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +66 -0
  100. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +132 -0
  101. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +228 -0
  102. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +74 -0
  103. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +16 -0
  104. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +648 -0
  105. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +105 -0
  106. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +68 -0
  107. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +71 -0
  108. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +13 -0
  109. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +162 -0
  110. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +131 -0
  111. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +104 -0
  112. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +37 -0
  113. package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +893 -0
  114. package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +35 -0
  115. package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +177 -0
  116. package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +7 -0
  117. package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +21 -0
  118. package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +112 -0
  119. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +111 -0
  120. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +214 -0
  121. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +70 -0
  122. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +392 -0
  123. package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +45 -0
  124. package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +9 -0
  125. package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +860 -0
  126. package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +105 -0
  127. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +189 -0
  128. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +299 -0
  129. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +201 -0
  130. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +47 -0
  131. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +239 -0
  132. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +50 -0
  133. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +259 -0
  134. package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +77 -0
  135. package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +534 -0
  136. package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +319 -0
  137. package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +325 -0
  138. package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +42 -0
  139. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +244 -0
  140. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +56 -0
  141. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +50 -0
  142. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +167 -0
  143. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +207 -0
  144. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +120 -0
  145. package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +8 -0
  146. package/node_modules/@luxusai/pi-hindsight/package.json +118 -0
  147. package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +75 -0
  148. package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -46
  149. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  150. package/node_modules/@narumitw/pi-btw/package.json +6 -6
  151. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +136 -22
  152. package/node_modules/{@herbertgao → @tifan}/pi-copy-response/README.md +2 -4
  153. package/node_modules/{@herbertgao → @tifan}/pi-copy-response/package.json +5 -15
  154. package/node_modules/{@herbertgao → @tifan}/pi-handoff/README.md +4 -6
  155. package/node_modules/@tifan/pi-handoff/package.json +43 -0
  156. package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/index.ts +1 -1
  157. package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/README.md +2 -4
  158. package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/package.json +5 -15
  159. package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/README.md +5 -7
  160. package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/package.json +5 -19
  161. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/README.md +4 -6
  162. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/package.json +6 -16
  163. package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/src/index.ts +1 -6
  164. package/node_modules/{@herbertgao → @tifan}/pi-recap/README.md +4 -6
  165. package/node_modules/@tifan/pi-recap/package.json +42 -0
  166. package/node_modules/{@herbertgao → @tifan}/pi-recap/src/models.ts +1 -6
  167. package/node_modules/{@herbertgao → @tifan}/pi-rename/README.md +13 -8
  168. package/node_modules/@tifan/pi-rename/package.json +47 -0
  169. package/node_modules/@tifan/pi-rename/src/herdr-label.ts +4 -0
  170. package/node_modules/{@herbertgao → @tifan}/pi-rename/src/index.ts +4 -16
  171. package/node_modules/{@herbertgao → @tifan}/pi-rename/src/models.ts +1 -6
  172. package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/README.md +2 -4
  173. package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/package.json +5 -15
  174. package/node_modules/pi-lens/CHANGELOG.md +96 -1
  175. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -1
  176. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +14 -5
  177. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +48 -18
  178. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -3
  179. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +16 -4
  180. package/node_modules/pi-lens/dist/clients/bash-file-access.js +3 -1
  181. package/node_modules/pi-lens/dist/clients/biome-client.js +1 -3
  182. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +21 -8
  183. package/node_modules/pi-lens/dist/clients/bounded-cache.js +24 -8
  184. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +4 -3
  185. package/node_modules/pi-lens/dist/clients/cache-manager.js +6 -7
  186. package/node_modules/pi-lens/dist/clients/cache-observability.js +461 -66
  187. package/node_modules/pi-lens/dist/clients/call-graph.js +238 -63
  188. package/node_modules/pi-lens/dist/clients/codebase-model.js +13 -5
  189. package/node_modules/pi-lens/dist/clients/complexity-client.js +1 -3
  190. package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -8
  191. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +1 -2
  192. package/node_modules/pi-lens/dist/clients/deadline-utils.js +3 -1
  193. package/node_modules/pi-lens/dist/clients/debug-heap.js +8 -1
  194. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +1 -1
  195. package/node_modules/pi-lens/dist/clients/dependency-checker.js +11 -7
  196. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -2
  197. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +5 -1
  198. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +2 -3
  199. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +13 -1
  200. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +3 -1
  201. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +2 -1
  202. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -4
  204. package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +3 -1
  205. package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +6 -2
  206. package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +31 -7
  207. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +5 -2
  208. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +10 -14
  209. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +5 -1
  210. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +1 -1
  211. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +3 -1
  212. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +25 -6
  213. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +1 -1
  214. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +1 -1
  215. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +3 -1
  216. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +13 -8
  217. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +4 -1
  218. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +25 -10
  219. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +1 -1
  220. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +1 -1
  221. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +1 -1
  222. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +28 -4
  223. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +6 -8
  224. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +212 -11
  225. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +1 -1
  226. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +8 -4
  227. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -6
  228. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +23 -14
  229. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -1
  230. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +7 -9
  231. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +7 -7
  233. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +6 -8
  234. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +13 -8
  235. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +13 -8
  236. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +17 -3
  237. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +7 -1
  238. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +24 -1
  239. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +35 -0
  240. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +1 -3
  241. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +6 -8
  242. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +1 -1
  243. package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +2 -1
  244. package/node_modules/pi-lens/dist/clients/dispatch/types.js +6 -1
  245. package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +6 -2
  246. package/node_modules/pi-lens/dist/clients/extension-log.js +5 -3
  247. package/node_modules/pi-lens/dist/clients/feature-hints.js +8 -1
  248. package/node_modules/pi-lens/dist/clients/file-kinds.js +34 -129
  249. package/node_modules/pi-lens/dist/clients/file-utils.js +17 -1
  250. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +57 -2
  251. package/node_modules/pi-lens/dist/clients/formatters.js +144 -27
  252. package/node_modules/pi-lens/dist/clients/freshness.js +38 -0
  253. package/node_modules/pi-lens/dist/clients/git-guard.js +43 -13
  254. package/node_modules/pi-lens/dist/clients/go-client.js +1 -3
  255. package/node_modules/pi-lens/dist/clients/grammar-source.js +1 -1
  256. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +30 -4
  257. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +1 -3
  258. package/node_modules/pi-lens/dist/clients/install-diagnostics.js +4 -2
  259. package/node_modules/pi-lens/dist/clients/installer/index.js +86 -77
  260. package/node_modules/pi-lens/dist/clients/instance-reaper.js +5 -2
  261. package/node_modules/pi-lens/dist/clients/instance-registry.js +4 -2
  262. package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
  263. package/node_modules/pi-lens/dist/clients/knip-client.js +29 -15
  264. package/node_modules/pi-lens/dist/clients/language-profile.js +4 -1
  265. package/node_modules/pi-lens/dist/clients/latency-logger.js +13 -2
  266. package/node_modules/pi-lens/dist/clients/lens-config.js +1 -1
  267. package/node_modules/pi-lens/dist/clients/lens-map.js +8 -3
  268. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +1 -1
  269. package/node_modules/pi-lens/dist/clients/lsp/config.js +4 -6
  270. package/node_modules/pi-lens/dist/clients/lsp/edits.js +119 -32
  271. package/node_modules/pi-lens/dist/clients/lsp/index.js +94 -35
  272. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +2 -1
  273. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +4 -1
  274. package/node_modules/pi-lens/dist/clients/lsp/launch.js +11 -3
  275. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +152 -0
  276. package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -7
  277. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +10 -2
  278. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +9 -4
  279. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -3
  280. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +10 -20
  281. package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +1 -1
  282. package/node_modules/pi-lens/dist/clients/memory-sampler.js +73 -7
  283. package/node_modules/pi-lens/dist/clients/metrics-client.js +1 -3
  284. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +8 -3
  285. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +7 -1
  286. package/node_modules/pi-lens/dist/clients/module-report.js +14 -17
  287. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +3 -5
  288. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +220 -0
  289. package/node_modules/pi-lens/dist/clients/package-manager.js +6 -1
  290. package/node_modules/pi-lens/dist/clients/pipeline.js +57 -9
  291. package/node_modules/pi-lens/dist/clients/project-conventions.js +2 -8
  292. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +10 -7
  293. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +2 -1
  294. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -1
  295. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +13 -9
  296. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +3 -1
  297. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -2
  298. package/node_modules/pi-lens/dist/clients/project-lens-config.js +12 -5
  299. package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +48 -0
  300. package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +15 -1
  301. package/node_modules/pi-lens/dist/clients/project-snapshot.js +472 -66
  302. package/node_modules/pi-lens/dist/clients/read-expansion.js +12 -2
  303. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +5 -4
  304. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +5 -2
  305. package/node_modules/pi-lens/dist/clients/read-guard.js +1 -1
  306. package/node_modules/pi-lens/dist/clients/resource-sampler.js +1 -1
  307. package/node_modules/pi-lens/dist/clients/reverse-deps.js +6 -5
  308. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +42 -17
  309. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +8 -2
  310. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +10 -1
  311. package/node_modules/pi-lens/dist/clients/review-graph/query.js +2 -1
  312. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +4 -2
  313. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +2 -2
  314. package/node_modules/pi-lens/dist/clients/ruff-client.js +6 -5
  315. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +63 -31
  316. package/node_modules/pi-lens/dist/clients/runtime-context.js +12 -4
  317. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +83 -4
  318. package/node_modules/pi-lens/dist/clients/runtime-session.js +14 -0
  319. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +59 -3
  320. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +148 -34
  321. package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -6
  322. package/node_modules/pi-lens/dist/clients/rust-client.js +1 -3
  323. package/node_modules/pi-lens/dist/clients/safe-spawn.js +150 -11
  324. package/node_modules/pi-lens/dist/clients/security-scan-client.js +1 -3
  325. package/node_modules/pi-lens/dist/clients/session-summary.js +3 -1
  326. package/node_modules/pi-lens/dist/clients/sg-runner.js +1 -3
  327. package/node_modules/pi-lens/dist/clients/source-filter.js +10 -6
  328. package/node_modules/pi-lens/dist/clients/source-walker.js +1 -1
  329. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +96 -0
  330. package/node_modules/pi-lens/dist/clients/startup-scan.js +4 -1
  331. package/node_modules/pi-lens/dist/clients/tool-definition.js +7 -0
  332. package/node_modules/pi-lens/dist/clients/tool-policy.js +26 -11
  333. package/node_modules/pi-lens/dist/clients/tool-render.js +2 -1
  334. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +10 -4
  335. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
  336. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +12 -5
  337. package/node_modules/pi-lens/dist/clients/warm-attach.js +12 -5
  338. package/node_modules/pi-lens/dist/clients/widget-state.js +27 -11
  339. package/node_modules/pi-lens/dist/clients/word-index.js +3 -1
  340. package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -2
  341. package/node_modules/pi-lens/dist/clients/zizmor-config.js +9 -1
  342. package/node_modules/pi-lens/dist/i18n.js +13 -5
  343. package/node_modules/pi-lens/dist/index.js +10797 -8627
  344. package/node_modules/pi-lens/dist/mcp/server.js +3 -1
  345. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +68 -12
  346. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +21 -7
  347. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +164 -35
  348. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +24 -7
  349. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
  350. package/node_modules/pi-lens/dist/tools/module-report.js +1 -1
  351. package/node_modules/pi-lens/dist/tools/project-report.js +1 -1
  352. package/node_modules/pi-lens/dist/tools/symbol-search.js +5 -2
  353. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +1 -1
  354. package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
  355. package/node_modules/pi-lens/package.json +160 -156
  356. package/node_modules/pi-lens/rules/typos/_typos.toml +2 -2
  357. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +31 -13
  358. package/node_modules/pi-lens/scripts/download-grammars.js +9 -3
  359. package/node_modules/pi-lens/scripts/rpc-load-check.mjs +30 -9
  360. package/node_modules/pi-mcp-adapter/CHANGELOG.md +47 -0
  361. package/node_modules/pi-mcp-adapter/README.md +42 -13
  362. package/node_modules/pi-mcp-adapter/commands.ts +4 -2
  363. package/node_modules/pi-mcp-adapter/config.ts +45 -5
  364. package/node_modules/pi-mcp-adapter/direct-tools.ts +103 -92
  365. package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +10 -0
  366. package/node_modules/pi-mcp-adapter/dist/agent-dir.js +63 -0
  367. package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +1 -0
  368. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +8 -0
  369. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +356 -0
  370. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -0
  371. package/node_modules/pi-mcp-adapter/dist/config.d.ts +123 -0
  372. package/node_modules/pi-mcp-adapter/dist/config.js +1087 -0
  373. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -0
  374. package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +19 -0
  375. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +319 -0
  376. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -0
  377. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +2 -0
  378. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +156 -0
  379. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -0
  380. package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +1 -0
  381. package/node_modules/pi-mcp-adapter/dist/resource-tools.js +15 -0
  382. package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +1 -0
  383. package/node_modules/pi-mcp-adapter/dist/types.d.ts +564 -0
  384. package/node_modules/pi-mcp-adapter/dist/types.js +287 -0
  385. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -0
  386. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +6 -0
  387. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +37 -0
  388. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +1 -0
  389. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +104 -0
  390. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +59 -0
  391. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +1 -0
  392. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +4 -0
  393. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +27 -0
  394. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +1 -0
  395. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +32 -0
  396. package/node_modules/pi-mcp-adapter/dist/utils.js +338 -0
  397. package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -0
  398. package/node_modules/pi-mcp-adapter/failure-backoff.ts +23 -0
  399. package/node_modules/pi-mcp-adapter/index.ts +204 -82
  400. package/node_modules/pi-mcp-adapter/init.ts +41 -30
  401. package/node_modules/pi-mcp-adapter/lifecycle.ts +16 -8
  402. package/node_modules/pi-mcp-adapter/mcp-code.ts +2 -0
  403. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +66 -16
  404. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +95 -7
  405. package/node_modules/pi-mcp-adapter/mcp-probe.ts +18 -4
  406. package/node_modules/pi-mcp-adapter/mcp-references.ts +368 -0
  407. package/node_modules/pi-mcp-adapter/mcp-status.ts +8 -19
  408. package/node_modules/pi-mcp-adapter/metadata-cache.ts +20 -12
  409. package/node_modules/pi-mcp-adapter/namespace-tools.ts +276 -0
  410. package/node_modules/pi-mcp-adapter/package.json +24 -6
  411. package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -10
  412. package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -0
  413. package/node_modules/pi-mcp-adapter/server-manager.ts +63 -12
  414. package/node_modules/pi-mcp-adapter/state.ts +1 -3
  415. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +16 -2
  416. package/node_modules/pi-mcp-adapter/types.ts +48 -1
  417. package/node_modules/pi-mcp-adapter/ui-server.ts +3 -19
  418. package/node_modules/pi-mcp-adapter/ui-session.ts +2 -1
  419. package/node_modules/pi-mcp-adapter/utils.ts +21 -19
  420. package/node_modules/pi-web-access/CHANGELOG.md +26 -0
  421. package/node_modules/pi-web-access/README.md +71 -14
  422. package/node_modules/pi-web-access/chrome-cookies.ts +115 -35
  423. package/node_modules/pi-web-access/credential-source.ts +6 -2
  424. package/node_modules/pi-web-access/curator-page.ts +5 -3
  425. package/node_modules/pi-web-access/curator-server.ts +2 -1
  426. package/node_modules/pi-web-access/extract.ts +89 -9
  427. package/node_modules/pi-web-access/fetch-params.ts +13 -0
  428. package/node_modules/pi-web-access/gemini-adc.ts +298 -0
  429. package/node_modules/pi-web-access/gemini-api.ts +59 -15
  430. package/node_modules/pi-web-access/gemini-search.ts +58 -18
  431. package/node_modules/pi-web-access/gemini-url-context.ts +3 -2
  432. package/node_modules/pi-web-access/gemini-web-config.ts +57 -7
  433. package/node_modules/pi-web-access/gemini-web.ts +9 -3
  434. package/node_modules/pi-web-access/github-api.ts +5 -4
  435. package/node_modules/pi-web-access/github-issue-pr.ts +700 -0
  436. package/node_modules/pi-web-access/index.ts +403 -297
  437. package/node_modules/pi-web-access/kimi-search.ts +234 -0
  438. package/node_modules/pi-web-access/openai-search.ts +118 -21
  439. package/node_modules/pi-web-access/package.json +3 -2
  440. package/node_modules/pi-web-access/ssrf-protection.ts +4 -1
  441. package/node_modules/pi-web-access/utils.ts +307 -1
  442. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  443. package/package.json +46 -37
  444. package/node_modules/@herbertgao/pi-copy-response/CHANGELOG.md +0 -49
  445. package/node_modules/@herbertgao/pi-copy-response/LICENSE +0 -22
  446. package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +0 -83
  447. package/node_modules/@herbertgao/pi-handoff/LICENSE +0 -22
  448. package/node_modules/@herbertgao/pi-handoff/package.json +0 -60
  449. package/node_modules/@herbertgao/pi-inline-skills/CHANGELOG.md +0 -57
  450. package/node_modules/@herbertgao/pi-inline-skills/LICENSE +0 -22
  451. package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +0 -39
  452. package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +0 -63
  453. package/node_modules/@herbertgao/pi-preferred-thinking/LICENSE +0 -22
  454. package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +0 -101
  455. package/node_modules/@herbertgao/pi-recap/LICENSE +0 -22
  456. package/node_modules/@herbertgao/pi-recap/package.json +0 -55
  457. package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +0 -49
  458. package/node_modules/@herbertgao/pi-rename/LICENSE +0 -22
  459. package/node_modules/@herbertgao/pi-rename/package.json +0 -63
  460. package/node_modules/@herbertgao/pi-titlebar-spinner/CHANGELOG.md +0 -25
  461. package/node_modules/@herbertgao/pi-titlebar-spinner/LICENSE +0 -22
  462. /package/node_modules/{@herbertgao → @tifan}/pi-copy-response/src/index.ts +0 -0
  463. /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/complete-text.ts +0 -0
  464. /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/session-query.ts +0 -0
  465. /package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/src/index.ts +0 -0
  466. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +0 -0
  467. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/viewer.mjs +0 -0
  468. /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/src/index.ts +0 -0
  469. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/index.ts +0 -0
  470. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/model-picker.ts +0 -0
  471. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/sanitize.ts +0 -0
  472. /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/tui.ts +0 -0
  473. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/model-picker.ts +0 -0
  474. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/naming.ts +0 -0
  475. /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/sanitize.ts +0 -0
  476. /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
- return redactCredential(redactCredential(text, apiKey), cloudflareApiKey);
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 resolvedApiKey = apiKey === undefined ? await getApiKey(init.signal ?? undefined) : apiKey;
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
- if ((resolvedApiKey || isGatewayConfigured()) && !allowedOrigins.has(parsedUrl.origin)) {
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
- for (const [name, value] of Object.entries(buildAuthHeaders(resolvedApiKey, cloudflareApiKey))) {
150
- headers.set(name, value);
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
- export function isGeminiApiAvailable(): boolean {
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
- }) || isGatewayConfigured();
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 { isOpenAISearchAvailable, searchWithOpenAI } from "./openai-search.ts";
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
- fallbackOn: Array<Extract<SearchProviderErrorKind, "transient" | "quota" | "network" | "invalid-response">>;
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, or invalid-response`);
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 { providers, fallbackOn };
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 = await searchWithOpenAI(query, options, options.extensionContext);
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. Sign into gemini.google.com in a supported Chromium-based browser",
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") return isOpenAISearchAvailable(options.extensionContext);
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() || !!(await isGeminiWebAvailable());
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
- if (!(await isResolvedProviderAvailable(provider, options))) {
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
- chromeProfile?: string;
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
- chromeProfile: normalizeChromeProfile(raw.chromeProfile),
76
+ browserCookies: parseBrowserCookies(raw.browserCookies),
37
77
  allowBrowserCookies: raw.allowBrowserCookies === true,
38
78
  };
39
79
  return cachedConfig;
40
80
  }
41
81
 
42
- export function getChromeProfileFromConfig(): string | undefined {
43
- return loadConfig().chromeProfile;
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
- return loadConfig().allowBrowserCookies === true;
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 { getChromeProfileFromConfig, isBrowserCookieAccessAllowed, normalizeChromeProfile } from "./gemini-web-config.ts";
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
- profile: normalizeChromeProfile(chromeProfile) ?? getChromeProfileFromConfig(),
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
- ghAvailable = !err;
17
- resolve(ghAvailable);
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
  }