@herbertgao/pi-extensions 2026.8.8 → 2026.8.9

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 (74) hide show
  1. package/README.md +3 -3
  2. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +24 -0
  3. package/node_modules/@czottmann/pi-automode/README.md +78 -112
  4. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +18 -14
  5. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +44 -0
  6. package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +5 -0
  7. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +198 -104
  8. package/node_modules/@czottmann/pi-automode/docs/configuration.md +155 -0
  9. package/node_modules/@czottmann/pi-automode/docs/defaults.md +55 -14
  10. package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +90 -0
  11. package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +61 -26
  12. package/node_modules/@czottmann/pi-automode/examples/automode.local.json +5 -0
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +172 -18
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +127 -30
  15. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +3 -0
  16. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +273 -31
  17. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +60 -5
  18. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +92 -8
  19. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +203 -13
  20. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +1 -0
  21. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +11 -0
  22. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +9 -1
  23. package/node_modules/@czottmann/pi-automode/package.json +9 -2
  24. package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +63 -0
  25. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +3 -3
  26. package/node_modules/@herbertgao/pi-cc-extensions/README.md +3 -3
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +8 -3
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +56 -29
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +15 -13
  31. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  32. package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +29 -0
  33. package/node_modules/@herbertgao/pi-handoff/README.md +15 -18
  34. package/node_modules/@herbertgao/pi-handoff/package.json +11 -4
  35. package/node_modules/@herbertgao/pi-handoff/src/complete-text.ts +33 -0
  36. package/node_modules/@herbertgao/pi-handoff/src/index.ts +127 -232
  37. package/node_modules/@herbertgao/pi-handoff/src/session-query.ts +15 -30
  38. package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +14 -0
  39. package/node_modules/@herbertgao/pi-mermaid-open/README.md +21 -4
  40. package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +11 -0
  41. package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/viewer.mjs +305 -0
  42. package/node_modules/@herbertgao/pi-mermaid-open/package.json +15 -4
  43. package/node_modules/@herbertgao/pi-mermaid-open/src/index.ts +351 -101
  44. package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +12 -0
  45. package/node_modules/@herbertgao/pi-preferred-thinking/README.md +30 -14
  46. package/node_modules/@herbertgao/pi-preferred-thinking/package.json +7 -4
  47. package/node_modules/@herbertgao/pi-preferred-thinking/src/index.ts +140 -85
  48. package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +12 -0
  49. package/node_modules/@herbertgao/pi-recap/README.md +5 -3
  50. package/node_modules/@herbertgao/pi-recap/package.json +9 -3
  51. package/node_modules/@herbertgao/pi-recap/src/index.ts +3 -7
  52. package/node_modules/@herbertgao/pi-recap/src/model-picker.ts +6 -19
  53. package/node_modules/@herbertgao/pi-recap/src/models.ts +9 -21
  54. package/node_modules/@herbertgao/pi-recap/src/tui.ts +1 -1
  55. package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +49 -0
  56. package/node_modules/@herbertgao/pi-rename/README.md +13 -11
  57. package/node_modules/@herbertgao/pi-rename/package.json +13 -3
  58. package/node_modules/@herbertgao/pi-rename/src/index.ts +135 -59
  59. package/node_modules/@herbertgao/pi-rename/src/models.ts +5 -13
  60. package/node_modules/@herbertgao/pi-rename/src/naming.ts +2 -6
  61. package/node_modules/@herbertgao/pi-stash/package.json +3 -3
  62. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
  63. package/node_modules/@herbertgao/pi-subagents/README.md +16 -3
  64. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  65. package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +15 -4
  66. package/node_modules/@herbertgao/pi-subagents/src/index.ts +16 -0
  67. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +5 -1
  68. package/node_modules/pi-web-access/CHANGELOG.md +13 -0
  69. package/node_modules/pi-web-access/README.md +2 -2
  70. package/node_modules/pi-web-access/chrome-cookies.ts +12 -7
  71. package/node_modules/pi-web-access/gemini-search.ts +28 -10
  72. package/node_modules/pi-web-access/index.ts +24 -10
  73. package/node_modules/pi-web-access/package.json +1 -1
  74. package/package.json +13 -12
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.24.2] - 2026-08-22
8
+
9
+ ### Highlights
10
+ - `auto` search now uses Codex-backed OpenAI search when Pi is running a Codex model.
11
+ - Non-Codex sessions still prefer Exa first, so zero-config search keeps its fast keyless path.
12
+ - Gemini Web browser-cookie access is more reliable on Windows Chrome and Edge profiles.
13
+
14
+ ### Changed
15
+ - Prefer Codex-backed OpenAI search in `auto` mode when the active Pi model is `openai-codex`; otherwise prefer Exa before OpenAI.
16
+
17
+ ### Fixed
18
+ - Fixed Windows Gemini Web browser-cookie extraction when Chromium cookie expiry values are too large for JavaScript numbers or PowerShell DPAPI key unprotect needs encoded command transport. Thanks to [@laixuanthoi](https://github.com/laixuanthoi) for issue #290.
19
+
7
20
  ## [0.24.1] - 2026-08-21
8
21
 
9
22
  ### Added
@@ -18,7 +18,7 @@
18
18
 
19
19
  **Video Understanding** — Point it at a YouTube video or local screen recording and ask questions about what's on screen. Full transcripts, visual descriptions, and frame extraction at exact timestamps.
20
20
 
21
- **Smart Fallbacks** — Every capability has a fallback chain. Search tries configured SearXNG first for local/private search, then OpenAI when suitable and available, Exa, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, and Gemini Web when browser cookies are enabled. With no SearXNG configured, the existing zero-config order is unchanged. YouTube tries Gemini Web when enabled, then API, then Perplexity. Blocked pages try configured self-hosted Firecrawl first. Third-party hosted page fetchers require explicit `fetchRouting.allowRemoteHostedProviders` opt-in for remote HTTP(S) targets.
21
+ **Smart Fallbacks** — Every capability has a fallback chain. Search tries configured SearXNG first for local/private search. When the active Pi model is `openai-codex`, it then tries Codex-backed OpenAI search. Otherwise it tries Exa before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, and Gemini Web when browser cookies are enabled. YouTube tries Gemini Web when enabled, then API, then Perplexity. Blocked pages try configured self-hosted Firecrawl first. Third-party hosted page fetchers require explicit `fetchRouting.allowRemoteHostedProviders` opt-in for remote HTTP(S) targets.
22
22
 
23
23
  **GitHub Cloning** — GitHub URLs are cloned locally instead of scraped. The agent gets real file contents and a local path to explore, not rendered HTML.
24
24
 
@@ -46,7 +46,7 @@ Works immediately with no API keys — Exa MCP provides zero-config search. If P
46
46
  }
