@herbertgao/pi-extensions 2026.8.7 → 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 (161) hide show
  1. package/README.md +8 -6
  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/compact-thinking.ts +63 -15
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +56 -29
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +78 -16
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +13 -0
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +30 -17
  33. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  34. package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +29 -0
  35. package/node_modules/@herbertgao/pi-handoff/README.md +15 -18
  36. package/node_modules/@herbertgao/pi-handoff/package.json +11 -4
  37. package/node_modules/@herbertgao/pi-handoff/src/complete-text.ts +33 -0
  38. package/node_modules/@herbertgao/pi-handoff/src/index.ts +127 -232
  39. package/node_modules/@herbertgao/pi-handoff/src/session-query.ts +15 -30
  40. package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +14 -0
  41. package/node_modules/@herbertgao/pi-mermaid-open/README.md +21 -4
  42. package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +11 -0
  43. package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/viewer.mjs +305 -0
  44. package/node_modules/@herbertgao/pi-mermaid-open/package.json +15 -4
  45. package/node_modules/@herbertgao/pi-mermaid-open/src/index.ts +351 -101
  46. package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +12 -0
  47. package/node_modules/@herbertgao/pi-preferred-thinking/README.md +30 -14
  48. package/node_modules/@herbertgao/pi-preferred-thinking/package.json +7 -4
  49. package/node_modules/@herbertgao/pi-preferred-thinking/src/index.ts +140 -85
  50. package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +12 -0
  51. package/node_modules/@herbertgao/pi-recap/README.md +5 -3
  52. package/node_modules/@herbertgao/pi-recap/package.json +9 -3
  53. package/node_modules/@herbertgao/pi-recap/src/index.ts +3 -7
  54. package/node_modules/@herbertgao/pi-recap/src/model-picker.ts +6 -19
  55. package/node_modules/@herbertgao/pi-recap/src/models.ts +9 -21
  56. package/node_modules/@herbertgao/pi-recap/src/tui.ts +1 -1
  57. package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +49 -0
  58. package/node_modules/@herbertgao/pi-rename/README.md +13 -11
  59. package/node_modules/@herbertgao/pi-rename/package.json +13 -3
  60. package/node_modules/@herbertgao/pi-rename/src/index.ts +135 -59
  61. package/node_modules/@herbertgao/pi-rename/src/models.ts +5 -13
  62. package/node_modules/@herbertgao/pi-rename/src/naming.ts +2 -6
  63. package/node_modules/@herbertgao/pi-stash/package.json +3 -3
  64. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
  65. package/node_modules/@herbertgao/pi-subagents/README.md +16 -3
  66. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  67. package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +15 -4
  68. package/node_modules/@herbertgao/pi-subagents/src/index.ts +16 -0
  69. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +5 -1
  70. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +4 -4
  71. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +154 -96
  72. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +3 -0
  73. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
  74. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +7 -5
  75. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
  76. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +3 -0
  77. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  78. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +137 -96
  79. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +44 -32
  80. package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
  81. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
  82. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
  83. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
  84. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
  85. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
  86. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
  87. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +56 -34
  88. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +50 -4
  89. package/node_modules/@narumitw/pi-btw/package.json +2 -2
  90. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
  91. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  92. package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
  93. package/node_modules/pi-lens/CHANGELOG.md +90 -0
  94. package/node_modules/pi-lens/README.md +106 -0
  95. package/node_modules/pi-lens/dist/clients/bash-file-access.js +97 -6
  96. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +16 -6
  97. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +14 -0
  98. package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
  99. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +22 -1
  100. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
  101. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
  102. package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +8 -10
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +10 -10
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +10 -15
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +19 -11
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +35 -13
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +8 -8
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +110 -23
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +117 -1
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +16 -14
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +8 -9
  119. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +22 -0
  120. package/node_modules/pi-lens/dist/clients/jscpd-client.js +5 -2
  121. package/node_modules/pi-lens/dist/clients/language-profile.js +7 -2
  122. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +27 -2
  123. package/node_modules/pi-lens/dist/clients/lsp/client.js +144 -5
  124. package/node_modules/pi-lens/dist/clients/lsp/index.js +151 -6
  125. package/node_modules/pi-lens/dist/clients/module-report.js +14 -1
  126. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
  127. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +18 -9
  128. package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
  129. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +7 -2
  130. package/node_modules/pi-lens/dist/clients/read-guard.js +88 -19
  131. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
  132. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
  133. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
  134. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +44 -0
  135. package/node_modules/pi-lens/dist/clients/runtime-session.js +41 -0
  136. package/node_modules/pi-lens/dist/clients/runtime-turn.js +47 -2
  137. package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
  138. package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
  139. package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
  140. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
  141. package/node_modules/pi-lens/dist/index.js +1224 -393
  142. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +10 -3
  143. package/node_modules/pi-lens/package.json +18 -5
  144. package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
  145. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
  146. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
  147. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
  148. package/node_modules/pi-web-access/CHANGELOG.md +27 -0
  149. package/node_modules/pi-web-access/README.md +8 -7
  150. package/node_modules/pi-web-access/chrome-cookies.ts +96 -20
  151. package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
  152. package/node_modules/pi-web-access/extract.ts +12 -2
  153. package/node_modules/pi-web-access/firecrawl.ts +18 -2
  154. package/node_modules/pi-web-access/gemini-search.ts +28 -10
  155. package/node_modules/pi-web-access/github-extract.ts +65 -36
  156. package/node_modules/pi-web-access/index.ts +43 -14
  157. package/node_modules/pi-web-access/openai-search.ts +17 -6
  158. package/node_modules/pi-web-access/package.json +1 -1
  159. package/node_modules/pi-web-access/pdf-extract.ts +18 -5
  160. package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
  161. package/package.json +19 -18
