@timurproko/a1 0.1.8-dev.157 → 0.1.8-dev.214
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 +32 -0
- package/bin/cli.js +2 -2
- package/bin/sync-pi-tui-proxy.js +1 -1
- package/bin/ui.js +18 -3
- package/dist/cli/dispatch.js +3 -3
- package/dist/cli/packages.js +1 -1
- package/dist/cli/version-stats.js +3 -3
- package/dist/composition/owned-ui.d.ts +4 -1
- package/dist/composition/owned-ui.js +9 -6
- package/dist/composition/settings-route-host.js +6 -4
- package/dist/contracts/agent-engine/capability-ports.d.ts +2 -2
- package/dist/contracts/agent-engine/domain-validation.js +22 -4
- package/dist/contracts/agent-engine/domain.d.ts +17 -0
- package/dist/contracts/owned-ui/model.d.ts +8 -0
- package/dist/contracts/owned-ui/validation.js +11 -0
- package/dist/features/launch/development-launch.js +1 -1
- package/dist/features/owned-ui/customization.d.ts +2 -0
- package/dist/features/owned-ui/customization.js +2 -0
- package/dist/features/owned-ui/diagnostics.d.ts +1 -0
- package/dist/features/owned-ui/diagnostics.js +1 -0
- package/dist/features/owned-ui/index.d.ts +1 -0
- package/dist/features/owned-ui/index.js +1 -0
- package/dist/features/owned-ui/project-trust-prompt.d.ts +25 -0
- package/dist/features/owned-ui/project-trust-prompt.js +149 -0
- package/dist/features/owned-ui/settings-app.js +69 -44
- package/dist/features/workspace/reducer.d.ts +1 -0
- package/dist/features/workspace/reducer.js +1 -0
- package/dist/features/workspace/router.d.ts +1 -0
- package/dist/features/workspace/router.js +1 -0
- package/dist/features/workspace/store.d.ts +1 -0
- package/dist/features/workspace/store.js +1 -0
- package/dist/foundation/launch-guardian/main.js +1 -1
- package/dist/foundation/native-host-protocol/codec.d.ts +2 -0
- package/dist/foundation/native-host-protocol/codec.js +2 -0
- package/dist/foundation/process-containment/linux-process-inspector.d.ts +1 -0
- package/dist/foundation/process-containment/linux-process-inspector.js +1 -0
- package/dist/foundation/process-containment/native-guardian-containment.d.ts +1 -0
- package/dist/foundation/process-containment/native-guardian-containment.js +1 -0
- package/dist/foundation/process-containment/windows-process-inspector.d.ts +1 -0
- package/dist/foundation/process-containment/windows-process-inspector.js +1 -0
- package/dist/foundation/protocol/client.d.ts +1 -0
- package/dist/foundation/protocol/client.js +1 -0
- package/dist/foundation/protocol/messages.d.ts +1 -0
- package/dist/foundation/protocol/messages.js +1 -0
- package/dist/foundation/release/bootstrap.js +6 -6
- package/dist/foundation/release/cohort-state.d.ts +1 -0
- package/dist/foundation/release/cohort-state.js +1 -0
- package/dist/foundation/release/release-gc.js +1 -1
- package/dist/foundation/release/release.js +1 -1
- package/dist/foundation/release/update-transaction.d.ts +1 -0
- package/dist/foundation/release/update-transaction.js +1 -0
- package/dist/foundation/release/update.js +12 -12
- package/dist/foundation/storage/control-store.d.ts +1 -0
- package/dist/foundation/storage/control-store.js +1 -0
- package/dist/foundation/structured-agent-runtime/backpressure.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/backpressure.js +1 -0
- package/dist/foundation/structured-agent-runtime/commands.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/commands.js +1 -0
- package/dist/foundation/structured-agent-runtime/reconnection.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/reconnection.js +1 -0
- package/dist/foundation/structured-agent-runtime/state.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/state.js +1 -0
- package/dist/foundation/supervision/main.js +1 -1
- package/dist/foundation/supervision/server.d.ts +1 -0
- package/dist/foundation/supervision/server.js +4 -6
- package/dist/integrations/pi/components/conformance.d.ts +1 -0
- package/dist/integrations/pi/components/conformance.js +1 -0
- package/dist/integrations/pi/components/shell-components.d.ts +1 -0
- package/dist/integrations/pi/components/shell-components.js +1 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +10 -0
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +19 -13
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +36 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +78 -0
- package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +3 -36
- package/dist/integrations/pi/components/shell-presenters-transcript.js +88 -128
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +11 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +22 -4
- package/dist/integrations/pi/engine/adapter.js +220 -70
- package/dist/integrations/pi/engine/conformance.d.ts +2 -0
- package/dist/integrations/pi/engine/conformance.js +2 -0
- package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
- package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
- package/dist/integrations/pi/engine/index.d.ts +3 -0
- package/dist/integrations/pi/engine/index.js +3 -0
- package/dist/integrations/pi/engine/model-auth-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/model-auth-integration.js +1 -0
- package/dist/integrations/pi/engine/package-integration.js +1 -1
- package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
- package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
- package/dist/integrations/pi/engine/resource-extension-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/resource-extension-integration.js +1 -0
- package/dist/integrations/pi/engine/runtime-integration.d.ts +16 -1
- package/dist/integrations/pi/engine/runtime-integration.js +34 -4
- package/dist/integrations/pi/engine/session-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/session-integration.js +2 -1
- package/dist/integrations/pi/engine/settings-effects.d.ts +66 -0
- package/dist/integrations/pi/engine/settings-effects.js +249 -0
- package/dist/integrations/pi/engine/settings-integration.d.ts +14 -26
- package/dist/integrations/pi/engine/settings-integration.js +102 -108
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +2 -1
- package/dist/integrations/pi/engine/workflow-controllers.js +1 -0
- package/dist/integrations/pi/session-ui/clipboard-image.d.ts +11 -0
- package/dist/integrations/pi/session-ui/clipboard-image.js +29 -0
- package/dist/integrations/pi/session-ui/index.d.ts +1 -0
- package/dist/integrations/pi/session-ui/index.js +1 -0
- package/dist/integrations/pi/session-ui/prompt-chips.js +6 -2
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +39 -4
- package/dist/integrations/pi/session-ui/session-shell-root.js +215 -80
- package/dist/integrations/pi/session-ui/session-shell.d.ts +10 -1
- package/dist/integrations/pi/session-ui/session-shell.js +256 -45
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +5 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +76 -11
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.d.ts +29 -0
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.js +79 -0
- package/dist/integrations/pi/session-ui/system-clipboard.d.ts +9 -0
- package/dist/integrations/pi/session-ui/system-clipboard.js +38 -9
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +166 -8
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +25 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +63 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +240 -0
- package/dist/integrations/pi/tui-runtime/index.d.ts +2 -0
- package/dist/integrations/pi/tui-runtime/index.js +2 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +39 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.js +139 -0
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/ui/apps/host.js +5 -9
- package/dist/ui/apps/registry.d.ts +1 -0
- package/dist/ui/apps/registry.js +1 -0
- package/dist/ui/components/dialog-panel.js +5 -3
- package/dist/ui/components/frame.d.ts +1 -0
- package/dist/ui/components/frame.js +1 -0
- package/dist/ui/components/index.d.ts +1 -0
- package/dist/ui/components/index.js +1 -0
- package/dist/ui/components/line-input.d.ts +1 -6
- package/dist/ui/components/line-input.js +4 -9
- package/dist/ui/components/list-view.d.ts +0 -6
- package/dist/ui/components/list-view.js +14 -7
- package/dist/ui/components/progress-status.d.ts +2 -0
- package/dist/ui/components/progress-status.js +4 -0
- package/dist/ui/components/scrollbar.js +1 -1
- package/dist/ui/components/shortcuts.d.ts +1 -0
- package/dist/ui/components/shortcuts.js +1 -0
- package/dist/ui/components/spans.d.ts +2 -5
- package/dist/ui/components/spans.js +28 -8
- package/dist/ui/components/surface.d.ts +0 -5
- package/dist/ui/components/surface.js +1 -5
- package/dist/ui/components/text-selection.d.ts +10 -1
- package/dist/ui/components/text-selection.js +96 -29
- package/dist/ui/components/text.js +3 -3
- package/dist/ui/components/transcript-viewport.d.ts +42 -0
- package/dist/ui/components/transcript-viewport.js +287 -39
- package/dist/ui/settings/sections.d.ts +6 -19
- package/dist/ui/settings/sections.js +17 -15
- package/dist/ui/settings/session.d.ts +8 -18
- package/dist/ui/settings/session.js +60 -52
- package/dist/ui/settings/store.d.ts +1 -0
- package/dist/ui/settings/store.js +2 -1
- package/docs/architecture/code-documentation.md +77 -0
- package/docs/architecture/project-structure.md +15 -1
- package/docs/architecture/ui-reference-provenance.md +23 -3
- package/docs/ci-release-runbook.md +98 -7
- package/docs/manual-owned-ui-checkpoint.md +28 -1
- package/docs/manual-terminal-colour-check.md +4 -3
- package/docs/repository-governance-live-acceptance.md +77 -0
- package/package.json +11 -3
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { PRODUCT_TEXT } from "../../../product-identity.js";
|
|
1
2
|
import { MOUSE_TRACKING_OFF, MOUSE_TRACKING_ON, parseMouseInput } from "../../../ui/components/index.js";
|
|
2
3
|
import { PINNED_PI_HIDDEN_COMMAND_NAMES, PINNED_PI_WORKFLOW_COMMAND_NAMES, } from "../engine/index.js";
|
|
3
4
|
import { createPiExtensionUiBridge, createPiQueuedInputStatus, createPiShellArmin, createPiShellAuthProviderSelector, createPiShellChangelog, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellEditor, createPiShellExtensionSelector, createPiShellFooter, createPiShellHeader, createPiShellHotkeys, createPiShellLoadedResources, createPiShellLoginDialog, createPiShellModelSelector, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionInfo, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellStatus, createPiShellTranscriptComponent, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, onPiThemeChange, piTheme, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellStatusText, renderPiShellTranscriptBlock, } from "../components/index.js";
|
|
4
|
-
import { PiTuiRuntimeAdapter, } from "../tui-runtime/index.js";
|
|
5
|
+
import { DamageAwareTerminalAdapter, PiTuiRuntimeAdapter, classifyPiTuiInput, } from "../tui-runtime/index.js";
|
|
6
|
+
import { canonicalizeClipboardImage } from "./clipboard-image.js";
|
|
7
|
+
import { STREAM_PRESENTATION_INTERVAL_MS, StreamPresentationCoalescer, } from "./stream-presentation-coalescer.js";
|
|
5
8
|
import { preloadSystemClipboard, readSystemClipboardContent, writeSystemClipboardText, } from "./system-clipboard.js";
|
|
6
9
|
import { OwnedUiSessionShellRoot, shellResourceEntries, } from "./session-shell-root.js";
|
|
7
10
|
export { OwnedUiSessionShellRoot } from "./session-shell-root.js";
|
|
11
|
+
/** Coordinates backend, owned presentation, and Pi TUI lifecycles for one interactive session. */
|
|
8
12
|
export class OwnedUiSessionShell {
|
|
9
13
|
backend;
|
|
10
14
|
root;
|
|
@@ -24,8 +28,17 @@ export class OwnedUiSessionShell {
|
|
|
24
28
|
#disposed = false;
|
|
25
29
|
#pointerReporting = false;
|
|
26
30
|
#customViewport;
|
|
31
|
+
#damageTerminal;
|
|
32
|
+
#streamPresentation;
|
|
27
33
|
#removeViewportPreInput;
|
|
28
34
|
#unsubscribeSettings;
|
|
35
|
+
#unbindPiSettings;
|
|
36
|
+
#unbindTerminalSettings;
|
|
37
|
+
#unbindShutdownSettings;
|
|
38
|
+
#terminalProgressEnabled = false;
|
|
39
|
+
#showImages = true;
|
|
40
|
+
#imageWidthCells = 80;
|
|
41
|
+
#fullscreenExitOutput = "transcript";
|
|
29
42
|
#compactionQueue = [];
|
|
30
43
|
#lastClearTime = 0;
|
|
31
44
|
#lastEscapeTime = 0;
|
|
@@ -43,11 +56,19 @@ export class OwnedUiSessionShell {
|
|
|
43
56
|
this.#resolveStopped = resolve;
|
|
44
57
|
});
|
|
45
58
|
let runtime;
|
|
59
|
+
let damageTerminal;
|
|
60
|
+
let streamPresentation;
|
|
46
61
|
let pendingClipboardWrite = Promise.resolve();
|
|
47
62
|
this.root = new OwnedUiSessionShellRoot(this.backend.view(), options.cwd, {
|
|
48
63
|
getColumns: () => runtime?.viewport().columns ?? options.terminal?.columns ?? 80,
|
|
49
64
|
getRows: () => runtime?.viewport().rows ?? options.terminal?.rows ?? 24,
|
|
50
65
|
requestRender: force => runtime?.requestRender(force),
|
|
66
|
+
onViewportFrame: frame => damageTerminal?.arm(frame.descriptor, {
|
|
67
|
+
overlayActive: runtime?.hasOverlay() ?? false,
|
|
68
|
+
selectionActive: this.root.hasActiveSelection(),
|
|
69
|
+
replacementSurfaceActive: !this.root.usesDefaultInputSurface(),
|
|
70
|
+
}),
|
|
71
|
+
enableDockInputReuse: options.inputPresentation?.viewportReuse !== false,
|
|
51
72
|
onSubmit: text => { void this.submit(text); },
|
|
52
73
|
onInterrupt: () => { void this.interrupt(); },
|
|
53
74
|
onClear: () => { void this.clearOrExit(); },
|
|
@@ -73,9 +94,17 @@ export class OwnedUiSessionShell {
|
|
|
73
94
|
await pendingClipboardWrite;
|
|
74
95
|
if (options.clipboard === undefined)
|
|
75
96
|
return readSystemClipboardContent();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
97
|
+
try {
|
|
98
|
+
const image = await options.clipboard.readImage?.();
|
|
99
|
+
if (image !== null && image !== undefined) {
|
|
100
|
+
const canonical = canonicalizeClipboardImage(image);
|
|
101
|
+
if (canonical !== null)
|
|
102
|
+
return { kind: "image", ...canonical };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Compatibility: treat an unavailable or malformed image as text-capable clipboard input.
|
|
107
|
+
}
|
|
79
108
|
const text = await options.clipboard.readText();
|
|
80
109
|
return text === null ? null : { kind: "text", text };
|
|
81
110
|
},
|
|
@@ -85,8 +114,10 @@ export class OwnedUiSessionShell {
|
|
|
85
114
|
}, this.backend.agentDir, {
|
|
86
115
|
getMessageRenderer: customType => this.backend.pinnedMessageRenderer(customType),
|
|
87
116
|
getToolDefinition: toolName => this.backend.pinnedToolDefinition(toolName),
|
|
88
|
-
}, options.sessionLayout
|
|
89
|
-
|
|
117
|
+
}, options.sessionLayout, {
|
|
118
|
+
resolve: assetId => this.backend.resolveTranscriptImage(assetId),
|
|
119
|
+
});
|
|
120
|
+
// Invariant: bare A1 owns a bounded viewport and therefore always runs on the alternate
|
|
90
121
|
// fullscreen surface. The pinned comparison profiles still honor Pi's mode.
|
|
91
122
|
const tuiMode = this.#customViewport
|
|
92
123
|
? "fullscreen"
|
|
@@ -94,15 +125,72 @@ export class OwnedUiSessionShell {
|
|
|
94
125
|
const runtimeOptions = {
|
|
95
126
|
root: this.root,
|
|
96
127
|
mode: tuiMode,
|
|
97
|
-
...(this.#customViewport ? {
|
|
128
|
+
...(this.#customViewport ? {
|
|
129
|
+
decorateTerminal: (terminal) => {
|
|
130
|
+
damageTerminal = new DamageAwareTerminalAdapter(terminal, {
|
|
131
|
+
regionalScroll: process.env.TERM !== "dumb",
|
|
132
|
+
onResize: () => streamPresentation?.noteImmediatePresentation(),
|
|
133
|
+
});
|
|
134
|
+
return damageTerminal;
|
|
135
|
+
},
|
|
136
|
+
...(options.inputPresentation?.coordination === false ? {} : {
|
|
137
|
+
inputCoordination: {
|
|
138
|
+
classify: (data, focusedOverlay) => classifyPiTuiInput(data, focusedOverlay ?? this.root.inputCoordinationSurface()),
|
|
139
|
+
onReceipt: () => streamPresentation?.noteImmediatePresentation(),
|
|
140
|
+
...(options.inputPresentation?.scheduler === undefined
|
|
141
|
+
? {}
|
|
142
|
+
: { scheduler: options.inputPresentation.scheduler }),
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
} : { layoutRoot: this.root.layoutRoot() }),
|
|
146
|
+
...(options.inputPresentation?.onEvent === undefined ? {} : {
|
|
147
|
+
inputDiagnostics: {
|
|
148
|
+
onEvent: options.inputPresentation.onEvent,
|
|
149
|
+
...(options.inputPresentation.now === undefined ? {} : { now: options.inputPresentation.now }),
|
|
150
|
+
},
|
|
151
|
+
}),
|
|
98
152
|
...(options.terminal === undefined ? {} : { terminal: options.terminal }),
|
|
99
153
|
hardwareCursor: this.backend.view().terminal.hardwareCursor,
|
|
100
154
|
};
|
|
101
155
|
runtime = new PiTuiRuntimeAdapter(runtimeOptions);
|
|
102
156
|
this.runtime = runtime;
|
|
157
|
+
this.#damageTerminal = damageTerminal ?? null;
|
|
158
|
+
const presentationInterval = options.streamPresentation?.intervalMs ?? STREAM_PRESENTATION_INTERVAL_MS;
|
|
159
|
+
streamPresentation = options.streamPresentation?.scheduler === undefined
|
|
160
|
+
? new StreamPresentationCoalescer(() => this.runtime.requestRender(), presentationInterval)
|
|
161
|
+
: new StreamPresentationCoalescer(() => this.runtime.requestRender(), presentationInterval, options.streamPresentation.scheduler);
|
|
162
|
+
this.#streamPresentation = streamPresentation;
|
|
163
|
+
const initialPiSettings = this.backend.pinnedSettingsSnapshot();
|
|
164
|
+
this.runtime.setHardwareCursor(initialPiSettings.showHardwareCursor);
|
|
165
|
+
this.runtime.setClearOnShrink(initialPiSettings.clearOnShrink);
|
|
166
|
+
this.#terminalProgressEnabled = initialPiSettings.showTerminalProgress;
|
|
167
|
+
this.#fullscreenExitOutput = initialPiSettings.fullscreenExitOutput;
|
|
168
|
+
this.#unbindShutdownSettings = this.backend.bindSettingsOwner("shutdown", {
|
|
169
|
+
fullscreenExitOutput: { apply() { } },
|
|
170
|
+
});
|
|
171
|
+
this.#unbindTerminalSettings = this.backend.bindSettingsOwner("terminal", {
|
|
172
|
+
showHardwareCursor: { apply: value => {
|
|
173
|
+
if (typeof value !== "boolean")
|
|
174
|
+
throw new TypeError("Hardware cursor setting is invalid");
|
|
175
|
+
this.runtime.setHardwareCursor(value);
|
|
176
|
+
} },
|
|
177
|
+
clearOnShrink: { apply: value => {
|
|
178
|
+
if (typeof value !== "boolean")
|
|
179
|
+
throw new TypeError("Clear-on-shrink setting is invalid");
|
|
180
|
+
this.runtime.setClearOnShrink(value);
|
|
181
|
+
} },
|
|
182
|
+
showTerminalProgress: { apply: value => {
|
|
183
|
+
if (typeof value !== "boolean")
|
|
184
|
+
throw new TypeError("Terminal progress setting is invalid");
|
|
185
|
+
this.#terminalProgressEnabled = value;
|
|
186
|
+
this.#syncTerminalProgress(this.view());
|
|
187
|
+
} },
|
|
188
|
+
});
|
|
103
189
|
this.#removeViewportPreInput = this.#customViewport
|
|
104
190
|
? this.runtime.addPreInputListener(data => {
|
|
105
|
-
|
|
191
|
+
if (options.inputPresentation?.coordination === false)
|
|
192
|
+
this.#streamPresentation.noteImmediatePresentation();
|
|
193
|
+
// Invariant: an overlay or editor-replacement screen owns its entire pointer
|
|
106
194
|
// surface. Letting the transcript pre-router inspect those reports
|
|
107
195
|
// steals settings value menus and numeric +/- controls before the
|
|
108
196
|
// settings app can receive them.
|
|
@@ -129,6 +217,53 @@ export class OwnedUiSessionShell {
|
|
|
129
217
|
this.#unsubscribeSettings = this.#customViewport && options.viewportSettings
|
|
130
218
|
? options.viewportSettings.onChange(settings => this.root.setViewportConfig(settings))
|
|
131
219
|
: () => { };
|
|
220
|
+
this.root.setEditorPaddingX(initialPiSettings.editorPaddingX);
|
|
221
|
+
this.root.setAutocompleteMaxVisible(initialPiSettings.autocompleteMaxVisible);
|
|
222
|
+
this.root.setOutputPad(initialPiSettings.outputPad);
|
|
223
|
+
this.root.setHideThinkingBlock(initialPiSettings.hideThinkingBlock);
|
|
224
|
+
this.root.setMermaidRenderingMode(initialPiSettings.mermaidRenderingMode);
|
|
225
|
+
this.#showImages = initialPiSettings.showImages;
|
|
226
|
+
this.#imageWidthCells = initialPiSettings.imageWidthCells;
|
|
227
|
+
this.root.setImagePresentation(this.#showImages, this.#imageWidthCells);
|
|
228
|
+
this.#unbindPiSettings = this.backend.bindSettingsOwner("shell", {
|
|
229
|
+
editorPaddingX: { apply: value => {
|
|
230
|
+
if (typeof value !== "number")
|
|
231
|
+
throw new TypeError("Editor padding is invalid");
|
|
232
|
+
this.root.setEditorPaddingX(value);
|
|
233
|
+
} },
|
|
234
|
+
autocompleteMaxVisible: { apply: value => {
|
|
235
|
+
if (typeof value !== "number")
|
|
236
|
+
throw new TypeError("Autocomplete maximum is invalid");
|
|
237
|
+
this.root.setAutocompleteMaxVisible(value);
|
|
238
|
+
} },
|
|
239
|
+
outputPad: { apply: value => {
|
|
240
|
+
if (value !== 0 && value !== 1)
|
|
241
|
+
throw new TypeError("Output padding is invalid");
|
|
242
|
+
this.root.setOutputPad(value);
|
|
243
|
+
} },
|
|
244
|
+
hideThinkingBlock: { apply: value => {
|
|
245
|
+
if (typeof value !== "boolean")
|
|
246
|
+
throw new TypeError("Thinking-block visibility is invalid");
|
|
247
|
+
this.root.setHideThinkingBlock(value);
|
|
248
|
+
} },
|
|
249
|
+
mermaidRenderingMode: { apply: value => {
|
|
250
|
+
if (value !== "off" && value !== "final" && value !== "streaming")
|
|
251
|
+
throw new TypeError("Mermaid mode is invalid");
|
|
252
|
+
this.root.setMermaidRenderingMode(value);
|
|
253
|
+
} },
|
|
254
|
+
showImages: { apply: value => {
|
|
255
|
+
if (typeof value !== "boolean")
|
|
256
|
+
throw new TypeError("Image visibility is invalid");
|
|
257
|
+
this.#showImages = value;
|
|
258
|
+
this.root.setImagePresentation(this.#showImages, this.#imageWidthCells);
|
|
259
|
+
} },
|
|
260
|
+
imageWidthCells: { apply: value => {
|
|
261
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
|
|
262
|
+
throw new TypeError("Image width is invalid");
|
|
263
|
+
this.#imageWidthCells = value;
|
|
264
|
+
this.root.setImagePresentation(this.#showImages, this.#imageWidthCells);
|
|
265
|
+
} },
|
|
266
|
+
});
|
|
132
267
|
this.#extensionBridge = createPiExtensionUiBridge({
|
|
133
268
|
runtime: {
|
|
134
269
|
getColumns: () => this.runtime.viewport().columns,
|
|
@@ -136,7 +271,7 @@ export class OwnedUiSessionShell {
|
|
|
136
271
|
requestRender: () => this.runtime.requestRender(),
|
|
137
272
|
},
|
|
138
273
|
agentDir: this.backend.agentDir,
|
|
139
|
-
setInputSurface: component => this.root.setInputSurface(component),
|
|
274
|
+
setInputSurface: component => this.root.setInputSurface(component, true, "opaque"),
|
|
140
275
|
showOverlay: (component, overlayOptions) => this.runtime.showOverlay(component, overlayOptions),
|
|
141
276
|
listenInput: handler => this.runtime.addInputListener(handler),
|
|
142
277
|
replaceWidget: (key, component, placement) => this.root.setExtensionWidget(key, component, placement),
|
|
@@ -150,7 +285,7 @@ export class OwnedUiSessionShell {
|
|
|
150
285
|
setEditorText: text => this.root.editor.setText(text),
|
|
151
286
|
pasteToEditor: text => this.root.editor.insertText(text),
|
|
152
287
|
addAutocompleteProvider: factory => this.root.editor.addAutocompleteProvider(factory),
|
|
153
|
-
setCustomEditor: component => this.root.setInputSurface(component),
|
|
288
|
+
setCustomEditor: component => this.root.setInputSurface(component, true, "opaque"),
|
|
154
289
|
getFooterData: () => this.root.extensionFooterData(),
|
|
155
290
|
getToolsExpanded: () => this.root.toolsExpanded,
|
|
156
291
|
setToolsExpanded: expanded => this.root.setToolsExpanded(expanded),
|
|
@@ -163,7 +298,7 @@ export class OwnedUiSessionShell {
|
|
|
163
298
|
});
|
|
164
299
|
this.root.editor.setAutocompleteCommands(this.backend.workflowAutocompleteCommands());
|
|
165
300
|
this.#unsubscribe = this.backend.onEvent(event => {
|
|
166
|
-
//
|
|
301
|
+
// Performance: a streamed chunk names one block, and touching only that block is what keeps the
|
|
167
302
|
// cost of a chunk the same in a long session as in a new one. Everything else
|
|
168
303
|
// resynchronizes the view, which is cheap next to re-reading the transcript.
|
|
169
304
|
if (event.type === "agent-run-started")
|
|
@@ -174,6 +309,7 @@ export class OwnedUiSessionShell {
|
|
|
174
309
|
const view = event.type === "transcript-block" && this.#sessionGeneration === this.backend.sessionGeneration
|
|
175
310
|
? this.#syncBlock(event.block)
|
|
176
311
|
: semanticOnly ? this.view() : this.#syncView();
|
|
312
|
+
this.#syncTerminalProgress(view);
|
|
177
313
|
if (view.lifecycle === "ready" && this.#compactionQueue.length > 0)
|
|
178
314
|
void this.#flushCompactionQueue();
|
|
179
315
|
if (event.type === "session-lifecycle" && event.lifecycle === "stopped")
|
|
@@ -185,11 +321,15 @@ export class OwnedUiSessionShell {
|
|
|
185
321
|
view() {
|
|
186
322
|
return this.backend.view();
|
|
187
323
|
}
|
|
324
|
+
damagePresentationDecision() {
|
|
325
|
+
return this.#damageTerminal?.lastDecision ?? null;
|
|
326
|
+
}
|
|
188
327
|
start() {
|
|
189
328
|
if (this.#started)
|
|
190
329
|
return;
|
|
191
330
|
this.#started = true;
|
|
192
331
|
this.runtime.start();
|
|
332
|
+
this.#syncTerminalProgress(this.view());
|
|
193
333
|
if (this.#customViewport)
|
|
194
334
|
this.#setPointerReporting(true);
|
|
195
335
|
void this.backend.bindExtensionUi(this.#extensionBridge.context, () => { void this.shutdown(); });
|
|
@@ -238,7 +378,11 @@ export class OwnedUiSessionShell {
|
|
|
238
378
|
}
|
|
239
379
|
if (this.view().status.workingMessage?.startsWith("Compacting") === true) {
|
|
240
380
|
this.root.editor.addToHistory(displayInput);
|
|
241
|
-
this.#compactionQueue.push({
|
|
381
|
+
this.#compactionQueue.push({
|
|
382
|
+
text: input,
|
|
383
|
+
type: "steer",
|
|
384
|
+
...(prepared.images.length === 0 ? {} : { images: prepared.images }),
|
|
385
|
+
});
|
|
242
386
|
this.root.appendWorkflowResult({ command: "compact", outcome: "completed", message: `Queued during compaction: ${input}` });
|
|
243
387
|
this.runtime.requestRender();
|
|
244
388
|
return { outcome: "completed", diagnostic: null };
|
|
@@ -269,7 +413,7 @@ export class OwnedUiSessionShell {
|
|
|
269
413
|
this.root.editor.setText("");
|
|
270
414
|
return { outcome: "completed", diagnostic: null };
|
|
271
415
|
}
|
|
272
|
-
//
|
|
416
|
+
// Compatibility: match Pi: with an empty editor, two escapes inside 500 ms open the
|
|
273
417
|
// configured session navigator. The first escape intentionally does not
|
|
274
418
|
// interrupt or mutate the prompt.
|
|
275
419
|
const action = this.backend.pinnedSettingsSnapshot().doubleEscapeAction;
|
|
@@ -336,14 +480,20 @@ export class OwnedUiSessionShell {
|
|
|
336
480
|
return workflowAdapterResult(result);
|
|
337
481
|
}
|
|
338
482
|
async queueFollowUp() {
|
|
339
|
-
const
|
|
340
|
-
if (!
|
|
483
|
+
const displayInput = this.root.editor.getText().trim();
|
|
484
|
+
if (!displayInput)
|
|
341
485
|
return rejected("nothing to queue");
|
|
342
|
-
this.root.
|
|
486
|
+
const prepared = this.root.preparePromptSubmission(displayInput);
|
|
487
|
+
const text = prepared.text.trim();
|
|
488
|
+
this.root.editor.addToHistory(displayInput);
|
|
343
489
|
this.root.editor.setText("");
|
|
344
490
|
this.root.resumeViewportFollowing();
|
|
345
491
|
if (this.view().status.workingMessage?.startsWith("Compacting") === true) {
|
|
346
|
-
this.#compactionQueue.push({
|
|
492
|
+
this.#compactionQueue.push({
|
|
493
|
+
text,
|
|
494
|
+
type: "follow-up",
|
|
495
|
+
...(prepared.images.length === 0 ? {} : { images: prepared.images }),
|
|
496
|
+
});
|
|
347
497
|
return { outcome: "completed", diagnostic: null };
|
|
348
498
|
}
|
|
349
499
|
return this.#execute({
|
|
@@ -351,6 +501,7 @@ export class OwnedUiSessionShell {
|
|
|
351
501
|
correlationId: this.#correlation("follow-up"),
|
|
352
502
|
sessionId: this.backend.sessionId,
|
|
353
503
|
text,
|
|
504
|
+
...(prepared.images.length === 0 ? {} : { images: prepared.images }),
|
|
354
505
|
});
|
|
355
506
|
}
|
|
356
507
|
restoreQueuedInput() {
|
|
@@ -381,7 +532,12 @@ export class OwnedUiSessionShell {
|
|
|
381
532
|
onCancel?.();
|
|
382
533
|
},
|
|
383
534
|
});
|
|
384
|
-
const handle = this.runtime.showOverlay(component, {
|
|
535
|
+
const handle = this.runtime.showOverlay(component, {
|
|
536
|
+
width: "70%",
|
|
537
|
+
maxHeight: "80%",
|
|
538
|
+
anchor: "center",
|
|
539
|
+
inputCoordination: "owned",
|
|
540
|
+
});
|
|
385
541
|
this.#dialogHandle = handle;
|
|
386
542
|
return handle;
|
|
387
543
|
}
|
|
@@ -581,7 +737,7 @@ export class OwnedUiSessionShell {
|
|
|
581
737
|
return;
|
|
582
738
|
}
|
|
583
739
|
if (callback === "onTuiModeChange") {
|
|
584
|
-
//
|
|
740
|
+
// Invariant: the custom bare-A1 surface is permanently fullscreen; this callback
|
|
585
741
|
// remains available only to pinned comparison profiles.
|
|
586
742
|
if (this.#customViewport)
|
|
587
743
|
return;
|
|
@@ -597,12 +753,13 @@ export class OwnedUiSessionShell {
|
|
|
597
753
|
this.#setPointerReporting(true);
|
|
598
754
|
}
|
|
599
755
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
756
|
+
void this.backend.applyPinnedSettingValue(callback, value).then(result => {
|
|
757
|
+
if (result.outcome === "failed")
|
|
758
|
+
this.root.appendWorkflowResult(result);
|
|
759
|
+
else if (callback === "onTuiModeChange")
|
|
760
|
+
this.root.appendWorkflowStatus(`TUI mode: ${value}`);
|
|
761
|
+
this.runtime.requestRender();
|
|
762
|
+
});
|
|
606
763
|
},
|
|
607
764
|
onCancel: close,
|
|
608
765
|
});
|
|
@@ -801,12 +958,7 @@ export class OwnedUiSessionShell {
|
|
|
801
958
|
this.root.appendDaxnuts();
|
|
802
959
|
}
|
|
803
960
|
}
|
|
804
|
-
|
|
805
|
-
* Turns terminal pointer reporting on for a screen that reads the pointer, and off for
|
|
806
|
-
* every path that ends it. While it is on the terminal hands A1 the wheel and the
|
|
807
|
-
* button instead of scrolling and selecting itself, so leaving it on outlives the
|
|
808
|
-
* screen that wanted it and takes the terminal's own scrolling and selection with it.
|
|
809
|
-
*/
|
|
961
|
+
// Invariant: pointer reporting is disabled on every path that ends the owning screen.
|
|
810
962
|
#setPointerReporting(enabled, forceOff = false) {
|
|
811
963
|
const effective = forceOff ? false : this.#customViewport || enabled;
|
|
812
964
|
if (this.#pointerReporting === effective)
|
|
@@ -823,32 +975,62 @@ export class OwnedUiSessionShell {
|
|
|
823
975
|
this.root.clearViewportPointerState();
|
|
824
976
|
this.#setPointerReporting(false, true);
|
|
825
977
|
this.#removeViewportPreInput();
|
|
978
|
+
this.#streamPresentation.dispose();
|
|
826
979
|
this.#unsubscribeSettings();
|
|
980
|
+
const exitMode = this.backend.disposed
|
|
981
|
+
? this.#fullscreenExitOutput
|
|
982
|
+
: this.backend.pinnedSettingsSnapshot().fullscreenExitOutput;
|
|
983
|
+
const exitTranscript = this.root.exitTranscript(this.runtime.viewport().columns);
|
|
984
|
+
const resume = this.backend.currentSessionResumeMetadata();
|
|
985
|
+
const resumeHint = resume === null
|
|
986
|
+
? ""
|
|
987
|
+
: `${dim("To resume this session:")} ${formatSessionResumeCommand(resume)}`;
|
|
988
|
+
const fullscreenExitText = this.runtime.mode !== "fullscreen"
|
|
989
|
+
? ""
|
|
990
|
+
: exitMode === "resume-hint"
|
|
991
|
+
? resumeHint
|
|
992
|
+
: [exitTranscript, resumeHint].filter(Boolean).join("\n\n");
|
|
993
|
+
this.#unbindPiSettings();
|
|
994
|
+
this.#unbindTerminalSettings();
|
|
995
|
+
this.#unbindShutdownSettings();
|
|
827
996
|
this.#unsubscribe();
|
|
828
997
|
this.#dialogHandle?.hide();
|
|
829
998
|
await this.backend.unbindExtensionUi();
|
|
830
999
|
this.#extensionBridge.dispose();
|
|
831
1000
|
await this.runtime.dispose();
|
|
1001
|
+
if (fullscreenExitText.length > 0)
|
|
1002
|
+
this.runtime.writeAfterStop(`${fullscreenExitText}\n`);
|
|
832
1003
|
}
|
|
833
|
-
|
|
834
|
-
* Applies one transcript block without re-reading the session. The listeners still hear
|
|
835
|
-
* the view they would have heard, so nothing downstream can tell the difference.
|
|
836
|
-
*/
|
|
1004
|
+
// Invariant: incremental block updates notify listeners with the same complete view contract.
|
|
837
1005
|
#syncBlock(block) {
|
|
838
1006
|
this.root.applyTranscriptBlock(block);
|
|
839
|
-
this.
|
|
1007
|
+
if (this.#customViewport && block.status === "live" && isCoalescedStreamBlock(block.kind)) {
|
|
1008
|
+
this.#streamPresentation.request();
|
|
1009
|
+
}
|
|
1010
|
+
else if (this.#streamPresentation.pending) {
|
|
1011
|
+
this.#streamPresentation.flush();
|
|
1012
|
+
}
|
|
1013
|
+
else {
|
|
1014
|
+
this.#streamPresentation.presentImmediate();
|
|
1015
|
+
}
|
|
840
1016
|
const view = this.view();
|
|
841
1017
|
for (const listener of this.#listeners)
|
|
842
1018
|
listener(view);
|
|
843
1019
|
return view;
|
|
844
1020
|
}
|
|
1021
|
+
#syncTerminalProgress(view) {
|
|
1022
|
+
if (!this.runtime.active)
|
|
1023
|
+
return;
|
|
1024
|
+
this.runtime.setTerminalProgress(this.#terminalProgressEnabled && view.lifecycle === "busy");
|
|
1025
|
+
}
|
|
845
1026
|
#syncView() {
|
|
1027
|
+
this.#streamPresentation.noteImmediatePresentation();
|
|
846
1028
|
const view = this.view();
|
|
847
1029
|
if (this.backend.sessionGeneration !== this.#sessionGeneration) {
|
|
848
1030
|
this.#sessionGeneration = this.backend.sessionGeneration;
|
|
849
1031
|
this.#activeLoginDialog = undefined;
|
|
850
1032
|
this.#extensionBridge.reset();
|
|
851
|
-
//
|
|
1033
|
+
// Invariant: a replaced session takes its transient viewport and owned-route state with it.
|
|
852
1034
|
this.root.resetViewport();
|
|
853
1035
|
this.#dialogHandle?.hide();
|
|
854
1036
|
this.#dialogHandle = undefined;
|
|
@@ -874,10 +1056,10 @@ export class OwnedUiSessionShell {
|
|
|
874
1056
|
return { outcome: "failed", diagnostic: "runtime is not active" };
|
|
875
1057
|
this.#dialogHandle?.hide();
|
|
876
1058
|
this.#dialogSource = "route";
|
|
877
|
-
//
|
|
1059
|
+
// Protocol: any-event reporting: hover and drag are what the screen is driven by, and
|
|
878
1060
|
// it also stops the terminal treating a drag as a text selection.
|
|
879
1061
|
this.#setPointerReporting(true);
|
|
880
|
-
//
|
|
1062
|
+
// Protocol: the interrupt chord is global, so it is watched on raw input rather than
|
|
881
1063
|
// through the overlay: the pinned shell handles that key before an overlay
|
|
882
1064
|
// ever sees it, which is why an owned screen must not rely on being asked.
|
|
883
1065
|
let armedAt = 0;
|
|
@@ -893,7 +1075,7 @@ export class OwnedUiSessionShell {
|
|
|
893
1075
|
}
|
|
894
1076
|
armedAt = now;
|
|
895
1077
|
this.runtime.requestRender();
|
|
896
|
-
//
|
|
1078
|
+
// Invariant: the presented screen owns the chord, so the pinned shell never sees a
|
|
897
1079
|
// stray interrupt while it is up.
|
|
898
1080
|
return { consume: true };
|
|
899
1081
|
});
|
|
@@ -907,7 +1089,7 @@ export class OwnedUiSessionShell {
|
|
|
907
1089
|
this.#dialogId = undefined;
|
|
908
1090
|
this.#dialogSource = undefined;
|
|
909
1091
|
};
|
|
910
|
-
//
|
|
1092
|
+
// Compatibility: fullscreen Pi owns a fallback text-selection layer before focused overlay
|
|
911
1093
|
// components see pointer input. Route every mouse report to the owned screen
|
|
912
1094
|
// at the pre-input boundary so dropdowns, value hover, and numeric +/- work,
|
|
913
1095
|
// and consume even unhandled reports so settings content is never selected.
|
|
@@ -945,7 +1127,12 @@ export class OwnedUiSessionShell {
|
|
|
945
1127
|
closeSurface();
|
|
946
1128
|
void this.shutdown();
|
|
947
1129
|
});
|
|
948
|
-
this.#dialogHandle = this.runtime.showOverlay(component, {
|
|
1130
|
+
this.#dialogHandle = this.runtime.showOverlay(component, {
|
|
1131
|
+
width: "100%",
|
|
1132
|
+
maxHeight: "100%",
|
|
1133
|
+
anchor: "top-left",
|
|
1134
|
+
inputCoordination: "owned",
|
|
1135
|
+
});
|
|
949
1136
|
this.#dialogId = surface.id;
|
|
950
1137
|
return { outcome: "completed", diagnostic: null };
|
|
951
1138
|
}
|
|
@@ -953,7 +1140,7 @@ export class OwnedUiSessionShell {
|
|
|
953
1140
|
if (!this.runtime.active)
|
|
954
1141
|
return;
|
|
955
1142
|
if (dialog === null) {
|
|
956
|
-
//
|
|
1143
|
+
// Invariant: locally owned routes (notably /settings) are independent of backend
|
|
957
1144
|
// lifecycle/status events and remain open while an agent is working.
|
|
958
1145
|
if (this.#dialogSource !== "backend")
|
|
959
1146
|
return;
|
|
@@ -981,7 +1168,12 @@ export class OwnedUiSessionShell {
|
|
|
981
1168
|
this.#dialogSource = undefined;
|
|
982
1169
|
},
|
|
983
1170
|
});
|
|
984
|
-
this.#dialogHandle = this.runtime.showOverlay(component, {
|
|
1171
|
+
this.#dialogHandle = this.runtime.showOverlay(component, {
|
|
1172
|
+
width: "70%",
|
|
1173
|
+
maxHeight: "80%",
|
|
1174
|
+
anchor: "center",
|
|
1175
|
+
inputCoordination: "owned",
|
|
1176
|
+
});
|
|
985
1177
|
this.#dialogId = dialog.id;
|
|
986
1178
|
}
|
|
987
1179
|
async #slashCommand(text) {
|
|
@@ -993,7 +1185,7 @@ export class OwnedUiSessionShell {
|
|
|
993
1185
|
return this.#openOwnedRoute(name);
|
|
994
1186
|
if (isWorkflowRoute(name))
|
|
995
1187
|
return this.runWorkflow({ command: name, argument });
|
|
996
|
-
//
|
|
1188
|
+
// Compatibility: unknown slash input, prompt templates, skills, and extension commands remain Pi prompt input.
|
|
997
1189
|
this.root.editor.addToHistory(text);
|
|
998
1190
|
this.root.resumeViewportFollowing();
|
|
999
1191
|
return this.#execute({
|
|
@@ -1117,6 +1309,7 @@ export class OwnedUiSessionShell {
|
|
|
1117
1309
|
correlationId: this.#correlation(`compaction-${item.type}`),
|
|
1118
1310
|
sessionId: this.backend.sessionId,
|
|
1119
1311
|
text: item.text,
|
|
1312
|
+
...(item.images === undefined ? {} : { images: item.images }),
|
|
1120
1313
|
});
|
|
1121
1314
|
}
|
|
1122
1315
|
}
|
|
@@ -1131,6 +1324,24 @@ export class OwnedUiSessionShell {
|
|
|
1131
1324
|
return `pi-shell-${prefix}-${this.#sequence}`;
|
|
1132
1325
|
}
|
|
1133
1326
|
}
|
|
1327
|
+
function isCoalescedStreamBlock(kind) {
|
|
1328
|
+
return kind === "assistant" || kind === "thinking" || kind === "tool-call" || kind === "tool-result";
|
|
1329
|
+
}
|
|
1330
|
+
export function formatSessionResumeCommand(metadata) {
|
|
1331
|
+
const args = [PRODUCT_TEXT.commandName];
|
|
1332
|
+
if (!metadata.usesDefaultSessionDir)
|
|
1333
|
+
args.push("--session-dir", quoteCommandArgument(metadata.sessionDir));
|
|
1334
|
+
args.push("--session", metadata.sessionId);
|
|
1335
|
+
return args.join(" ");
|
|
1336
|
+
}
|
|
1337
|
+
export function quoteCommandArgument(value) {
|
|
1338
|
+
if (value.length > 0 && !/[^a-zA-Z0-9_\-./~:@]/.test(value))
|
|
1339
|
+
return value;
|
|
1340
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
1341
|
+
}
|
|
1342
|
+
function dim(value) {
|
|
1343
|
+
return `\u001b[2m${value}\u001b[22m`;
|
|
1344
|
+
}
|
|
1134
1345
|
function modelReference(model) {
|
|
1135
1346
|
if (typeof model !== "object" || model === null)
|
|
1136
1347
|
return "";
|
|
@@ -24,11 +24,16 @@ export declare class SessionViewportController {
|
|
|
24
24
|
get config(): OwnedUiViewportSettings;
|
|
25
25
|
get editorPointerSelecting(): boolean;
|
|
26
26
|
get transcriptPointerSelecting(): boolean;
|
|
27
|
+
get hasSelection(): boolean;
|
|
28
|
+
get selectionRevision(): number;
|
|
29
|
+
get presentationRevision(): number;
|
|
30
|
+
get frame(): TranscriptViewportFrame | null;
|
|
27
31
|
setEditorPointerFrame(frame: {
|
|
28
32
|
readonly rowStart: number;
|
|
29
33
|
readonly rowEnd: number;
|
|
30
34
|
} | undefined): void;
|
|
31
35
|
compose(input: TranscriptViewportFrameInput): TranscriptViewportFrame;
|
|
36
|
+
composeDockOnly(dockRows: readonly string[], width: number, height: number): TranscriptViewportFrame | null;
|
|
32
37
|
/** Returns true when document wrapping may have changed. */
|
|
33
38
|
setConfig(config: OwnedUiViewportSettings): boolean;
|
|
34
39
|
resumeFollowing(): void;
|