@herbertgao/pi-extensions 2026.8.15 → 2026.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +4 -1
  2. package/THIRD_PARTY_NOTICES.md +26 -0
  3. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +20 -0
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +46 -3
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +6 -0
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +5 -0
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +34 -30
  9. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  10. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  11. package/node_modules/@narumitw/pi-btw/README.md +5 -1
  12. package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -14
  13. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  14. package/node_modules/@narumitw/pi-btw/package.json +4 -4
  15. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +158 -7
  16. package/node_modules/@narumitw/pi-btw/src/text.ts +18 -0
  17. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +5 -16
  18. package/node_modules/@narumitw/pi-caffeinate/LICENSE +21 -0
  19. package/node_modules/@narumitw/pi-caffeinate/README.md +224 -0
  20. package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +1112 -0
  21. package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +7 -0
  22. package/node_modules/@narumitw/pi-caffeinate/package.json +53 -0
  23. package/node_modules/@narumitw/pi-caffeinate/src/caffeinate.ts +811 -0
  24. package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +153 -0
  25. package/node_modules/@narumitw/pi-caffeinate/src/index.ts +1 -0
  26. package/node_modules/@narumitw/pi-caffeinate/src/inhibitor-process.ts +43 -0
  27. package/node_modules/@narumitw/pi-caffeinate/src/inhibitors.ts +167 -0
  28. package/node_modules/@narumitw/pi-caffeinate/src/settings.ts +202 -0
  29. package/node_modules/@tifan/pi-handoff/README.md +6 -3
  30. package/node_modules/@tifan/pi-handoff/package.json +1 -1
  31. package/node_modules/@tifan/pi-handoff/src/index.ts +8 -3
  32. package/node_modules/pi-mcp-adapter/CHANGELOG.md +27 -0
  33. package/node_modules/pi-mcp-adapter/README.md +13 -13
  34. package/node_modules/pi-mcp-adapter/commands.ts +58 -21
  35. package/node_modules/pi-mcp-adapter/config.ts +18 -4
  36. package/node_modules/pi-mcp-adapter/direct-tools.ts +26 -6
  37. package/node_modules/pi-mcp-adapter/dist/config.d.ts +4 -0
  38. package/node_modules/pi-mcp-adapter/dist/config.js +13 -4
  39. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
  40. package/node_modules/pi-mcp-adapter/dist/types.d.ts +11 -3
  41. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
  42. package/node_modules/pi-mcp-adapter/error-signal.ts +15 -4
  43. package/node_modules/pi-mcp-adapter/errors.ts +141 -0
  44. package/node_modules/pi-mcp-adapter/host-html-template.ts +58 -5
  45. package/node_modules/pi-mcp-adapter/index.ts +2 -3
  46. package/node_modules/pi-mcp-adapter/init.ts +5 -0
  47. package/node_modules/pi-mcp-adapter/mcp-panel.ts +30 -9
  48. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +66 -28
  49. package/node_modules/pi-mcp-adapter/mcp-status.ts +2 -0
  50. package/node_modules/pi-mcp-adapter/package.json +2 -1
  51. package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -13
  52. package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +217 -0
  53. package/node_modules/pi-mcp-adapter/server-manager.ts +337 -6
  54. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +1 -0
  55. package/node_modules/pi-mcp-adapter/types.ts +18 -3
  56. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +18 -2
  57. package/node_modules/pi-mcp-adapter/ui-server.ts +179 -54
  58. package/node_modules/pi-mcp-adapter/ui-session.ts +28 -8
  59. package/package.json +11 -7
@@ -482,8 +482,10 @@ import {
482
482
  } from "@earendil-works/pi-coding-agent";
483
483
  import {
484
484
  isKeyRelease,
485
+ isKittyProtocolActive,
485
486
  Key as Key2,
486
487
  matchesKey as matchesKey2,
488
+ parseKey,
487
489
  TuiAltScreen,
488
490
  truncateToWidth as truncateToWidth2
489
491
  } from "@earendil-works/pi-tui";
