pi-ui-extend 1.0.23 → 1.0.28
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/README.md +5 -1
- package/dist/app/app.d.ts +1 -0
- package/dist/app/app.js +12 -0
- package/dist/app/constants.d.ts +1 -1
- package/dist/app/constants.js +1 -1
- package/dist/app/icons.d.ts +1 -0
- package/dist/app/icons.js +2 -0
- package/dist/app/input/input-controller.d.ts +2 -0
- package/dist/app/input/input-controller.js +8 -5
- package/dist/app/rendering/render-controller.js +2 -0
- package/dist/app/rendering/status-line-renderer.d.ts +4 -1
- package/dist/app/rendering/status-line-renderer.js +12 -0
- package/dist/app/runtime.d.ts +1 -8
- package/dist/app/runtime.js +0 -39
- package/dist/app/screen/mouse-controller.d.ts +4 -1
- package/dist/app/screen/mouse-controller.js +9 -0
- package/dist/app/session/agent-pause-controller.d.ts +30 -0
- package/dist/app/session/agent-pause-controller.js +178 -0
- package/dist/app/session/session-event-controller.d.ts +1 -0
- package/dist/app/session/session-event-controller.js +22 -15
- package/dist/app/session/session-lifecycle-controller.d.ts +1 -0
- package/dist/app/session/session-lifecycle-controller.js +1 -0
- package/dist/app/types.d.ts +10 -0
- package/dist/config.js +1 -1
- package/dist/default-pix-config.js +2 -2
- package/external/pi-tools-suite/README.md +1 -1
- package/external/pi-tools-suite/docs/browser-qa-subagent.md +34 -2
- package/external/pi-tools-suite/package.json +3 -3
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +24 -18
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +14 -3
- package/external/pi-tools-suite/src/async-subagents/core/process.ts +19 -0
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +97 -17
- package/external/pi-tools-suite/src/async-subagents/core/stop.ts +4 -2
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/SKILL.md +108 -13
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/qa-design.md +80 -0
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/qa-flow.example.jsonc +54 -1
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/scripts/browser-qa-runner.mjs +952 -76
- package/external/pi-tools-suite/src/coding-discipline/index.ts +2 -94
- package/external/pi-tools-suite/src/dcp/index.ts +21 -0
- package/external/pi-tools-suite/src/dcp/pruner-compression-blocks.ts +92 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +21 -16
- package/external/pi-tools-suite/src/todo/index.ts +86 -46
- package/external/pi-tools-suite/src/todo/todo.ts +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -371,12 +371,16 @@ Both support the published schema:
|
|
|
371
371
|
"apply_patch": { "defaultExpanded": true }
|
|
372
372
|
}
|
|
373
373
|
},
|
|
374
|
-
"promptEnhancer": { "modelRef": "
|
|
374
|
+
"promptEnhancer": { "modelRef": "openai-codex/gpt-5.6-luna" },
|
|
375
375
|
"autocomplete": {
|
|
376
376
|
"modelRef": "zai/glm-5-turbo",
|
|
377
377
|
"debounceMs": 350,
|
|
378
378
|
"timeoutMs": 3000
|
|
379
379
|
},
|
|
380
|
+
"sessionTitle": {
|
|
381
|
+
"modelRef": "openai-codex/gpt-5.6-luna",
|
|
382
|
+
"fallbackModels": ["zai/glm-5-turbo"]
|
|
383
|
+
},
|
|
380
384
|
"dictation": { "language": "en" },
|
|
381
385
|
"ignoreContextFiles": false,
|
|
382
386
|
"maxProjectSessions": 0
|
package/dist/app/app.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export declare class PiUiExtendApp {
|
|
|
36
36
|
private readonly popupMenus;
|
|
37
37
|
private readonly voiceController;
|
|
38
38
|
private readonly sessionEvents;
|
|
39
|
+
private readonly agentPauseController;
|
|
39
40
|
private readonly shellController;
|
|
40
41
|
private readonly queuedMessages;
|
|
41
42
|
private readonly workspaceActions;
|
package/dist/app/app.js
CHANGED
|
@@ -31,6 +31,7 @@ import { AppSessionLifecycleController } from "./session/session-lifecycle-contr
|
|
|
31
31
|
import { AppShellController } from "./commands/shell-controller.js";
|
|
32
32
|
import { runInteractiveShellCommand } from "./commands/shell-command.js";
|
|
33
33
|
import { AppSessionEventController } from "./session/session-event-controller.js";
|
|
34
|
+
import { AgentPauseController } from "./session/agent-pause-controller.js";
|
|
34
35
|
import { AppStatusController } from "./screen/status-controller.js";
|
|
35
36
|
import { StatusLineRenderer } from "./rendering/status-line-renderer.js";
|
|
36
37
|
import { AppModelUsageController } from "./model/model-usage-controller.js";
|
|
@@ -91,6 +92,7 @@ export class PiUiExtendApp {
|
|
|
91
92
|
popupMenus;
|
|
92
93
|
voiceController;
|
|
93
94
|
sessionEvents;
|
|
95
|
+
agentPauseController;
|
|
94
96
|
shellController;
|
|
95
97
|
queuedMessages;
|
|
96
98
|
workspaceActions;
|
|
@@ -167,6 +169,11 @@ export class PiUiExtendApp {
|
|
|
167
169
|
runtimeSession: () => this.runtime?.session,
|
|
168
170
|
render: () => this.scheduleRender(),
|
|
169
171
|
});
|
|
172
|
+
this.agentPauseController = new AgentPauseController({
|
|
173
|
+
showToast: (message, kind) => this.showToast(message, kind),
|
|
174
|
+
render: () => this.scheduleRender(),
|
|
175
|
+
isCurrentSession: (session) => this.runtime?.session === session,
|
|
176
|
+
});
|
|
170
177
|
this.modelUsageController = new AppModelUsageController({
|
|
171
178
|
runtimeSession: () => this.runtime?.session,
|
|
172
179
|
render: () => this.render(),
|
|
@@ -308,6 +315,8 @@ export class PiUiExtendApp {
|
|
|
308
315
|
promptEnhancerStatusWidgetEnabled: () => this.promptEnhancer.statusWidgetEnabled(),
|
|
309
316
|
terminalBellSoundStatusWidgetText: () => this.terminalBellSoundController.statusWidgetText(),
|
|
310
317
|
terminalBellSoundStatusWidgetEnabled: () => this.terminalBellSoundController.isEnabled(),
|
|
318
|
+
agentPauseStatusWidgetText: () => this.agentPauseController.statusWidgetText(this.runtime?.session),
|
|
319
|
+
agentPauseStatusWidgetActive: () => this.agentPauseController.statusWidgetActive(this.runtime?.session),
|
|
311
320
|
voiceStatusWidgetText: () => this.voiceController.statusWidgetText(),
|
|
312
321
|
voiceStatusWidgetActive: () => this.voiceController.statusWidgetActive(),
|
|
313
322
|
conversationQuickScrollDirections: () => this.conversationQuickScrollDirections(),
|
|
@@ -633,6 +642,7 @@ export class PiUiExtendApp {
|
|
|
633
642
|
this.render();
|
|
634
643
|
},
|
|
635
644
|
toggleTerminalBellSound: () => this.toggleTerminalBellSound(),
|
|
645
|
+
toggleAgentPause: () => this.agentPauseController.toggle(this.runtime?.session),
|
|
636
646
|
handleExtensionInputMouse: (event) => this.extensionUiController.handleCustomUiMouse(event),
|
|
637
647
|
render: () => this.render(),
|
|
638
648
|
}, this.popupMenus, this.popupActions, this.scrollController, this.commandController);
|
|
@@ -783,6 +793,7 @@ export class PiUiExtendApp {
|
|
|
783
793
|
createExtensionCommandContextActions: (runtime) => this.extensionActions.createCommandContextActions(runtime),
|
|
784
794
|
handleExtensionError: (error) => this.extensionActions.handleExtensionError(error),
|
|
785
795
|
handleSessionEvent: (event) => this.handleSessionEvent(event),
|
|
796
|
+
bindAgentPause: (session) => this.agentPauseController.bind(session),
|
|
786
797
|
addEntry: (entry) => this.addEntry(entry),
|
|
787
798
|
setStatus: (status) => this.setStatus(status),
|
|
788
799
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
@@ -809,6 +820,7 @@ export class PiUiExtendApp {
|
|
|
809
820
|
this.mouseController.statusTerminalBellSoundTarget = undefined;
|
|
810
821
|
this.mouseController.statusSessionTarget = undefined;
|
|
811
822
|
this.mouseController.statusPromptEnhancerTarget = undefined;
|
|
823
|
+
this.mouseController.statusAgentPauseTarget = undefined;
|
|
812
824
|
this.mouseController.statusVoiceMicTarget = undefined;
|
|
813
825
|
this.mouseController.statusVoiceLanguageTarget = undefined;
|
|
814
826
|
this.mouseController.tabLineTargets.length = 0;
|
package/dist/app/constants.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ResolvedToolRule } from "../config.js";
|
|
2
2
|
export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
3
3
|
export declare const THINKING_MENU_MAX_ROWS: number;
|
|
4
|
-
export declare const PI_FAVORITE_MODEL_REFS: readonly ["amazon-bedrock/us.anthropic.claude-opus-4-6-v1", "anthropic/claude-opus-4-8", "openai/gpt-5.4", "azure-openai-responses/gpt-5.4", "openai-codex/gpt-5.6-sol", "deepseek/deepseek-v4-pro", "google/gemini-3.1-pro-preview", "google-vertex/gemini-3.1-pro-preview", "github-copilot/gpt-5.4", "openrouter/moonshotai/kimi-k2.6", "vercel-ai-gateway/zai/glm-5.2", "xai/grok-4.5", "groq/openai/gpt-oss-120b", "cerebras/
|
|
4
|
+
export declare const PI_FAVORITE_MODEL_REFS: readonly ["amazon-bedrock/us.anthropic.claude-opus-4-6-v1", "anthropic/claude-opus-4-8", "openai/gpt-5.4", "azure-openai-responses/gpt-5.4", "openai-codex/gpt-5.6-sol", "deepseek/deepseek-v4-pro", "google/gemini-3.1-pro-preview", "google-vertex/gemini-3.1-pro-preview", "github-copilot/gpt-5.4", "openrouter/moonshotai/kimi-k2.6", "vercel-ai-gateway/zai/glm-5.2", "xai/grok-4.5", "groq/openai/gpt-oss-120b", "cerebras/gpt-oss-120b", "zai/glm-5.3", "mistral/devstral-medium-latest", "minimax/MiniMax-M2.7", "minimax-cn/MiniMax-M2.7", "moonshotai/kimi-k2.6", "moonshotai-cn/kimi-k2.6", "huggingface/moonshotai/Kimi-K2.6", "fireworks/accounts/fireworks/models/kimi-k2p6", "together/moonshotai/Kimi-K2.6", "opencode/kimi-k2.6", "opencode-go/kimi-k2.6", "kimi-coding/kimi-for-coding", "cloudflare-workers-ai/@cf/moonshotai/kimi-k2.6", "cloudflare-ai-gateway/workers-ai/@cf/moonshotai/kimi-k2.6", "xiaomi/mimo-v2.5-pro", "xiaomi-token-plan-cn/mimo-v2.5-pro", "xiaomi-token-plan-ams/mimo-v2.5-pro", "xiaomi-token-plan-sgp/mimo-v2.5-pro"];
|
|
5
5
|
export declare const SLASH_COMMAND_MENU_MAX_ROWS = 6;
|
|
6
6
|
export declare const RESUME_MENU_MAX_ROWS = 20;
|
|
7
7
|
export declare const RESUME_MENU_INITIAL_SESSION_ROWS = 30;
|
package/dist/app/constants.js
CHANGED
|
@@ -15,7 +15,7 @@ export const PI_FAVORITE_MODEL_REFS = [
|
|
|
15
15
|
"vercel-ai-gateway/zai/glm-5.2",
|
|
16
16
|
"xai/grok-4.5",
|
|
17
17
|
"groq/openai/gpt-oss-120b",
|
|
18
|
-
"cerebras/
|
|
18
|
+
"cerebras/gpt-oss-120b",
|
|
19
19
|
"zai/glm-5.3",
|
|
20
20
|
"mistral/devstral-medium-latest",
|
|
21
21
|
"minimax/MiniMax-M2.7",
|
package/dist/app/icons.d.ts
CHANGED
package/dist/app/icons.js
CHANGED
|
@@ -28,6 +28,7 @@ const NERD_FONT_ICONS = {
|
|
|
28
28
|
microphone: "\u{f036c}",
|
|
29
29
|
plus: "\u{f0415}",
|
|
30
30
|
pause: "\u{f03e4}",
|
|
31
|
+
play: "\u{f040a}",
|
|
31
32
|
record: "\u{f044a}",
|
|
32
33
|
refresh: "\u{f0450}",
|
|
33
34
|
volumeHigh: "\u{f057e}",
|
|
@@ -61,6 +62,7 @@ const FALLBACK_ICONS = {
|
|
|
61
62
|
microphone: "m",
|
|
62
63
|
plus: "+",
|
|
63
64
|
pause: "⏸",
|
|
65
|
+
play: "▶",
|
|
64
66
|
record: "●",
|
|
65
67
|
refresh: "↻",
|
|
66
68
|
volumeHigh: "♪",
|
|
@@ -9,6 +9,7 @@ export type InputControllerHost = {
|
|
|
9
9
|
handleExtensionTerminalInput(data: string): ExtensionTerminalInputResult;
|
|
10
10
|
extensionInputUsesEditor?(): boolean;
|
|
11
11
|
isShiftPressed?(): boolean;
|
|
12
|
+
isCommandPressed?(): boolean;
|
|
12
13
|
getInput(): string;
|
|
13
14
|
getDirectPopupMenu(): DirectPopupMenu | undefined;
|
|
14
15
|
resetRequestHistoryNavigation(): void;
|
|
@@ -68,5 +69,6 @@ export declare class AppInputController {
|
|
|
68
69
|
private deleteCurrentInputLine;
|
|
69
70
|
private handleChar;
|
|
70
71
|
private isShiftPressed;
|
|
72
|
+
private isCommandPressed;
|
|
71
73
|
}
|
|
72
74
|
export {};
|
|
@@ -179,7 +179,7 @@ export class AppInputController {
|
|
|
179
179
|
break;
|
|
180
180
|
// Native undo/redo shortcuts must retain their individual key behavior.
|
|
181
181
|
const lower = char.toLowerCase();
|
|
182
|
-
if ((lower === "z" || lower === "y") &&
|
|
182
|
+
if ((lower === "z" || lower === "y") && this.isCommandPressed())
|
|
183
183
|
break;
|
|
184
184
|
length += 1;
|
|
185
185
|
}
|
|
@@ -417,7 +417,7 @@ export class AppInputController {
|
|
|
417
417
|
return "consumed";
|
|
418
418
|
}
|
|
419
419
|
handleArrowUp() {
|
|
420
|
-
if (
|
|
420
|
+
if (this.isCommandPressed()) {
|
|
421
421
|
this.host.scrollByPage(-1);
|
|
422
422
|
return;
|
|
423
423
|
}
|
|
@@ -438,7 +438,7 @@ export class AppInputController {
|
|
|
438
438
|
this.host.scrollByLines(-1);
|
|
439
439
|
}
|
|
440
440
|
handleArrowDown() {
|
|
441
|
-
if (
|
|
441
|
+
if (this.isCommandPressed()) {
|
|
442
442
|
this.host.scrollByPage(1);
|
|
443
443
|
return;
|
|
444
444
|
}
|
|
@@ -517,7 +517,7 @@ export class AppInputController {
|
|
|
517
517
|
this.redoInput();
|
|
518
518
|
return true;
|
|
519
519
|
}
|
|
520
|
-
if (!
|
|
520
|
+
if (!this.isCommandPressed())
|
|
521
521
|
return false;
|
|
522
522
|
const lower = char.toLowerCase();
|
|
523
523
|
if (lower === "z") {
|
|
@@ -595,7 +595,7 @@ export class AppInputController {
|
|
|
595
595
|
this.host.handleEnter();
|
|
596
596
|
return;
|
|
597
597
|
}
|
|
598
|
-
if (char === "\u0015" || ((char === "\u007f" || char === "\b") &&
|
|
598
|
+
if (char === "\u0015" || ((char === "\u007f" || char === "\b") && this.isCommandPressed())) {
|
|
599
599
|
this.deleteCurrentInputLine();
|
|
600
600
|
return;
|
|
601
601
|
}
|
|
@@ -625,6 +625,9 @@ export class AppInputController {
|
|
|
625
625
|
isShiftPressed() {
|
|
626
626
|
return this.host.isShiftPressed?.() ?? isNativeShiftPressed();
|
|
627
627
|
}
|
|
628
|
+
isCommandPressed() {
|
|
629
|
+
return this.host.isCommandPressed?.() ?? isNativeCommandPressed();
|
|
630
|
+
}
|
|
628
631
|
}
|
|
629
632
|
function normalizeBracketedPastePayload(payload) {
|
|
630
633
|
return payload.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
@@ -73,6 +73,7 @@ export class AppRenderController {
|
|
|
73
73
|
this.deps.mouseController.statusTerminalBellSoundTarget = undefined;
|
|
74
74
|
this.deps.mouseController.statusSessionTarget = undefined;
|
|
75
75
|
this.deps.mouseController.statusPromptEnhancerTarget = undefined;
|
|
76
|
+
this.deps.mouseController.statusAgentPauseTarget = undefined;
|
|
76
77
|
this.deps.mouseController.statusVoiceMicTarget = undefined;
|
|
77
78
|
this.deps.mouseController.statusVoiceLanguageTarget = undefined;
|
|
78
79
|
this.deps.mouseController.tabLineTargets.length = 0;
|
|
@@ -284,6 +285,7 @@ export class AppRenderController {
|
|
|
284
285
|
this.deps.mouseController.statusTerminalBellSoundTarget = this.deps.statusLineRenderer.terminalBellSoundTarget?.(statusLayout, statusRow);
|
|
285
286
|
this.deps.mouseController.statusSessionTarget = this.deps.statusLineRenderer.sessionTarget(statusLayout.text, statusRow, statusLayout.sessionLabel, statusLayout.workspaceLabel);
|
|
286
287
|
this.deps.mouseController.statusPromptEnhancerTarget = this.deps.statusLineRenderer.promptEnhancerTarget(statusLayout, statusRow);
|
|
288
|
+
this.deps.mouseController.statusAgentPauseTarget = this.deps.statusLineRenderer.agentPauseTarget?.(statusLayout, statusRow);
|
|
287
289
|
this.deps.mouseController.statusVoiceMicTarget = this.deps.statusLineRenderer.voiceMicTarget(statusLayout, statusRow);
|
|
288
290
|
this.deps.mouseController.statusVoiceLanguageTarget = this.deps.statusLineRenderer.voiceLanguageTarget(statusLayout, statusRow);
|
|
289
291
|
this.deps.mouseController.renderedRowTexts.set(statusRow, statusLayout.text);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { Theme } from "../../theme.js";
|
|
3
|
-
import type { SessionActivity, StatusCompactToolsTarget, StatusContextTarget, StatusDraftQueueTarget, StatusInternalClipboardTarget, StatusLineLayout, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusQuickScrollTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
3
|
+
import type { SessionActivity, StatusAgentPauseTarget, StatusCompactToolsTarget, StatusContextTarget, StatusDraftQueueTarget, StatusInternalClipboardTarget, StatusLineLayout, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusQuickScrollTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
4
4
|
import type { ScreenStyler } from "../screen/screen-styler.js";
|
|
5
5
|
import { type ModelColorsConfig } from "../../config.js";
|
|
6
6
|
export type StatusLineRendererHost = {
|
|
@@ -24,6 +24,8 @@ export type StatusLineRendererHost = {
|
|
|
24
24
|
promptEnhancerStatusWidgetEnabled(): boolean;
|
|
25
25
|
terminalBellSoundStatusWidgetText(): string;
|
|
26
26
|
terminalBellSoundStatusWidgetEnabled(): boolean;
|
|
27
|
+
agentPauseStatusWidgetText?(): string;
|
|
28
|
+
agentPauseStatusWidgetActive?(): boolean;
|
|
27
29
|
voiceStatusWidgetText(): string;
|
|
28
30
|
voiceStatusWidgetActive(): boolean;
|
|
29
31
|
conversationQuickScrollDirections?(): {
|
|
@@ -49,6 +51,7 @@ export declare class StatusLineRenderer {
|
|
|
49
51
|
contextTarget(statusText: string, row: number, layout: StatusLineLayout): StatusContextTarget | undefined;
|
|
50
52
|
modelUsageTarget(statusText: string, row: number, layout: StatusLineLayout): StatusModelUsageTarget | undefined;
|
|
51
53
|
promptEnhancerTarget(layout: StatusLineLayout, row: number): StatusPromptEnhancerTarget | undefined;
|
|
54
|
+
agentPauseTarget(layout: StatusLineLayout, row: number): StatusAgentPauseTarget | undefined;
|
|
52
55
|
voiceMicTarget(layout: StatusLineLayout, row: number): StatusVoiceMicTarget | undefined;
|
|
53
56
|
voiceLanguageTarget(layout: StatusLineLayout, row: number): StatusVoiceLanguageTarget | undefined;
|
|
54
57
|
userJumpTarget(layout: StatusLineLayout, row: number): StatusUserJumpTarget | undefined;
|
|
@@ -91,6 +91,10 @@ export class StatusLineRenderer {
|
|
|
91
91
|
appendWidget(quickScrollDirections.down ? this.iconButtonText(APP_ICONS.down) : "", (column, text) => {
|
|
92
92
|
layout.quickScrollDownWidget = this.widgetLayout(column, text);
|
|
93
93
|
});
|
|
94
|
+
const agentPauseWidgetText = this.host.agentPauseStatusWidgetText?.() ?? "";
|
|
95
|
+
appendWidget(agentPauseWidgetText ? this.iconButtonText(agentPauseWidgetText) : "", (column, text) => {
|
|
96
|
+
layout.agentPauseWidget = this.widgetLayout(column, text);
|
|
97
|
+
});
|
|
94
98
|
const voiceWidgetText = this.host.voiceStatusWidgetText();
|
|
95
99
|
appendWidget(this.voiceBorderWidgetText(voiceWidgetText), (column, text) => {
|
|
96
100
|
layout.voiceWidget = this.voiceWidgetLayout(column, voiceWidgetText, text);
|
|
@@ -156,6 +160,7 @@ export class StatusLineRenderer {
|
|
|
156
160
|
pushWidgetSegment(layout.terminalBellSoundWidget, this.host.terminalBellSoundStatusWidgetEnabled() ? colors.info : colors.muted);
|
|
157
161
|
pushWidgetSegment(layout.thinkingExpandWidget, this.host.allThinkingExpandedActive?.() ? colors.info : colors.muted);
|
|
158
162
|
pushWidgetSegment(layout.compactToolsWidget, this.host.superCompactToolsActive?.() ? colors.info : colors.muted);
|
|
163
|
+
pushWidgetSegment(layout.agentPauseWidget, this.host.agentPauseStatusWidgetActive?.() ? colors.info : colors.muted);
|
|
159
164
|
const voiceWidget = layout.voiceWidget;
|
|
160
165
|
if (voiceWidget) {
|
|
161
166
|
segments.push({
|
|
@@ -229,6 +234,12 @@ export class StatusLineRenderer {
|
|
|
229
234
|
return undefined;
|
|
230
235
|
return { row, startColumn: widget.startColumn, endColumn: widget.endColumn };
|
|
231
236
|
}
|
|
237
|
+
agentPauseTarget(layout, row) {
|
|
238
|
+
const widget = layout.agentPauseWidget;
|
|
239
|
+
if (!widget)
|
|
240
|
+
return undefined;
|
|
241
|
+
return { row, startColumn: widget.startColumn, endColumn: widget.endColumn };
|
|
242
|
+
}
|
|
232
243
|
voiceMicTarget(layout, row) {
|
|
233
244
|
const voiceWidget = layout.voiceWidget;
|
|
234
245
|
if (!voiceWidget)
|
|
@@ -359,6 +370,7 @@ export class StatusLineRenderer {
|
|
|
359
370
|
{ widget: layout.terminalBellSoundWidget, foreground: this.host.terminalBellSoundStatusWidgetEnabled() ? colors.info : colors.muted },
|
|
360
371
|
{ widget: layout.thinkingExpandWidget, foreground: this.host.allThinkingExpandedActive?.() ? colors.info : colors.muted },
|
|
361
372
|
{ widget: layout.compactToolsWidget, foreground: this.host.superCompactToolsActive?.() ? colors.info : colors.muted },
|
|
373
|
+
{ widget: layout.agentPauseWidget, foreground: this.host.agentPauseStatusWidgetActive?.() ? colors.info : colors.muted },
|
|
362
374
|
].filter((entry) => Boolean(entry.widget));
|
|
363
375
|
for (const { widget, foreground } of widgets) {
|
|
364
376
|
segments.push({
|
package/dist/app/runtime.d.ts
CHANGED
|
@@ -46,13 +46,6 @@ type RuntimeSessionManagerModelState = Pick<SessionManager, "getEntries" | "getB
|
|
|
46
46
|
export declare function resolvePixRuntimeModelRef(options: Pick<AppOptions, "modelRef">, sessionManager: RuntimeSessionManagerModelState, config?: PixConfig): string | undefined;
|
|
47
47
|
export declare function resolvePixRuntimeInitialThinkingLevel(options: Pick<AppOptions, "modelRef">, sessionManager: RuntimeSessionManagerModelState, config: PixConfig): ThinkingLevel | undefined;
|
|
48
48
|
export declare function resolveSessionModelRefFromTail(entries: readonly SessionEntry[]): string | undefined;
|
|
49
|
-
|
|
50
|
-
* pi-ai 0.84.2 predates GLM-5.3's final thinking contract. The released model
|
|
51
|
-
* is always-thinking and accepts exactly low/high/max via reasoning_effort.
|
|
52
|
-
* Patch the mutable catalog model before AgentSession clamps the selected level.
|
|
53
|
-
*/
|
|
54
|
-
export declare function patchGlm53ThinkingMetadata(model: unknown): boolean;
|
|
55
|
-
export declare function patchPixModelRuntimeCompatibility(modelRuntime: Pick<AgentSessionServices["modelRuntime"], "getModels">): number;
|
|
56
|
-
export declare function refreshPixModelRuntimeForStartup(modelRuntime: Pick<AgentSessionServices["modelRuntime"], "refresh" | "getModels">): Promise<void>;
|
|
49
|
+
export declare function refreshPixModelRuntimeForStartup(modelRuntime: Pick<AgentSessionServices["modelRuntime"], "refresh">): Promise<void>;
|
|
57
50
|
export declare function createPixRuntime(options: AppOptions, runtimeOptions?: CreatePixRuntimeOptions): Promise<AgentSessionRuntime>;
|
|
58
51
|
export {};
|
package/dist/app/runtime.js
CHANGED
|
@@ -235,49 +235,10 @@ export function resolveSessionModelRefFromTail(entries) {
|
|
|
235
235
|
return undefined;
|
|
236
236
|
return thinkingLevel ? `${modelRef}:${thinkingLevel}` : modelRef;
|
|
237
237
|
}
|
|
238
|
-
const GLM_53_THINKING_LEVEL_MAP = {
|
|
239
|
-
off: null,
|
|
240
|
-
minimal: null,
|
|
241
|
-
low: "low",
|
|
242
|
-
medium: null,
|
|
243
|
-
high: "high",
|
|
244
|
-
xhigh: null,
|
|
245
|
-
max: "max",
|
|
246
|
-
};
|
|
247
|
-
/**
|
|
248
|
-
* pi-ai 0.84.2 predates GLM-5.3's final thinking contract. The released model
|
|
249
|
-
* is always-thinking and accepts exactly low/high/max via reasoning_effort.
|
|
250
|
-
* Patch the mutable catalog model before AgentSession clamps the selected level.
|
|
251
|
-
*/
|
|
252
|
-
export function patchGlm53ThinkingMetadata(model) {
|
|
253
|
-
if (!model || typeof model !== "object" || Array.isArray(model))
|
|
254
|
-
return false;
|
|
255
|
-
const candidate = model;
|
|
256
|
-
if (candidate.id !== "glm-5.3")
|
|
257
|
-
return false;
|
|
258
|
-
if (!candidate.compat || typeof candidate.compat !== "object" || Array.isArray(candidate.compat))
|
|
259
|
-
return false;
|
|
260
|
-
const compat = candidate.compat;
|
|
261
|
-
if (compat.thinkingFormat !== "zai")
|
|
262
|
-
return false;
|
|
263
|
-
candidate.reasoning = true;
|
|
264
|
-
candidate.thinkingLevelMap = { ...GLM_53_THINKING_LEVEL_MAP };
|
|
265
|
-
candidate.compat = { ...compat, supportsReasoningEffort: true };
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
export function patchPixModelRuntimeCompatibility(modelRuntime) {
|
|
269
|
-
let patched = 0;
|
|
270
|
-
for (const model of modelRuntime.getModels()) {
|
|
271
|
-
if (patchGlm53ThinkingMetadata(model))
|
|
272
|
-
patched += 1;
|
|
273
|
-
}
|
|
274
|
-
return patched;
|
|
275
|
-
}
|
|
276
238
|
export async function refreshPixModelRuntimeForStartup(modelRuntime) {
|
|
277
239
|
// Startup only needs the locally configured model catalog. Remote catalog
|
|
278
240
|
// refreshes belong to explicit model-management flows and must not block boot.
|
|
279
241
|
await modelRuntime.refresh({ allowNetwork: false });
|
|
280
|
-
patchPixModelRuntimeCompatibility(modelRuntime);
|
|
281
242
|
}
|
|
282
243
|
export async function createPixRuntime(options, runtimeOptions = {}) {
|
|
283
244
|
const agentDir = getAgentDir();
|
|
@@ -6,7 +6,7 @@ import type { ToastEntry, ToastVariant } from "../../ui.js";
|
|
|
6
6
|
import type { AppPopupActionController } from "../popup/popup-action-controller.js";
|
|
7
7
|
import type { AppPopupMenuController } from "../popup/popup-menu-controller.js";
|
|
8
8
|
import type { AppScrollController } from "./scroll-controller.js";
|
|
9
|
-
import type { Entry, ImageClickTarget, MouseEvent, MouseSelection, StatusContextTarget, StatusCompactToolsTarget, StatusDraftQueueTarget, StatusInternalClipboardTarget, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusQuickScrollTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, TabLineMouseTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
9
|
+
import type { Entry, ImageClickTarget, MouseEvent, MouseSelection, StatusAgentPauseTarget, StatusContextTarget, StatusCompactToolsTarget, StatusDraftQueueTarget, StatusInternalClipboardTarget, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusQuickScrollTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, TabLineMouseTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
10
10
|
import { type RenderedLink } from "./file-links.js";
|
|
11
11
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
type ClickFlash = {
|
|
@@ -63,6 +63,7 @@ export type AppMouseControllerHost = {
|
|
|
63
63
|
toggleAllThinkingExpanded?(): void;
|
|
64
64
|
toggleSuperCompactTools?(): void;
|
|
65
65
|
toggleTerminalBellSound?(): void;
|
|
66
|
+
toggleAgentPause?(): void | Promise<void>;
|
|
66
67
|
copyTextToClipboard?(text: string): void | Promise<void>;
|
|
67
68
|
handleExtensionInputMouse(event: MouseEvent & {
|
|
68
69
|
localRow: number;
|
|
@@ -114,6 +115,7 @@ export declare class AppMouseController {
|
|
|
114
115
|
statusTerminalBellSoundTarget: StatusTerminalBellSoundTarget | undefined;
|
|
115
116
|
statusSessionTarget: StatusSessionTarget | undefined;
|
|
116
117
|
statusPromptEnhancerTarget: StatusPromptEnhancerTarget | undefined;
|
|
118
|
+
statusAgentPauseTarget: StatusAgentPauseTarget | undefined;
|
|
117
119
|
statusVoiceMicTarget: StatusVoiceMicTarget | undefined;
|
|
118
120
|
statusVoiceLanguageTarget: StatusVoiceLanguageTarget | undefined;
|
|
119
121
|
readonly tabLineTargets: TabLineMouseTarget[];
|
|
@@ -172,6 +174,7 @@ export declare class AppMouseController {
|
|
|
172
174
|
private handleStatusTerminalBellSoundClick;
|
|
173
175
|
private handleStatusSessionClick;
|
|
174
176
|
private handleStatusPromptEnhancerClick;
|
|
177
|
+
private handleStatusAgentPauseClick;
|
|
175
178
|
private handleStatusVoiceMicClick;
|
|
176
179
|
private handleStatusVoiceLanguageClick;
|
|
177
180
|
private handleStatusQuickScrollClick;
|
|
@@ -35,6 +35,7 @@ export class AppMouseController {
|
|
|
35
35
|
statusTerminalBellSoundTarget;
|
|
36
36
|
statusSessionTarget;
|
|
37
37
|
statusPromptEnhancerTarget;
|
|
38
|
+
statusAgentPauseTarget;
|
|
38
39
|
statusVoiceMicTarget;
|
|
39
40
|
statusVoiceLanguageTarget;
|
|
40
41
|
tabLineTargets = [];
|
|
@@ -333,6 +334,7 @@ export class AppMouseController {
|
|
|
333
334
|
this.statusTerminalBellSoundTarget,
|
|
334
335
|
this.statusSessionTarget,
|
|
335
336
|
this.statusPromptEnhancerTarget,
|
|
337
|
+
this.statusAgentPauseTarget,
|
|
336
338
|
this.statusVoiceMicTarget,
|
|
337
339
|
this.statusVoiceLanguageTarget,
|
|
338
340
|
].find((candidate) => !!candidate
|
|
@@ -510,6 +512,7 @@ export class AppMouseController {
|
|
|
510
512
|
|| this.handleStatusCompactToolsClick(event)
|
|
511
513
|
|| this.handleStatusTerminalBellSoundClick(event)
|
|
512
514
|
|| this.handleStatusPromptEnhancerClick(event)
|
|
515
|
+
|| this.handleStatusAgentPauseClick(event)
|
|
513
516
|
|| this.handleStatusVoiceMicClick(event)
|
|
514
517
|
|| this.handleStatusVoiceLanguageClick(event);
|
|
515
518
|
}
|
|
@@ -570,6 +573,12 @@ export class AppMouseController {
|
|
|
570
573
|
void this.host.enhancePrompt();
|
|
571
574
|
return true;
|
|
572
575
|
}
|
|
576
|
+
handleStatusAgentPauseClick(event) {
|
|
577
|
+
if (!this.statusTargetContains(this.statusAgentPauseTarget, event))
|
|
578
|
+
return false;
|
|
579
|
+
void this.host.toggleAgentPause?.();
|
|
580
|
+
return true;
|
|
581
|
+
}
|
|
573
582
|
handleStatusVoiceMicClick(event) {
|
|
574
583
|
if (!this.statusTargetContains(this.statusVoiceMicTarget, event))
|
|
575
584
|
return false;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export type AgentPauseState = "idle" | "pause-requested" | "paused" | "resuming";
|
|
3
|
+
export type AgentPauseControllerHost = {
|
|
4
|
+
showToast(message: string, kind: "success" | "error" | "warning" | "info"): void;
|
|
5
|
+
render(): void;
|
|
6
|
+
isCurrentSession(session: AgentSession): boolean;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Implements a turn-boundary pause without interrupting an active tool batch.
|
|
10
|
+
*
|
|
11
|
+
* The pinned SDK exposes Agent.shouldStopAfterTurn and Agent.continue(), but not a
|
|
12
|
+
* session-level continuation method. The small private adapter below mirrors the
|
|
13
|
+
* bookkeeping in AgentSession._runAgentPrompt so resumed runs still get retries,
|
|
14
|
+
* compaction, queue draining, isStreaming, and agent_settled behavior.
|
|
15
|
+
*/
|
|
16
|
+
export declare class AgentPauseController {
|
|
17
|
+
private readonly host;
|
|
18
|
+
private readonly records;
|
|
19
|
+
constructor(host: AgentPauseControllerHost);
|
|
20
|
+
bind(session: AgentSession): void;
|
|
21
|
+
state(session: AgentSession | undefined): AgentPauseState;
|
|
22
|
+
statusWidgetText(session: AgentSession | undefined): string;
|
|
23
|
+
statusWidgetActive(session: AgentSession | undefined): boolean;
|
|
24
|
+
toggle(session: AgentSession | undefined): Promise<void>;
|
|
25
|
+
private resume;
|
|
26
|
+
private setState;
|
|
27
|
+
private finishSettlement;
|
|
28
|
+
private canContinue;
|
|
29
|
+
private sessionInternals;
|
|
30
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { APP_ICONS } from "../icons.js";
|
|
2
|
+
/**
|
|
3
|
+
* Implements a turn-boundary pause without interrupting an active tool batch.
|
|
4
|
+
*
|
|
5
|
+
* The pinned SDK exposes Agent.shouldStopAfterTurn and Agent.continue(), but not a
|
|
6
|
+
* session-level continuation method. The small private adapter below mirrors the
|
|
7
|
+
* bookkeeping in AgentSession._runAgentPrompt so resumed runs still get retries,
|
|
8
|
+
* compaction, queue draining, isStreaming, and agent_settled behavior.
|
|
9
|
+
*/
|
|
10
|
+
export class AgentPauseController {
|
|
11
|
+
host;
|
|
12
|
+
records = new WeakMap();
|
|
13
|
+
constructor(host) {
|
|
14
|
+
this.host = host;
|
|
15
|
+
}
|
|
16
|
+
bind(session) {
|
|
17
|
+
if (this.records.has(session))
|
|
18
|
+
return;
|
|
19
|
+
const internals = this.sessionInternals(session);
|
|
20
|
+
const record = {
|
|
21
|
+
state: "idle",
|
|
22
|
+
pauseBoundaryReached: false,
|
|
23
|
+
originalHandlePostAgentRun: internals._handlePostAgentRun.bind(session),
|
|
24
|
+
};
|
|
25
|
+
this.records.set(session, record);
|
|
26
|
+
session.subscribe((event) => {
|
|
27
|
+
if (event.type === "agent_start" && record.state === "paused") {
|
|
28
|
+
// A new prompt supersedes a paused continuation.
|
|
29
|
+
this.setState(record, "idle");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const originalEmitAgentSettled = internals._emitAgentSettled.bind(session);
|
|
33
|
+
internals._emitAgentSettled = async () => {
|
|
34
|
+
try {
|
|
35
|
+
await originalEmitAgentSettled();
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
this.finishSettlement(record);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const originalShouldStopAfterTurn = session.agent.shouldStopAfterTurn;
|
|
42
|
+
const shouldStopAfterTurn = async (context, signal) => {
|
|
43
|
+
if (await originalShouldStopAfterTurn?.(context, signal)) {
|
|
44
|
+
if (record.state === "pause-requested") {
|
|
45
|
+
record.pauseBoundaryReached = false;
|
|
46
|
+
this.setState(record, "idle");
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
if (record.state !== "pause-requested")
|
|
51
|
+
return false;
|
|
52
|
+
record.pauseBoundaryReached = true;
|
|
53
|
+
return true;
|
|
54
|
+
};
|
|
55
|
+
session.agent.shouldStopAfterTurn = shouldStopAfterTurn;
|
|
56
|
+
internals._handlePostAgentRun = async () => {
|
|
57
|
+
if (record.state === "paused")
|
|
58
|
+
return false;
|
|
59
|
+
const pauseBoundaryReached = record.pauseBoundaryReached;
|
|
60
|
+
record.pauseBoundaryReached = false;
|
|
61
|
+
const shouldContinue = await record.originalHandlePostAgentRun();
|
|
62
|
+
if (pauseBoundaryReached || record.state === "pause-requested") {
|
|
63
|
+
if (shouldContinue || this.canContinue(session)) {
|
|
64
|
+
record.pauseSettled = new Promise((resolve) => {
|
|
65
|
+
record.resolvePauseSettled = resolve;
|
|
66
|
+
});
|
|
67
|
+
this.setState(record, "paused");
|
|
68
|
+
this.host.showToast("Agent paused after the current turn", "success");
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
this.setState(record, "idle");
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return shouldContinue;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
state(session) {
|
|
78
|
+
if (!session)
|
|
79
|
+
return "idle";
|
|
80
|
+
return this.records.get(session)?.state ?? "idle";
|
|
81
|
+
}
|
|
82
|
+
statusWidgetText(session) {
|
|
83
|
+
return this.state(session) === "paused" ? APP_ICONS.play : APP_ICONS.pause;
|
|
84
|
+
}
|
|
85
|
+
statusWidgetActive(session) {
|
|
86
|
+
if (!session)
|
|
87
|
+
return false;
|
|
88
|
+
return this.state(session) !== "idle" || session.isStreaming || session.agent.state.isStreaming;
|
|
89
|
+
}
|
|
90
|
+
async toggle(session) {
|
|
91
|
+
if (!session) {
|
|
92
|
+
this.host.showToast("No active agent session", "info");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.bind(session);
|
|
96
|
+
const record = this.records.get(session);
|
|
97
|
+
if (record.state === "paused") {
|
|
98
|
+
await this.resume(session, record);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (record.state === "pause-requested" || record.state === "resuming")
|
|
102
|
+
return;
|
|
103
|
+
if (!session.isStreaming && !session.agent.state.isStreaming) {
|
|
104
|
+
this.host.showToast("Agent is not running", "info");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.setState(record, "pause-requested");
|
|
108
|
+
this.host.showToast("Pause requested; waiting for the current turn to finish", "info");
|
|
109
|
+
}
|
|
110
|
+
async resume(session, record) {
|
|
111
|
+
this.setState(record, "resuming");
|
|
112
|
+
this.host.showToast("Continuing agent", "info");
|
|
113
|
+
try {
|
|
114
|
+
// isIdle becomes true before async agent_settled extension handlers finish,
|
|
115
|
+
// so wait for the event itself rather than relying on waitForIdle().
|
|
116
|
+
await record.pauseSettled;
|
|
117
|
+
if (!this.host.isCurrentSession(session)) {
|
|
118
|
+
throw new Error("agent session changed before it could continue");
|
|
119
|
+
}
|
|
120
|
+
const internals = this.sessionInternals(session);
|
|
121
|
+
internals._isAgentRunActive = true;
|
|
122
|
+
try {
|
|
123
|
+
// Continue exactly as AgentSession._runAgentPrompt would.
|
|
124
|
+
await session.agent.continue();
|
|
125
|
+
while (this.host.isCurrentSession(session)) {
|
|
126
|
+
const shouldContinue = await record.originalHandlePostAgentRun();
|
|
127
|
+
if (!shouldContinue || !this.host.isCurrentSession(session))
|
|
128
|
+
break;
|
|
129
|
+
await session.agent.continue();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
internals._systemPromptOverride = undefined;
|
|
134
|
+
internals._flushPendingBashMessages();
|
|
135
|
+
await internals._emitAgentSettled();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
this.setState(record, "paused");
|
|
140
|
+
this.host.showToast(`Could not continue agent: ${errorMessage(error)}`, "error");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this.setState(record, "idle");
|
|
144
|
+
}
|
|
145
|
+
setState(record, state) {
|
|
146
|
+
if (record.state === state)
|
|
147
|
+
return;
|
|
148
|
+
record.state = state;
|
|
149
|
+
this.host.render();
|
|
150
|
+
}
|
|
151
|
+
finishSettlement(record) {
|
|
152
|
+
record.resolvePauseSettled?.();
|
|
153
|
+
delete record.resolvePauseSettled;
|
|
154
|
+
if (record.state === "pause-requested") {
|
|
155
|
+
record.pauseBoundaryReached = false;
|
|
156
|
+
this.setState(record, "idle");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
canContinue(session) {
|
|
160
|
+
const messages = session.agent.state.messages;
|
|
161
|
+
const lastMessage = messages[messages.length - 1];
|
|
162
|
+
return Boolean(lastMessage && lastMessage.role !== "assistant") || session.agent.hasQueuedMessages();
|
|
163
|
+
}
|
|
164
|
+
sessionInternals(session) {
|
|
165
|
+
const internals = session;
|
|
166
|
+
if (typeof internals._handlePostAgentRun !== "function"
|
|
167
|
+
|| typeof internals._flushPendingBashMessages !== "function"
|
|
168
|
+
|| typeof internals._emitAgentSettled !== "function"
|
|
169
|
+
|| typeof internals._isAgentRunActive !== "boolean"
|
|
170
|
+
|| !("_systemPromptOverride" in internals)) {
|
|
171
|
+
throw new Error("Agent pause is incompatible with this pi SDK version");
|
|
172
|
+
}
|
|
173
|
+
return internals;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function errorMessage(error) {
|
|
177
|
+
return error instanceof Error ? error.message : String(error);
|
|
178
|
+
}
|
|
@@ -144,6 +144,7 @@ export declare class AppSessionEventController {
|
|
|
144
144
|
touchEntry(entry: Entry): void;
|
|
145
145
|
addEntry(entry: Entry): void;
|
|
146
146
|
prependEntries(entries: readonly Entry[]): void;
|
|
147
|
+
private prependLoadedHistoryEntries;
|
|
147
148
|
private shiftHistoryWindow;
|
|
148
149
|
private setHistoryWindowStart;
|
|
149
150
|
private historyWindowSize;
|