pi-minimal 0.3.1 → 0.5.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 +60 -0
- package/CONTEXT.md +83 -0
- package/README.md +6 -3
- package/dist/config.js +21 -9
- package/dist/edit-diff.js +74 -0
- package/dist/footer-contribution-events.js +5 -3
- package/dist/footer-contributions.js +15 -13
- package/dist/git-state.js +31 -11
- package/dist/index.js +23 -206
- package/dist/reclaim.js +0 -3
- package/dist/session.js +155 -0
- package/dist/tools.js +224 -281
- package/dist/tracker.js +2 -2
- package/dist/working-status.js +2 -1
- package/doc/archive/README.md +3 -0
- package/doc/footer-contributions.md +7 -7
- package/package.json +4 -1
- package/release-notes.md +45 -19
- package/src/config.ts +20 -9
- package/src/edit-diff.ts +73 -0
- package/src/footer-contribution-events.ts +7 -4
- package/src/footer-contributions.ts +15 -13
- package/src/git-state.ts +29 -10
- package/src/index.ts +25 -199
- package/src/reclaim.ts +0 -4
- package/src/session.ts +159 -0
- package/src/tools.ts +279 -312
- package/src/tracker.ts +11 -5
- package/src/working-status.ts +2 -1
- package/test/config.test.ts +41 -20
- package/test/footer-contribution-events.test.ts +15 -0
- package/test/git-state.test.ts +35 -0
- package/test/index.test.ts +45 -3
- package/test/tools.test.ts +98 -0
- package/test/working-status.test.ts +53 -0
- /package/doc/{plans/2026-09-22-pi-minimal-package.md → archive/2026-09-22-plan-pi-minimal-package.md} +0 -0
- /package/doc/{specs/2026-09-22-pi-minimal-package.md → archive/2026-09-22-spec-pi-minimal-package.md} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,230 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { installHeader } from "./header.js";
|
|
4
|
-
import { installFooter } from "./footer.js";
|
|
5
|
-
import { createFooterContributions } from "./footer-contributions.js";
|
|
6
|
-
import { bindFooterContributionEvents } from "./footer-contribution-events.js";
|
|
7
|
-
import { installCwd } from "./cwd.js";
|
|
8
|
-
import { listSiblings, parseAgentList, parseTabList } from "./herdr.js";
|
|
9
|
-
import { hideGauntletWidgets } from "./tracker.js";
|
|
1
|
+
import { installCodeBox } from "./code-box.js";
|
|
2
|
+
import { createSession } from "./session.js";
|
|
10
3
|
import { installToolRenderers, stopLiveWatch } from "./tools.js";
|
|
11
|
-
import { setSessionCwd } from "./tool-rows.js";
|
|
12
|
-
import { applyReclaim, reclaimPolicy } from "./reclaim.js";
|
|
13
|
-
import { installWorkingStatus } from "./working-status.js";
|
|
14
|
-
import { installTurnRule } from "./turn-rule.js";
|
|
15
4
|
import { installTranscript } from "./transcript.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
import { installTurnRule } from "./turn-rule.js";
|
|
6
|
+
import { installWorkingStatus } from "./working-status.js";
|
|
7
|
+
/**
|
|
8
|
+
* Process-wide hooks are installed once at load (renderers, transformers, the code-box patch);
|
|
9
|
+
* everything else lives on a `Session` created at session_start and disposed at session_shutdown
|
|
10
|
+
* or when the next session starts.
|
|
11
|
+
*/
|
|
20
12
|
export default function piMinimalExtension(pi) {
|
|
21
13
|
const stopWorkingStatus = installWorkingStatus(pi);
|
|
22
14
|
const stopTurnRule = installTurnRule(pi);
|
|
23
15
|
installToolRenderers(pi);
|
|
24
16
|
installTranscript(pi);
|
|
25
17
|
installCodeBox();
|
|
26
|
-
|
|
27
|
-
let stopFooter = () => { };
|
|
28
|
-
let stopContributionEvents = () => { };
|
|
29
|
-
let sessionActive = false;
|
|
30
|
-
let fastTimer;
|
|
31
|
-
let slowTimer;
|
|
32
|
-
let stealTimer;
|
|
33
|
-
let inFlight;
|
|
34
|
-
let siblings;
|
|
35
|
-
let generation = 0;
|
|
36
|
-
let hideWidgets = true;
|
|
18
|
+
let active;
|
|
37
19
|
let busy = false;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (fastTimer)
|
|
42
|
-
clearInterval(fastTimer);
|
|
43
|
-
if (slowTimer)
|
|
44
|
-
clearInterval(slowTimer);
|
|
45
|
-
if (stealTimer)
|
|
46
|
-
clearInterval(stealTimer);
|
|
47
|
-
fastTimer = undefined;
|
|
48
|
-
slowTimer = undefined;
|
|
49
|
-
stealTimer = undefined;
|
|
50
|
-
inFlight?.abort();
|
|
51
|
-
inFlight = undefined;
|
|
52
|
-
};
|
|
53
|
-
const scheduleFast = (ctx) => {
|
|
54
|
-
if (fastTimer)
|
|
55
|
-
return;
|
|
56
|
-
if (slowTimer)
|
|
57
|
-
clearInterval(slowTimer);
|
|
58
|
-
slowTimer = undefined;
|
|
59
|
-
fastTimer = setInterval(() => {
|
|
60
|
-
void probe(ctx);
|
|
61
|
-
}, 2000);
|
|
62
|
-
};
|
|
63
|
-
const scheduleSlow = (ctx) => {
|
|
64
|
-
if (slowTimer)
|
|
65
|
-
return;
|
|
66
|
-
if (fastTimer)
|
|
67
|
-
clearInterval(fastTimer);
|
|
68
|
-
fastTimer = undefined;
|
|
69
|
-
slowTimer = setInterval(() => {
|
|
70
|
-
void probe(ctx);
|
|
71
|
-
}, 10000);
|
|
72
|
-
};
|
|
73
|
-
const probe = async (ctx) => {
|
|
74
|
-
if (process.env.HERDR_ENV !== "1")
|
|
75
|
-
return;
|
|
76
|
-
if (inFlight)
|
|
77
|
-
return;
|
|
78
|
-
const ac = new AbortController();
|
|
79
|
-
const gen = generation;
|
|
80
|
-
inFlight = ac;
|
|
81
|
-
try {
|
|
82
|
-
const agentRun = await pi.exec("herdr", ["agent", "list"], {
|
|
83
|
-
timeout: 3000,
|
|
84
|
-
signal: ac.signal,
|
|
85
|
-
});
|
|
86
|
-
if (generation !== gen)
|
|
87
|
-
return;
|
|
88
|
-
const tabRun = await pi.exec("herdr", ["tab", "list"], {
|
|
89
|
-
timeout: 3000,
|
|
90
|
-
signal: ac.signal,
|
|
91
|
-
});
|
|
92
|
-
if (generation !== gen)
|
|
93
|
-
return;
|
|
94
|
-
if (agentRun.code !== 0 || tabRun.code !== 0 || agentRun.killed || tabRun.killed) {
|
|
95
|
-
siblings = undefined;
|
|
96
|
-
scheduleSlow(ctx);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
siblings = listSiblings(parseAgentList(agentRun.stdout), parseTabList(tabRun.stdout), process.env.HERDR_PANE_ID, process.env.HERDR_TAB_ID);
|
|
100
|
-
if (siblings)
|
|
101
|
-
scheduleFast(ctx);
|
|
102
|
-
else
|
|
103
|
-
scheduleSlow(ctx);
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
if (generation !== gen)
|
|
107
|
-
return;
|
|
108
|
-
siblings = undefined;
|
|
109
|
-
scheduleSlow(ctx);
|
|
110
|
-
}
|
|
111
|
-
finally {
|
|
112
|
-
if (inFlight === ac)
|
|
113
|
-
inFlight = undefined;
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
const hideForeignChrome = (ctx, reason) => {
|
|
117
|
-
if (ctx.mode !== "tui")
|
|
118
|
-
return;
|
|
119
|
-
applyReclaim(reason, ctx.ui, {
|
|
120
|
-
widgets: () => {
|
|
121
|
-
if (hideWidgets)
|
|
122
|
-
hideGauntletWidgets(ctx);
|
|
123
|
-
},
|
|
124
|
-
chrome: () => {
|
|
125
|
-
installHeader(ctx);
|
|
126
|
-
installChromeFooter(ctx);
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
const contextPct = (ctx) => {
|
|
131
|
-
const usage = ctx.getContextUsage?.();
|
|
132
|
-
const window = usage?.contextWindow || ctx.model?.contextWindow;
|
|
133
|
-
if (typeof usage?.tokens !== "number" || !window)
|
|
134
|
-
return undefined;
|
|
135
|
-
return Math.max(0, Math.min(100, Math.round((usage.tokens / window) * 100)));
|
|
136
|
-
};
|
|
137
|
-
const installChromeFooter = (ctx) => {
|
|
138
|
-
stopFooter();
|
|
139
|
-
stopFooter = installFooter(ctx, {
|
|
140
|
-
busy: () => busy,
|
|
141
|
-
editorText: () => (typeof ctx.ui.getEditorText === "function" ? ctx.ui.getEditorText() : ""),
|
|
142
|
-
contextPct: () => contextPct(ctx),
|
|
143
|
-
}, contributions);
|
|
144
|
-
};
|
|
145
|
-
const installStatusLine = (ctx) => {
|
|
146
|
-
installCwd(ctx, {
|
|
147
|
-
gitState: gitState.get,
|
|
148
|
-
siblings: () => siblings,
|
|
149
|
-
onGitChange: gitState.onChange,
|
|
150
|
-
});
|
|
151
|
-
};
|
|
152
|
-
const pinChrome = (ctx, reason) => {
|
|
153
|
-
hideForeignChrome(ctx, reason);
|
|
154
|
-
if (ctx.mode !== "tui" || !reclaimPolicy(reason).reinstallChrome)
|
|
155
|
-
return;
|
|
156
|
-
ctx.ui.setWidget("tw-cwd", undefined);
|
|
157
|
-
installStatusLine(ctx);
|
|
158
|
-
};
|
|
159
|
-
pi.on("session_start", async (_event, ctx) => {
|
|
160
|
-
stopFooter();
|
|
161
|
-
stopContributionEvents();
|
|
162
|
-
sessionActive = true;
|
|
163
|
-
generation += 1;
|
|
164
|
-
stopContributionEvents = bindFooterContributionEvents(pi.events, contributions, ctx.sessionManager.getSessionId(), ctx.mode);
|
|
165
|
-
if (ctx.mode !== "tui")
|
|
166
|
-
return;
|
|
167
|
-
const config = loadPiMinimalConfig({
|
|
168
|
-
agentDir: getAgentDir(),
|
|
169
|
-
cwd: ctx.cwd,
|
|
170
|
-
projectTrusted: ctx.isProjectTrusted(),
|
|
171
|
-
});
|
|
172
|
-
hideWidgets = config.hideGauntletWidgets;
|
|
173
|
-
currentCwd = ctx.cwd;
|
|
174
|
-
setSessionCwd(ctx.cwd);
|
|
175
|
-
try {
|
|
176
|
-
const settings = SettingsManager.create(ctx.cwd, undefined, { projectTrusted: ctx.isProjectTrusted() });
|
|
177
|
-
setChromeMargin(settings.getOutputPad());
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
// Keep the default margin when settings are unavailable.
|
|
181
|
-
}
|
|
182
|
-
installHeader(ctx);
|
|
183
|
-
installChromeFooter(ctx);
|
|
184
|
-
installStatusLine(ctx);
|
|
185
|
-
void gitState.refresh(true);
|
|
186
|
-
pinChrome(ctx, "session_start");
|
|
187
|
-
ctx.ui.setHiddenThinkingLabel("◆ Thought");
|
|
188
|
-
ctx.ui.setWorkingIndicator();
|
|
189
|
-
const sessionGeneration = generation;
|
|
190
|
-
const settle = () => {
|
|
191
|
-
if (sessionActive && generation === sessionGeneration)
|
|
192
|
-
pinChrome(ctx, "session_settle");
|
|
193
|
-
};
|
|
194
|
-
setTimeout(settle, 0);
|
|
195
|
-
setTimeout(settle, 50);
|
|
196
|
-
if (!stealTimer) {
|
|
197
|
-
stealTimer = setInterval(() => hideForeignChrome(ctx, "interval"), 200);
|
|
198
|
-
}
|
|
199
|
-
if (process.env.HERDR_ENV === "1") {
|
|
200
|
-
await probe(ctx);
|
|
201
|
-
}
|
|
20
|
+
pi.on("session_start", (_event, ctx) => {
|
|
21
|
+
active?.dispose();
|
|
22
|
+
active = createSession(pi, ctx, { busy: () => busy });
|
|
202
23
|
});
|
|
203
24
|
pi.on("agent_start", () => {
|
|
204
25
|
busy = true;
|
|
205
26
|
});
|
|
206
27
|
pi.on("agent_end", () => {
|
|
207
28
|
busy = false;
|
|
208
|
-
|
|
29
|
+
active?.refreshGit();
|
|
209
30
|
});
|
|
210
|
-
pi.on("turn_end", (
|
|
211
|
-
|
|
212
|
-
|
|
31
|
+
pi.on("turn_end", () => {
|
|
32
|
+
active?.pin("turn_end");
|
|
33
|
+
active?.refreshGit();
|
|
213
34
|
});
|
|
214
|
-
pi.on("tool_execution_end", (
|
|
215
|
-
|
|
216
|
-
|
|
35
|
+
pi.on("tool_execution_end", () => {
|
|
36
|
+
active?.pin("tool_execution_end");
|
|
37
|
+
active?.refreshGit();
|
|
217
38
|
});
|
|
218
|
-
pi.on("session_shutdown",
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
stopContributionEvents();
|
|
39
|
+
pi.on("session_shutdown", () => {
|
|
40
|
+
active?.dispose();
|
|
41
|
+
active = undefined;
|
|
222
42
|
busy = false;
|
|
223
|
-
stopTimers();
|
|
224
43
|
stopWorkingStatus();
|
|
225
44
|
stopTurnRule();
|
|
226
45
|
stopLiveWatch();
|
|
227
|
-
generation += 1;
|
|
228
|
-
siblings = undefined;
|
|
229
46
|
});
|
|
230
47
|
}
|
package/dist/reclaim.js
CHANGED
|
@@ -2,9 +2,6 @@ export function reclaimPolicy(reason) {
|
|
|
2
2
|
if (reason === "session_start") {
|
|
3
3
|
return { resetEditor: true, reinstallChrome: true };
|
|
4
4
|
}
|
|
5
|
-
if (reason === "interval") {
|
|
6
|
-
return { resetEditor: false, reinstallChrome: false };
|
|
7
|
-
}
|
|
8
5
|
// session_settle / turn_end / tool_execution_end: restore chrome, keep editor
|
|
9
6
|
return { resetEditor: false, reinstallChrome: true };
|
|
10
7
|
}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { getAgentDir, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { setChromeMargin } from "./chrome.js";
|
|
3
|
+
import { loadPiMinimalConfig } from "./config.js";
|
|
4
|
+
import { installCwd } from "./cwd.js";
|
|
5
|
+
import { installFooter } from "./footer.js";
|
|
6
|
+
import { bindFooterContributionEvents } from "./footer-contribution-events.js";
|
|
7
|
+
import { createFooterContributions } from "./footer-contributions.js";
|
|
8
|
+
import { createGitState } from "./git-state.js";
|
|
9
|
+
import { installHeader } from "./header.js";
|
|
10
|
+
import { listSiblings, parseAgentList, parseTabList } from "./herdr.js";
|
|
11
|
+
import { applyReclaim, reclaimPolicy } from "./reclaim.js";
|
|
12
|
+
import { setSessionCwd } from "./tool-rows.js";
|
|
13
|
+
import { setEditDiffMode } from "./tools.js";
|
|
14
|
+
import { hideGauntletWidgets } from "./tracker.js";
|
|
15
|
+
const HERDR_FAST_MS = 2000;
|
|
16
|
+
const HERDR_SLOW_MS = 10000;
|
|
17
|
+
const HERDR_EXEC_TIMEOUT_MS = 3000;
|
|
18
|
+
/**
|
|
19
|
+
* Everything pi-minimal owns for one session: config, cwd, the contribution registry, the git and
|
|
20
|
+
* Herdr pollers, and the header/footer/status-line chrome. Disposal stops every timer and makes
|
|
21
|
+
* late async results inert, so two sessions in one process never share or overwrite each other's
|
|
22
|
+
* state. Non-TUI sessions get a session too, but it only binds the contribution protocol (which
|
|
23
|
+
* replies `not-tui`) and installs no chrome.
|
|
24
|
+
*/
|
|
25
|
+
export function createSession(pi, ctx, deps) {
|
|
26
|
+
const id = ctx.sessionManager.getSessionId();
|
|
27
|
+
let alive = true;
|
|
28
|
+
const contributions = createFooterContributions();
|
|
29
|
+
const stopContributionEvents = bindFooterContributionEvents(pi.events, contributions, id, ctx.mode);
|
|
30
|
+
if (ctx.mode !== "tui") {
|
|
31
|
+
return { id, pin() { }, refreshGit() { }, dispose() { if (!alive)
|
|
32
|
+
return; alive = false; stopContributionEvents(); } };
|
|
33
|
+
}
|
|
34
|
+
const config = loadPiMinimalConfig({ agentDir: getAgentDir(), cwd: ctx.cwd, projectTrusted: ctx.isProjectTrusted() });
|
|
35
|
+
setSessionCwd(ctx.cwd);
|
|
36
|
+
setEditDiffMode(config.editDiff);
|
|
37
|
+
try {
|
|
38
|
+
const settings = SettingsManager.create(ctx.cwd, undefined, { projectTrusted: ctx.isProjectTrusted() });
|
|
39
|
+
setChromeMargin(settings.getOutputPad());
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Keep the current margin when settings are unavailable.
|
|
43
|
+
}
|
|
44
|
+
const gitState = createGitState(pi, () => ctx.cwd);
|
|
45
|
+
let stopFooter = () => { };
|
|
46
|
+
let siblings;
|
|
47
|
+
let herdrTimer;
|
|
48
|
+
let herdrPeriod = 0;
|
|
49
|
+
let herdrInFlight;
|
|
50
|
+
const settleTimers = [];
|
|
51
|
+
const contextPct = () => {
|
|
52
|
+
const usage = ctx.getContextUsage?.();
|
|
53
|
+
const window = usage?.contextWindow || ctx.model?.contextWindow;
|
|
54
|
+
if (typeof usage?.tokens !== "number" || !window)
|
|
55
|
+
return undefined;
|
|
56
|
+
return Math.max(0, Math.min(100, Math.round((usage.tokens / window) * 100)));
|
|
57
|
+
};
|
|
58
|
+
const installChromeFooter = () => {
|
|
59
|
+
stopFooter();
|
|
60
|
+
stopFooter = installFooter(ctx, {
|
|
61
|
+
busy: deps.busy,
|
|
62
|
+
editorText: () => (typeof ctx.ui.getEditorText === "function" ? ctx.ui.getEditorText() : ""),
|
|
63
|
+
contextPct,
|
|
64
|
+
}, contributions);
|
|
65
|
+
};
|
|
66
|
+
const installStatusLine = () => {
|
|
67
|
+
installCwd(ctx, { gitState: gitState.get, siblings: () => siblings, onGitChange: gitState.onChange });
|
|
68
|
+
};
|
|
69
|
+
const pin = (reason) => {
|
|
70
|
+
if (!alive)
|
|
71
|
+
return;
|
|
72
|
+
applyReclaim(reason, ctx.ui, {
|
|
73
|
+
widgets: () => { if (config.hideGauntletWidgets)
|
|
74
|
+
hideGauntletWidgets(ctx); },
|
|
75
|
+
chrome: () => { installHeader(ctx); installChromeFooter(); },
|
|
76
|
+
});
|
|
77
|
+
if (!reclaimPolicy(reason).reinstallChrome)
|
|
78
|
+
return;
|
|
79
|
+
ctx.ui.setWidget("tw-cwd", undefined);
|
|
80
|
+
installStatusLine();
|
|
81
|
+
};
|
|
82
|
+
const scheduleHerdr = (periodMs) => {
|
|
83
|
+
if (!alive || herdrPeriod === periodMs)
|
|
84
|
+
return;
|
|
85
|
+
if (herdrTimer)
|
|
86
|
+
clearInterval(herdrTimer);
|
|
87
|
+
herdrPeriod = periodMs;
|
|
88
|
+
herdrTimer = setInterval(() => { void probeHerdr(); }, periodMs);
|
|
89
|
+
};
|
|
90
|
+
const probeHerdr = async () => {
|
|
91
|
+
if (!alive || herdrInFlight)
|
|
92
|
+
return;
|
|
93
|
+
const ac = new AbortController();
|
|
94
|
+
herdrInFlight = ac;
|
|
95
|
+
try {
|
|
96
|
+
const agentRun = await pi.exec("herdr", ["agent", "list"], { timeout: HERDR_EXEC_TIMEOUT_MS, signal: ac.signal });
|
|
97
|
+
if (!alive)
|
|
98
|
+
return;
|
|
99
|
+
const tabRun = await pi.exec("herdr", ["tab", "list"], { timeout: HERDR_EXEC_TIMEOUT_MS, signal: ac.signal });
|
|
100
|
+
if (!alive)
|
|
101
|
+
return;
|
|
102
|
+
if (agentRun.code !== 0 || tabRun.code !== 0 || agentRun.killed || tabRun.killed) {
|
|
103
|
+
siblings = undefined;
|
|
104
|
+
scheduleHerdr(HERDR_SLOW_MS);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
siblings = listSiblings(parseAgentList(agentRun.stdout), parseTabList(tabRun.stdout), process.env.HERDR_PANE_ID, process.env.HERDR_TAB_ID);
|
|
108
|
+
scheduleHerdr(siblings ? HERDR_FAST_MS : HERDR_SLOW_MS);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
if (!alive)
|
|
112
|
+
return;
|
|
113
|
+
siblings = undefined;
|
|
114
|
+
scheduleHerdr(HERDR_SLOW_MS);
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
if (herdrInFlight === ac)
|
|
118
|
+
herdrInFlight = undefined;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
// Install once, then re-assert shortly after: other extensions' session_start handlers may draw after ours.
|
|
122
|
+
installHeader(ctx);
|
|
123
|
+
installChromeFooter();
|
|
124
|
+
installStatusLine();
|
|
125
|
+
void gitState.refresh(true);
|
|
126
|
+
pin("session_start");
|
|
127
|
+
ctx.ui.setHiddenThinkingLabel("◆ Thought");
|
|
128
|
+
ctx.ui.setWorkingIndicator();
|
|
129
|
+
for (const delay of [0, 50])
|
|
130
|
+
settleTimers.push(setTimeout(() => pin("session_settle"), delay));
|
|
131
|
+
if (process.env.HERDR_ENV === "1")
|
|
132
|
+
void probeHerdr();
|
|
133
|
+
return {
|
|
134
|
+
id,
|
|
135
|
+
pin,
|
|
136
|
+
refreshGit(force) { if (alive)
|
|
137
|
+
void gitState.refresh(force); },
|
|
138
|
+
dispose() {
|
|
139
|
+
if (!alive)
|
|
140
|
+
return;
|
|
141
|
+
alive = false;
|
|
142
|
+
for (const timer of settleTimers.splice(0))
|
|
143
|
+
clearTimeout(timer);
|
|
144
|
+
if (herdrTimer)
|
|
145
|
+
clearInterval(herdrTimer);
|
|
146
|
+
herdrTimer = undefined;
|
|
147
|
+
herdrInFlight?.abort();
|
|
148
|
+
herdrInFlight = undefined;
|
|
149
|
+
siblings = undefined;
|
|
150
|
+
gitState.dispose();
|
|
151
|
+
stopFooter();
|
|
152
|
+
stopContributionEvents();
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|