pi-cc-extensions 0.5.0 → 0.5.2

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.
@@ -320,6 +320,9 @@ const TOOL_MOUSE_DISABLE = "\x1b[?1006l\x1b[?1000l";
320
320
  let toolMouseTui: any = null;
321
321
  let toolMouseUi: any = null;
322
322
  let toolMouseInputUnsubscribe: (() => void) | null = null;
323
+ let toolMouseInputPatchTui: any = null;
324
+ let toolMouseInputPatchOriginalAdd: ((...args: any[]) => any) | null = null;
325
+ let toolMouseInputPatchWrapper: ((...args: any[]) => any) | null = null;
323
326
 
324
327
  function parseSgrMousePackets(data: string): SgrMousePacket[] | null {
325
328
  const pattern = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
@@ -441,19 +444,75 @@ function toggleToolAtMouseClick(tui: any, packet: SgrMousePacket): boolean {
441
444
  return true;
442
445
  }
443
446
 
447
+ /**
448
+ * Pi TUI input listeners are ordered by registration. pi-zentui's fixed editor
449
+ * consumes left-button presses for selection, so a later click listener never
450
+ * sees tool rows. Keep this handler first while still returning undefined for
451
+ * scroll/selection events so pi-zentui remains the owner of those interactions.
452
+ */
453
+ function prioritizeToolMouseInput(tui: any): void {
454
+ const listeners = tui?.inputListeners;
455
+ if (!(listeners instanceof Set) || !listeners.has(handleToolMouseInput)) return;
456
+
457
+ const ordered = Array.from(listeners);
458
+ if (ordered[0] === handleToolMouseInput) return;
459
+ listeners.clear();
460
+ listeners.add(handleToolMouseInput);
461
+ for (const listener of ordered) {
462
+ if (listener !== handleToolMouseInput) listeners.add(listener);
463
+ }
464
+ }
465
+
466
+ function patchToolMouseInputPriority(tui: any): void {
467
+ if (toolMouseInputPatchTui === tui) {
468
+ prioritizeToolMouseInput(tui);
469
+ return;
470
+ }
471
+
472
+ restoreToolMouseInputPriority();
473
+ const originalAdd = tui?.addInputListener;
474
+ if (typeof originalAdd !== "function") return;
475
+
476
+ const wrapper = function (this: any, ...args: any[]): any {
477
+ const result = Reflect.apply(originalAdd, this, args);
478
+ prioritizeToolMouseInput(this);
479
+ return result;
480
+ };
481
+ tui.addInputListener = wrapper;
482
+ toolMouseInputPatchTui = tui;
483
+ toolMouseInputPatchOriginalAdd = originalAdd;
484
+ toolMouseInputPatchWrapper = wrapper;
485
+ prioritizeToolMouseInput(tui);
486
+ }
487
+
488
+ function restoreToolMouseInputPriority(): void {
489
+ if (
490
+ toolMouseInputPatchTui
491
+ && toolMouseInputPatchOriginalAdd
492
+ && toolMouseInputPatchTui.addInputListener === toolMouseInputPatchWrapper
493
+ ) {
494
+ toolMouseInputPatchTui.addInputListener = toolMouseInputPatchOriginalAdd;
495
+ }
496
+ toolMouseInputPatchTui = null;
497
+ toolMouseInputPatchOriginalAdd = null;
498
+ toolMouseInputPatchWrapper = null;
499
+ }
500
+
444
501
  function handleToolMouseInput(data: string): { consume: true } | undefined {
445
502
  if (!toolMouseTui) return undefined;
446
503
  const packets = parseSgrMousePackets(data);
447
504
  if (!packets) return undefined;
448
505
 
506
+ let consumed = false;
449
507
  for (const packet of packets) {
450
- if (isSgrLeftPress(packet)) {
451
- toggleToolAtMouseClick(toolMouseTui, packet);
508
+ if (isSgrLeftPress(packet) && toggleToolAtMouseClick(toolMouseTui, packet)) {
509
+ consumed = true;
452
510
  }
453
511
  }
454
- // The default editor cannot interpret mouse escape sequences. Consume them
455
- // even when the click was outside a tool result.
456
- return { consume: true };
512
+
513
+ // Let scrolling, motion, release, and clicks outside tool results reach the
514
+ // normal TUI input chain (including other extensions such as pi-zentui).
515
+ return consumed ? { consume: true } : undefined;
457
516
  }
458
517
 
459
518
  function teardownToolMouseInteraction(): void {
@@ -469,6 +528,7 @@ function teardownToolMouseInteraction(): void {
469
528
  } catch {
470
529
  // The UI context may already have been reset during /reload.
471
530
  }
531
+ restoreToolMouseInputPriority();
472
532
  toolMouseTui = null;
473
533
  toolMouseUi = null;
474
534
  }
@@ -481,6 +541,7 @@ function installToolMouseInteraction(ctx: any): void {
481
541
  toolMouseUi = ctx.ui;
482
542
  ctx.ui.setWidget(TOOL_MOUSE_WIDGET_KEY, (tui: any) => {
483
543
  toolMouseTui = tui;
544
+ patchToolMouseInputPriority(tui);
484
545
  tui?.terminal?.write?.(TOOL_MOUSE_ENABLE);
485
546
  // Keep the widget visually empty so Pi's default input bar/layout remains.
486
547
  return { render: () => [], invalidate() {} };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Personal extensions for the Pi coding agent",
5
5
  "type": "module",
6
6
  "keywords": [