@astralyn/pi 0.84.2 → 0.84.4
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 +41 -0
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -3
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/project-trust.d.ts.map +1 -1
- package/dist/cli/project-trust.js +1 -4
- package/dist/cli/project-trust.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +3 -5
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -25
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +29 -408
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +89 -0
- package/dist/core/compaction-controller.d.ts.map +1 -0
- package/dist/core/compaction-controller.js +428 -0
- package/dist/core/compaction-controller.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.js +3 -3
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -27
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/provider-attribution.js +2 -2
- package/dist/core/provider-attribution.js.map +1 -1
- package/dist/core/settings-manager.js +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/telemetry.d.ts +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/extensions/deepwiki/index.d.ts.map +1 -1
- package/dist/extensions/deepwiki/index.js +23 -1
- package/dist/extensions/deepwiki/index.js.map +1 -1
- package/dist/extensions/deepwiki/render.d.ts +1 -1
- package/dist/extensions/deepwiki/render.d.ts.map +1 -1
- package/dist/extensions/deepwiki/render.js +4 -2
- package/dist/extensions/deepwiki/render.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js +0 -1
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts +4 -0
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -0
- package/dist/extensions/subagent/agents-command.js +230 -0
- package/dist/extensions/subagent/agents-command.js.map +1 -0
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +2 -0
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/display-name.d.ts +6 -0
- package/dist/extensions/subagent/display-name.d.ts.map +1 -0
- package/dist/extensions/subagent/display-name.js +13 -0
- package/dist/extensions/subagent/display-name.js.map +1 -0
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +19 -126
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +1 -10
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/settings.d.ts +0 -1
- package/dist/extensions/subagent/settings.d.ts.map +1 -1
- package/dist/extensions/subagent/settings.js +3 -7
- package/dist/extensions/subagent/settings.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +2 -0
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/subagent/ui/model-list.d.ts +67 -0
- package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/model-list.js +242 -0
- package/dist/extensions/subagent/ui/model-list.js.map +1 -0
- package/dist/extensions/subagent/ui/profile-editor.d.ts +54 -0
- package/dist/extensions/subagent/ui/profile-editor.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/profile-editor.js +154 -0
- package/dist/extensions/subagent/ui/profile-editor.js.map +1 -0
- package/dist/extensions/subagent/ui/profile-picker.d.ts +32 -0
- package/dist/extensions/subagent/ui/profile-picker.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/profile-picker.js +149 -0
- package/dist/extensions/subagent/ui/profile-picker.js.map +1 -0
- package/dist/extensions/todo/constants.d.ts +6 -17
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js +20 -31
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +36 -57
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +20 -59
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/schema.js +23 -69
- package/dist/extensions/todo/schema.js.map +1 -1
- package/dist/extensions/todo/state.d.ts +23 -65
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js +238 -1262
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +19 -10
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +411 -463
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/extensions/todo/widget.d.ts +15 -0
- package/dist/extensions/todo/widget.d.ts.map +1 -0
- package/dist/extensions/todo/widget.js +50 -0
- package/dist/extensions/todo/widget.js.map +1 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -4
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +6 -12
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts +28 -0
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-chrome.js +81 -0
- package/dist/modes/interactive/components/tool-chrome.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +0 -3
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +11 -108
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +35 -52
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -8
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/subagent.md +20 -5
- package/docs/bundled/extensions/todo.md +84 -24
- package/docs/bundled/tool-presentation.md +3 -3
- package/docs/extensions.md +6 -23
- package/docs/settings.md +1 -1
- package/docs/usage.md +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/extensions/subagent/picker.d.ts +0 -31
- package/dist/extensions/subagent/picker.d.ts.map +0 -1
- package/dist/extensions/subagent/picker.js +0 -109
- package/dist/extensions/subagent/picker.js.map +0 -1
- package/dist/extensions/todo/overlay.d.ts +0 -24
- package/dist/extensions/todo/overlay.d.ts.map +0 -1
- package/dist/extensions/todo/overlay.js +0 -135
- package/dist/extensions/todo/overlay.js.map +0 -1
- package/dist/utils/coalescing-terminal.d.ts +0 -132
- package/dist/utils/coalescing-terminal.d.ts.map +0 -1
- package/dist/utils/coalescing-terminal.js +0 -292
- package/dist/utils/coalescing-terminal.js.map +0 -1
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Container, type Focusable } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { Theme } from "../../modes/interactive/theme/theme.ts";
|
|
3
|
-
export interface PickerItem<T> {
|
|
4
|
-
value: T;
|
|
5
|
-
label: string;
|
|
6
|
-
detail?: string;
|
|
7
|
-
current?: boolean;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Searchable selector matching the native /model experience: type to
|
|
11
|
-
* fuzzy-filter, arrows wrap around the list, enter confirms, escape
|
|
12
|
-
* cancels (resolves undefined). Mounted via ctx.ui.custom().
|
|
13
|
-
*/
|
|
14
|
-
export declare class SearchPickerComponent<T> extends Container implements Focusable {
|
|
15
|
-
private readonly theme;
|
|
16
|
-
private readonly items;
|
|
17
|
-
private readonly onDone;
|
|
18
|
-
private readonly searchInput;
|
|
19
|
-
private readonly listContainer;
|
|
20
|
-
private filtered;
|
|
21
|
-
private selectedIndex;
|
|
22
|
-
private _focused;
|
|
23
|
-
get focused(): boolean;
|
|
24
|
-
set focused(value: boolean);
|
|
25
|
-
constructor(theme: Theme, title: string, items: PickerItem<T>[], onDone: (value: T | undefined) => void);
|
|
26
|
-
private filter;
|
|
27
|
-
private confirm;
|
|
28
|
-
private updateList;
|
|
29
|
-
handleInput(keyData: string): void;
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=picker.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/picker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAoD,MAAM,wBAAwB,CAAC;AAGrH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAEpE,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAID;;;;GAIG;AACH,qBAAa,qBAAqB,CAAC,CAAC,CAAE,SAAQ,SAAU,YAAW,SAAS;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAY;IAC1C,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,aAAa,CAAK;IAE1B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;gBAEW,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI;IA8BvG,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,UAAU;IAiClB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAmBlC"}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { Container, fuzzyFilter, getKeybindings, Input, Spacer, Text } from "@earendil-works/pi-tui";
|
|
2
|
-
import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
|
|
3
|
-
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
4
|
-
const MAX_VISIBLE = 10;
|
|
5
|
-
/**
|
|
6
|
-
* Searchable selector matching the native /model experience: type to
|
|
7
|
-
* fuzzy-filter, arrows wrap around the list, enter confirms, escape
|
|
8
|
-
* cancels (resolves undefined). Mounted via ctx.ui.custom().
|
|
9
|
-
*/
|
|
10
|
-
export class SearchPickerComponent extends Container {
|
|
11
|
-
get focused() {
|
|
12
|
-
return this._focused;
|
|
13
|
-
}
|
|
14
|
-
set focused(value) {
|
|
15
|
-
this._focused = value;
|
|
16
|
-
this.searchInput.focused = value;
|
|
17
|
-
}
|
|
18
|
-
constructor(theme, title, items, onDone) {
|
|
19
|
-
super();
|
|
20
|
-
this.selectedIndex = 0;
|
|
21
|
-
this._focused = false;
|
|
22
|
-
this.theme = theme;
|
|
23
|
-
this.items = items;
|
|
24
|
-
this.onDone = onDone;
|
|
25
|
-
this.filtered = items;
|
|
26
|
-
const currentIndex = items.findIndex((item) => item.current);
|
|
27
|
-
if (currentIndex >= 0)
|
|
28
|
-
this.selectedIndex = currentIndex;
|
|
29
|
-
this.addChild(new DynamicBorder());
|
|
30
|
-
this.addChild(new Spacer(1));
|
|
31
|
-
this.addChild(new Text(theme.fg("toolTitle", theme.bold(title)), 0, 0));
|
|
32
|
-
this.addChild(new Spacer(1));
|
|
33
|
-
this.searchInput = new Input();
|
|
34
|
-
this.addChild(this.searchInput);
|
|
35
|
-
this.addChild(new Spacer(1));
|
|
36
|
-
this.listContainer = new Container();
|
|
37
|
-
this.addChild(this.listContainer);
|
|
38
|
-
this.addChild(new Spacer(1));
|
|
39
|
-
this.addChild(new Text(`${theme.fg("muted", "↑↓")} ${theme.fg("dim", "navigate")} ${keyHint("tui.select.confirm", "select")} ${keyHint("tui.select.cancel", "cancel")}`, 0, 0));
|
|
40
|
-
this.addChild(new DynamicBorder());
|
|
41
|
-
this.updateList();
|
|
42
|
-
}
|
|
43
|
-
filter(query) {
|
|
44
|
-
this.filtered = query
|
|
45
|
-
? fuzzyFilter(this.items, query, (item) => `${item.label} ${item.detail ?? ""}`)
|
|
46
|
-
: this.items;
|
|
47
|
-
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filtered.length - 1));
|
|
48
|
-
this.updateList();
|
|
49
|
-
}
|
|
50
|
-
confirm() {
|
|
51
|
-
const selected = this.filtered[this.selectedIndex];
|
|
52
|
-
if (selected)
|
|
53
|
-
this.onDone(selected.value);
|
|
54
|
-
}
|
|
55
|
-
updateList() {
|
|
56
|
-
this.listContainer.clear();
|
|
57
|
-
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(MAX_VISIBLE / 2), this.filtered.length - MAX_VISIBLE));
|
|
58
|
-
const endIndex = Math.min(startIndex + MAX_VISIBLE, this.filtered.length);
|
|
59
|
-
for (let index = startIndex; index < endIndex; index++) {
|
|
60
|
-
const item = this.filtered[index];
|
|
61
|
-
if (!item)
|
|
62
|
-
continue;
|
|
63
|
-
const isSelected = index === this.selectedIndex;
|
|
64
|
-
const marker = item.current ? this.theme.fg("success", " ✓") : "";
|
|
65
|
-
const line = isSelected
|
|
66
|
-
? `${this.theme.fg("accent", "→ ")}${this.theme.fg("accent", item.label)}${marker}`
|
|
67
|
-
: ` ${item.label}${marker}`;
|
|
68
|
-
this.listContainer.addChild(new Text(line, 0, 0));
|
|
69
|
-
}
|
|
70
|
-
if (startIndex > 0 || endIndex < this.filtered.length) {
|
|
71
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filtered.length})`), 0, 0));
|
|
72
|
-
}
|
|
73
|
-
if (this.filtered.length === 0) {
|
|
74
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", " No matches"), 0, 0));
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const detail = this.filtered[this.selectedIndex]?.detail;
|
|
78
|
-
if (detail) {
|
|
79
|
-
this.listContainer.addChild(new Spacer(1));
|
|
80
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", ` ${detail}`), 0, 0));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
handleInput(keyData) {
|
|
84
|
-
const kb = getKeybindings();
|
|
85
|
-
if (kb.matches(keyData, "tui.select.up")) {
|
|
86
|
-
if (this.filtered.length === 0)
|
|
87
|
-
return;
|
|
88
|
-
this.selectedIndex = this.selectedIndex === 0 ? this.filtered.length - 1 : this.selectedIndex - 1;
|
|
89
|
-
this.updateList();
|
|
90
|
-
}
|
|
91
|
-
else if (kb.matches(keyData, "tui.select.down")) {
|
|
92
|
-
if (this.filtered.length === 0)
|
|
93
|
-
return;
|
|
94
|
-
this.selectedIndex = this.selectedIndex === this.filtered.length - 1 ? 0 : this.selectedIndex + 1;
|
|
95
|
-
this.updateList();
|
|
96
|
-
}
|
|
97
|
-
else if (kb.matches(keyData, "tui.select.confirm")) {
|
|
98
|
-
this.confirm();
|
|
99
|
-
}
|
|
100
|
-
else if (kb.matches(keyData, "tui.select.cancel")) {
|
|
101
|
-
this.onDone(undefined);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
this.searchInput.handleInput(keyData);
|
|
105
|
-
this.filter(this.searchInput.getValue());
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=picker.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"picker.js","sourceRoot":"","sources":["../../../src/extensions/subagent/picker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, type Focusable, fuzzyFilter, getKeybindings, Input, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport { DynamicBorder } from \"../../modes/interactive/components/dynamic-border.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\nexport interface PickerItem<T> {\n\tvalue: T;\n\tlabel: string;\n\tdetail?: string;\n\tcurrent?: boolean;\n}\n\nconst MAX_VISIBLE = 10;\n\n/**\n * Searchable selector matching the native /model experience: type to\n * fuzzy-filter, arrows wrap around the list, enter confirms, escape\n * cancels (resolves undefined). Mounted via ctx.ui.custom().\n */\nexport class SearchPickerComponent<T> extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly items: PickerItem<T>[];\n\tprivate readonly onDone: (value: T | undefined) => void;\n\tprivate readonly searchInput: Input;\n\tprivate readonly listContainer: Container;\n\tprivate filtered: PickerItem<T>[];\n\tprivate selectedIndex = 0;\n\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(theme: Theme, title: string, items: PickerItem<T>[], onDone: (value: T | undefined) => void) {\n\t\tsuper();\n\t\tthis.theme = theme;\n\t\tthis.items = items;\n\t\tthis.onDone = onDone;\n\t\tthis.filtered = items;\n\t\tconst currentIndex = items.findIndex((item) => item.current);\n\t\tif (currentIndex >= 0) this.selectedIndex = currentIndex;\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"toolTitle\", theme.bold(title)), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(\n\t\t\t\t`${theme.fg(\"muted\", \"↑↓\")} ${theme.fg(\"dim\", \"navigate\")} ${keyHint(\"tui.select.confirm\", \"select\")} ${keyHint(\"tui.select.cancel\", \"cancel\")}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.updateList();\n\t}\n\n\tprivate filter(query: string): void {\n\t\tthis.filtered = query\n\t\t\t? fuzzyFilter(this.items, query, (item) => `${item.label} ${item.detail ?? \"\"}`)\n\t\t\t: this.items;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filtered.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate confirm(): void {\n\t\tconst selected = this.filtered[this.selectedIndex];\n\t\tif (selected) this.onDone(selected.value);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(MAX_VISIBLE / 2), this.filtered.length - MAX_VISIBLE),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + MAX_VISIBLE, this.filtered.length);\n\t\tfor (let index = startIndex; index < endIndex; index++) {\n\t\t\tconst item = this.filtered[index];\n\t\t\tif (!item) continue;\n\t\t\tconst isSelected = index === this.selectedIndex;\n\t\t\tconst marker = item.current ? this.theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tconst line = isSelected\n\t\t\t\t? `${this.theme.fg(\"accent\", \"→ \")}${this.theme.fg(\"accent\", item.label)}${marker}`\n\t\t\t\t: ` ${item.label}${marker}`;\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\t\tif (startIndex > 0 || endIndex < this.filtered.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(this.theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filtered.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\t\tif (this.filtered.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", \" No matches\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\t\tconst detail = this.filtered[this.selectedIndex]?.detail;\n\t\tif (detail) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", ` ${detail}`), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filtered.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filtered.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filtered.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filtered.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t} else if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tthis.confirm();\n\t\t} else if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onDone(undefined);\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filter(this.searchInput.getValue());\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { ExtensionUIContext } from "../../core/extensions/types.ts";
|
|
2
|
-
export declare class TodoOverlay {
|
|
3
|
-
private ui;
|
|
4
|
-
private tui;
|
|
5
|
-
private registered;
|
|
6
|
-
private knownStatuses;
|
|
7
|
-
private completedAt;
|
|
8
|
-
private hiddenCompleted;
|
|
9
|
-
private completionHideTimer;
|
|
10
|
-
/** Pure render cache: same width + visibility state → skip rebuild. */
|
|
11
|
-
private cachedWidth;
|
|
12
|
-
private cachedLines;
|
|
13
|
-
setUI(ui: ExtensionUIContext): void;
|
|
14
|
-
resetVisibility(): void;
|
|
15
|
-
update(): void;
|
|
16
|
-
/** Track new completions for a short confirmation window; hide historical ones. */
|
|
17
|
-
private syncVisibilityFromState;
|
|
18
|
-
private scheduleCompletionHide;
|
|
19
|
-
private clearCompletionHideTimer;
|
|
20
|
-
private invalidateRenderCache;
|
|
21
|
-
private render;
|
|
22
|
-
dispose(): void;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=overlay.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/overlay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAUzE,qBAAa,WAAW;IACvB,OAAO,CAAC,EAAE,CAAiC;IAC3C,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,mBAAmB,CAA4C;IACvE,uEAAuE;IACvE,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,WAAW,CAAuB;IAE1C,KAAK,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI;IAMnC,eAAe,IAAI,IAAI;IAQvB,MAAM,IAAI,IAAI;IAoCd,mFAAmF;IACnF,OAAO,CAAC,uBAAuB;IAyC/B,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,MAAM;IAUd,OAAO,IAAI,IAAI;CAOf"}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { getTodoState } from "./state.js";
|
|
2
|
-
import { hasVisibleOverlayItems, renderOverlayLines } from "./view.js";
|
|
3
|
-
const WIDGET_KEY = "todos";
|
|
4
|
-
const RECENT_COMPLETION_MS = 30_000;
|
|
5
|
-
export class TodoOverlay {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.registered = false;
|
|
8
|
-
this.knownStatuses = new Map();
|
|
9
|
-
this.completedAt = new Map();
|
|
10
|
-
this.hiddenCompleted = new Set();
|
|
11
|
-
}
|
|
12
|
-
setUI(ui) {
|
|
13
|
-
if (this.ui === ui)
|
|
14
|
-
return;
|
|
15
|
-
this.dispose();
|
|
16
|
-
this.ui = ui;
|
|
17
|
-
}
|
|
18
|
-
resetVisibility() {
|
|
19
|
-
this.clearCompletionHideTimer();
|
|
20
|
-
this.knownStatuses.clear();
|
|
21
|
-
this.completedAt.clear();
|
|
22
|
-
this.hiddenCompleted.clear();
|
|
23
|
-
this.invalidateRenderCache();
|
|
24
|
-
}
|
|
25
|
-
update() {
|
|
26
|
-
if (!this.ui)
|
|
27
|
-
return;
|
|
28
|
-
const state = getTodoState();
|
|
29
|
-
this.syncVisibilityFromState(state);
|
|
30
|
-
this.invalidateRenderCache();
|
|
31
|
-
// Register/unregister based on state, never as a render side effect.
|
|
32
|
-
if (!hasVisibleOverlayItems(state, this.hiddenCompleted)) {
|
|
33
|
-
if (this.registered)
|
|
34
|
-
this.ui.setWidget(WIDGET_KEY, undefined);
|
|
35
|
-
this.registered = false;
|
|
36
|
-
this.tui = undefined;
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (!this.registered) {
|
|
40
|
-
this.ui.setWidget(WIDGET_KEY, (tui, theme) => {
|
|
41
|
-
this.tui = tui;
|
|
42
|
-
return {
|
|
43
|
-
render: (width) => this.render(theme, width),
|
|
44
|
-
invalidate: () => {
|
|
45
|
-
this.registered = false;
|
|
46
|
-
this.tui = undefined;
|
|
47
|
-
this.invalidateRenderCache();
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}, { placement: "aboveEditor" });
|
|
51
|
-
this.registered = true;
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
this.tui?.requestRender();
|
|
55
|
-
}
|
|
56
|
-
/** Track new completions for a short confirmation window; hide historical ones. */
|
|
57
|
-
syncVisibilityFromState(state) {
|
|
58
|
-
const now = Date.now();
|
|
59
|
-
const nextStatuses = new Map();
|
|
60
|
-
for (const item of state.items) {
|
|
61
|
-
nextStatuses.set(item.id, item.status);
|
|
62
|
-
const previousStatus = this.knownStatuses.get(item.id);
|
|
63
|
-
if (item.status !== "completed") {
|
|
64
|
-
this.completedAt.delete(item.id);
|
|
65
|
-
this.hiddenCompleted.delete(item.id);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (previousStatus === undefined) {
|
|
69
|
-
// A replayed/reloaded completion is old from this overlay's point of
|
|
70
|
-
// view. Keep the live surface focused on current work.
|
|
71
|
-
this.hiddenCompleted.add(item.id);
|
|
72
|
-
this.completedAt.delete(item.id);
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (previousStatus !== "completed") {
|
|
76
|
-
this.completedAt.set(item.id, now);
|
|
77
|
-
this.hiddenCompleted.delete(item.id);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
for (const id of this.knownStatuses.keys()) {
|
|
81
|
-
if (nextStatuses.has(id))
|
|
82
|
-
continue;
|
|
83
|
-
this.completedAt.delete(id);
|
|
84
|
-
this.hiddenCompleted.delete(id);
|
|
85
|
-
}
|
|
86
|
-
this.knownStatuses = nextStatuses;
|
|
87
|
-
for (const [id, completedAt] of this.completedAt) {
|
|
88
|
-
if (now - completedAt < RECENT_COMPLETION_MS)
|
|
89
|
-
continue;
|
|
90
|
-
this.completedAt.delete(id);
|
|
91
|
-
this.hiddenCompleted.add(id);
|
|
92
|
-
}
|
|
93
|
-
this.scheduleCompletionHide();
|
|
94
|
-
}
|
|
95
|
-
scheduleCompletionHide() {
|
|
96
|
-
this.clearCompletionHideTimer();
|
|
97
|
-
let earliestExpiry = Infinity;
|
|
98
|
-
for (const completedAt of this.completedAt.values()) {
|
|
99
|
-
earliestExpiry = Math.min(earliestExpiry, completedAt + RECENT_COMPLETION_MS);
|
|
100
|
-
}
|
|
101
|
-
if (!Number.isFinite(earliestExpiry))
|
|
102
|
-
return;
|
|
103
|
-
this.completionHideTimer = setTimeout(() => {
|
|
104
|
-
this.completionHideTimer = undefined;
|
|
105
|
-
this.update();
|
|
106
|
-
}, Math.max(10, earliestExpiry - Date.now()));
|
|
107
|
-
}
|
|
108
|
-
clearCompletionHideTimer() {
|
|
109
|
-
if (this.completionHideTimer === undefined)
|
|
110
|
-
return;
|
|
111
|
-
clearTimeout(this.completionHideTimer);
|
|
112
|
-
this.completionHideTimer = undefined;
|
|
113
|
-
}
|
|
114
|
-
invalidateRenderCache() {
|
|
115
|
-
this.cachedWidth = undefined;
|
|
116
|
-
this.cachedLines = undefined;
|
|
117
|
-
}
|
|
118
|
-
render(theme, width) {
|
|
119
|
-
const normalizedWidth = Math.max(1, width);
|
|
120
|
-
if (this.cachedLines !== undefined && this.cachedWidth === normalizedWidth)
|
|
121
|
-
return this.cachedLines;
|
|
122
|
-
const lines = renderOverlayLines(getTodoState(), theme, normalizedWidth, this.hiddenCompleted);
|
|
123
|
-
this.cachedWidth = normalizedWidth;
|
|
124
|
-
this.cachedLines = lines;
|
|
125
|
-
return lines;
|
|
126
|
-
}
|
|
127
|
-
dispose() {
|
|
128
|
-
this.ui?.setWidget(WIDGET_KEY, undefined);
|
|
129
|
-
this.tui = undefined;
|
|
130
|
-
this.registered = false;
|
|
131
|
-
this.ui = undefined;
|
|
132
|
-
this.resetVisibility();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=overlay.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../src/extensions/todo/overlay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TUI } from \"@earendil-works/pi-tui\";\nimport type { ExtensionUIContext } from \"../../core/extensions/types.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\n\nimport type { TodoState, TodoStatus } from \"./schema.ts\";\nimport { getTodoState } from \"./state.ts\";\nimport { hasVisibleOverlayItems, renderOverlayLines } from \"./view.ts\";\n\nconst WIDGET_KEY = \"todos\";\nconst RECENT_COMPLETION_MS = 30_000;\n\nexport class TodoOverlay {\n\tprivate ui: ExtensionUIContext | undefined;\n\tprivate tui: TUI | undefined;\n\tprivate registered = false;\n\tprivate knownStatuses = new Map<number, TodoStatus>();\n\tprivate completedAt = new Map<number, number>();\n\tprivate hiddenCompleted = new Set<number>();\n\tprivate completionHideTimer: ReturnType<typeof setTimeout> | undefined;\n\t/** Pure render cache: same width + visibility state → skip rebuild. */\n\tprivate cachedWidth: number | undefined;\n\tprivate cachedLines: string[] | undefined;\n\n\tsetUI(ui: ExtensionUIContext): void {\n\t\tif (this.ui === ui) return;\n\t\tthis.dispose();\n\t\tthis.ui = ui;\n\t}\n\n\tresetVisibility(): void {\n\t\tthis.clearCompletionHideTimer();\n\t\tthis.knownStatuses.clear();\n\t\tthis.completedAt.clear();\n\t\tthis.hiddenCompleted.clear();\n\t\tthis.invalidateRenderCache();\n\t}\n\n\tupdate(): void {\n\t\tif (!this.ui) return;\n\t\tconst state = getTodoState();\n\t\tthis.syncVisibilityFromState(state);\n\t\tthis.invalidateRenderCache();\n\n\t\t// Register/unregister based on state, never as a render side effect.\n\t\tif (!hasVisibleOverlayItems(state, this.hiddenCompleted)) {\n\t\t\tif (this.registered) this.ui.setWidget(WIDGET_KEY, undefined);\n\t\t\tthis.registered = false;\n\t\t\tthis.tui = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.registered) {\n\t\t\tthis.ui.setWidget(\n\t\t\t\tWIDGET_KEY,\n\t\t\t\t(tui, theme) => {\n\t\t\t\t\tthis.tui = tui;\n\t\t\t\t\treturn {\n\t\t\t\t\t\trender: (width: number) => this.render(theme, width),\n\t\t\t\t\t\tinvalidate: () => {\n\t\t\t\t\t\t\tthis.registered = false;\n\t\t\t\t\t\t\tthis.tui = undefined;\n\t\t\t\t\t\t\tthis.invalidateRenderCache();\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t{ placement: \"aboveEditor\" },\n\t\t\t);\n\t\t\tthis.registered = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.tui?.requestRender();\n\t}\n\n\t/** Track new completions for a short confirmation window; hide historical ones. */\n\tprivate syncVisibilityFromState(state: TodoState): void {\n\t\tconst now = Date.now();\n\t\tconst nextStatuses = new Map<number, TodoStatus>();\n\n\t\tfor (const item of state.items) {\n\t\t\tnextStatuses.set(item.id, item.status);\n\t\t\tconst previousStatus = this.knownStatuses.get(item.id);\n\t\t\tif (item.status !== \"completed\") {\n\t\t\t\tthis.completedAt.delete(item.id);\n\t\t\t\tthis.hiddenCompleted.delete(item.id);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (previousStatus === undefined) {\n\t\t\t\t// A replayed/reloaded completion is old from this overlay's point of\n\t\t\t\t// view. Keep the live surface focused on current work.\n\t\t\t\tthis.hiddenCompleted.add(item.id);\n\t\t\t\tthis.completedAt.delete(item.id);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (previousStatus !== \"completed\") {\n\t\t\t\tthis.completedAt.set(item.id, now);\n\t\t\t\tthis.hiddenCompleted.delete(item.id);\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of this.knownStatuses.keys()) {\n\t\t\tif (nextStatuses.has(id)) continue;\n\t\t\tthis.completedAt.delete(id);\n\t\t\tthis.hiddenCompleted.delete(id);\n\t\t}\n\t\tthis.knownStatuses = nextStatuses;\n\n\t\tfor (const [id, completedAt] of this.completedAt) {\n\t\t\tif (now - completedAt < RECENT_COMPLETION_MS) continue;\n\t\t\tthis.completedAt.delete(id);\n\t\t\tthis.hiddenCompleted.add(id);\n\t\t}\n\t\tthis.scheduleCompletionHide();\n\t}\n\n\tprivate scheduleCompletionHide(): void {\n\t\tthis.clearCompletionHideTimer();\n\t\tlet earliestExpiry = Infinity;\n\t\tfor (const completedAt of this.completedAt.values()) {\n\t\t\tearliestExpiry = Math.min(earliestExpiry, completedAt + RECENT_COMPLETION_MS);\n\t\t}\n\t\tif (!Number.isFinite(earliestExpiry)) return;\n\n\t\tthis.completionHideTimer = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.completionHideTimer = undefined;\n\t\t\t\tthis.update();\n\t\t\t},\n\t\t\tMath.max(10, earliestExpiry - Date.now()),\n\t\t);\n\t}\n\n\tprivate clearCompletionHideTimer(): void {\n\t\tif (this.completionHideTimer === undefined) return;\n\t\tclearTimeout(this.completionHideTimer);\n\t\tthis.completionHideTimer = undefined;\n\t}\n\n\tprivate invalidateRenderCache(): void {\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tprivate render(theme: Theme, width: number): string[] {\n\t\tconst normalizedWidth = Math.max(1, width);\n\t\tif (this.cachedLines !== undefined && this.cachedWidth === normalizedWidth) return this.cachedLines;\n\n\t\tconst lines = renderOverlayLines(getTodoState(), theme, normalizedWidth, this.hiddenCompleted);\n\t\tthis.cachedWidth = normalizedWidth;\n\t\tthis.cachedLines = lines;\n\t\treturn lines;\n\t}\n\n\tdispose(): void {\n\t\tthis.ui?.setWidget(WIDGET_KEY, undefined);\n\t\tthis.tui = undefined;\n\t\tthis.registered = false;\n\t\tthis.ui = undefined;\n\t\tthis.resetVisibility();\n\t}\n}\n"]}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { ProcessTerminal } from "@earendil-works/pi-tui";
|
|
2
|
-
/**
|
|
3
|
-
* ProcessTerminal that (1) coalesces every write issued within one synchronous
|
|
4
|
-
* task into a single stdout write and (2) keeps content-driven full redraws
|
|
5
|
-
* from destroying the terminal's scrollback.
|
|
6
|
-
*
|
|
7
|
-
* Coalescing: pi-tui emits each render pass as several separate stdout
|
|
8
|
-
* writes: the frame wrapped in synchronized output (CSI ?2026h/l), then a
|
|
9
|
-
* relative cursor move that parks the hardware cursor at the focused
|
|
10
|
-
* component's caret for IME composition, then a cursor visibility toggle.
|
|
11
|
-
* Terminals that anchor the IME candidate window to the hardware cursor
|
|
12
|
-
* (Windows Terminal and other ConPTY hosts, WezTerm) can process the frame
|
|
13
|
-
* write before the reposition write arrives, briefly leaving the cursor at
|
|
14
|
-
* the end of the last repainted line. With an IME active this makes the
|
|
15
|
-
* candidate window jump between the caret and the right edge of the input
|
|
16
|
-
* line on every keystroke. Merging the writes makes each frame atomic, so the
|
|
17
|
-
* only cursor position a terminal can observe is the final one.
|
|
18
|
-
*
|
|
19
|
-
* Scrollback preservation: pi-tui's fullRender(clear) opens with
|
|
20
|
-
* `2J H 3J`, wiping the terminal's scrollback, and then replays the entire
|
|
21
|
-
* transcript. During streaming, content-driven triggers (a line changing
|
|
22
|
-
* above the viewport during markdown reflow) fire this routinely, which — in
|
|
23
|
-
* terminals that clamp the scroll offset when scrollback vanishes, notably
|
|
24
|
-
* Windows Terminal — yanks a scrolled-up reader to the top of the buffer on
|
|
25
|
-
* every reflow (upstream #6502, #5576, #6050; rejected upstream fix #4204).
|
|
26
|
-
*
|
|
27
|
-
* Preservation is therefore windowed, not permanent: the host marks agent
|
|
28
|
-
* runs via setAgentRunActive, which turns preservation on at run start and
|
|
29
|
-
* keeps it on until the user's next input after the run settles, since they
|
|
30
|
-
* may still be scrolled up reading. The input half of the window is observed
|
|
31
|
-
* directly on this terminal's own input path, so it needs no TUI listener
|
|
32
|
-
* and survives renderer switches (which reuse this terminal) untouched. An
|
|
33
|
-
* idle-session full redraw — Ctrl+O toggles, mode switches — passes through
|
|
34
|
-
* with upstream's wipe-and-replay, whose result is byte-perfect: scrollback
|
|
35
|
-
* becomes the clean new transcript. Mid-run user toggles can arm
|
|
36
|
-
* passNextFullRedraw for the same clean replay on their own frame.
|
|
37
|
-
*
|
|
38
|
-
* While preservation is active, a matching frame is rewritten to repaint
|
|
39
|
-
* without the wipe. With setViewportTopProvider wired, the rewrite knows
|
|
40
|
-
* which transcript line the visible screen starts at, so a frame that grew
|
|
41
|
-
* the transcript repaints the on-screen rows with the new content at those
|
|
42
|
-
* same positions and then scrolls the extra lines in at the bottom row.
|
|
43
|
-
* Each bottom-row newline pushes the top row — already repainted with the
|
|
44
|
-
* correct new content — into scrollback, exactly like ordinary streaming
|
|
45
|
-
* output, so scrollback ends up byte-equivalent to the upstream full replay
|
|
46
|
-
* without ever clearing it. Without the provider, or when the transcript
|
|
47
|
-
* shrank (lines cannot be pulled back out of scrollback), the rewrite falls
|
|
48
|
-
* back to overwriting the visible screen in place with the bottom
|
|
49
|
-
* viewport-height rows, at the cost of a stale seam above the screen. ED 2
|
|
50
|
-
* is avoided entirely in rewritten frames because conhost/Windows Terminal
|
|
51
|
-
* implement it by scrolling the screen contents into scrollback rather than
|
|
52
|
-
* erasing in place.
|
|
53
|
-
*
|
|
54
|
-
* Width- and height-change redraws keep the upstream wipe because re-wrapped
|
|
55
|
-
* content genuinely invalidates old scrollback, and frames containing kitty
|
|
56
|
-
* graphics pass through untouched. A frame that does not match the expected
|
|
57
|
-
* shape is passed through unchanged, so if upstream reshapes its render
|
|
58
|
-
* output the wrapper degrades back to stock behavior.
|
|
59
|
-
*/
|
|
60
|
-
export declare class CoalescingTerminal extends ProcessTerminal {
|
|
61
|
-
private pending;
|
|
62
|
-
private flushQueued;
|
|
63
|
-
private lastWriteColumns;
|
|
64
|
-
private lastWriteRows;
|
|
65
|
-
private viewportTopProvider;
|
|
66
|
-
private preserve;
|
|
67
|
-
private passArmed;
|
|
68
|
-
private agentRunActive;
|
|
69
|
-
private flushOnExit;
|
|
70
|
-
/**
|
|
71
|
-
* Enable or disable the scrollback-preserving rewrite. Preservation is
|
|
72
|
-
* only worth its imperfections (stale renderings above the screen, seams
|
|
73
|
-
* on shrink) while the transcript is mutating on its own and the reader
|
|
74
|
-
* may be scrolled up — i.e. during an agent run and until the user's next
|
|
75
|
-
* input after it settles. Outside that window every full redraw passes
|
|
76
|
-
* through with upstream's wipe-and-replay, whose result is byte-perfect:
|
|
77
|
-
* scrollback becomes the clean new transcript. Default: disabled.
|
|
78
|
-
* setAgentRunActive drives this for the normal agent-run window; this
|
|
79
|
-
* primitive remains for direct control in tests.
|
|
80
|
-
*/
|
|
81
|
-
setScrollbackPreservation(enabled: boolean): void;
|
|
82
|
-
/**
|
|
83
|
-
* Open or close the agent-run half of the preservation window. Opening
|
|
84
|
-
* (agent_start) turns preservation on. Closing (agent_settled) leaves
|
|
85
|
-
* preservation on: trailing reflow frames may land after the run while
|
|
86
|
-
* the reader is still scrolled up. The window then closes on the user's
|
|
87
|
-
* next input, observed in start()'s input wrapper — once the user acts
|
|
88
|
-
* they are back at the bottom, and upstream's clean wipe-and-replay wins
|
|
89
|
-
* again until the next run.
|
|
90
|
-
*/
|
|
91
|
-
setAgentRunActive(active: boolean): void;
|
|
92
|
-
/**
|
|
93
|
-
* Arm a one-shot exemption for an explicit user action (Ctrl+O tool
|
|
94
|
-
* expansion, thinking visibility) so its own full redraw keeps the
|
|
95
|
-
* upstream wipe-and-replay even while preservation is active mid-run.
|
|
96
|
-
* The user just pressed a key, so they are interacting at the bottom;
|
|
97
|
-
* a clean replay beats preservation's stale-seam trade-offs there. The
|
|
98
|
-
* flag is cleared by the next write so it cannot leak onto a later
|
|
99
|
-
* streaming redraw.
|
|
100
|
-
*/
|
|
101
|
-
passNextFullRedraw(): void;
|
|
102
|
-
/**
|
|
103
|
-
* Wire the renderer's notion of which transcript line the visible screen
|
|
104
|
-
* currently starts at (pi-tui's `previousViewportTop`). Full-redraw frames
|
|
105
|
-
* that grew the transcript then scroll the new above-screen lines into
|
|
106
|
-
* scrollback instead of dropping them. The provider is read while the
|
|
107
|
-
* frame is being written, i.e. before the renderer updates its own
|
|
108
|
-
* bookkeeping for that frame; returning undefined falls back to the
|
|
109
|
-
* bottom-anchored in-place repaint.
|
|
110
|
-
*/
|
|
111
|
-
setViewportTopProvider(provider: () => number | undefined): void;
|
|
112
|
-
constructor();
|
|
113
|
-
start(onInput: (data: string) => void, onResize: () => void): void;
|
|
114
|
-
write(data: string): void;
|
|
115
|
-
moveBy(lines: number): void;
|
|
116
|
-
hideCursor(): void;
|
|
117
|
-
showCursor(): void;
|
|
118
|
-
clearLine(): void;
|
|
119
|
-
clearFromCursor(): void;
|
|
120
|
-
clearScreen(): void;
|
|
121
|
-
stop(): void;
|
|
122
|
-
/**
|
|
123
|
-
* Rewrite a full-redraw frame (`?2026h 2J H 3J <lines> ?2026l`) so it
|
|
124
|
-
* repaints the screen without wiping scrollback. Anything that does not
|
|
125
|
-
* match this exact shape — including width-change redraws and frames
|
|
126
|
-
* touching kitty images — passes through unchanged.
|
|
127
|
-
*/
|
|
128
|
-
private preserveScrollback;
|
|
129
|
-
private readViewportTop;
|
|
130
|
-
private flush;
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=coalescing-terminal.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"coalescing-terminal.d.ts","sourceRoot":"","sources":["../../src/utils/coalescing-terminal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AASzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,qBAAa,kBAAmB,SAAQ,eAAe;IACtD,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,mBAAmB,CAAyC;IACpE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAsB;IAEzC;;;;;;;;;;OAUG;IACH,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIjD;;;;;;;;OAQG;IACH,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAKxC;;;;;;;;OAQG;IACH,kBAAkB,IAAI,IAAI;IAI1B;;;;;;;;OAQG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI;;IAWvD,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAoBlE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAUzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3B,UAAU,IAAI,IAAI;IAIlB,UAAU,IAAI,IAAI;IAIlB,SAAS,IAAI,IAAI;IAIjB,eAAe,IAAI,IAAI;IAIvB,WAAW,IAAI,IAAI;IAInB,IAAI,IAAI,IAAI;IAQrB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IA2E1B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,KAAK;CASb"}
|