@@ -1,4 +1,4 @@
1
- import { ThinkingPreviewBlock } from "../../feature/compact-thinking.ts";
1
+ import { ThinkingPreviewBlock, thinkingRunKey } from "../../feature/compact-thinking.ts";
2
2
  import { hasActiveTextPreview, showTextPreview } from "../../feature/context.ts";
3
3
  import { ToolGroupComponent } from "../tool/grouping.ts";
4
4
  import { isCompactAssistantComponent, setHoveredCompactAssistant } from "../compact-mode.ts";
@@ -58,6 +58,7 @@ import {
58
58
  setHoveredToolCallId,
59
59
  setHoveredToolGroup,
60
60
  setHoveredThinking,
61
+ setHoveredMessageDisplay,
61
62
  setHoveredToolIo,
62
63
  type FullscreenHoverTarget,
63
64
  } from "./hover.ts";
@@ -85,7 +86,8 @@ const TOOL_MOUSE_MOTION_ENABLE = "\x1b[?1003h\x1b[?1006h";
85
86
  const TOOL_MOUSE_MOTION_DISABLE = "\x1b[?1003l";
86
87
  const FULLSCREEN_MOTION_ENABLED = Symbol("ccstyle.fullscreen-motion-enabled");
87
88
  const TOOL_MOUSE_OWNER_KEY = Symbol.for("pi.ccstyle.tool-mouse-owner");
88
- const DEFAULT_TOOL_MOUSE_OWNER = {};
89
+ type ToolMouseOwner = object;
90
+ const DEFAULT_TOOL_MOUSE_OWNER: ToolMouseOwner = {};
89
91
  export const TOOL_MOUSE_DISABLE = "\x1b[?1006l\x1b[?1003l\x1b[?1000l";
90
92
 
91
93
  let toolMouseUi: any = null;
@@ -95,7 +97,7 @@ let toolMouseRenderPatchOriginal: ((...args: any[]) => any) | null = null;
95
97
  let toolMouseRenderPatchWrapper: ((...args: any[]) => any) | null = null;
96
98
  let toolMouseRenderPatchState: { active: boolean } | null = null;
97
99
  let toolMouseRawWrite: ((data: string) => unknown) | null = null;
98
- let toolMouseInstallationOwner: object | null = null;
100
+ let toolMouseInstallationOwner: ToolMouseOwner | null = null;
99
101
  let fullscreenMotionTerminal: any = null;
100
102
  let ownsFullscreenMotion = false;
101
103
  let sessionRenderTimer: ReturnType<typeof setTimeout> | null = null;
