@esso0428/pi-subagents 0.17.22 → 0.17.23
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.
- package/CHANGELOG.md +5 -0
- package/package.json +1 -1
- package/src/ui/agent-widget.ts +29 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.17.23] - 2026-10-02
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Stopped the agents roster from stealing keys from open modals**: the widget's focus detection used `focused instanceof Editor`, which is always false when the extension resolves its own copy of `@earendil-works/pi-tui` at a different version than pi's host (for example a hoisted peer pinned to an older release). The check silently degraded to "focused is null", so the widget's global `onTerminalInput` listener claimed the keyboard during teardown and transient render states and consumed `↑`/`↓`/`enter`/`escape` from modals such as the `/agents` menus. Focus detection now identifies the prompt editor structurally and fails closed, so the listener only claims input while the editor provably owns it.
|
|
14
|
+
|
|
10
15
|
## [0.17.22] - 2026-10-01
|
|
11
16
|
|
|
12
17
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@esso0428/pi-subagents",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.23",
|
|
4
4
|
"description": "A pi extension that brings smart Claude Code-style autonomous sub-agents to pi, with npm:pi-subagents-style JSON agent overrides.",
|
|
5
5
|
"author": "ESSO0428",
|
|
6
6
|
"repository": {
|
package/src/ui/agent-widget.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Uses the callback form of setWidget for themed rendering.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { isKeyRelease, Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
9
9
|
import type { AgentManager } from "../agent-manager.js";
|
|
10
10
|
import { getConfig } from "../agent-types.js";
|
|
11
11
|
import type { AgentInvocation, AgentRecord, SubagentType, WidgetMode } from "../types.js";
|
|
@@ -238,6 +238,24 @@ export function describeActivity(activeTools: Map<string, string>, responseText?
|
|
|
238
238
|
return "thinking…";
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Structural check for pi's prompt editor.
|
|
243
|
+
*
|
|
244
|
+
* `instanceof Editor` is unusable here: an extension can resolve its own copy
|
|
245
|
+
* of `@earendil-works/pi-tui` at a different version than the host's, and the
|
|
246
|
+
* two `Editor` class objects are then unrelated identities, so the check is
|
|
247
|
+
* always false. Modals opened with `ctx.ui.custom()` — including the `/agents`
|
|
248
|
+
* menus — focus a plain `{ render, invalidate, handleInput }` object instead,
|
|
249
|
+
* so the editor's text-buffer methods identify it across pi-tui copies.
|
|
250
|
+
*/
|
|
251
|
+
function isPromptEditor(component: unknown): boolean {
|
|
252
|
+
if (typeof component !== "object" || component === null) return false;
|
|
253
|
+
const candidate = component as { getText?: unknown; setText?: unknown; submitValue?: unknown };
|
|
254
|
+
return typeof candidate.getText === "function"
|
|
255
|
+
&& typeof candidate.setText === "function"
|
|
256
|
+
&& typeof candidate.submitValue === "function";
|
|
257
|
+
}
|
|
258
|
+
|
|
241
259
|
// ---- Widget manager ----
|
|
242
260
|
|
|
243
261
|
export class AgentWidget {
|
|
@@ -373,10 +391,17 @@ export class AgentWidget {
|
|
|
373
391
|
return [...running, ...queued, ...finished];
|
|
374
392
|
}
|
|
375
393
|
|
|
376
|
-
/**
|
|
394
|
+
/**
|
|
395
|
+
* True when pi's prompt editor owns the keyboard.
|
|
396
|
+
*
|
|
397
|
+
* Deliberately fails closed: an unknown or absent focus target means the
|
|
398
|
+
* widget does not own the keyboard, so its global terminal listener stays out
|
|
399
|
+
* of the way. The previous `focused == null` fallback claimed input during
|
|
400
|
+
* teardown and transient render states, which let roster navigation swallow
|
|
401
|
+
* ↑/↓/enter/escape from an open modal.
|
|
402
|
+
*/
|
|
377
403
|
private editorHasFocus(): boolean {
|
|
378
|
-
|
|
379
|
-
return focused == null || focused instanceof Editor;
|
|
404
|
+
return isPromptEditor((this.tui as { focusedComponent?: unknown } | undefined)?.focusedComponent);
|
|
380
405
|
}
|
|
381
406
|
|
|
382
407
|
private selectedIndexOf(records: readonly AgentRecord[]): number {
|