@@ -495,6 +497,18 @@ function sanitizeSingleLine(text) {
495
497
  return code > 31 && (code < 127 || code > 159);
496
498
  }).join("").replace(/ +/gu, " ").trim();
497
499
  }
500
+ function formatKeyLabel2(key) {
501
+ const sanitized = sanitizeSingleLine(key);
502
+ if (!sanitized) return "";
503
+ return sanitized.split("+").map((part) => {
504
+ const lower = part.toLowerCase();
505
+ if (lower === "shift") return "Shift";
506
+ if (lower === "ctrl") return "Ctrl";
507
+ if (lower === "alt") return "Alt";
508
+ if (lower === "super") return "Super";
509
+ return part.length === 1 ? part.toUpperCase() : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`;
510
+ }).join("+");
511
+ }
498
512
 
499
513
  // src/fullscreen-ui.ts
500
514
  var FullscreenUiDisposedError = class extends Error {
@@ -607,6 +621,88 @@ var BtwTuiAltScreen = class extends TuiAltScreen {
607
621
  };
608
622
  var BRACKETED_PASTE_START = "\x1B[200~";
609
623
  var BRACKETED_PASTE_END = "\x1B[201~";
624
+ var ALT_SCREEN_ACTIONS_BEFORE_BOTTOM = [
625
+ "tui.altScreen.search",
626
+ "tui.altScreen.searchNext",
627
+ "tui.altScreen.searchPrevious",
628
+ "tui.altScreen.searchClose",
629
+ "tui.altScreen.pageUp",
630
+ "tui.altScreen.pageDown",
631
+ "tui.altScreen.halfPageUp",
632
+ "tui.altScreen.halfPageDown",
633
+ "tui.altScreen.lineUp",
634
+ "tui.altScreen.lineDown",
635
+ "tui.altScreen.previousPrompt",
636
+ "tui.altScreen.nextPrompt",
637
+ "tui.altScreen.top"
638
+ ];
639
+ var KEY_MODIFIER_ORDER = ["shift", "ctrl", "alt", "super"];
640
+ var MATCHABLE_SPECIAL_KEYS = /* @__PURE__ */ new Set([
641
+ "space",
642
+ "tab",
643
+ "enter",
644
+ "backspace",
645
+ "delete",
646
+ "insert",
647
+ "home",
648
+ "end",
649
+ "pageup",
650
+ "pagedown",
651
+ "up",
652
+ "down",
653
+ "left",
654
+ "right"
655
+ ]);
656
+ var MATCHABLE_SYMBOL_KEYS = new Set("`-=[]\\;',./!@#$%^&*()_+|~{}:<>?");
657
+ function normalizedKeyId(key) {
658
+ const parts = key.toLowerCase().split("+");
659
+ const base = parts.at(-1);
660
+ if (!base) return "";
661
+ const normalizedBase = base === "esc" ? "escape" : base === "return" ? "enter" : base;
662
+ const modifiers = KEY_MODIFIER_ORDER.filter((modifier) => parts.includes(modifier));
663
+ return [...modifiers, normalizedBase].join("+");
664
+ }
665
+ function formatEffectiveKeyLabel(key) {
666
+ const parts = key.split("+");
667
+ const base = parts.at(-1);
668
+ if (base === "pageup") parts[parts.length - 1] = "pageUp";
669
+ if (base === "pagedown") parts[parts.length - 1] = "pageDown";
670
+ return formatKeyLabel2(parts.join("+"));
671
+ }
672
+ function canMatchKeyInput(key) {
673
+ const parts = key.split("+");
674
+ const base = parts.at(-1) ?? "";
675
+ const modifiers = parts.slice(0, -1);
676
+ if (base === "escape") return modifiers.length === 0;
677
+ if (base === "clear") {
678
+ return modifiers.length === 0 || modifiers.length === 1 && (modifiers[0] === "shift" || modifiers[0] === "ctrl");
679
+ }
680
+ if (/^f(?:[1-9]|1[0-2])$/u.test(base)) return modifiers.length === 0;
681
+ return MATCHABLE_SPECIAL_KEYS.has(base) || base.length === 1 && (/^[a-z0-9]$/u.test(base) || MATCHABLE_SYMBOL_KEYS.has(base));
682
+ }
683
+ function rawCtrlInput(base) {
684
+ if (base.length !== 1) return void 0;
685
+ const rawBase = base === "-" ? "_" : base;
686
+ if (!"abcdefghijklmnopqrstuvwxyz[\\]_".includes(rawBase)) return void 0;
687
+ return String.fromCharCode(rawBase.charCodeAt(0) & 31);
688
+ }
689
+ function legacyRawInput(key) {
690
+ const parts = key.split("+");
691
+ const base = parts.at(-1) ?? "";
692
+ if (parts.length === 2 && parts[0] === "ctrl") return rawCtrlInput(base);
693
+ if (isKittyProtocolActive()) return void 0;
694
+ if (parts.length === 2 && parts[0] === "alt" && base.length === 1) return `\x1B${base}`;
695
+ if (parts.length === 3 && parts[0] === "ctrl" && parts[1] === "alt") {
696
+ const input = rawCtrlInput(base);
697
+ return input ? `\x1B${input}` : void 0;
698
+ }
699
+ return void 0;
700
+ }
701
+ function keyInputIdentity(key) {
702
+ const identity = normalizedKeyId(key);
703
+ const input = legacyRawInput(identity);
704
+ return input ? normalizedKeyId(parseKey(input) ?? identity) : identity;
705
+ }
610
706
  function hasManualSelectionCopyApi() {
611
707
  return typeof TuiAltScreen.prototype.hasActiveSelection === "function" && typeof TuiAltScreen.prototype.copyActiveSelectionToClipboard === "function";
612
708
  }
@@ -625,6 +721,25 @@ function createBtwFullscreenTui(parent, theme, keybindings, copyOnSelect, manual
625
721
  mouse: true,
626
722
  copyOnSelect,
627
723
  searchMatchStyle: (text) => theme.underline(styleSearchMatch(text)),
724
+ scrollToEndIndicator: () => {
725
+ const unavailableKeyIdentities = /* @__PURE__ */ new Set([keyInputIdentity(Key2.ctrl("c"))]);
726
+ for (const action of ALT_SCREEN_ACTIONS_BEFORE_BOTTOM) {
727
+ for (const actionKey of keybindings.getKeys(action)) {
728
+ unavailableKeyIdentities.add(keyInputIdentity(String(actionKey)));
729
+ }
730
+ }
731
+ if (!copyOnSelect) {
732
+ for (const copyKey of keybindings.getKeys("app.message.copy")) {
733
+ unavailableKeyIdentities.add(keyInputIdentity(String(copyKey)));
734
+ }
735
+ }
736
+ const key = keybindings.getKeys("tui.altScreen.bottom").map((candidate) => keyInputIdentity(String(candidate))).find(
737
+ (identity) => identity && canMatchKeyInput(identity) && !unavailableKeyIdentities.has(identity) && formatEffectiveKeyLabel(identity)
738
+ );
739
+ const label = theme.fg("text", " \u2193 Jump to latest message");
740
+ const shortcut = key ? theme.fg("muted", ` \xB7 ${formatEffectiveKeyLabel(key)}`) : "";
741
+ return theme.bg("selectedBg", `${label}${shortcut} `);
742
+ },
628
743
  searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
629
744
  openUrl,
630
745
  copySelection: async (text) => {
@@ -693,9 +808,11 @@ var BtwFullscreenHost = class {
693
808
  disposed = false;
694
809
  finished = false;
695
810
  parentStopped = false;
696
- parentRestarted = false;
811
+ parentRestoreAttempted = false;
697
812
  fullscreenCreated = false;
698
813
  fullscreenStopped = false;
814
+ parentRestoreQueued = false;
815
+ parentRestorePromise;
699
816
  cleanupError;
700
817
  setParentOverlay(overlay) {
701
818
  this.parentOverlay = overlay;
@@ -728,7 +845,7 @@ var BtwFullscreenHost = class {
728
845
  try {
729
846
  this.hardCancelActiveCustom?.();
730
847
  } finally {
731
- this.restoreParent();
848
+ this.queueParentRestore();
732
849
  }
733
850
  return { consume: true };
734
851
  });
@@ -741,14 +858,33 @@ var BtwFullscreenHost = class {
741
858
  } catch (error) {
742
859
  this.cleanupError ??= error;
743
860
  }
744
- this.restoreParent();
861
+ if (this.parentRestorePromise) await this.parentRestorePromise;
862
+ else this.restoreParent();
745
863
  if (this.cleanupError !== void 0) outcome = { kind: "failed", error: this.cleanupError };
746
864
  this.finished = true;
747
865
  this.done(outcome);
748
866
  }
867
+ queueParentRestore() {
868
+ if (this.parentRestoreQueued || this.parentRestoreAttempted) return;
869
+ this.parentRestoreQueued = true;
870
+ this.parentRestorePromise = Promise.resolve().then(async () => {
871
+ try {
872
+ await this.fullscreen?.terminal.drainInput?.();
873
+ } catch (error) {
874
+ this.cleanupError ??= error;
875
+ }
876
+ this.parentRestoreQueued = false;
877
+ this.restoreParent();
878
+ });
879
+ }
749
880
  restoreParent() {
750
- this.removeHardCancelListener?.();
881
+ const removeHardCancelListener = this.removeHardCancelListener;
751
882
  this.removeHardCancelListener = void 0;
883
+ try {
884
+ removeHardCancelListener?.();
885
+ } catch (error) {
886
+ this.cleanupError ??= error;
887
+ }
752
888
  if (this.fullscreenCreated && !this.fullscreenStopped) {
753
889
  this.fullscreenStopped = true;
754
890
  try {
@@ -757,7 +893,7 @@ var BtwFullscreenHost = class {
757
893
  this.cleanupError ??= error;
758
894
  }
759
895
  }
760
- if (!this.parentStopped || this.parentRestarted) return;
896
+ if (!this.parentStopped || this.parentRestoreAttempted) return;
761
897
  const parentOverlay = this.parentOverlay;
762
898
  this.parentOverlay = void 0;
763
899
  try {
@@ -766,8 +902,8 @@ var BtwFullscreenHost = class {
766
902
  this.cleanupError ??= error;
767
903
  }
768
904
  try {
905
+ this.parentRestoreAttempted = true;
769
906
  this.parent.start();
770
- this.parentRestarted = true;
771
907
  this.parent.renderNow(false);
772
908
  } catch (error) {
773
909
  this.cleanupError ??= error;
@@ -2355,14 +2491,7 @@ function renderSideThreadHeader(width, theme, thinkingLevel) {
2355
2491
  return theme.fg("muted", `${title}${"\u2500".repeat(ruleWidth)}`);
2356
2492
  }
2357
2493
  function thinkingKeyLabel(keybindings) {
2358
- const key = sanitizeSingleLine(String(keybindings.getKeys("app.thinking.cycle")[0] ?? "shift+tab")) || "Shift+Tab";
2359
- return key.split("+").map((part) => {
2360
- const lower = part.toLowerCase();
2361
- if (lower === "shift") return "Shift";
2362
- if (lower === "ctrl") return "Ctrl";
2363
- if (lower === "alt") return "Alt";
2364
- return part.length === 1 ? part.toUpperCase() : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`;
2365
- }).join("+");
2494
+ return formatKeyLabel2(String(keybindings.getKeys("app.thinking.cycle")[0] ?? "shift+tab")) || "Shift+Tab";
2366
2495
  }
2367
2496
  function fitComposerLayout(header, contentLines, footer, editorLines, availableRows, statusLines = []) {
2368
2497
  const lines = [header, ...contentLines, ...statusLines, footer, ...editorLines];