@esso0428/pi-subagents 0.15.17 → 0.17.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.
- package/CHANGELOG.md +17 -0
- package/README.md +10 -12
- package/dist/agent-history-list.d.ts.map +1 -1
- package/dist/agent-history-list.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -40
- package/dist/index.js.map +1 -1
- package/dist/output-file.js +3 -3
- package/dist/output-file.js.map +1 -1
- package/dist/settings.d.ts +1 -8
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +0 -5
- package/dist/settings.js.map +1 -1
- package/dist/ui/agent-widget.d.ts +66 -28
- package/dist/ui/agent-widget.d.ts.map +1 -1
- package/dist/ui/agent-widget.js +325 -134
- package/dist/ui/agent-widget.js.map +1 -1
- package/dist/ui/ccstyle/diff/ansi-utils.js +2 -2
- package/dist/ui/ccstyle/diff/ansi-utils.js.map +1 -1
- package/dist/ui/ccstyle/diff/diff-presentation.d.ts.map +1 -1
- package/dist/ui/ccstyle/diff/diff-presentation.js +0 -1
- package/dist/ui/ccstyle/diff/diff-presentation.js.map +1 -1
- package/dist/ui/ccstyle/diff/diff-renderer.d.ts +1 -1
- package/dist/ui/ccstyle/diff/diff-renderer.d.ts.map +1 -1
- package/dist/ui/ccstyle/diff/diff-renderer.js +15 -10
- package/dist/ui/ccstyle/diff/diff-renderer.js.map +1 -1
- package/dist/ui/ccstyle/diff/line-width-safety.d.ts.map +1 -1
- package/dist/ui/ccstyle/diff/line-width-safety.js +1 -2
- package/dist/ui/ccstyle/diff/line-width-safety.js.map +1 -1
- package/dist/ui/ccstyle/diff/shiki-highlight.d.ts +19 -0
- package/dist/ui/ccstyle/diff/shiki-highlight.d.ts.map +1 -0
- package/dist/ui/ccstyle/diff/shiki-highlight.js +85 -0
- package/dist/ui/ccstyle/diff/shiki-highlight.js.map +1 -0
- package/dist/ui/ccstyle/tool-renderer.d.ts +1 -1
- package/dist/ui/ccstyle/tool-renderer.d.ts.map +1 -1
- package/dist/ui/ccstyle/tool-renderer.js +1 -1
- package/dist/ui/ccstyle/tool-renderer.js.map +1 -1
- package/dist/ui/ccstyle/tool-result.d.ts +9 -1
- package/dist/ui/ccstyle/tool-result.d.ts.map +1 -1
- package/dist/ui/ccstyle/tool-result.js +137 -5
- package/dist/ui/ccstyle/tool-result.js.map +1 -1
- package/dist/ui/conversation-blocks.d.ts.map +1 -1
- package/dist/ui/conversation-blocks.js +14 -13
- package/dist/ui/conversation-blocks.js.map +1 -1
- package/dist/ui/conversation-role.d.ts +1 -1
- package/dist/ui/conversation-role.d.ts.map +1 -1
- package/dist/ui/conversation-search.js +4 -4
- package/dist/ui/conversation-search.js.map +1 -1
- package/dist/ui/conversation-timeline.d.ts +17 -1
- package/dist/ui/conversation-timeline.d.ts.map +1 -1
- package/dist/ui/conversation-timeline.js +116 -43
- package/dist/ui/conversation-timeline.js.map +1 -1
- package/dist/ui/conversation-viewer.d.ts +5 -1
- package/dist/ui/conversation-viewer.d.ts.map +1 -1
- package/dist/ui/conversation-viewer.js +67 -26
- package/dist/ui/conversation-viewer.js.map +1 -1
- package/dist/write-execution.d.ts.map +1 -1
- package/dist/write-execution.js +1 -1
- package/dist/write-execution.js.map +1 -1
- package/package.json +6 -5
- package/src/agent-history-list.ts +1 -1
- package/src/index.ts +19 -73
- package/src/output-file.ts +3 -3
- package/src/settings.ts +1 -12
- package/src/ui/agent-widget.ts +264 -114
- package/src/ui/ccstyle/diff/ansi-utils.ts +2 -2
- package/src/ui/ccstyle/diff/diff-presentation.ts +0 -1
- package/src/ui/ccstyle/diff/diff-renderer.ts +22 -21
- package/src/ui/ccstyle/diff/line-width-safety.ts +1 -2
- package/src/ui/ccstyle/diff/shiki-highlight.ts +97 -0
- package/src/ui/ccstyle/tool-renderer.ts +3 -3
- package/src/ui/ccstyle/tool-result.ts +175 -7
- package/src/ui/conversation-role.ts +1 -1
- package/src/ui/conversation-search.ts +4 -4
- package/src/ui/conversation-timeline.ts +7 -7
- package/src/ui/conversation-viewer.ts +16 -7
- package/src/write-execution.ts +2 -2
- package/dist/ui/fleet-list.d.ts +0 -122
- package/dist/ui/fleet-list.d.ts.map +0 -1
- package/dist/ui/fleet-list.js +0 -375
- package/dist/ui/fleet-list.js.map +0 -1
- package/src/ui/deferred-ui-refresh.ts +0 -72
- package/src/ui/fleet-list.ts +0 -585
- package/test/agent-history-list.test.ts +0 -121
- package/test/agent-manager-history.test.ts +0 -88
- package/test/agent-menu-history-navigation.test.ts +0 -86
- package/test/output-file-history.test.ts +0 -50
- package/test/ui/agent-widget.test.ts +0 -172
- package/test/ui/conversation-blocks.test.ts +0 -103
- package/test/ui/conversation-diff.test.ts +0 -91
- package/test/ui/conversation-search.test.ts +0 -55
- package/test/ui/conversation-viewer.test.ts +0 -438
- package/test/ui/deferred-ui-refresh.test.ts +0 -55
- package/test/ui/fleet-list.test.ts +0 -389
- package/test/write-execution.test.ts +0 -83
- package/tsconfig.json +0 -16
package/dist/ui/fleet-list.d.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* fleet-list.ts — Claude Code-style "FleetView" list rendered below the editor.
|
|
3
|
-
*
|
|
4
|
-
* Shows `main` + each running/queued subagent as a navigable list. Pressing ↓ (or
|
|
5
|
-
* ←) at an empty prompt activates the list; ↑/↓ move the selection (filled ● marker),
|
|
6
|
-
* Enter opens the selected agent's live conversation overlay, Esc returns to the prompt.
|
|
7
|
-
* A viewer stays open when its agent finishes so the final output remains readable.
|
|
8
|
-
*
|
|
9
|
-
* Mechanics (see plan): the list is a `belowEditor` widget (render-only), and ALL key
|
|
10
|
-
* handling goes through `onTerminalInput` — which fires before the focused editor and
|
|
11
|
-
* can `consume` keys — gated on `getEditorText() === ""` so normal typing is untouched.
|
|
12
|
-
*/
|
|
13
|
-
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
14
|
-
import type { AgentManager } from "../agent-manager.js";
|
|
15
|
-
import { type AgentActivity, type Theme } from "./agent-widget.js";
|
|
16
|
-
/** Maximum total rows contributed by FleetView, including hint and indicators. */
|
|
17
|
-
export declare const FLEET_MAX_RENDER_ROWS = 6;
|
|
18
|
-
/** Minimal UI surface the FleetView needs from `ctx.ui` (structural subset). */
|
|
19
|
-
export type FleetUICtx = {
|
|
20
|
-
setWidget(key: string, content: undefined | ((tui: any, theme: Theme) => {
|
|
21
|
-
render(width: number): string[];
|
|
22
|
-
invalidate(): void;
|
|
23
|
-
dispose?(): void;
|
|
24
|
-
}), options?: {
|
|
25
|
-
placement?: "aboveEditor" | "belowEditor";
|
|
26
|
-
}): void;
|
|
27
|
-
onTerminalInput(handler: (data: string) => {
|
|
28
|
-
consume?: boolean;
|
|
29
|
-
data?: string;
|
|
30
|
-
} | undefined): () => void;
|
|
31
|
-
getEditorText(): string;
|
|
32
|
-
notify(message: string, type?: "info" | "warning" | "error"): void;
|
|
33
|
-
custom<T>(factory: (tui: any, theme: Theme, keybindings: any, done: (result: T) => void) => {
|
|
34
|
-
render(width: number): string[];
|
|
35
|
-
invalidate(): void;
|
|
36
|
-
dispose?(): void;
|
|
37
|
-
}, options?: {
|
|
38
|
-
overlay?: boolean;
|
|
39
|
-
overlayOptions?: unknown;
|
|
40
|
-
onHandle?: (handle: unknown) => void;
|
|
41
|
-
}): Promise<T>;
|
|
42
|
-
};
|
|
43
|
-
/** `11s` — integer seconds, no decimal/suffix (matches Claude Code, unlike formatMs). */
|
|
44
|
-
export declare function formatFleetElapsed(ms: number): string;
|
|
45
|
-
/** `↓ 13.1k tokens` — down-arrow prefix, compact magnitude, plural "tokens". */
|
|
46
|
-
export declare function formatFleetTokens(count: number): string;
|
|
47
|
-
/**
|
|
48
|
-
* Calculate a bounded agent slice for the complete logical roster.
|
|
49
|
-
* `selectedRosterIndex` includes main at index 0; `end` is exclusive.
|
|
50
|
-
*/
|
|
51
|
-
export declare function calculateFleetAgentWindow(agentCount: number, selectedRosterIndex: number): {
|
|
52
|
-
start: number;
|
|
53
|
-
end: number;
|
|
54
|
-
hiddenAbove: number;
|
|
55
|
-
hiddenBelow: number;
|
|
56
|
-
};
|
|
57
|
-
export declare class FleetList {
|
|
58
|
-
private manager;
|
|
59
|
-
private agentActivity;
|
|
60
|
-
private getCwd;
|
|
61
|
-
private pi?;
|
|
62
|
-
private getCtx;
|
|
63
|
-
private ui;
|
|
64
|
-
private tui;
|
|
65
|
-
private inputUnsub;
|
|
66
|
-
private widgetRegistered;
|
|
67
|
-
private lastRosterKey;
|
|
68
|
-
private timer;
|
|
69
|
-
private enabled;
|
|
70
|
-
/** Whether arrow keys currently navigate the list (vs. flow to the editor). */
|
|
71
|
-
private active;
|
|
72
|
-
/** 0 = `main`, 1..N = subagents. */
|
|
73
|
-
private selectedIndex;
|
|
74
|
-
/** Set while a conversation overlay is open; calling it closes the overlay. */
|
|
75
|
-
private viewerClose;
|
|
76
|
-
private viewingAgentId;
|
|
77
|
-
constructor(manager: AgentManager, agentActivity: Map<string, AgentActivity>, getCwd?: () => string | undefined, pi?: ExtensionAPI | undefined, getCtx?: () => ExtensionContext | undefined);
|
|
78
|
-
setEnabled(enabled: boolean): void;
|
|
79
|
-
/** Capture the UI context and (re)register the global input handler. */
|
|
80
|
-
setUICtx(ui: FleetUICtx): void;
|
|
81
|
-
/** Ensure the re-render timer is running (called when an agent spawns). */
|
|
82
|
-
ensureTimer(): void;
|
|
83
|
-
/**
|
|
84
|
-
* Called when an agent finishes. The viewer (if open on it) stays open so the
|
|
85
|
-
* final output remains readable; refresh the active-only roster.
|
|
86
|
-
*/
|
|
87
|
-
onAgentFinished(_id: string): void;
|
|
88
|
-
dispose(): void;
|
|
89
|
-
/** Re-register/refresh the below-editor widget; clears it when no agents remain. */
|
|
90
|
-
update(): void;
|
|
91
|
-
/**
|
|
92
|
-
* Active agents shown in the list, ordered earliest-launched first so the
|
|
93
|
-
* ones you started sooner sit at the top. Pending agents with no session yet
|
|
94
|
-
* are hidden until they start. (`listAgents()` is newest-first, so we
|
|
95
|
-
* re-sort.)
|
|
96
|
-
*/
|
|
97
|
-
private agentRecords;
|
|
98
|
-
private roster;
|
|
99
|
-
private clampSelection;
|
|
100
|
-
/** Returns `{consume:true}` to swallow a key, or undefined to let it through. */
|
|
101
|
-
handleKey(data: string): {
|
|
102
|
-
consume?: boolean;
|
|
103
|
-
data?: string;
|
|
104
|
-
} | undefined;
|
|
105
|
-
/**
|
|
106
|
-
* True when pi's prompt editor owns the keyboard. pi's editor is an `Editor`
|
|
107
|
-
* subclass (CustomEditor) while every dialog/selector is not, and the loader
|
|
108
|
-
* aliases pi-tui to pi's own copy, so `instanceof` is a reliable identity
|
|
109
|
-
* check. `focusedComponent` is TUI-private (no public accessor), hence the
|
|
110
|
-
* best-effort peek: unknowable focus (no tui seen yet, nothing focused)
|
|
111
|
-
* counts as the editor so activation keeps working.
|
|
112
|
-
*/
|
|
113
|
-
private editorHasFocus;
|
|
114
|
-
private deactivate;
|
|
115
|
-
private openSelected;
|
|
116
|
-
/** Reset overlay state and return to the list (on close, auto-close, or error). */
|
|
117
|
-
private clearViewer;
|
|
118
|
-
private renderBar;
|
|
119
|
-
private bullet;
|
|
120
|
-
private renderAgentRow;
|
|
121
|
-
}
|
|
122
|
-
//# sourceMappingURL=fleet-list.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-list.d.ts","sourceRoot":"","sources":["../../src/ui/fleet-list.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/fleet-list.js
DELETED
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* fleet-list.ts — Claude Code-style "FleetView" list rendered below the editor.
|
|
3
|
-
*
|
|
4
|
-
* Shows `main` + each running/queued subagent as a navigable list. Pressing ↓ (or
|
|
5
|
-
* ←) at an empty prompt activates the list; ↑/↓ move the selection (filled ● marker),
|
|
6
|
-
* Enter opens the selected agent's live conversation overlay, Esc returns to the prompt.
|
|
7
|
-
* A viewer stays open when its agent finishes so the final output remains readable.
|
|
8
|
-
*
|
|
9
|
-
* Mechanics (see plan): the list is a `belowEditor` widget (render-only), and ALL key
|
|
10
|
-
* handling goes through `onTerminalInput` — which fires before the focused editor and
|
|
11
|
-
* can `consume` keys — gated on `getEditorText() === ""` so normal typing is untouched.
|
|
12
|
-
*/
|
|
13
|
-
import { Editor, isKeyRelease, Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
14
|
-
import { canOpenActiveAgent } from "../agent-history-list.js";
|
|
15
|
-
import { getLifetimeTotal } from "../usage.js";
|
|
16
|
-
import { getDisplayName } from "./agent-widget.js";
|
|
17
|
-
import { ConversationViewer, VIEWPORT_HEIGHT_PCT } from "./conversation-viewer.js";
|
|
18
|
-
/** Widget key for the below-editor fleet list. */
|
|
19
|
-
const FLEET_KEY = "fleet";
|
|
20
|
-
/** Maximum total rows contributed by FleetView, including hint and indicators. */
|
|
21
|
-
export const FLEET_MAX_RENDER_ROWS = 6;
|
|
22
|
-
const FLEET_BASE_ROWS = 2; // hint + main
|
|
23
|
-
const FLEET_BODY_ROWS = FLEET_MAX_RENDER_ROWS - FLEET_BASE_ROWS;
|
|
24
|
-
/** Re-render cadence so elapsed/token stats tick while agents run. */
|
|
25
|
-
const TICK_MS = 200;
|
|
26
|
-
/** `11s` — integer seconds, no decimal/suffix (matches Claude Code, unlike formatMs). */
|
|
27
|
-
export function formatFleetElapsed(ms) {
|
|
28
|
-
return `${Math.max(0, Math.round(ms / 1000))}s`;
|
|
29
|
-
}
|
|
30
|
-
/** `↓ 13.1k tokens` — down-arrow prefix, compact magnitude, plural "tokens". */
|
|
31
|
-
export function formatFleetTokens(count) {
|
|
32
|
-
let compact;
|
|
33
|
-
if (count >= 1_000_000)
|
|
34
|
-
compact = `${(count / 1_000_000).toFixed(1)}M`;
|
|
35
|
-
else if (count >= 1_000)
|
|
36
|
-
compact = `${(count / 1_000).toFixed(1)}k`;
|
|
37
|
-
else
|
|
38
|
-
compact = `${count}`;
|
|
39
|
-
return `↓ ${compact} tokens`;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Calculate a bounded agent slice for the complete logical roster.
|
|
43
|
-
* `selectedRosterIndex` includes main at index 0; `end` is exclusive.
|
|
44
|
-
*/
|
|
45
|
-
export function calculateFleetAgentWindow(agentCount, selectedRosterIndex) {
|
|
46
|
-
const count = Math.max(0, Math.floor(agentCount));
|
|
47
|
-
if (count === 0)
|
|
48
|
-
return { start: 0, end: 0, hiddenAbove: 0, hiddenBelow: 0 };
|
|
49
|
-
const selectedAgent = Math.min(count - 1, Math.max(0, Math.floor(selectedRosterIndex) - 1));
|
|
50
|
-
const reserveAbove = selectedAgent > 0 ? 1 : 0;
|
|
51
|
-
const reserveBelow = selectedAgent < count - 1 ? 1 : 0;
|
|
52
|
-
const visibleCount = Math.max(1, FLEET_BODY_ROWS - reserveAbove - reserveBelow);
|
|
53
|
-
const start = Math.min(Math.max(0, selectedAgent - visibleCount + 1), Math.max(0, count - visibleCount));
|
|
54
|
-
const end = Math.min(count, start + visibleCount);
|
|
55
|
-
return { start, end, hiddenAbove: start, hiddenBelow: count - end };
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Place `right` flush to `width`, truncating `left` first so the stats survive.
|
|
59
|
-
* The final clamp guarantees the line never exceeds `width` (which would wrap and
|
|
60
|
-
* desync pi's line-diff → flicker) even on a terminal too narrow for the stats.
|
|
61
|
-
*/
|
|
62
|
-
function rightAlign(left, right, width) {
|
|
63
|
-
const rightW = visibleWidth(right);
|
|
64
|
-
const maxLeft = Math.max(0, width - rightW - 1);
|
|
65
|
-
const leftClamped = truncateToWidth(left, maxLeft);
|
|
66
|
-
const gap = Math.max(1, width - visibleWidth(leftClamped) - rightW);
|
|
67
|
-
return truncateToWidth(leftClamped + " ".repeat(gap) + right, width);
|
|
68
|
-
}
|
|
69
|
-
export class FleetList {
|
|
70
|
-
manager;
|
|
71
|
-
agentActivity;
|
|
72
|
-
getCwd;
|
|
73
|
-
pi;
|
|
74
|
-
getCtx;
|
|
75
|
-
ui;
|
|
76
|
-
tui;
|
|
77
|
-
inputUnsub;
|
|
78
|
-
widgetRegistered = false;
|
|
79
|
-
lastRosterKey;
|
|
80
|
-
timer;
|
|
81
|
-
enabled = true;
|
|
82
|
-
/** Whether arrow keys currently navigate the list (vs. flow to the editor). */
|
|
83
|
-
active = false;
|
|
84
|
-
/** 0 = `main`, 1..N = subagents. */
|
|
85
|
-
selectedIndex = 0;
|
|
86
|
-
/** Set while a conversation overlay is open; calling it closes the overlay. */
|
|
87
|
-
viewerClose;
|
|
88
|
-
viewingAgentId;
|
|
89
|
-
constructor(manager, agentActivity, getCwd = () => undefined, pi, getCtx = () => undefined) {
|
|
90
|
-
this.manager = manager;
|
|
91
|
-
this.agentActivity = agentActivity;
|
|
92
|
-
this.getCwd = getCwd;
|
|
93
|
-
this.pi = pi;
|
|
94
|
-
this.getCtx = getCtx;
|
|
95
|
-
}
|
|
96
|
-
// ---- Lifecycle ----
|
|
97
|
-
setEnabled(enabled) {
|
|
98
|
-
if (enabled === this.enabled)
|
|
99
|
-
return;
|
|
100
|
-
this.enabled = enabled;
|
|
101
|
-
if (!enabled)
|
|
102
|
-
this.active = false;
|
|
103
|
-
this.update();
|
|
104
|
-
}
|
|
105
|
-
/** Capture the UI context and (re)register the global input handler. */
|
|
106
|
-
setUICtx(ui) {
|
|
107
|
-
if (ui === this.ui)
|
|
108
|
-
return;
|
|
109
|
-
this.inputUnsub?.();
|
|
110
|
-
this.ui = ui;
|
|
111
|
-
this.widgetRegistered = false;
|
|
112
|
-
this.lastRosterKey = undefined;
|
|
113
|
-
this.tui = undefined;
|
|
114
|
-
this.inputUnsub = ui.onTerminalInput(data => this.handleKey(data));
|
|
115
|
-
}
|
|
116
|
-
/** Ensure the re-render timer is running (called when an agent spawns). */
|
|
117
|
-
ensureTimer() {
|
|
118
|
-
if (!this.timer)
|
|
119
|
-
this.timer = setInterval(() => this.update(), TICK_MS);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Called when an agent finishes. The viewer (if open on it) stays open so the
|
|
123
|
-
* final output remains readable; refresh the active-only roster.
|
|
124
|
-
*/
|
|
125
|
-
onAgentFinished(_id) {
|
|
126
|
-
this.update();
|
|
127
|
-
}
|
|
128
|
-
dispose() {
|
|
129
|
-
if (this.timer) {
|
|
130
|
-
clearInterval(this.timer);
|
|
131
|
-
this.timer = undefined;
|
|
132
|
-
}
|
|
133
|
-
this.inputUnsub?.();
|
|
134
|
-
this.inputUnsub = undefined;
|
|
135
|
-
if (this.viewerClose) {
|
|
136
|
-
this.viewerClose();
|
|
137
|
-
this.viewerClose = undefined;
|
|
138
|
-
}
|
|
139
|
-
this.viewingAgentId = undefined;
|
|
140
|
-
if (this.ui && this.widgetRegistered)
|
|
141
|
-
this.ui.setWidget(FLEET_KEY, undefined);
|
|
142
|
-
this.widgetRegistered = false;
|
|
143
|
-
this.lastRosterKey = undefined;
|
|
144
|
-
this.tui = undefined;
|
|
145
|
-
this.active = false;
|
|
146
|
-
// Null last so a `viewerClose()` microtask above can't re-register the widget.
|
|
147
|
-
this.ui = undefined;
|
|
148
|
-
}
|
|
149
|
-
/** Re-register/refresh the below-editor widget; clears it when no agents remain. */
|
|
150
|
-
update() {
|
|
151
|
-
if (!this.ui)
|
|
152
|
-
return;
|
|
153
|
-
const records = this.agentRecords();
|
|
154
|
-
const hasAgents = this.enabled && records.length > 0;
|
|
155
|
-
const rosterKey = records.map(record => record.id).join("\0");
|
|
156
|
-
const rosterChanged = rosterKey !== this.lastRosterKey;
|
|
157
|
-
this.lastRosterKey = rosterKey;
|
|
158
|
-
if (!hasAgents) {
|
|
159
|
-
if (this.widgetRegistered) {
|
|
160
|
-
this.ui.setWidget(FLEET_KEY, undefined);
|
|
161
|
-
this.widgetRegistered = false;
|
|
162
|
-
this.tui = undefined;
|
|
163
|
-
}
|
|
164
|
-
if (this.timer) {
|
|
165
|
-
clearInterval(this.timer);
|
|
166
|
-
this.timer = undefined;
|
|
167
|
-
}
|
|
168
|
-
this.active = false;
|
|
169
|
-
this.selectedIndex = 0;
|
|
170
|
-
this.lastRosterKey = undefined;
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
this.clampSelection();
|
|
174
|
-
this.ensureTimer(); // keep stats ticking whenever the list is shown (e.g. after a re-enable)
|
|
175
|
-
if (!this.widgetRegistered) {
|
|
176
|
-
this.ui.setWidget(FLEET_KEY, (tui, theme) => {
|
|
177
|
-
this.tui = tui;
|
|
178
|
-
return {
|
|
179
|
-
render: (w) => this.renderBar(w, theme),
|
|
180
|
-
invalidate: () => { this.widgetRegistered = false; this.tui = undefined; },
|
|
181
|
-
};
|
|
182
|
-
}, { placement: "belowEditor" });
|
|
183
|
-
this.widgetRegistered = true;
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
this.tui?.requestRender(rosterChanged);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
// ---- Roster ----
|
|
190
|
-
/**
|
|
191
|
-
* Active agents shown in the list, ordered earliest-launched first so the
|
|
192
|
-
* ones you started sooner sit at the top. Pending agents with no session yet
|
|
193
|
-
* are hidden until they start. (`listAgents()` is newest-first, so we
|
|
194
|
-
* re-sort.)
|
|
195
|
-
*/
|
|
196
|
-
agentRecords() {
|
|
197
|
-
return this.manager.listAgents()
|
|
198
|
-
.filter(record => canOpenActiveAgent(record))
|
|
199
|
-
.sort((a, b) => a.startedAt - b.startedAt);
|
|
200
|
-
}
|
|
201
|
-
roster() {
|
|
202
|
-
return [{ kind: "main" }, ...this.agentRecords().map(record => ({ kind: "agent", record }))];
|
|
203
|
-
}
|
|
204
|
-
clampSelection() {
|
|
205
|
-
const max = this.roster().length - 1;
|
|
206
|
-
if (this.selectedIndex > max)
|
|
207
|
-
this.selectedIndex = Math.max(0, max);
|
|
208
|
-
if (this.selectedIndex < 0)
|
|
209
|
-
this.selectedIndex = 0;
|
|
210
|
-
}
|
|
211
|
-
// ---- Key handling ----
|
|
212
|
-
/** Returns `{consume:true}` to swallow a key, or undefined to let it through. */
|
|
213
|
-
handleKey(data) {
|
|
214
|
-
if (!this.enabled || !this.ui)
|
|
215
|
-
return undefined;
|
|
216
|
-
// Input listeners receive BOTH key-press and key-release (the kitty protocol
|
|
217
|
-
// emits both, and matchesKey matches either) — act on press only, or every
|
|
218
|
-
// tap would move/fire twice. Repeats still pass through for held-key nav.
|
|
219
|
-
if (isKeyRelease(data))
|
|
220
|
-
return undefined;
|
|
221
|
-
// While an overlay is open, let it own all input.
|
|
222
|
-
if (this.viewerClose)
|
|
223
|
-
return undefined;
|
|
224
|
-
// Input listeners fire BEFORE the focused component, and dialogs
|
|
225
|
-
// (ctx.ui.select/confirm/input, pi's own menus) swap the prompt editor out
|
|
226
|
-
// while getEditorText() still reads the detached — empty — editor. So when
|
|
227
|
-
// anything but the editor owns the keyboard, stay out of its keys (#123).
|
|
228
|
-
if (!this.editorHasFocus()) {
|
|
229
|
-
if (this.active)
|
|
230
|
-
this.deactivate();
|
|
231
|
-
return undefined;
|
|
232
|
-
}
|
|
233
|
-
if (!this.active) {
|
|
234
|
-
// Activate: ↓ or ← at an empty prompt moves focus into the list.
|
|
235
|
-
const isActivator = matchesKey(data, "down") || matchesKey(data, "left");
|
|
236
|
-
if (isActivator && this.agentRecords().length > 0 && this.ui.getEditorText() === "") {
|
|
237
|
-
this.active = true;
|
|
238
|
-
this.selectedIndex = 0;
|
|
239
|
-
this.update();
|
|
240
|
-
return { consume: true };
|
|
241
|
-
}
|
|
242
|
-
return undefined;
|
|
243
|
-
}
|
|
244
|
-
// Active — arrows navigate, Enter opens, Esc / Up-past-top exits.
|
|
245
|
-
if (matchesKey(data, "down")) {
|
|
246
|
-
const max = this.roster().length - 1;
|
|
247
|
-
this.selectedIndex = Math.min(max, this.selectedIndex + 1);
|
|
248
|
-
this.update();
|
|
249
|
-
return { consume: true };
|
|
250
|
-
}
|
|
251
|
-
if (matchesKey(data, "up")) {
|
|
252
|
-
if (this.selectedIndex === 0) {
|
|
253
|
-
this.deactivate();
|
|
254
|
-
return { consume: true };
|
|
255
|
-
}
|
|
256
|
-
this.selectedIndex -= 1;
|
|
257
|
-
this.update();
|
|
258
|
-
return { consume: true };
|
|
259
|
-
}
|
|
260
|
-
if (matchesKey(data, "escape")) {
|
|
261
|
-
this.deactivate();
|
|
262
|
-
return { consume: true };
|
|
263
|
-
}
|
|
264
|
-
if (matchesKey(data, Key.enter)) {
|
|
265
|
-
this.openSelected();
|
|
266
|
-
return { consume: true };
|
|
267
|
-
}
|
|
268
|
-
// Any other key cancels navigation and flows to the editor.
|
|
269
|
-
this.deactivate();
|
|
270
|
-
return undefined;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* True when pi's prompt editor owns the keyboard. pi's editor is an `Editor`
|
|
274
|
-
* subclass (CustomEditor) while every dialog/selector is not, and the loader
|
|
275
|
-
* aliases pi-tui to pi's own copy, so `instanceof` is a reliable identity
|
|
276
|
-
* check. `focusedComponent` is TUI-private (no public accessor), hence the
|
|
277
|
-
* best-effort peek: unknowable focus (no tui seen yet, nothing focused)
|
|
278
|
-
* counts as the editor so activation keeps working.
|
|
279
|
-
*/
|
|
280
|
-
editorHasFocus() {
|
|
281
|
-
const focused = this.tui?.focusedComponent;
|
|
282
|
-
return focused == null || focused instanceof Editor;
|
|
283
|
-
}
|
|
284
|
-
deactivate() {
|
|
285
|
-
this.active = false;
|
|
286
|
-
this.selectedIndex = 0;
|
|
287
|
-
this.update();
|
|
288
|
-
}
|
|
289
|
-
openSelected() {
|
|
290
|
-
const entry = this.roster()[this.selectedIndex];
|
|
291
|
-
if (!entry || entry.kind === "main") {
|
|
292
|
-
// `main` = return to the prompt; the native transcript is already shown.
|
|
293
|
-
this.deactivate();
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const record = entry.record;
|
|
297
|
-
if (!this.ui)
|
|
298
|
-
return;
|
|
299
|
-
if (!canOpenActiveAgent(record) || !record.session) {
|
|
300
|
-
this.ui.notify(`Agent is ${record.status} — no live session available.`, "info");
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
const session = record.session;
|
|
304
|
-
const ctx = this.getCtx();
|
|
305
|
-
const pi = this.pi;
|
|
306
|
-
if (!ctx || !pi) {
|
|
307
|
-
this.ui.notify("Agent conversation is unavailable — no active session.", "info");
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
const activity = this.agentActivity.get(record.id);
|
|
311
|
-
this.viewingAgentId = record.id;
|
|
312
|
-
void this.ui.custom((tui, theme, keybindings, done) => {
|
|
313
|
-
this.viewerClose = () => done(undefined);
|
|
314
|
-
return new ConversationViewer(tui, session, record, activity, theme, done, () => {
|
|
315
|
-
if (this.manager.abort(record.id))
|
|
316
|
-
this.ui?.notify(`Stopped "${record.description}".`, "info");
|
|
317
|
-
}, keybindings, (message) => this.manager.steer(record.id, message), { pi, ctx, readOnly: false });
|
|
318
|
-
}, {
|
|
319
|
-
overlay: true,
|
|
320
|
-
overlayOptions: { anchor: "center", width: "90%", maxHeight: `${VIEWPORT_HEIGHT_PCT}%` },
|
|
321
|
-
}).then(() => this.clearViewer(), () => this.clearViewer());
|
|
322
|
-
}
|
|
323
|
-
/** Reset overlay state and return to the list (on close, auto-close, or error). */
|
|
324
|
-
clearViewer() {
|
|
325
|
-
// Keep the cursor on the agent we were viewing — re-resolve by id so it
|
|
326
|
-
// still feels natural if the list reordered (an earlier agent finished)
|
|
327
|
-
// while the overlay was open. If that agent is gone, leave the index for
|
|
328
|
-
// update()'s clamp to settle.
|
|
329
|
-
if (this.viewingAgentId) {
|
|
330
|
-
const idx = this.roster().findIndex(e => e.kind === "agent" && e.record.id === this.viewingAgentId);
|
|
331
|
-
if (idx >= 0)
|
|
332
|
-
this.selectedIndex = idx;
|
|
333
|
-
}
|
|
334
|
-
this.viewerClose = undefined;
|
|
335
|
-
this.viewingAgentId = undefined;
|
|
336
|
-
this.update();
|
|
337
|
-
}
|
|
338
|
-
// ---- Rendering ----
|
|
339
|
-
renderBar(width, theme) {
|
|
340
|
-
const agents = this.roster().slice(1);
|
|
341
|
-
if (agents.length === 0)
|
|
342
|
-
return [];
|
|
343
|
-
// Clamp locally so a render between a roster shrink and the next update()
|
|
344
|
-
// (e.g. on terminal resize) never loses the selection marker.
|
|
345
|
-
const sel = Math.min(this.selectedIndex, agents.length);
|
|
346
|
-
const hint = this.active
|
|
347
|
-
? "↑↓ select · enter view · esc back"
|
|
348
|
-
: "esc to interrupt · ← for agents · ↓ to manage";
|
|
349
|
-
const lines = [];
|
|
350
|
-
lines.push(truncateToWidth(" " + theme.fg("dim", hint), width));
|
|
351
|
-
lines.push(truncateToWidth(` ${this.bullet(0, sel, theme)} main`, width));
|
|
352
|
-
const window = calculateFleetAgentWindow(agents.length, sel);
|
|
353
|
-
if (window.hiddenAbove > 0) {
|
|
354
|
-
lines.push(rightAlign("", theme.fg("dim", `↑ ${window.hiddenAbove} more`), width));
|
|
355
|
-
}
|
|
356
|
-
for (let a = window.start; a < window.end; a++) {
|
|
357
|
-
lines.push(this.renderAgentRow(a + 1, sel, agents[a].record, width, theme));
|
|
358
|
-
}
|
|
359
|
-
if (window.hiddenBelow > 0) {
|
|
360
|
-
lines.push(rightAlign("", theme.fg("dim", `↓ ${window.hiddenBelow} more`), width));
|
|
361
|
-
}
|
|
362
|
-
return lines;
|
|
363
|
-
}
|
|
364
|
-
bullet(rosterIndex, sel, theme) {
|
|
365
|
-
return rosterIndex === sel ? theme.fg("accent", "●") : theme.fg("dim", "○");
|
|
366
|
-
}
|
|
367
|
-
renderAgentRow(rosterIndex, sel, record, width, theme) {
|
|
368
|
-
const left = ` ${this.bullet(rosterIndex, sel, theme)} ${theme.fg("muted", getDisplayName(record.type))} ${record.description}`;
|
|
369
|
-
const tokens = getLifetimeTotal(this.agentActivity.get(record.id)?.lifetimeUsage ?? record.lifetimeUsage);
|
|
370
|
-
const elapsedMs = (record.completedAt ?? Date.now()) - record.startedAt; // freezes once finished
|
|
371
|
-
const right = theme.fg("dim", `${formatFleetElapsed(elapsedMs)} · ${formatFleetTokens(tokens)}`);
|
|
372
|
-
return rightAlign(left, right, width);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
//# sourceMappingURL=fleet-list.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-list.js","sourceRoot":"","sources":["../../src/ui/fleet-list.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG9G,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAsB,cAAc,EAAc,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEnF,kDAAkD;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC;AAC1B,kFAAkF;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AACvC,MAAM,eAAe,GAAG,CAAC,CAAC,CAAC,cAAc;AACzC,MAAM,eAAe,GAAG,qBAAqB,GAAG,eAAe,CAAC;AAChE,sEAAsE;AACtE,MAAM,OAAO,GAAG,GAAG,CAAC;AAqBpB,yFAAyF;AACzF,MAAM,UAAU,kBAAkB,CAAC,EAAU;IAC3C,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;AAClD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,OAAe,CAAC;IACpB,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,GAAG,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;SAClE,IAAI,KAAK,IAAI,KAAK;QAAE,OAAO,GAAG,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;;QAC/D,OAAO,GAAG,GAAG,KAAK,EAAE,CAAC;IAC1B,OAAO,KAAK,OAAO,SAAS,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,UAAkB,EAClB,mBAA2B;IAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAE7E,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC5B,KAAK,GAAG,CAAC,EACT,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CACjD,CAAC;IACF,MAAM,YAAY,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,aAAa,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC;IAChF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,YAAY,GAAG,CAAC,CAAC,EAC7C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,CAClC,CAAC;IACF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC;IAClD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,GAAG,GAAG,EAAE,CAAC;AACtE,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,IAAY,EAAE,KAAa,EAAE,KAAa;IAC5D,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,CAAC;IACpE,OAAO,eAAe,CAAC,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,OAAO,SAAS;IAkBV;IACA;IACA;IACA;IACA;IArBF,EAAE,CAAyB;IAC3B,GAAG,CAAkB;IACrB,UAAU,CAA2B;IACrC,gBAAgB,GAAG,KAAK,CAAC;IACzB,aAAa,CAAqB;IAClC,KAAK,CAA6C;IAElD,OAAO,GAAG,IAAI,CAAC;IACvB,+EAA+E;IACvE,MAAM,GAAG,KAAK,CAAC;IACvB,oCAAoC;IAC5B,aAAa,GAAG,CAAC,CAAC;IAC1B,+EAA+E;IACvE,WAAW,CAA2B;IACtC,cAAc,CAAqB;IAE3C,YACU,OAAqB,EACrB,aAAyC,EACzC,SAAmC,GAAG,EAAE,CAAC,SAAS,EAClD,EAAiB,EACjB,SAA6C,GAAG,EAAE,CAAC,SAAS;QAJ5D,YAAO,GAAP,OAAO,CAAc;QACrB,kBAAa,GAAb,aAAa,CAA4B;QACzC,WAAM,GAAN,MAAM,CAA4C;QAClD,OAAE,GAAF,EAAE,CAAe;QACjB,WAAM,GAAN,MAAM,CAAsD;IACnE,CAAC;IAEJ,sBAAsB;IAEtB,UAAU,CAAC,OAAgB;QACzB,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO;YAAE,OAAO;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,wEAAwE;IACxE,QAAQ,CAAC,EAAc;QACrB,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE;YAAE,OAAO;QAC3B,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QACpB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,2EAA2E;IAC3E,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;IAC1E,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,GAAW;QACzB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QAAC,CAAC;QACtE,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QACpB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAAC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAAC,CAAC;QAC3E,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,gBAAgB;YAAE,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC9E,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,+EAA+E;QAC/E,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC;IACtB,CAAC;IAED,oFAAoF;IACpF,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,aAAa,GAAG,SAAS,KAAK,IAAI,CAAC,aAAa,CAAC;QACvD,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAE/B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC1B,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBACxC,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;gBAC9B,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;YACvB,CAAC;YACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;YAAC,CAAC;YACtE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,yEAAyE;QAE7F,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;gBAC1C,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;gBACf,OAAO;oBACL,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC;oBAC/C,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC;iBAC3E,CAAC;YACJ,CAAC,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,mBAAmB;IAEnB;;;;;OAKG;IACK,YAAY;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;aAC7B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;aAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;IAEO,MAAM;QACZ,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxG,CAAC;IAEO,cAAc;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,aAAa,GAAG,GAAG;YAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACpE,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC;YAAE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,yBAAyB;IAEzB,iFAAiF;IACjF,SAAS,CAAC,IAAY;QACpB,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,SAAS,CAAC;QAChD,6EAA6E;QAC7E,2EAA2E;QAC3E,0EAA0E;QAC1E,IAAI,YAAY,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QACzC,kDAAkD;QAClD,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,SAAS,CAAC;QACvC,iEAAiE;QACjE,2EAA2E;QAC3E,2EAA2E;QAC3E,0EAA0E;QAC1E,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,iEAAiE;YACjE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACzE,IAAI,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC;gBACpF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,kEAAkE;QAClE,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAAC,CAAC;YAC9E,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC;YACxB,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAAC,CAAC;QAChF,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAAC,CAAC;QAEnF,4DAA4D;QAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACK,cAAc;QACpB,MAAM,OAAO,GAAI,IAAI,CAAC,GAAkD,EAAE,gBAAgB,CAAC;QAC3F,OAAO,OAAO,IAAI,IAAI,IAAI,OAAO,YAAY,MAAM,CAAC;IACtD,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEO,YAAY;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACpC,yEAAyE;YACzE,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO;QACrB,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACnD,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,MAAM,CAAC,MAAM,+BAA+B,EAAE,MAAM,CAAC,CAAC;YACjF,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,wDAAwD,EAAE,MAAM,CAAC,CAAC;YACjF,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,EAAE,CAAC;QAEhC,KAAK,IAAI,CAAC,EAAE,CAAC,MAAM,CACjB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC,WAAW,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzC,OAAO,IAAI,kBAAkB,CAC3B,GAAG,EACH,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,GAAG,EAAE;gBACH,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;oBAAE,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,MAAM,CAAC,WAAW,IAAI,EAAE,MAAM,CAAC,CAAC;YACjG,CAAC,EACD,WAAW,EACX,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,EAC3D,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAC7B,CAAC;QACJ,CAAC,EACD;YACE,OAAO,EAAE,IAAI;YACb,cAAc,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,mBAAmB,GAAG,EAAE;SACzF,CACF,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,mFAAmF;IAC3E,WAAW;QACjB,wEAAwE;QACxE,wEAAwE;QACxE,yEAAyE;QACzE,8BAA8B;QAC9B,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,cAAc,CAAC,CAAC;YACpG,IAAI,GAAG,IAAI,CAAC;gBAAE,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,sBAAsB;IAEd,SAAS,CAAC,KAAa,EAAE,KAAY;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAiB,CAAC;QACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACnC,0EAA0E;QAC1E,8DAA8D;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM;YACtB,CAAC,CAAC,mCAAmC;YACrC,CAAC,CAAC,+CAA+C,CAAC;QACpD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QAE3E,MAAM,MAAM,GAAG,yBAAyB,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7D,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,MAAM,CAAC,WAAW,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACrF,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,MAAM,CAAC,WAAW,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACrF,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,MAAM,CAAC,WAAmB,EAAE,GAAW,EAAE,KAAY;QAC3D,OAAO,WAAW,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9E,CAAC;IAEO,cAAc,CAAC,WAAmB,EAAE,GAAW,EAAE,MAAmB,EAAE,KAAa,EAAE,KAAY;QACvG,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QAClI,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1G,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,wBAAwB;QACjG,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjG,OAAO,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/** Coalesced, deferred render requests for structural UI changes. */
|
|
2
|
-
|
|
3
|
-
const DEFAULT_DELAY_MS = 50;
|
|
4
|
-
const DEFAULT_MAX_WAIT_MS = 200;
|
|
5
|
-
|
|
6
|
-
export interface DeferredUiRefresh {
|
|
7
|
-
/** Schedule one render request after the debounce/max-wait window. */
|
|
8
|
-
schedule(): void;
|
|
9
|
-
/** Cancel the current pending render request, if any. */
|
|
10
|
-
cancel(): void;
|
|
11
|
-
/** Cancel and permanently disable this scheduler. */
|
|
12
|
-
dispose(): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createDeferredUiRefresh(
|
|
16
|
-
requestRender: () => void,
|
|
17
|
-
options: {
|
|
18
|
-
delayMs?: number;
|
|
19
|
-
maxWaitMs?: number;
|
|
20
|
-
now?: () => number;
|
|
21
|
-
} = {},
|
|
22
|
-
): DeferredUiRefresh {
|
|
23
|
-
const delayMs = Math.max(0, options.delayMs ?? DEFAULT_DELAY_MS);
|
|
24
|
-
const maxWaitMs = Math.max(0, options.maxWaitMs ?? DEFAULT_MAX_WAIT_MS);
|
|
25
|
-
const now = options.now ?? Date.now;
|
|
26
|
-
|
|
27
|
-
let debounceTimer: ReturnType<typeof setTimeout> | undefined;
|
|
28
|
-
let firstScheduledAt: number | undefined;
|
|
29
|
-
let disposed = false;
|
|
30
|
-
|
|
31
|
-
const clearPendingTimer = () => {
|
|
32
|
-
if (debounceTimer !== undefined) {
|
|
33
|
-
clearTimeout(debounceTimer);
|
|
34
|
-
debounceTimer = undefined;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const flush = () => {
|
|
39
|
-
// Clear all state before invoking user code. A render callback may schedule
|
|
40
|
-
// another refresh, which should begin a fresh debounce window.
|
|
41
|
-
clearPendingTimer();
|
|
42
|
-
firstScheduledAt = undefined;
|
|
43
|
-
if (disposed) return;
|
|
44
|
-
requestRender();
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const schedule = () => {
|
|
48
|
-
if (disposed) return;
|
|
49
|
-
|
|
50
|
-
const current = now();
|
|
51
|
-
if (firstScheduledAt === undefined) firstScheduledAt = current;
|
|
52
|
-
|
|
53
|
-
clearPendingTimer();
|
|
54
|
-
const maxDeadline = firstScheduledAt + maxWaitMs;
|
|
55
|
-
const remainingMaxWait = Math.max(0, maxDeadline - current);
|
|
56
|
-
const wait = Math.min(delayMs, remainingMaxWait);
|
|
57
|
-
debounceTimer = setTimeout(flush, wait);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const cancel = () => {
|
|
61
|
-
clearPendingTimer();
|
|
62
|
-
firstScheduledAt = undefined;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const dispose = () => {
|
|
66
|
-
if (disposed) return;
|
|
67
|
-
cancel();
|
|
68
|
-
disposed = true;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
return { schedule, cancel, dispose };
|
|
72
|
-
}
|