47
47
  ```
48
48
 
49
- In `auto` mode (default), `web_search` tries a configured SearXNG endpoint first for local/private search, then OpenAI when suitable and available, Exa (direct API if keyed, MCP if not), Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Perplexity, Gemini API, and Gemini Web when browser-cookie access is enabled. With no SearXNG configured, the existing zero-config order is unchanged. Exa handles search; curator summary drafts are generated separately by the configured Pi summary model, defaulting to Claude Haiku, Codex Luna, Codex Terra, Gemini 3.6 Flash, GPT-5 mini, then DeepSeek V4 Flash when available. Slow summary drafts fall back to a deterministic result summary after a bounded deadline.
49
+ In `auto` mode (default), `web_search` tries a configured SearXNG endpoint first for local/private search. When the active Pi model is `openai-codex`, it then tries Codex-backed OpenAI search. Otherwise it tries Exa (direct API if keyed, MCP if not) before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Perplexity, Gemini API, and Gemini Web when browser-cookie access is enabled. Exa handles search; curator summary drafts are generated separately by the configured Pi summary model, defaulting to Claude Haiku, Codex Luna, Codex Terra, Gemini 3.6 Flash, GPT-5 mini, then DeepSeek V4 Flash when available. Slow summary drafts fall back to a deterministic result summary after a bounded deadline.
50
50
 
51
51
  If your OpenAI key belongs to a third-party Responses-compatible gateway, set `openaiResponsesUrl` to that gateway's full Responses endpoint. The default remains `https://api.openai.com/v1/responses`.
