@timurproko/a1 0.2.7-dev.808 → 0.2.7-dev.810
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 +4 -2
- package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
- package/dist/app/session-shell/dialog-coordinator.js +133 -0
- package/dist/app/session-shell/dock-chrome.d.ts +34 -0
- package/dist/app/session-shell/dock-chrome.js +109 -0
- package/dist/app/session-shell/exit-notice.d.ts +1 -1
- package/dist/app/session-shell/exit-notice.js +1 -1
- package/dist/app/session-shell/extension-surface.d.ts +30 -0
- package/dist/app/session-shell/extension-surface.js +105 -0
- package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
- package/dist/app/session-shell/input-surface-switch.js +85 -0
- package/dist/app/session-shell/login-interaction.d.ts +27 -0
- package/dist/app/session-shell/login-interaction.js +91 -0
- package/dist/app/session-shell/prompt-submission.d.ts +48 -0
- package/dist/app/session-shell/prompt-submission.js +276 -0
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +41 -0
- package/dist/app/session-shell/resident-tab-coordinator.js +120 -0
- package/dist/app/session-shell/response-copy-transport.d.ts +13 -0
- package/dist/app/session-shell/response-copy-transport.js +16 -7
- package/dist/app/session-shell/session-concern.d.ts +22 -0
- package/dist/app/session-shell/session-concern.js +29 -0
- package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
- package/dist/app/session-shell/session-lifecycle.js +49 -0
- package/dist/app/session-shell/session-shell-root.d.ts +1 -1
- package/dist/app/session-shell/session-shell-root.js +182 -931
- package/dist/app/session-shell/session-shell.d.ts +2 -8
- package/dist/app/session-shell/session-shell.js +202 -901
- package/dist/app/session-shell/settings-bindings.d.ts +17 -0
- package/dist/app/session-shell/settings-bindings.js +91 -0
- package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
- package/dist/app/session-shell/shell-editor-factory.js +102 -0
- package/dist/app/session-shell/shell-host.d.ts +6 -0
- package/dist/app/session-shell/shell-host.js +8 -0
- package/dist/app/session-shell/shell-layout.d.ts +64 -0
- package/dist/app/session-shell/shell-layout.js +18 -0
- package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
- package/dist/app/session-shell/suggestion-surface.js +63 -0
- package/dist/app/session-shell/transcript-document.d.ts +78 -0
- package/dist/app/session-shell/transcript-document.js +365 -0
- package/dist/app/session-shell/viewport-layout.d.ts +31 -0
- package/dist/app/session-shell/viewport-layout.js +160 -0
- package/dist/app/session-shell/workflow-output.d.ts +33 -0
- package/dist/app/session-shell/workflow-output.js +174 -0
- package/dist/app/session-shell/workflow-router.d.ts +25 -0
- package/dist/app/session-shell/workflow-router.js +39 -0
- package/dist/composition/owned-ui.d.ts +4 -25
- package/dist/composition/owned-ui.js +26 -270
- package/dist/composition/resident-tab-bridge.d.ts +16 -0
- package/dist/composition/resident-tab-bridge.js +159 -0
- package/dist/composition/session-backend.d.ts +19 -0
- package/dist/composition/session-backend.js +1 -0
- package/dist/composition/session-runtime-registry.d.ts +20 -0
- package/dist/composition/session-runtime-registry.js +85 -0
- package/dist/composition/startup-route.d.ts +32 -0
- package/dist/composition/startup-route.js +72 -0
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
- package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -4
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +77 -98
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +4 -77
- package/dist/integrations/pi/engine/adapter.js +85 -393
- package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
- package/dist/integrations/pi/engine/command-dispatch.js +57 -0
- package/dist/integrations/pi/engine/host.js +2 -2
- package/dist/integrations/pi/engine/ports.d.ts +56 -0
- package/dist/integrations/pi/engine/ports.js +89 -0
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/view-state.d.ts +42 -0
- package/dist/integrations/pi/engine/view-state.js +126 -0
- package/dist/integrations/pi/startup-public.js +164 -150
- package/dist/integrations/pi/startup-public.manifest.json +351 -310
- package/dist/integrations/pi/tui-runtime/adapter.js +4 -0
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +1 -1
- package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/dist/runtime-payload-inventory.json +5181 -5369
- package/dist/ui/components/transcript-viewport.js +10 -19
- package/docs/architecture/boundaries.md +14 -0
- package/docs/architecture/resident-tabs.md +8 -8
- package/docs/architecture/response-copy-delivery.md +1 -1
- package/docs/architecture/toolchain.md +2 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -185,13 +185,15 @@ a1 update npm:pi-mcp-adapter
|
|
|
185
185
|
|
|
186
186
|
## Develop
|
|
187
187
|
|
|
188
|
+
A source build needs Node.js, npm, git, and Rustup. Windows additionally needs Visual Studio or Visual Studio Build Tools with the **Desktop development with C++** workload, MSVC x64/x86 tools, and a Windows SDK; Visual Studio Code is not required. A1 discovers installed Rustup and Visual Studio tools and initializes them for build children, so Git Bash and ordinary PowerShell do not need manual `PATH` or developer-shell setup. It never installs these tools or accepts their licenses automatically.
|
|
189
|
+
|
|
188
190
|
Install exact locked dependencies:
|
|
189
191
|
|
|
190
192
|
```text
|
|
191
193
|
npm ci
|
|
192
194
|
```
|
|
193
195
|
|
|
194
|
-
Compile TypeScript and the
|
|
196
|
+
Compile TypeScript and the native addons into `dist`:
|
|
195
197
|
|
|
196
198
|
```text
|
|
197
199
|
npm run build
|
|
@@ -221,7 +223,7 @@ Complete non-physical suite:
|
|
|
221
223
|
npm run test:full
|
|
222
224
|
```
|
|
223
225
|
|
|
224
|
-
Report Node, npm, git, Rust, and
|
|
226
|
+
Report Node, npm, git, Rust, dependency, and Windows C++ readiness. Missing Windows tools are listed in setup order; after installing them, rerun the same build command:
|
|
225
227
|
|
|
226
228
|
```text
|
|
227
229
|
npm run doctor
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { OwnedUiCommandResult, OwnedUiDialog } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { UiRouteHost, UiRouteInput } from "../../ui/apps/contracts.js";
|
|
3
|
+
import type { PiShellSelectorOption } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
4
|
+
import type { PiTuiOverlayHandle } from "../../integrations/pi/tui-runtime/contracts.js";
|
|
5
|
+
import type { OwnedUiPresenterTerminal } from "./shell-host.js";
|
|
6
|
+
import type { OwnedUiSessionShellOptions, OwnedUiSessionShellRoot } from "./session-shell-root.js";
|
|
7
|
+
type StartupRoute = NonNullable<OwnedUiSessionShellOptions["engine"]["startupRoute"]>;
|
|
8
|
+
export interface SessionDialogPorts {
|
|
9
|
+
readonly terminal: Pick<OwnedUiPresenterTerminal, "running" | "hasOverlay" | "showOverlay" | "openRoute" | "requestRender">;
|
|
10
|
+
readonly root: Pick<OwnedUiSessionShellRoot, "dismissNotice" | "setInputSurface" | "usesDefaultInputSurface">;
|
|
11
|
+
readonly routeHost: UiRouteHost | null;
|
|
12
|
+
readonly disposed: () => boolean;
|
|
13
|
+
/** A route, or the interrupt chord over it, asked to leave A1. */
|
|
14
|
+
readonly exit: () => void;
|
|
15
|
+
/** A rendered route closed itself. */
|
|
16
|
+
readonly routeClosed?: (route: string) => void;
|
|
17
|
+
readonly startupRoute?: StartupRoute;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Owns the one modal overlay a session shows at a time, whichever source opened it: an owned route,
|
|
21
|
+
* a local selector, or a backend dialog. Opening one hides the previous one, and every close path
|
|
22
|
+
* clears the same state.
|
|
23
|
+
*/
|
|
24
|
+
export declare class SessionDialogCoordinator {
|
|
25
|
+
#private;
|
|
26
|
+
constructor(ports: SessionDialogPorts);
|
|
27
|
+
/** Clears the replacement input surface a selector put in the dock; the shared close action of every dock selector. */
|
|
28
|
+
readonly closeInputSurface: () => void;
|
|
29
|
+
showSelector(title: string, options: readonly PiShellSelectorOption[], onSelect: (id: string) => void, onCancel?: () => void): PiTuiOverlayHandle;
|
|
30
|
+
/** Mirrors the backend's pending dialog; locally owned routes and selectors are left alone when it has none. */
|
|
31
|
+
syncBackend(dialog: OwnedUiDialog | null): void;
|
|
32
|
+
openRoute(route: string, input?: UiRouteInput, onClosed?: () => void | Promise<void>): OwnedUiCommandResult;
|
|
33
|
+
claimsRoute(name: string): boolean;
|
|
34
|
+
/** Retains a route requested before the runtime runs; the latest request wins. */
|
|
35
|
+
retainStartupRoute(route: string): void;
|
|
36
|
+
/** Opens the retained startup route once no overlay or replacement input surface holds the screen. */
|
|
37
|
+
presentStartupRoute(): void;
|
|
38
|
+
/** A replaced session takes its dialog with it; a retained startup route still opens. */
|
|
39
|
+
onSessionReplaced(): void;
|
|
40
|
+
dispose(): void;
|
|
41
|
+
}
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createPiShellDialog, createPiShellSelector } from "../../integrations/pi/components/shell-selectors-dialogs.js";
|
|
2
|
+
const OVERLAY_OPTIONS = { width: "70%", maxHeight: "80%", anchor: "center", inputCoordination: "owned" };
|
|
3
|
+
const STARTUP_ROUTE_RETRY_MS = 25;
|
|
4
|
+
/**
|
|
5
|
+
* Owns the one modal overlay a session shows at a time, whichever source opened it: an owned route,
|
|
6
|
+
* a local selector, or a backend dialog. Opening one hides the previous one, and every close path
|
|
7
|
+
* clears the same state.
|
|
8
|
+
*/
|
|
9
|
+
export class SessionDialogCoordinator {
|
|
10
|
+
#ports;
|
|
11
|
+
#handle;
|
|
12
|
+
#id;
|
|
13
|
+
#source;
|
|
14
|
+
#startupRoute;
|
|
15
|
+
#startupRouteTimer;
|
|
16
|
+
constructor(ports) {
|
|
17
|
+
this.#ports = ports;
|
|
18
|
+
this.#startupRoute = ports.startupRoute;
|
|
19
|
+
}
|
|
20
|
+
/** Clears the replacement input surface a selector put in the dock; the shared close action of every dock selector. */
|
|
21
|
+
closeInputSurface = () => {
|
|
22
|
+
this.#ports.root.setInputSurface(null);
|
|
23
|
+
this.#ports.terminal.requestRender();
|
|
24
|
+
};
|
|
25
|
+
showSelector(title, options, onSelect, onCancel) {
|
|
26
|
+
this.#handle?.hide();
|
|
27
|
+
this.#source = "local";
|
|
28
|
+
this.#id = undefined;
|
|
29
|
+
const component = createPiShellSelector({
|
|
30
|
+
title,
|
|
31
|
+
options,
|
|
32
|
+
onSelect: id => {
|
|
33
|
+
onSelect(id);
|
|
34
|
+
this.#close();
|
|
35
|
+
},
|
|
36
|
+
onCancel: () => {
|
|
37
|
+
this.#close();
|
|
38
|
+
onCancel?.();
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const handle = this.#ports.terminal.showOverlay(component, OVERLAY_OPTIONS);
|
|
42
|
+
this.#handle = handle;
|
|
43
|
+
return handle;
|
|
44
|
+
}
|
|
45
|
+
/** Mirrors the backend's pending dialog; locally owned routes and selectors are left alone when it has none. */
|
|
46
|
+
syncBackend(dialog) {
|
|
47
|
+
if (!this.#ports.terminal.running)
|
|
48
|
+
return;
|
|
49
|
+
if (dialog === null) {
|
|
50
|
+
// Invariant: locally owned routes (notably /settings) are independent of backend
|
|
51
|
+
// lifecycle/status events and remain open while an agent is working.
|
|
52
|
+
if (this.#source === "backend")
|
|
53
|
+
this.#close();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (this.#source === "backend" && this.#id === dialog.id)
|
|
57
|
+
return;
|
|
58
|
+
this.#handle?.hide();
|
|
59
|
+
this.#source = "backend";
|
|
60
|
+
const component = createPiShellDialog(dialog, { onSelect: () => this.#close(), onCancel: () => this.#close() });
|
|
61
|
+
this.#handle = this.#ports.terminal.showOverlay(component, OVERLAY_OPTIONS);
|
|
62
|
+
this.#id = dialog.id;
|
|
63
|
+
}
|
|
64
|
+
openRoute(route, input, onClosed) {
|
|
65
|
+
const surface = this.#ports.routeHost?.open(route, input) ?? null;
|
|
66
|
+
if (surface === null)
|
|
67
|
+
return { outcome: "failed", diagnostic: `route is unavailable: ${route}` };
|
|
68
|
+
if (!this.#ports.terminal.running)
|
|
69
|
+
return { outcome: "failed", diagnostic: "runtime is not active" };
|
|
70
|
+
this.#ports.root.dismissNotice();
|
|
71
|
+
this.#handle?.hide();
|
|
72
|
+
this.#source = "route";
|
|
73
|
+
const handle = this.#ports.terminal.openRoute(surface, {
|
|
74
|
+
exit: () => this.#ports.exit(),
|
|
75
|
+
closed: rendered => {
|
|
76
|
+
if (this.#handle === handle)
|
|
77
|
+
this.#clear();
|
|
78
|
+
if (rendered) {
|
|
79
|
+
try {
|
|
80
|
+
void onClosed?.()?.catch(() => undefined);
|
|
81
|
+
}
|
|
82
|
+
catch { /* Rationale: a failed acknowledgement stays pending. */ }
|
|
83
|
+
this.#ports.routeClosed?.(route);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
this.#handle = handle;
|
|
88
|
+
this.#id = surface.id;
|
|
89
|
+
return { outcome: "completed", diagnostic: null };
|
|
90
|
+
}
|
|
91
|
+
claimsRoute(name) {
|
|
92
|
+
return this.#ports.routeHost?.claims(name) ?? false;
|
|
93
|
+
}
|
|
94
|
+
/** Retains a route requested before the runtime runs; the latest request wins. */
|
|
95
|
+
retainStartupRoute(route) {
|
|
96
|
+
this.#startupRoute = { route };
|
|
97
|
+
}
|
|
98
|
+
/** Opens the retained startup route once no overlay or replacement input surface holds the screen. */
|
|
99
|
+
presentStartupRoute() {
|
|
100
|
+
const pending = this.#startupRoute;
|
|
101
|
+
if (pending === undefined || this.#ports.disposed() || !this.#ports.terminal.running)
|
|
102
|
+
return;
|
|
103
|
+
if (this.#ports.terminal.hasOverlay() || !this.#ports.root.usesDefaultInputSurface()) {
|
|
104
|
+
this.#startupRouteTimer = setTimeout(() => {
|
|
105
|
+
this.#startupRouteTimer = undefined;
|
|
106
|
+
this.presentStartupRoute();
|
|
107
|
+
}, STARTUP_ROUTE_RETRY_MS);
|
|
108
|
+
this.#startupRouteTimer.unref?.();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.#startupRoute = undefined;
|
|
112
|
+
this.openRoute(pending.route, pending.input, pending.onClosed);
|
|
113
|
+
}
|
|
114
|
+
/** A replaced session takes its dialog with it; a retained startup route still opens. */
|
|
115
|
+
onSessionReplaced() {
|
|
116
|
+
this.#close();
|
|
117
|
+
}
|
|
118
|
+
dispose() {
|
|
119
|
+
if (this.#startupRouteTimer !== undefined)
|
|
120
|
+
clearTimeout(this.#startupRouteTimer);
|
|
121
|
+
this.#startupRouteTimer = undefined;
|
|
122
|
+
this.#handle?.hide();
|
|
123
|
+
}
|
|
124
|
+
#close() {
|
|
125
|
+
this.#handle?.hide();
|
|
126
|
+
this.#clear();
|
|
127
|
+
}
|
|
128
|
+
#clear() {
|
|
129
|
+
this.#handle = undefined;
|
|
130
|
+
this.#id = undefined;
|
|
131
|
+
this.#source = undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ImageAttachmentError, OwnedUiSessionViewModel } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { TranscriptViewportFrame } from "../../ui/components/transcript-viewport.js";
|
|
3
|
+
import { type PiShellReleaseUpdateBanner } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
4
|
+
import type { SessionViewportController } from "./session-viewport-controller.js";
|
|
5
|
+
export interface DockNotice {
|
|
6
|
+
readonly kind: "status" | "warning" | "error" | "new-session";
|
|
7
|
+
readonly message: string;
|
|
8
|
+
readonly errorCode?: ImageAttachmentError["code"];
|
|
9
|
+
}
|
|
10
|
+
export interface DockChromePorts {
|
|
11
|
+
/** Chrome changed; the root invalidates its chrome components. */
|
|
12
|
+
readonly invalidateChrome: () => void;
|
|
13
|
+
readonly requestRender: () => void;
|
|
14
|
+
readonly viewport: Pick<SessionViewportController, "tailControlHovered" | "setTailControl">;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The transient chrome around bare A1's dock: the one command notice above the editor, the release
|
|
18
|
+
* banner above Working with its close control, and the short copy acknowledgement.
|
|
19
|
+
*/
|
|
20
|
+
export declare class DockChrome {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(ports: DockChromePorts);
|
|
23
|
+
get notice(): DockNotice | undefined;
|
|
24
|
+
setNotice(notice: DockNotice): void;
|
|
25
|
+
dismissNotice(): void;
|
|
26
|
+
/** Forgets the notice without a chrome invalidation; the caller invalidates as part of a larger change. */
|
|
27
|
+
forgetNotice(): void;
|
|
28
|
+
renderNotice(width: number, outputPad: 0 | 1): readonly string[];
|
|
29
|
+
showCopyAcknowledgement(message: string): void;
|
|
30
|
+
clearCopyAcknowledgement(requestRender: boolean): void;
|
|
31
|
+
renderCopyAcknowledgement(width: number): string | undefined;
|
|
32
|
+
renderReleaseBanner(diagnostics: OwnedUiSessionViewModel["diagnostics"], width: number): PiShellReleaseUpdateBanner | undefined;
|
|
33
|
+
locateReleaseClose(frame: TranscriptViewportFrame, banner: PiShellReleaseUpdateBanner | undefined, tailEnd: number, tailLength: number): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { renderPiShellCommandMessage, renderPiShellReleaseUpdateBanner, renderPiShellStatusText, } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
2
|
+
import { PINNED_PI_LAYOUT, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
|
|
3
|
+
import { piShellTruncateToWidth } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
4
|
+
import { parseReleaseUpdateDiagnostic } from "./transcript-document.js";
|
|
5
|
+
const COPY_ACKNOWLEDGEMENT_DURATION_MS = 1_000;
|
|
6
|
+
/**
|
|
7
|
+
* The transient chrome around bare A1's dock: the one command notice above the editor, the release
|
|
8
|
+
* banner above Working with its close control, and the short copy acknowledgement.
|
|
9
|
+
*/
|
|
10
|
+
export class DockChrome {
|
|
11
|
+
#ports;
|
|
12
|
+
#notice;
|
|
13
|
+
// Invariant: bare A1 docks the release notice above the live status; closing it lasts for this session only.
|
|
14
|
+
#releaseDismissed = false;
|
|
15
|
+
#releaseCloseTarget;
|
|
16
|
+
#copyAcknowledgement;
|
|
17
|
+
#copyAcknowledgementTimer;
|
|
18
|
+
constructor(ports) {
|
|
19
|
+
this.#ports = ports;
|
|
20
|
+
}
|
|
21
|
+
get notice() {
|
|
22
|
+
return this.#notice;
|
|
23
|
+
}
|
|
24
|
+
setNotice(notice) {
|
|
25
|
+
this.#notice = notice;
|
|
26
|
+
this.#ports.invalidateChrome();
|
|
27
|
+
}
|
|
28
|
+
dismissNotice() {
|
|
29
|
+
if (this.#notice === undefined)
|
|
30
|
+
return;
|
|
31
|
+
this.#notice = undefined;
|
|
32
|
+
this.#ports.invalidateChrome();
|
|
33
|
+
}
|
|
34
|
+
/** Forgets the notice without a chrome invalidation; the caller invalidates as part of a larger change. */
|
|
35
|
+
forgetNotice() {
|
|
36
|
+
this.#notice = undefined;
|
|
37
|
+
}
|
|
38
|
+
renderNotice(width, outputPad) {
|
|
39
|
+
const notice = this.#notice;
|
|
40
|
+
if (notice === undefined)
|
|
41
|
+
return [];
|
|
42
|
+
if (notice.kind === "status") {
|
|
43
|
+
// Compatibility: Pi pads its status text by one cell regardless of the output pad setting.
|
|
44
|
+
return ["", ...renderPiShellStatusText(notice.message, width, PINNED_PI_LAYOUT.outputPad)];
|
|
45
|
+
}
|
|
46
|
+
return renderPiShellCommandMessage({
|
|
47
|
+
kind: notice.kind === "new-session" ? "accent" : notice.kind,
|
|
48
|
+
message: notice.message,
|
|
49
|
+
}, width, outputPad);
|
|
50
|
+
}
|
|
51
|
+
showCopyAcknowledgement(message) {
|
|
52
|
+
this.clearCopyAcknowledgement(false);
|
|
53
|
+
this.#copyAcknowledgement = message;
|
|
54
|
+
const timer = setTimeout(() => {
|
|
55
|
+
if (this.#copyAcknowledgementTimer !== timer)
|
|
56
|
+
return;
|
|
57
|
+
this.#copyAcknowledgementTimer = undefined;
|
|
58
|
+
this.#copyAcknowledgement = undefined;
|
|
59
|
+
this.#ports.invalidateChrome();
|
|
60
|
+
this.#ports.requestRender();
|
|
61
|
+
}, COPY_ACKNOWLEDGEMENT_DURATION_MS);
|
|
62
|
+
timer.unref?.();
|
|
63
|
+
this.#copyAcknowledgementTimer = timer;
|
|
64
|
+
this.#ports.invalidateChrome();
|
|
65
|
+
this.#ports.requestRender();
|
|
66
|
+
}
|
|
67
|
+
clearCopyAcknowledgement(requestRender) {
|
|
68
|
+
if (this.#copyAcknowledgementTimer !== undefined)
|
|
69
|
+
clearTimeout(this.#copyAcknowledgementTimer);
|
|
70
|
+
this.#copyAcknowledgementTimer = undefined;
|
|
71
|
+
if (this.#copyAcknowledgement === undefined)
|
|
72
|
+
return;
|
|
73
|
+
this.#copyAcknowledgement = undefined;
|
|
74
|
+
this.#ports.invalidateChrome();
|
|
75
|
+
if (requestRender)
|
|
76
|
+
this.#ports.requestRender();
|
|
77
|
+
}
|
|
78
|
+
renderCopyAcknowledgement(width) {
|
|
79
|
+
if (this.#copyAcknowledgement === undefined || width <= 0)
|
|
80
|
+
return undefined;
|
|
81
|
+
return piTheme().fg("accent", piShellTruncateToWidth(this.#copyAcknowledgement, width));
|
|
82
|
+
}
|
|
83
|
+
renderReleaseBanner(diagnostics, width) {
|
|
84
|
+
if (this.#releaseDismissed)
|
|
85
|
+
return undefined;
|
|
86
|
+
const diagnostic = diagnostics.findLast(item => item.code === "release-update");
|
|
87
|
+
const release = diagnostic === undefined ? null : parseReleaseUpdateDiagnostic(diagnostic.message);
|
|
88
|
+
if (release === null)
|
|
89
|
+
return undefined;
|
|
90
|
+
return renderPiShellReleaseUpdateBanner(release, width, this.#ports.viewport.tailControlHovered(this.#releaseCloseTarget));
|
|
91
|
+
}
|
|
92
|
+
locateReleaseClose(frame, banner, tailEnd, tailLength) {
|
|
93
|
+
// Invariant: the tail is the document suffix, so the control's document row is fixed relative to its
|
|
94
|
+
// end; alignment gap rows precede it and the viewport scroll decides whether it is on screen.
|
|
95
|
+
const bannerStart = tailEnd + frame.descriptor.transientAlignmentGapRows - tailLength - frame.scrollTop + 1;
|
|
96
|
+
const rowStart = banner === undefined ? 0 : Math.max(1, bannerStart + banner.close.rowStart);
|
|
97
|
+
const rowEnd = banner === undefined ? 0 : Math.min(frame.hits.viewportHeight, bannerStart + banner.close.rowEnd);
|
|
98
|
+
this.#releaseCloseTarget = banner !== undefined && rowStart <= rowEnd
|
|
99
|
+
? { rowStart, rowEnd, columnStart: banner.close.columnStart, columnEnd: banner.close.columnEnd }
|
|
100
|
+
: undefined;
|
|
101
|
+
this.#ports.viewport.setTailControl(this.#releaseCloseTarget === undefined ? undefined : {
|
|
102
|
+
...this.#releaseCloseTarget,
|
|
103
|
+
activate: () => {
|
|
104
|
+
this.#releaseDismissed = true;
|
|
105
|
+
this.#releaseCloseTarget = undefined;
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { renameSync, rmSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
9
|
-
import { formatSessionResumeCommand } from "./session-
|
|
9
|
+
import { formatSessionResumeCommand } from "./session-lifecycle.js";
|
|
10
10
|
export function uncleanExitNoticeLines(resume) {
|
|
11
11
|
return [
|
|
12
12
|
`${PRODUCT_IDENTITY.displayName} was stopped unexpectedly.`,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { OwnedUiSessionViewModel } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { PiShellComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
3
|
+
export type ExtensionWidgetPlacement = "aboveEditor" | "belowEditor";
|
|
4
|
+
/**
|
|
5
|
+
* What extensions draw into the shell: a header that replaces the built-in one, a footer, widgets
|
|
6
|
+
* above and below the editor, footer statuses, and a working message. It owns those components and
|
|
7
|
+
* disposes each one it replaces; the root decides what to invalidate after a change.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ExtensionSurface {
|
|
10
|
+
#private;
|
|
11
|
+
get header(): PiShellComponentPort | null;
|
|
12
|
+
get footer(): PiShellComponentPort | null;
|
|
13
|
+
get working(): {
|
|
14
|
+
readonly message: string | undefined;
|
|
15
|
+
readonly visible: boolean;
|
|
16
|
+
};
|
|
17
|
+
placeWidget(key: string, component: PiShellComponentPort | null, placement: ExtensionWidgetPlacement): void;
|
|
18
|
+
replaceHeader(component: PiShellComponentPort | null): void;
|
|
19
|
+
replaceFooter(component: PiShellComponentPort | null): void;
|
|
20
|
+
setStatus(key: string, text: string | undefined): void;
|
|
21
|
+
setWorking(message: string | undefined, visible: boolean): void;
|
|
22
|
+
statuses(): Map<string, string>;
|
|
23
|
+
/** The view with extension statuses merged over the engine's footer statuses. */
|
|
24
|
+
withStatuses(view: OwnedUiSessionViewModel): OwnedUiSessionViewModel;
|
|
25
|
+
renderWidgets(placement: ExtensionWidgetPlacement, width: number): readonly string[];
|
|
26
|
+
invalidate(): void;
|
|
27
|
+
/** Disposes and forgets everything an extension set; working visibility is the extension's own choice and stays. */
|
|
28
|
+
reset(): void;
|
|
29
|
+
dispose(): void;
|
|
30
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What extensions draw into the shell: a header that replaces the built-in one, a footer, widgets
|
|
3
|
+
* above and below the editor, footer statuses, and a working message. It owns those components and
|
|
4
|
+
* disposes each one it replaces; the root decides what to invalidate after a change.
|
|
5
|
+
*/
|
|
6
|
+
export class ExtensionSurface {
|
|
7
|
+
#header = null;
|
|
8
|
+
#footer = null;
|
|
9
|
+
#widgets = new Map();
|
|
10
|
+
#statuses = new Map();
|
|
11
|
+
#workingMessage;
|
|
12
|
+
#workingVisible = true;
|
|
13
|
+
get header() {
|
|
14
|
+
return this.#header;
|
|
15
|
+
}
|
|
16
|
+
get footer() {
|
|
17
|
+
return this.#footer;
|
|
18
|
+
}
|
|
19
|
+
get working() {
|
|
20
|
+
return { message: this.#workingMessage, visible: this.#workingVisible };
|
|
21
|
+
}
|
|
22
|
+
placeWidget(key, component, placement) {
|
|
23
|
+
const previous = this.#widgets.get(key)?.component;
|
|
24
|
+
if (component === null)
|
|
25
|
+
this.#widgets.delete(key);
|
|
26
|
+
else
|
|
27
|
+
this.#widgets.set(key, { component, placement });
|
|
28
|
+
if (previous !== undefined && previous !== component)
|
|
29
|
+
previous.dispose?.();
|
|
30
|
+
}
|
|
31
|
+
replaceHeader(component) {
|
|
32
|
+
if (this.#header !== component)
|
|
33
|
+
this.#header?.dispose?.();
|
|
34
|
+
this.#header = component;
|
|
35
|
+
}
|
|
36
|
+
replaceFooter(component) {
|
|
37
|
+
if (this.#footer !== component)
|
|
38
|
+
this.#footer?.dispose?.();
|
|
39
|
+
this.#footer = component;
|
|
40
|
+
}
|
|
41
|
+
setStatus(key, text) {
|
|
42
|
+
if (text === undefined)
|
|
43
|
+
this.#statuses.delete(key);
|
|
44
|
+
else
|
|
45
|
+
this.#statuses.set(key, text);
|
|
46
|
+
}
|
|
47
|
+
setWorking(message, visible) {
|
|
48
|
+
this.#workingMessage = message;
|
|
49
|
+
this.#workingVisible = visible;
|
|
50
|
+
}
|
|
51
|
+
statuses() {
|
|
52
|
+
return new Map(this.#statuses);
|
|
53
|
+
}
|
|
54
|
+
/** The view with extension statuses merged over the engine's footer statuses. */
|
|
55
|
+
withStatuses(view) {
|
|
56
|
+
const footer = view.status.footer;
|
|
57
|
+
const statuses = new Map(footer?.extensionStatuses ?? []);
|
|
58
|
+
for (const [key, text] of this.#statuses)
|
|
59
|
+
statuses.set(key, text);
|
|
60
|
+
return {
|
|
61
|
+
...view,
|
|
62
|
+
status: {
|
|
63
|
+
...view.status,
|
|
64
|
+
footer: {
|
|
65
|
+
...footer,
|
|
66
|
+
branch: footer?.branch ?? null,
|
|
67
|
+
sessionName: footer?.sessionName ?? null,
|
|
68
|
+
availableProviderCount: footer?.availableProviderCount ?? 1,
|
|
69
|
+
extensionStatuses: [...statuses],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
renderWidgets(placement, width) {
|
|
75
|
+
const rows = [...this.#widgets.values()]
|
|
76
|
+
.filter(widget => widget.placement === placement)
|
|
77
|
+
.flatMap(widget => widget.component.render(width));
|
|
78
|
+
return placement === "aboveEditor" ? ["", ...rows] : rows;
|
|
79
|
+
}
|
|
80
|
+
invalidate() {
|
|
81
|
+
this.#header?.invalidate();
|
|
82
|
+
this.#footer?.invalidate();
|
|
83
|
+
for (const { component } of this.#widgets.values())
|
|
84
|
+
component.invalidate();
|
|
85
|
+
}
|
|
86
|
+
/** Disposes and forgets everything an extension set; working visibility is the extension's own choice and stays. */
|
|
87
|
+
reset() {
|
|
88
|
+
this.#header?.dispose?.();
|
|
89
|
+
this.#footer?.dispose?.();
|
|
90
|
+
for (const { component } of this.#widgets.values())
|
|
91
|
+
component.dispose?.();
|
|
92
|
+
this.#header = null;
|
|
93
|
+
this.#footer = null;
|
|
94
|
+
this.#widgets.clear();
|
|
95
|
+
this.#statuses.clear();
|
|
96
|
+
this.#workingMessage = undefined;
|
|
97
|
+
}
|
|
98
|
+
dispose() {
|
|
99
|
+
this.#header?.dispose?.();
|
|
100
|
+
this.#footer?.dispose?.();
|
|
101
|
+
for (const { component } of this.#widgets.values())
|
|
102
|
+
component.dispose?.();
|
|
103
|
+
this.#widgets.clear();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PiShellComponentPort, PiShellEditorPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
2
|
+
import { type PiTuiInputSurfaceKind } from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
|
|
3
|
+
import type { SessionViewportController } from "./session-viewport-controller.js";
|
|
4
|
+
export interface InputSurfaceSwitchPorts {
|
|
5
|
+
/** Whether keystrokes that cannot change the transcript may repaint the dock alone. */
|
|
6
|
+
readonly dockInputReuse: boolean;
|
|
7
|
+
readonly viewport: Pick<SessionViewportController, "invalidateInputSurface" | "presentationRevision">;
|
|
8
|
+
/** The surface changed; listeners outside the root react. */
|
|
9
|
+
readonly onChanged?: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Which component receives the dock's input: the prompt editor, or a selector, dialog, or prompt
|
|
13
|
+
* that temporarily replaces it. It also records whether the latest keystroke is safe for a
|
|
14
|
+
* dock-only repaint; that receipt-time evidence never authorizes reuse by itself.
|
|
15
|
+
*/
|
|
16
|
+
export declare class InputSurfaceSwitch {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(editor: PiShellEditorPort, ports: InputSurfaceSwitchPorts);
|
|
19
|
+
get surface(): PiShellComponentPort;
|
|
20
|
+
get coordination(): PiTuiInputSurfaceKind;
|
|
21
|
+
get usesEditor(): boolean;
|
|
22
|
+
get dockInputCandidate(): boolean;
|
|
23
|
+
get dockInputRevision(): number | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Shows `component` in the dock, or the editor for null. Returns false when the surface is
|
|
26
|
+
* unchanged, in which case only its coordination kind is updated.
|
|
27
|
+
*/
|
|
28
|
+
set(component: PiShellComponentPort | null, disposePrevious: boolean, coordination: Exclude<PiTuiInputSurfaceKind, "editor">): boolean;
|
|
29
|
+
handleInput(data: string): void;
|
|
30
|
+
/** Reads and clears the dock-only candidate for one composition. */
|
|
31
|
+
takeDockInputCandidate(): boolean;
|
|
32
|
+
/** Something outside the dock changed, so the latest keystroke no longer qualifies for reuse. */
|
|
33
|
+
clearDockInputCandidate(): void;
|
|
34
|
+
/** Disposes a replacement surface; the editor is disposed by its owner. */
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { classifyPiTuiInput } from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
|
|
2
|
+
/**
|
|
3
|
+
* Which component receives the dock's input: the prompt editor, or a selector, dialog, or prompt
|
|
4
|
+
* that temporarily replaces it. It also records whether the latest keystroke is safe for a
|
|
5
|
+
* dock-only repaint; that receipt-time evidence never authorizes reuse by itself.
|
|
6
|
+
*/
|
|
7
|
+
export class InputSurfaceSwitch {
|
|
8
|
+
#editor;
|
|
9
|
+
#ports;
|
|
10
|
+
#surface;
|
|
11
|
+
#coordination = "editor";
|
|
12
|
+
#dockInputCandidate = false;
|
|
13
|
+
// Invariant: receipt-time eligibility is evidence, never authorization for composition-time reuse.
|
|
14
|
+
#dockInputRevision;
|
|
15
|
+
constructor(editor, ports) {
|
|
16
|
+
this.#editor = editor;
|
|
17
|
+
this.#ports = ports;
|
|
18
|
+
this.#surface = editor;
|
|
19
|
+
}
|
|
20
|
+
get surface() {
|
|
21
|
+
return this.#surface;
|
|
22
|
+
}
|
|
23
|
+
get coordination() {
|
|
24
|
+
return this.#coordination;
|
|
25
|
+
}
|
|
26
|
+
get usesEditor() {
|
|
27
|
+
return this.#surface === this.#editor;
|
|
28
|
+
}
|
|
29
|
+
get dockInputCandidate() {
|
|
30
|
+
return this.#dockInputCandidate;
|
|
31
|
+
}
|
|
32
|
+
get dockInputRevision() {
|
|
33
|
+
return this.#dockInputRevision;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Shows `component` in the dock, or the editor for null. Returns false when the surface is
|
|
37
|
+
* unchanged, in which case only its coordination kind is updated.
|
|
38
|
+
*/
|
|
39
|
+
set(component, disposePrevious, coordination) {
|
|
40
|
+
const next = component ?? this.#editor;
|
|
41
|
+
const nextCoordination = next === this.#editor ? "editor" : coordination;
|
|
42
|
+
if (next === this.#surface) {
|
|
43
|
+
this.#coordination = nextCoordination;
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
this.#dockInputCandidate = false;
|
|
47
|
+
this.#ports.viewport.invalidateInputSurface();
|
|
48
|
+
this.#surface.setFocused?.(false);
|
|
49
|
+
if (disposePrevious && this.#surface !== this.#editor)
|
|
50
|
+
this.#surface.dispose?.();
|
|
51
|
+
this.#surface = next;
|
|
52
|
+
this.#coordination = nextCoordination;
|
|
53
|
+
this.#ports.onChanged?.();
|
|
54
|
+
this.#surface.setFocused?.(true);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
handleInput(data) {
|
|
58
|
+
this.#dockInputCandidate = this.#ports.dockInputReuse && classifyPiTuiInput(data, this.#coordination) === "safe";
|
|
59
|
+
this.#dockInputRevision = this.#dockInputCandidate ? this.#ports.viewport.presentationRevision : undefined;
|
|
60
|
+
try {
|
|
61
|
+
this.#surface.handleInput?.(data);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
this.#dockInputCandidate = false;
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Reads and clears the dock-only candidate for one composition. */
|
|
69
|
+
takeDockInputCandidate() {
|
|
70
|
+
const candidate = this.#dockInputCandidate;
|
|
71
|
+
this.#dockInputCandidate = false;
|
|
72
|
+
return candidate;
|
|
73
|
+
}
|
|
74
|
+
/** Something outside the dock changed, so the latest keystroke no longer qualifies for reuse. */
|
|
75
|
+
clearDockInputCandidate() {
|
|
76
|
+
this.#dockInputCandidate = false;
|
|
77
|
+
this.#dockInputRevision = undefined;
|
|
78
|
+
}
|
|
79
|
+
/** Disposes a replacement surface; the editor is disposed by its owner. */
|
|
80
|
+
dispose() {
|
|
81
|
+
this.clearDockInputCandidate();
|
|
82
|
+
if (this.#surface !== this.#editor)
|
|
83
|
+
this.#surface.dispose?.();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { OwnedUiWorkflowInteractionRequest, OwnedUiWorkflowLoginNotification, OwnedUiWorkflowLoginStart } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { ProgramStatusReporter } from "../../integrations/pi/components/upstream/program-status-reporter.js";
|
|
3
|
+
import type { SessionConcern } from "./session-concern.js";
|
|
4
|
+
import type { OwnedUiSessionShellRoot } from "./session-shell-root.js";
|
|
5
|
+
import { type OwnedUiPresenterTerminal } from "./shell-host.js";
|
|
6
|
+
export interface LoginInteractionPorts {
|
|
7
|
+
readonly terminal: Pick<OwnedUiPresenterTerminal, "viewport" | "requestRender">;
|
|
8
|
+
readonly root: Pick<OwnedUiSessionShellRoot, "setInputSurface">;
|
|
9
|
+
readonly programStatus: Pick<ProgramStatusReporter, "setBlocked">;
|
|
10
|
+
/** The blocked-on-authentication state changed; the presenter republishes terminal progress. */
|
|
11
|
+
readonly syncProgress: () => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The engine's login flow in the dock: one login dialog at a time, the prompts and selections the
|
|
15
|
+
* engine asks through it, and the terminal's blocked-on-authentication status while it is open.
|
|
16
|
+
*/
|
|
17
|
+
export declare class LoginInteraction implements SessionConcern {
|
|
18
|
+
#private;
|
|
19
|
+
constructor(ports: LoginInteractionPorts);
|
|
20
|
+
start(request: OwnedUiWorkflowLoginStart): void;
|
|
21
|
+
/** Answers an engine prompt through the open dialog; null when no login is in progress or it is cancelled. */
|
|
22
|
+
requestInput(request: OwnedUiWorkflowInteractionRequest): Promise<string | null>;
|
|
23
|
+
notify(event: OwnedUiWorkflowLoginNotification): void;
|
|
24
|
+
finish(): void;
|
|
25
|
+
/** A replaced session forgets its dialog; the presenter clears the input surface as part of the same replacement. */
|
|
26
|
+
onSessionReplaced(): void;
|
|
27
|
+
}
|