@@ -155,13 +157,21 @@ function updateToolSummaryHover(tui: any, packet: SgrMousePacket): void {
155
157
  }
156
158
 
157
159
  const EXPAND_PANEL_DOUBLE_CLICK_MS = 400;
158
- let lastExpandPanelClick: { card: any; at: number } | null = null;
160
+ type ExpandPanelIdentity = string | object;
161
+ let lastExpandPanelClick: { id: ExpandPanelIdentity; at: number } | null = null;
162
+
163
+ function expandPanelIdentity(card: any): ExpandPanelIdentity {
164
+ return card instanceof ThinkingPreviewBlock
165
+ ? thinkingRunKey(card.messageTimestamp, card.runStartIndex)
166
+ : card;
167
+ }
159
168
 
160
169
  function isExpandPanelDoubleClick(card: any): boolean {
161
170
  const now = Date.now();
171
+ const id = expandPanelIdentity(card);
162
172
  const prev = lastExpandPanelClick;
163
- lastExpandPanelClick = { card, at: now };
164
- return Boolean(prev && prev.card === card && now - prev.at <= EXPAND_PANEL_DOUBLE_CLICK_MS);
173
+ lastExpandPanelClick = { id, at: now };
174
+ return Boolean(prev && prev.id === id && now - prev.at <= EXPAND_PANEL_DOUBLE_CLICK_MS);
165
175
  }
166
176
 
167
177
  function clearExpandPanelDoubleClick(): void {
@@ -174,6 +184,7 @@ function collapseExpandedCard(tui: any, card: any): boolean {
174
184
  setHoveredToolCallId(null);
175
185
  setHoveredToolGroup(null);
176
186
  setHoveredThinking(null);
187
+ setHoveredMessageDisplay(null);
177
188
  setHoveredToolIo(null, null);
178
189
  setHoveredCompactAssistant(null);
179
190
  card.invalidate?.();
@@ -346,6 +357,7 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
346
357
  setHoveredToolCallId(null);
347
358
  setHoveredToolGroup(null);
348
359
  setHoveredThinking(null);
360
+ setHoveredMessageDisplay(null);
349
361
  setHoveredToolIo(null, null);
350
362
  setHoveredCompactAssistant(null);
351
363
  card.invalidate?.();
@@ -417,8 +429,7 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
417
429
  // compact 摘要行:折叠时仅提示文字高亮,展开卡整体高亮。
418
430
  if (component.expanded || overHint) target = { kind: "assistant", component };
419
431
  } else if (isMessageDisplayComponent(component)) {
420
- // skill/compaction/branch:折叠只点 hint;展开后双击收起。
421
- if (component.expanded || overHint) target = { kind: "assistant", component };
432
+ if (overHint) target = { kind: "message", component };
422
433
  }
423
434
  }
424
435
  }
@@ -462,7 +473,7 @@ function patchFullscreenViewportInput(tui: any): void {
462
473
  }
463
474
  }
464
475
  }
465
- return Reflect.apply(original, this, [data]);
476
+ return original.apply(this, [data]);
466
477
  };
467
478
  }
468
479
 
@@ -602,7 +613,7 @@ function wrapToolRendersForFrame(
602
613
  ) {
603
614
  const boxOriginal = box.render;
604
615
  const boxWrapped = function (this: any, ...boxArgs: any[]) {
605
- const boxLines = Reflect.apply(boxOriginal, this, boxArgs);
616
+ const boxLines = boxOriginal.apply(this, boxArgs);
606
617
  if (Array.isArray(boxLines)) contentBoxLines = boxLines.length;
607
618
  return boxLines;
608
619
  };
@@ -612,7 +623,7 @@ function wrapToolRendersForFrame(
612
623
  }
613
624
  }