52
52
 
@@ -375,8 +375,9 @@ async function readWindowsEncryptionKey(config: BrowserConfig, home: string): Pr
375
375
 
376
376
  function unprotectWindowsData(protectedData: Buffer): Promise<Buffer | null> {
377
377
  return new Promise((resolve) => {
378
- const script = "$data=[Convert]::FromBase64String($args[0]);$clear=[Security.Cryptography.ProtectedData]::Unprotect($data,$null,[Security.Cryptography.DataProtectionScope]::CurrentUser);[Console]::Write([Convert]::ToBase64String($clear))";
379
- execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script, protectedData.toString("base64")], { timeout: 5000, maxBuffer: 1024 * 1024 }, (err, stdout) => {
378
+ const script = "Add-Type -AssemblyName System.Security;$data=[Convert]::FromBase64String($env:PIWA_PROTECTED);$clear=[System.Security.Cryptography.ProtectedData]::Unprotect($data,$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser);[Console]::Write([Convert]::ToBase64String($clear))";
379
+ const encoded = Buffer.from(script, "utf16le").toString("base64");
380
+ execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", encoded], { timeout: 5000, maxBuffer: 1024 * 1024, env: { ...process.env, PIWA_PROTECTED: protectedData.toString("base64") } }, (err, stdout) => {
380
381
  if (err) { resolve(null); return; }
381
382
  try {
382
383
  resolve(Buffer.from(stdout.trim(), "base64"));
@@ -509,10 +510,10 @@ async function queryCookieRows(dbPath: string, hosts: string[], names: Iterable<
509
510
  const columns = await readCookieColumns(dbPath);
510
511
  if (columns.status === "failure") return columns;
511
512
  const pathExpr = columns.columns.has("path") ? "path" : "'/' AS path";
512
- const expiresExpr = columns.columns.has("expires_utc") ? "expires_utc" : "0 AS expires_utc";
513
- const expiryFilter = filterExpired && columns.columns.has("expires_utc") ? ` AND (expires_utc = 0 OR expires_utc > ${chromeExpiryNowMicros()})` : "";
513
+ const expiresExpr = columns.columns.has("expires_utc") ? chromeExpiryMillisExpr() : "0";
514
+ const expiryFilter = filterExpired && columns.columns.has("expires_utc") ? ` AND (${expiresExpr} = 0 OR ${expiresExpr} > ${chromeExpiryNowMillis()})` : "";
514
515
  const partitionFilter = filterExpired ? unpartitionedCookieFilter(columns.columns) : "";
515
- return runSqliteQuery(dbPath, `SELECT name, value, host_key, ${pathExpr}, ${expiresExpr}, hex(encrypted_value) AS encrypted_value_hex FROM cookies WHERE ${buildCookieWhere(hosts, names ?? undefined)}${expiryFilter}${partitionFilter} ORDER BY length(path) DESC, expires_utc ASC`);
516
+ return runSqliteQuery(dbPath, `SELECT name, value, host_key, ${pathExpr}, ${expiresExpr} AS expires_utc, hex(encrypted_value) AS encrypted_value_hex FROM cookies WHERE ${buildCookieWhere(hosts, names ?? undefined)}${expiryFilter}${partitionFilter} ORDER BY length(path) DESC, ${expiresExpr} ASC`);
516
517
  }
517
518
 
518
519
  async function readCookieColumns(dbPath: string): Promise<{ status: "success"; columns: Set<string> } | { status: "failure"; failure: SqliteFailure }> {
@@ -521,8 +522,12 @@ async function readCookieColumns(dbPath: string): Promise<{ status: "success"; c
521
522
  return { status: "success", columns: new Set(result.rows.map(row => typeof row.name === "string" ? row.name : "")) };
522
523
  }
523
524
 
524
- function chromeExpiryNowMicros(): number {
525
- return (Date.now() + 11644473600000) * 1000;
525
+ function chromeExpiryMillisExpr(): string {
526
+ return "CASE WHEN expires_utc = 0 THEN 0 ELSE CAST(expires_utc / 1000 AS INTEGER) + CASE WHEN expires_utc % 1000 = 0 THEN 0 ELSE 1 END END";
527
+ }
528
+
529
+ function chromeExpiryNowMillis(): number {
530
+ return Date.now() + 11644473600000;
526
531
  }
527
532
 
528
533
  function unpartitionedCookieFilter(columns: Set<string>): string {
@@ -216,6 +216,24 @@ function shouldTryOpenAIInAuto(options: SearchOptions): boolean {
216
216
  return true;
217
217
  }
218
218
 
219
+ function isOpenAICodexSelected(ctx?: ExtensionContext): boolean {
220
+ return ctx?.model?.provider === "openai-codex";
221
+ }
222
+
223
+ async function tryOpenAIInAuto(query: string, options: FullSearchOptions, fallbackErrors: string[]): Promise<AttributedSearchResponse | null> {
224
+ if (!shouldTryOpenAIInAuto(options)) return null;
225
+ try {
226
+ if (await isOpenAISearchAvailable(options.extensionContext)) {
227
+ const result = await searchWithOpenAI(query, options, options.extensionContext);
228
+ return { ...result, provider: "openai" };
229
+ }
230
+ } catch (err) {
231
+ if (isAbortError(err)) throw err;
232
+ fallbackErrors.push(`OpenAI: ${errorMessage(err)}`);
233
+ }
234
+ return null;
235
+ }
236
+
219
237
  async function searchWithGemini(
220
238
  query: string,
221
239
  options: SearchOptions,
@@ -524,16 +542,11 @@ export async function search(query: string, options: FullSearchOptions = {}): Pr
524
542
  }
525
543
  }
526
544
 
527
- if (shouldTryOpenAIInAuto(options)) {
528
- try {
529
- if (await isOpenAISearchAvailable(options.extensionContext)) {
530
- const result = await searchWithOpenAI(query, options, options.extensionContext);
531
- return { ...result, provider: "openai" };
532
- }
533
- } catch (err) {
534
- if (isAbortError(err)) throw err;
535
- fallbackErrors.push(`OpenAI: ${errorMessage(err)}`);
536
- }
545
+ let triedOpenAI = false;
546
+ if (!options.extensionContext || isOpenAICodexSelected(options.extensionContext)) {
547
+ triedOpenAI = true;
548
+ const result = await tryOpenAIInAuto(query, options, fallbackErrors);
549
+ if (result) return result;
537
550
  }
538
551
 
539
552
  if (isExaAvailable()) {
@@ -546,6 +559,11 @@ export async function search(query: string, options: FullSearchOptions = {}): Pr
546
559
  }
547
560
  }
548
561
 
562
+ if (!triedOpenAI) {
563
+ const result = await tryOpenAIInAuto(query, options, fallbackErrors);
564
+ if (result) return result;
565
+ }
566
+
549
567
  if (isBraveAvailable()) {
550
568
  try {
551
569
  const result = await searchWithBrave(query, options);
@@ -152,7 +152,7 @@ interface WebSearchConfig {
152
152
  };
153
153
  }
154
154
 
155
- interface ProviderAvailability {
155
+ export interface ProviderAvailability {
156
156
  all: boolean;
157
157
  openai: boolean;
158
158
  brave: boolean;
@@ -184,7 +184,7 @@ interface ProviderAvailability {
184
184
 
185
185
  type WebSearchWorkflow = "none" | "summary-review" | "auto-summary";
186
186
  type CuratorWorkflow = "summary-review";
187
- type CuratorProvider = Exclude<SearchProvider, "auto">;
187
+ export type CuratorProvider = Exclude<SearchProvider, "auto">;
188
188
  type SummaryWorkflow = "summary-review" | "auto-summary";
189
189
 
190
190
  interface CuratorBootstrap {
@@ -420,13 +420,16 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
420
420
  };
421
421
  }
422
422
 
423
- function shouldPreferOpenAI(options?: Pick<PendingCurate, "numResults" | "recencyFilter">): boolean {
424
- if (!options) return true;
425
- if (options.recencyFilter) return false;
426
- if (typeof options.numResults === "number" && Number.isFinite(options.numResults) && Math.floor(options.numResults) !== 5) {
423
+ function shouldUseOpenAICodexDefault(ctx?: Pick<ExtensionContext, "model">): boolean {
424
+ return ctx?.model?.provider === "openai-codex";
425
+ }
426
+
427
+ function shouldPreferOpenAI(options: Pick<PendingCurate, "numResults" | "recencyFilter"> | undefined, preferOpenAICodexDefault: boolean): boolean {
428
+ if (options?.recencyFilter) return false;
429
+ if (typeof options?.numResults === "number" && Number.isFinite(options.numResults) && Math.floor(options.numResults) !== 5) {
427
430
  return false;
428
431
  }
429
- return true;
432
+ return preferOpenAICodexDefault;
430
433
  }
431
434
 
432
435
  async function loadCuratorBootstrap(
@@ -439,15 +442,25 @@ async function loadCuratorBootstrap(
439
442
  if (Array.isArray(provider)) availableProviders.all = true;
440
443
  return {
441
444
  availableProviders,
442
- defaultProvider: resolveProvider(provider, availableProviders, options),
445
+ defaultProvider: resolveCuratorDefaultProvider(provider, availableProviders, ctx, options),
443
446
  timeoutSeconds: getCuratorTimeoutSeconds(),
444
447
  };
445
448
  }
446
449
 
450
+ export function resolveCuratorDefaultProvider(
451
+ provider: SearchProviderSelection,
452
+ available: ProviderAvailability,
453
+ ctx?: Pick<ExtensionContext, "model">,
454
+ options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
455
+ ): CuratorProvider {
456
+ return resolveProvider(provider, available, options, shouldUseOpenAICodexDefault(ctx));
457
+ }
458
+
447
459
  function firstAvailableProvider(available: ProviderAvailability, preferOpenAI: boolean, fallback: ResolvedSearchProvider): ResolvedSearchProvider {
448
460
  if (available.searxng) return "searxng";
449
461
  if (preferOpenAI && available.openai) return "openai";
450
462
  if (available.exa) return "exa";
463
+ if (available.openai) return "openai";
451
464
  if (available.brave) return "brave";
452
465
  if (available.parallel) return "parallel";
453
466
  if (available.tinyfish) return "tinyfish";
@@ -470,9 +483,10 @@ function resolveProvider(
470
483
  provider: SearchProviderSelection,
471
484
  available: ProviderAvailability,
472
485
  options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
486
+ preferOpenAICodexDefault = false,
473
487
  ): CuratorProvider {
474
488
  if (Array.isArray(provider)) return "all";
475
- const preferOpenAI = shouldPreferOpenAI(options);
489
+ const preferOpenAI = shouldPreferOpenAI(options, preferOpenAICodexDefault);
476
490
 
477
491
  if (provider === "auto") {
478
492
  const routing = getConfiguredSearchRouting();
@@ -1660,7 +1674,7 @@ export default function (pi: ExtensionAPI) {
1660
1674
  name: toolNames.webSearch,
1661
1675
  label: "Web Search",
1662
1676
  description:
1663
- `Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider, auto-selects OpenAI when suitable and available, then Exa, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web. When SearXNG is configured, it is preferred first for local/private search.`,
1677
+ `Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider, SearXNG is preferred first for local/private search. When the active Pi model is openai-codex, Codex-backed OpenAI search is preferred next. Otherwise Exa is preferred before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web.`,
1664
1678
  promptSnippet:
1665
1679
  "Use for web research questions. Prefer {queries:[...]} with 2-4 varied angles over a single query for broader coverage. Omit provider unless explicitly overriding the configured default.",
1666
1680
  parameters: Type.Object({
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-web-access",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Exa, Perplexity, and Gemini.",
5
5
  "type": "module",
6
6
  "scripts": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herbertgao/pi-extensions",
3
- "version": "2026.8.8",
3
+ "version": "2026.8.9",
4
4
  "description": "Aggregate installer for HerbertGao-maintained Pi extensions.",
5
5
  "keywords": [
6
6
  "extensions",
@@ -36,22 +36,22 @@
36
36
  "dependencies": {
37
37
  "@ast-grep/cli": "^0.45.0",
38
38
  "@ast-grep/napi": "^0.45.0",
39
- "@czottmann/pi-automode": "1.11.0",
39
+ "@czottmann/pi-automode": "1.12.0",
40
40
  "@dietrichgebert/ponytail": "4.9.0",
41
41
  "@earendil-works/pi-coding-agent": "^0.84.2",
42
42
  "@earendil-works/pi-tui": "^0.84.2",
43
43
  "@effect/platform-node": "4.0.0-beta.103",
44
44
  "@effect/platform-node-shared": "4.0.0-beta.103",
45
- "@herbertgao/pi-cc-extensions": "0.8.57",
45
+ "@herbertgao/pi-cc-extensions": "0.8.58",
46
46
  "@herbertgao/pi-copy-response": "0.2.6",
47
- "@herbertgao/pi-handoff": "1.1.2",
47
+ "@herbertgao/pi-handoff": "2.0.0",
48
48
  "@herbertgao/pi-inline-skills": "1.0.5",
49
- "@herbertgao/pi-mermaid-open": "0.1.3",
50
- "@herbertgao/pi-preferred-thinking": "0.3.0",
51
- "@herbertgao/pi-recap": "0.4.4",
52
- "@herbertgao/pi-rename": "0.4.2",
53
- "@herbertgao/pi-stash": "0.1.1",
54
- "@herbertgao/pi-subagents": "0.16.0",
49
+ "@herbertgao/pi-mermaid-open": "0.2.0",
50
+ "@herbertgao/pi-preferred-thinking": "0.4.0",
51
+ "@herbertgao/pi-recap": "0.4.5",
52
+ "@herbertgao/pi-rename": "0.5.0",
53
+ "@herbertgao/pi-stash": "0.1.2",
54
+ "@herbertgao/pi-subagents": "0.16.1",
55
55
  "@herbertgao/pi-titlebar-spinner": "0.1.3",
56
56
  "@juicesharp/rpiv-ask-user-question": "2.7.0",
57
57
  "@juicesharp/rpiv-config": "^2.7.0",
@@ -73,7 +73,7 @@
73
73
  "croner": "^10.0.1",
74
74
  "cross-spawn": "^7.0.6",
75
75
  "effect": "4.0.0-beta.103",
76
- "grok-mermaid": "^0.2.2",
76
+ "grok-mermaid": "0.2.2",
77
77
  "jiti": "^2.7.0",
78
78
  "js-yaml": "^5.2.2",
79
79
  "linkedom": "^0.16.0",
@@ -84,7 +84,7 @@
84
84
  "pi-footer": "0.5.1",
85
85
  "pi-lens": "4.1.1",
86
86
  "pi-mcp-adapter": "2.27.0",
87
- "pi-web-access": "0.24.1",
87
+ "pi-web-access": "0.24.2",
88
88
  "pidusage": "^4.0.1",
89
89
  "promise.try": "^2.0.1",
90
90
  "qrcode-terminal": "^0.12.0",
@@ -159,6 +159,7 @@
159
159
  "./node_modules/@herbertgao/pi-cc-extensions/themes/cc-light.json"
160
160
  ],
161
161
  "skills": [
162
+ "./node_modules/@czottmann/pi-automode/skills",
162
163
  "./node_modules/@dietrichgebert/ponytail/skills",
163
164
  "./node_modules/pi-mcp-adapter/skills",
164
165
  "./node_modules/pi-lens/skills"