614
625
  try {
615
- const lines = Reflect.apply(originalRender, this, renderArgs);
626
+ const lines = originalRender.apply(this, renderArgs);
616
627
  if (!Array.isArray(lines)) return lines;
617
628
  renderedTools.push({
618
629
  component,
@@ -688,10 +699,10 @@ function patchToolMouseMotionAfterRender(tui: any): void {
688
699
  const rawWrite = typeof terminal?.write === "function" ? terminal.write : undefined;
689
700
  if (typeof original !== "function") return;
690
701
 
691
- toolMouseRawWrite = rawWrite ? (data) => Reflect.apply(rawWrite, terminal, [data]) : null;
702
+ toolMouseRawWrite = rawWrite ? (data) => rawWrite.apply(terminal, [data]) : null;
692
703
  const patchState = { active: true };
693
704
  const wrapper = function (this: any, ...args: any[]) {
694
- if (!patchState.active) return Reflect.apply(original, this, args);
705
+ if (!patchState.active) return original.apply(this, args);
695
706
  const renderedTools: FrameToolRender[] = [];
696
707
  const idToComponent = new Map<number, any>();
697
708
  const frame: IoViewFrameState = {
@@ -708,7 +719,7 @@ function patchToolMouseMotionAfterRender(tui: any): void {
708
719
  let sawTuiRender = false;
709
720
  if (originalTuiRender) {
710
721
  const wrappedTuiRender = function (this: any, ...renderArgs: any[]) {
711
- const lines = Reflect.apply(originalTuiRender, this, renderArgs);
722
+ const lines = originalTuiRender.apply(this, renderArgs);
712
723
  if (!Array.isArray(lines)) return lines;
713
724
  sawTuiRender = true;
714
725
  const extracted = extractToolFramePlacements(
@@ -725,7 +736,7 @@ function patchToolMouseMotionAfterRender(tui: any): void {
725
736
  const previousFrame = getActiveIoViewFrame();
726
737
  setActiveIoViewFrame(frame);
727
738
  try {
728
- const result = Reflect.apply(original, this, args);
739
+ const result = original.apply(this, args);
729
740
  succeeded = true;
730
741
  // Test harnesses may paint via doRender without tui.render; recover markers there.
731
742
  if (!sawTuiRender && Array.isArray(this.previousLines)) {
@@ -802,7 +813,7 @@ function handleToolMouseInput(data: string): { consume: true } | undefined {
802
813
  }
803
814
 
804
815
  export function teardownToolMouseInteraction(
805
- owner: object = toolMouseInstallationOwner ?? DEFAULT_TOOL_MOUSE_OWNER,
816
+ owner: ToolMouseOwner = toolMouseInstallationOwner ?? DEFAULT_TOOL_MOUSE_OWNER,
806
817
  ): void {
807
818
  const host = globalThis as any;
808
819
  if (host[TOOL_MOUSE_OWNER_KEY] && host[TOOL_MOUSE_OWNER_KEY] !== owner) return;
@@ -815,6 +826,7 @@ export function teardownToolMouseInteraction(
815
826
  setHoveredToolCallId(null);
816
827
  setHoveredToolGroup(null);
817
828
  setHoveredThinking(null);
829
+ setHoveredMessageDisplay(null);
818
830
  setHoveredToolIo(null, null);
819
831
  setHoveredCompactAssistant(null);
820
832
  clearExpandPanelDoubleClick();
@@ -842,6 +854,7 @@ export function teardownToolMouseInteraction(
842
854
  export function resetToolHoverState(): void {
843
855
  setHoveredToolCallId(null);
844
856
  setHoveredThinking(null);
857
+ setHoveredMessageDisplay(null);
845
858
  setHoveredCompactAssistant(null);
846
859
  setScrollButtonVisible(false);
847
860
  setScrollButtonHovered(false);
@@ -850,7 +863,7 @@ export function resetToolHoverState(): void {
850
863
 
851
864
  export function installToolMouseInteraction(
852
865
  ctx: any,
853
- owner: object = DEFAULT_TOOL_MOUSE_OWNER,
866
+ owner: ToolMouseOwner = DEFAULT_TOOL_MOUSE_OWNER,
854
867
  ): void {
855
868
  teardownToolMouseInteraction(toolMouseInstallationOwner ?? owner);
856
869
  if (ctx?.mode !== "tui" || !ctx?.hasUI) return;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herbertgao/pi-cc-extensions",
3
- "version": "0.8.56",
3
+ "version": "0.8.58",
4
4
  "license": "MIT",
5
5
  "description": "A Pi productivity suite with Claude Code-style UI, context inspection, and agent/session references",
6
6
  "type": "module",
@@ -69,8 +69,8 @@
69
69
  },
70
70
  "x-upstream": {
71
71
  "package": "pi-cc-extensions",
72
- "version": "0.8.63",
72
+ "version": "0.8.66",
73
73
  "repository": "https://github.com/minuque/pi-cc-extensions",
74
- "commit": "6b7447eb9d82afa9ea26dd7433c59ff56663098e"
74
+ "commit": "e971a39d1685590de81bd445e3a829279d216039"
75
75
  }
76
76
  }
@@ -1,5 +1,34 @@
1
1
  # @tifan/pi-handoff
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#116](https://github.com/HerbertGao/pi-extensions/pull/116) [`ecda398`](https://github.com/HerbertGao/pi-extensions/commit/ecda398b9a95212c512d53325c617e485e6ded8d) Thanks [@HerbertGao](https://github.com/HerbertGao)! - Adopt prompt-marker handoffs that generate a handoff artifact and start a clean session, while retaining the session query tool and local rename package integration.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`ecda398`](https://github.com/HerbertGao/pi-extensions/commit/ecda398b9a95212c512d53325c617e485e6ded8d)]:
12
+ - @herbertgao/pi-rename@0.5.0
13
+
14
+ ## 2.0.1
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [[`b2ea184`](https://github.com/tifandotme/pi-extensions/commit/b2ea1841e99243aa4773bd5c33f43c40248859db)]:
19
+ - @tifan/pi-rename@0.5.0
20
+
21
+ ## 2.0.0
22
+
23
+ ### Major Changes
24
+
25
+ - [`297e825`](https://github.com/tifandotme/pi-extensions/commit/297e825ba42eeed32814a34cd4fe5bdbe935b11c) Thanks [@tifandotme](https://github.com/tifandotme)! - Replace `/handoff-session` with the `-handoff` prompt marker and automatically start the new session from the generated handoff.
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies [[`e8709bc`](https://github.com/tifandotme/pi-extensions/commit/e8709bc388aa8e094918ec465cfab511358f18ff)]:
30
+ - @tifan/pi-rename@0.4.3
31
+
3
32
  ## 1.1.2
4
33
 
5
34
  ### Patch Changes
@@ -10,42 +10,39 @@ Start a fresh pi session from a handoff document, and query past sessions for co
10
10
  pi install npm:@herbertgao/pi-handoff
11
11
  ```
12
12
 
13
- For local development:
13
+ ## Requirements
14
+
15
+ Matt Pocock's [`handoff` skill](https://github.com/mattpocock/skills/blob/main/skills/productivity/handoff/SKILL.md) is required:
14
16
 
15
17
  ```bash
16
- pi install /absolute/path/to/pi-extensions/packages/pi-handoff
18
+ npx skills add https://github.com/mattpocock/skills --global --skill handoff
17
19
  ```
18
20
 
19
- You also need a `handoff` skill installed and discoverable by pi. For example, install or expose Matt Pocock's `handoff` skill, then run `/reload`.
20
-
21
21
  ## How it works
22
22
 
23
- Run `/handoff-session` to generate a handoff document from the current session and start a clean session from it. The command asks what the next session is for, uses the installed `handoff` skill as the document policy, and writes the handoff under the OS temp directory.
23
+ Submit a prompt containing a standalone `-handoff` marker to generate a handoff document from the current session and automatically start a clean session from it. The marker can appear anywhere in the prompt. The handoff is written under the OS temp directory.
24
24
 
25
- The new session name is generated from the current conversation using pi-rename-style rules: lowercase, hyphen-separated, and under 60 characters. Naming uses `openai-codex/gpt-5.6-luna` when available, with a local fallback. The focus answer is used for the handoff document, not for the session name. The prompt is left in the editor for review and manual submit.
25
+ The new session name uses the current session name when available. Otherwise, it uses the next-session focus, sanitized to lowercase, hyphen-separated text under 60 characters.
26
26
 
27
27
  The handoff includes the previous session path when available, so the next agent can use `session_query` if the handoff omits a detail.
28
28
 
29
- ## Commands
29
+ ## Usage
30
30
 
31
- - `/handoff-session`: Generate a handoff from the current session and start a renamed session from it.
31
+ ```text
32
+ fix the auth flow -handoff
33
+ ```
32
34
 
33
- ## Tools
35
+ The standalone `-handoff` marker is consumed before the prompt reaches the agent. The text before and after it becomes the next-session focus. A prompt containing only `-handoff` continues the current work.
34
36
 
35
- - `session_query`: Answer a question about a previous pi session, given the full path to its `.jsonl` file and the question to ask.
37
+ ## `session_query`
36
38
 
37
- ## Behavior
39
+ `session_query`: Answer a question about a previous pi session, given the full path to its `.jsonl` file and the question to ask. It uses the configured `openai-codex/gpt-5.6-luna` model, which must be available and authenticated.
38
40
 
39
- - Uses the current selected model to generate the handoff document.
40
- - Uses `openai-codex/gpt-5.6-luna` to name the new pi session when available.
41
- - Requires a discoverable skill named exactly `handoff`.
42
- - Writes stable, readable files under the OS temp directory, such as `/tmp/pi-handoffs/pi-handoff-2026-06-01-inline-skills.md`.
43
- - Starts a clean session with native parent-session linking.
44
- - Does not autosend.
41
+ Pi provides session loading and compaction-aware context reconstruction, but not semantic questions about an arbitrary previous session. `session_query` supplies that model-powered query layer.
45
42
 
46
43
  ## Release notes
47
44
 
48
- See [CHANGELOG.md](CHANGELOG.md)
45
+ See [CHANGELOG.md](CHANGELOG.md).
49
46
 
50
47
  ## License
51
48
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herbertgao/pi-handoff",
3
- "version": "1.1.2",
3
+ "version": "2.0.0",
4
4
  "description": "Transfer pi session context to a new session and query past sessions.",
5
5
  "keywords": [
6
6
  "handoff",
@@ -33,7 +33,14 @@
33
33
  "provenance": true
34
34
  },
35
35
  "dependencies": {
36
- "@herbertgao/pi-rename": "^0.4.2"
36
+ "@herbertgao/pi-rename": "^0.5.0",
37
+ "typebox": "^1.1.38"
38
+ },
39
+ "peerDependencies": {
40
+ "@earendil-works/pi-agent-core": ">=0.84.2",
41
+ "@earendil-works/pi-ai": ">=0.84.2",
42
+ "@earendil-works/pi-coding-agent": ">=0.84.2",
43
+ "@earendil-works/pi-tui": ">=0.84.2"
37
44
  },
38
45
  "engines": {
39
46
  "node": ">=20"
@@ -46,8 +53,8 @@
46
53
  },
47
54
  "x-upstream": {
48
55
  "package": "@tifan/pi-handoff",
49
- "version": "1.1.2",
56
+ "version": "2.0.1",
50
57
  "repository": "https://github.com/tifandotme/pi-extensions",
51
- "commit": "460d580"
58
+ "commit": "3f6b5e628e31817960a02cfae9bcb4a3f4bcd79b"
52
59
  }
53
60
  }
@@ -0,0 +1,33 @@
1
+ import { complete, type Message } from "@earendil-works/pi-ai/compat"
2
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent"
3
+
4
+ export async function completeText(
5
+ ctx: Pick<ExtensionContext, "modelRegistry">,
6
+ model: NonNullable<ExtensionContext["model"]>,
7
+ systemPrompt: string,
8
+ message: Message,
9
+ signal?: AbortSignal,
10
+ ): Promise<string | null> {
11
+ const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model)
12
+ if (!auth.ok) throw new Error(auth.error)
13
+
14
+ const response = await complete(
15
+ model,
16
+ { systemPrompt, messages: [message] },
17
+ {
18
+ ...(auth.apiKey ? { apiKey: auth.apiKey } : {}),
19
+ ...(auth.headers ? { headers: auth.headers } : {}),
20
+ ...(signal ? { signal } : {}),
21
+ },
22
+ )
23
+
24
+ if (response.stopReason === "aborted") return null
25
+
26
+ return response.content
27
+ .filter((content): content is { type: "text"; text: string } => {
28
+ return content.type === "text"
29
+ })
30
+ .map((content) => content.text)
31
+ .join("\n")
32
+ .trim()
33
+ }