@timurproko/a1 0.2.7-dev.806 → 0.2.7-dev.809
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/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/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 +209 -897
- 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 +26 -4
- 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 +6 -25
- package/dist/composition/owned-ui.js +48 -242
- 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/settings-route-host.d.ts +6 -1
- package/dist/composition/settings-route-host.js +7 -6
- package/dist/composition/startup-route.d.ts +32 -0
- package/dist/composition/startup-route.js +72 -0
- package/dist/features/owned-ui/settings-app.d.ts +4 -1
- package/dist/features/owned-ui/settings-app.js +9 -3
- package/dist/features/resident-tab/shortcut-declarations.js +1 -1
- package/dist/features/resident-tab/status-deriver.d.ts +4 -3
- package/dist/features/resident-tab/status-deriver.js +2 -5
- package/dist/foundation/release/bootstrap.js +2 -2
- package/dist/foundation/resident-tabs/bridge-client.d.ts +1 -1
- package/dist/foundation/resident-tabs/bridge-client.js +2 -1
- package/dist/foundation/resident-tabs/fixture-control.d.ts +7 -0
- package/dist/foundation/resident-tabs/fixture-control.js +35 -0
- package/dist/foundation/resident-tabs/progress-observation.d.ts +7 -0
- package/dist/foundation/resident-tabs/progress-observation.js +119 -0
- package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/index.js +1 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +5 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.js +5 -0
- 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/session-runtime.js +5 -2
- 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/tui-runtime/adapter.d.ts +6 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +28 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +11 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +30 -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/product-identity.d.ts +2 -2
- package/dist/product-identity.js +2 -2
- package/dist/product-identity.json +6 -0
- package/dist/ui/settings/manager.d.ts +6 -0
- package/dist/ui/settings/manager.js +25 -0
- package/docs/architecture/boundaries.md +14 -0
- package/docs/architecture/resident-tabs.md +23 -18
- package/package.json +2 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OwnedUiSessionSettingsPort, OwnedUiSessionSettingsSnapshot } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { OwnedUiPresenterTerminal } from "./shell-host.js";
|
|
3
|
+
import type { OwnedUiSessionShellRoot } from "./session-shell-root.js";
|
|
4
|
+
/** What the session's live setting effects reach: terminal modes, root presentation, and the presenter's progress flag. */
|
|
5
|
+
export interface SessionSettingsTargets {
|
|
6
|
+
readonly terminal: Pick<OwnedUiPresenterTerminal, "setHardwareCursor" | "setClearOnShrink" | "setWheelScrollLines">;
|
|
7
|
+
readonly root: Pick<OwnedUiSessionShellRoot, "setEditorPaddingX" | "setAutocompleteMaxVisible" | "setOutputPad" | "setHideThinkingBlock" | "setMermaidRenderingMode" | "setImagePresentation" | "setFullscreenCopyOnSelect">;
|
|
8
|
+
setTerminalProgress(enabled: boolean): void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Applies the snapshot's presentation settings, then binds every live setting effect the session
|
|
12
|
+
* owns, one owner at a time. The returned function releases the owners in reverse; a failed bind
|
|
13
|
+
* releases the owners already bound before it throws.
|
|
14
|
+
*/
|
|
15
|
+
export declare function bindSessionSettings(settings: Pick<OwnedUiSessionSettingsPort, "bindOwner" | "productMode">, snapshot: OwnedUiSessionSettingsSnapshot, targets: SessionSettingsTargets, options: {
|
|
16
|
+
readonly customViewport: boolean;
|
|
17
|
+
}): () => void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const isBoolean = (value) => typeof value === "boolean";
|
|
2
|
+
const isNumber = (value) => typeof value === "number";
|
|
3
|
+
const isOutputPad = (value) => value === 0 || value === 1;
|
|
4
|
+
const isMermaidMode = (value) => value === "off" || value === "final" || value === "streaming";
|
|
5
|
+
const isImageWidth = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
6
|
+
const isWheelDistance = (value) => value === "auto" || typeof value === "number" && Number.isSafeInteger(value) && value >= 1 && value <= 100;
|
|
7
|
+
function snapshotValue(snapshot, key) {
|
|
8
|
+
const values = snapshot;
|
|
9
|
+
return values[key];
|
|
10
|
+
}
|
|
11
|
+
/** One validated setting; `seeded` also installs the snapshot's value at bind time. */
|
|
12
|
+
function setting(owner, key, invalid, accepts, apply, seeded = true) {
|
|
13
|
+
return {
|
|
14
|
+
owner,
|
|
15
|
+
key,
|
|
16
|
+
live: value => {
|
|
17
|
+
if (!accepts(value))
|
|
18
|
+
throw new TypeError(invalid);
|
|
19
|
+
apply(value);
|
|
20
|
+
},
|
|
21
|
+
...(seeded ? {
|
|
22
|
+
seed: (snapshot) => {
|
|
23
|
+
const value = snapshotValue(snapshot, key);
|
|
24
|
+
if (accepts(value))
|
|
25
|
+
apply(value);
|
|
26
|
+
},
|
|
27
|
+
} : {}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function settingBindings(targets, snapshot, customViewport, bare) {
|
|
31
|
+
const { root, terminal } = targets;
|
|
32
|
+
let showImages = snapshot.showImages;
|
|
33
|
+
let imageWidthCells = snapshot.imageWidthCells;
|
|
34
|
+
const presentImages = () => root.setImagePresentation(showImages, imageWidthCells);
|
|
35
|
+
return [
|
|
36
|
+
// Invariant: bare A1 prints only the resume hint at exit, so the pinned exit-output
|
|
37
|
+
// choice is hidden there and cannot be bound; the comparison profile binds and honors it.
|
|
38
|
+
...(bare ? [] : [{ owner: "shutdown", key: "fullscreenExitOutput", live: () => { } }]),
|
|
39
|
+
setting("terminal", "showHardwareCursor", "Hardware cursor setting is invalid", isBoolean, value => terminal.setHardwareCursor(value)),
|
|
40
|
+
setting("terminal", "clearOnShrink", "Clear-on-shrink setting is invalid", isBoolean, value => terminal.setClearOnShrink(value)),
|
|
41
|
+
setting("terminal", "showTerminalProgress", "Terminal progress setting is invalid", isBoolean, value => targets.setTerminalProgress(value)),
|
|
42
|
+
setting("shell", "editorPaddingX", "Editor padding is invalid", isNumber, value => root.setEditorPaddingX(value)),
|
|
43
|
+
setting("shell", "autocompleteMaxVisible", "Autocomplete maximum is invalid", isNumber, value => root.setAutocompleteMaxVisible(value)),
|
|
44
|
+
setting("shell", "outputPad", "Output padding is invalid", isOutputPad, value => root.setOutputPad(value)),
|
|
45
|
+
setting("shell", "hideThinkingBlock", "Thinking-block visibility is invalid", isBoolean, value => root.setHideThinkingBlock(value)),
|
|
46
|
+
setting("shell", "mermaidRenderingMode", "Mermaid mode is invalid", isMermaidMode, value => root.setMermaidRenderingMode(value)),
|
|
47
|
+
setting("shell", "showImages", "Image visibility is invalid", isBoolean, value => { showImages = value; presentImages(); }, false),
|
|
48
|
+
setting("shell", "imageWidthCells", "Image width is invalid", isImageWidth, value => { imageWidthCells = value; presentImages(); }, false),
|
|
49
|
+
{ owner: null, key: "imageWidthCells", live: () => { }, seed: presentImages },
|
|
50
|
+
// Invariant: the custom viewport owns copy-on-select; the pinned comparison profile keeps Pi's wheel distance.
|
|
51
|
+
customViewport
|
|
52
|
+
? setting("shell", "fullscreenCopyOnSelect", "Fullscreen copy-on-select setting is invalid", isBoolean, value => root.setFullscreenCopyOnSelect(value))
|
|
53
|
+
: setting("shell", "fullscreenWheelScrollLines", "Fullscreen wheel-scroll distance is invalid", isWheelDistance, value => terminal.setWheelScrollLines(value), false),
|
|
54
|
+
...(customViewport ? [] : [{
|
|
55
|
+
owner: null,
|
|
56
|
+
key: "fullscreenCopyOnSelect",
|
|
57
|
+
live: () => { },
|
|
58
|
+
seed: (initial) => root.setFullscreenCopyOnSelect(initial.fullscreenCopyOnSelect),
|
|
59
|
+
}]),
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Applies the snapshot's presentation settings, then binds every live setting effect the session
|
|
64
|
+
* owns, one owner at a time. The returned function releases the owners in reverse; a failed bind
|
|
65
|
+
* releases the owners already bound before it throws.
|
|
66
|
+
*/
|
|
67
|
+
export function bindSessionSettings(settings, snapshot, targets, options) {
|
|
68
|
+
const bindings = settingBindings(targets, snapshot, options.customViewport, settings.productMode === "bare");
|
|
69
|
+
for (const binding of bindings)
|
|
70
|
+
binding.seed?.(snapshot);
|
|
71
|
+
const owners = [...new Set(bindings.flatMap(binding => binding.owner === null ? [] : [binding.owner]))];
|
|
72
|
+
const releases = [];
|
|
73
|
+
const release = () => {
|
|
74
|
+
for (const unbind of releases.splice(0).reverse())
|
|
75
|
+
unbind();
|
|
76
|
+
};
|
|
77
|
+
try {
|
|
78
|
+
for (const owner of owners) {
|
|
79
|
+
const handlers = {};
|
|
80
|
+
for (const binding of bindings.filter(candidate => candidate.owner === owner)) {
|
|
81
|
+
handlers[binding.key] = { apply: value => binding.live(value) };
|
|
82
|
+
}
|
|
83
|
+
releases.push(settings.bindOwner(owner, handlers));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
release();
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
return release;
|
|
91
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type PiShellEditorOptions, type PiShellEditorPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
2
|
+
import type { PasteEvent, PasteSource } from "./paste-protocol.js";
|
|
3
|
+
import type { PromptChipStore } from "./prompt-chips.js";
|
|
4
|
+
/** The shell callbacks the editor is wired to; the editor receives the whole object as its own options. */
|
|
5
|
+
export type ShellEditorHandlers = Omit<PiShellEditorOptions, "onChange" | "onToolsExpand" | "keybindingProfile"> & {
|
|
6
|
+
readonly requestRender: (force?: boolean) => void;
|
|
7
|
+
readonly onEditorChange?: (text: string) => void;
|
|
8
|
+
readonly captureClipboardPaste?: () => PasteSource;
|
|
9
|
+
readonly pasteDiagnostics?: (event: PasteEvent) => void;
|
|
10
|
+
};
|
|
11
|
+
export interface ShellEditorPorts {
|
|
12
|
+
readonly handlers: ShellEditorHandlers;
|
|
13
|
+
readonly customViewport: boolean;
|
|
14
|
+
readonly cwd: string;
|
|
15
|
+
readonly agentDir?: string;
|
|
16
|
+
readonly promptChips: PromptChipStore;
|
|
17
|
+
/** True while a pointer drag selects editor text, which paints links as plain underlines. */
|
|
18
|
+
readonly editorPointerSelecting: () => boolean;
|
|
19
|
+
/** The next payload-free paste diagnostic id, shared with the viewport's own paste diagnostics. */
|
|
20
|
+
readonly nextPasteDiagnosticRequest: () => number;
|
|
21
|
+
readonly toggleToolsExpanded: () => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Builds the session's prompt editor: chip-aware paste, selection, and hyperlink decoration over
|
|
25
|
+
* the Pi editor, plus bare A1's prompt presentation and terminal paste diagnostics.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createShellEditor(ports: ShellEditorPorts): PiShellEditorPort;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { caretCell } from "../../ui/components/line-input.js";
|
|
2
|
+
import { PromptInput } from "../../ui/components/prompt-input.js";
|
|
3
|
+
import { backgroundSgrSpan, hyperlinkSgrSpan } from "../../ui/components/spans.js";
|
|
4
|
+
import { faint, stripAnsi } from "../../ui/components/text.js";
|
|
5
|
+
import { createPiShellEditor } from "../../integrations/pi/components/shell-editor-autocomplete.js";
|
|
6
|
+
import { piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
|
|
7
|
+
import { piShellTruncateToWidth, piShellVisibleWidth, } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
8
|
+
import { EditorHyperlinkBudget } from "./editor-hyperlink-budget.js";
|
|
9
|
+
import { canPreparePasteInline } from "./paste-text-preparation.js";
|
|
10
|
+
/**
|
|
11
|
+
* Builds the session's prompt editor: chip-aware paste, selection, and hyperlink decoration over
|
|
12
|
+
* the Pi editor, plus bare A1's prompt presentation and terminal paste diagnostics.
|
|
13
|
+
*/
|
|
14
|
+
export function createShellEditor(ports) {
|
|
15
|
+
const { handlers, customViewport, promptChips } = ports;
|
|
16
|
+
let terminalPasteDiagnosticRequest;
|
|
17
|
+
const editor = createPiShellEditor({
|
|
18
|
+
...handlers,
|
|
19
|
+
keybindingProfile: customViewport ? "a1" : "pi",
|
|
20
|
+
...(handlers.keybindings === undefined ? {} : { keybindings: handlers.keybindings }),
|
|
21
|
+
paintEditorSelection: (line, from, to, atomic) => backgroundSgrSpan(line, from, to, atomic ? "\u001b[7m" : "\u001b[27m\u001b[48;2;38;79;120m", atomic ? "\u001b[27m" : "\u001b[49m", piShellVisibleWidth),
|
|
22
|
+
transformPastedContent: content => {
|
|
23
|
+
try {
|
|
24
|
+
return promptChips.transformPastedContent(content, editor.getText());
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
handlers.onPasteRejected?.(error);
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
...(customViewport ? {
|
|
32
|
+
beginClipboardPaste: () => promptChips.beginPaste(editor.getText(), handlers.captureClipboardPaste?.() ?? { kind: "provided", read: signal => handlers.readClipboardContent?.(signal) ?? Promise.resolve(null) }, error => handlers.onPasteRejected?.(error), () => handlers.requestRender()),
|
|
33
|
+
onPasteInput: (bytes, phase) => {
|
|
34
|
+
try {
|
|
35
|
+
if (phase === "framing")
|
|
36
|
+
terminalPasteDiagnosticRequest = ports.nextPasteDiagnosticRequest();
|
|
37
|
+
const request = terminalPasteDiagnosticRequest ?? ports.nextPasteDiagnosticRequest();
|
|
38
|
+
handlers.pasteDiagnostics?.({ request, phase, bytes, atMs: performance.now(), pending: 0, transport: "terminal",
|
|
39
|
+
...(phase === "settled" ? { outcome: "ready" } : {}) });
|
|
40
|
+
if (phase === "settled")
|
|
41
|
+
terminalPasteDiagnosticRequest = undefined;
|
|
42
|
+
}
|
|
43
|
+
catch { /* Invariant: payload-free diagnostics cannot interfere with the input path. */ }
|
|
44
|
+
},
|
|
45
|
+
deferTextPaste: text => !canPreparePasteInline(text),
|
|
46
|
+
beginTextPaste: text => promptChips.beginPaste(editor.getText(), { kind: "text", text }, error => handlers.onPasteRejected?.(error)),
|
|
47
|
+
} : {}),
|
|
48
|
+
editorAtomicRanges: line => promptChips.atomicRanges(line),
|
|
49
|
+
editorHiddenRanges: line => promptChips.hiddenRanges(line),
|
|
50
|
+
decorateEditorRow: editorRowDecorator(promptChips, ports.editorPointerSelecting),
|
|
51
|
+
expandCopiedEditorText: text => promptChips.expandCopiedText(text),
|
|
52
|
+
cwd: ports.cwd,
|
|
53
|
+
...(ports.agentDir === undefined ? {} : { agentDir: ports.agentDir }),
|
|
54
|
+
onToolsExpand: () => ports.toggleToolsExpanded(),
|
|
55
|
+
...(customViewport ? {
|
|
56
|
+
promptPresentation: {
|
|
57
|
+
input: new PromptInput({ fg: (token, text) => piTheme().fg(token, text) }, {
|
|
58
|
+
measure: piShellVisibleWidth,
|
|
59
|
+
truncate: piShellTruncateToWidth,
|
|
60
|
+
}),
|
|
61
|
+
styleSuggestion: faint,
|
|
62
|
+
styleSuggestionCaret: caretCell,
|
|
63
|
+
},
|
|
64
|
+
} : {}),
|
|
65
|
+
onChange: text => {
|
|
66
|
+
handlers.onEditorChange?.(text);
|
|
67
|
+
// Concurrency: Pi clears before onSubmit; capture waiting references before pruning removed chips.
|
|
68
|
+
queueMicrotask(() => promptChips.reconcileDraft(editor.getText()));
|
|
69
|
+
},
|
|
70
|
+
...(handlers.onPromptSuggestionAccepted === undefined ? {} : { onPromptSuggestionAccepted: handlers.onPromptSuggestionAccepted }),
|
|
71
|
+
});
|
|
72
|
+
return editor;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Dims unsent chips and turns the draft's URLs into terminal hyperlinks, each target once per
|
|
76
|
+
* decoration pass; while a pointer drag selects, links paint as plain underlines instead.
|
|
77
|
+
*/
|
|
78
|
+
function editorRowDecorator(promptChips, editorPointerSelecting) {
|
|
79
|
+
const editorHyperlinks = new EditorHyperlinkBudget();
|
|
80
|
+
return (row, width, rowIndex) => {
|
|
81
|
+
if (rowIndex === 0)
|
|
82
|
+
editorHyperlinks.reset();
|
|
83
|
+
const plain = stripAnsi(row);
|
|
84
|
+
const dimmed = promptChips.unsentRanges(plain).reduce((result, range) => backgroundSgrSpan(result, piShellVisibleWidth(plain.slice(0, range.start)), piShellVisibleWidth(plain.slice(0, range.end)), "\u001b[2m", "\u001b[22m", piShellVisibleWidth), row);
|
|
85
|
+
const ranges = promptChips.hyperlinkRanges(plain);
|
|
86
|
+
if (ranges.length === 0 || !editorHyperlinks.takeCleanup())
|
|
87
|
+
return dimmed;
|
|
88
|
+
const linkResetAndTail = `\u001b]8;;\u001b\\\u001b[24m${" ".repeat(Math.max(0, width - piShellVisibleWidth(dimmed)))}`;
|
|
89
|
+
// Platform: VS15 is zero-column and default-ignorable. It breaks Windows Terminal's
|
|
90
|
+
// plain-text URL detector only in the held-button paint; semantic text stays exact.
|
|
91
|
+
const selecting = editorPointerSelecting();
|
|
92
|
+
const paintRow = selecting
|
|
93
|
+
? dimmed.replaceAll("https://", "https:︎//").replaceAll("http://", "http:︎//")
|
|
94
|
+
: dimmed;
|
|
95
|
+
const decorated = selecting
|
|
96
|
+
? ranges.reduce((result, range) => backgroundSgrSpan(result, piShellVisibleWidth(plain.slice(0, range.start)), piShellVisibleWidth(plain.slice(0, range.end)), "\u001b[4:4m", "\u001b[24m", piShellVisibleWidth), paintRow)
|
|
97
|
+
: ranges.filter(range => editorHyperlinks.take(range.target)).reduce((result, range) => hyperlinkSgrSpan(result, piShellVisibleWidth(plain.slice(0, range.start)), piShellVisibleWidth(plain.slice(0, range.end)), range.target, piShellVisibleWidth), dimmed);
|
|
98
|
+
// Platform: Windows Terminal can retain stale native dotted-link cells when a mutable
|
|
99
|
+
// prompt replaces a longer URL. Explicit non-link spaces overwrite that tail.
|
|
100
|
+
return `${decorated}${linkResetAndTail}`;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -78,6 +78,12 @@ export interface OwnedUiTerminalHostOptions {
|
|
|
78
78
|
readonly backgroundSettings?: OwnedUiBackgroundSettingsPort;
|
|
79
79
|
readonly quitOutro?: OwnedUiShellPresentationOptions["quitOutro"];
|
|
80
80
|
}
|
|
81
|
+
/** The size and render request a Pi component reads from the terminal it is shown on, read on every call. */
|
|
82
|
+
export declare function componentRuntime(terminal: Pick<OwnedUiPresenterTerminal, "viewport" | "requestRender">): {
|
|
83
|
+
getColumns(): number;
|
|
84
|
+
getRows(): number;
|
|
85
|
+
requestRender(): void;
|
|
86
|
+
};
|
|
81
87
|
/** The terminal a session's shell options call for: its layout, TUI mode, cursor, and presentation seams. */
|
|
82
88
|
export declare function sessionTerminalHostOptions(options: OwnedUiSessionShellOptions): OwnedUiTerminalHostOptions;
|
|
83
89
|
/**
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { MOUSE_TRACKING_OFF, MOUSE_TRACKING_ON, parseMouseInput } from "../../ui/components/mouse.js";
|
|
2
2
|
import { readVisibleHyperlinks } from "../../ui/components/visible-hyperlinks.js";
|
|
3
3
|
import { piCanvasBackgroundAnsi } from "../../integrations/pi/components/theme.js";
|
|
4
|
+
import { residentFixtureControl } from "../../foundation/resident-tabs/fixture-control.js";
|
|
5
|
+
import { residentProgressObserver } from "../../foundation/resident-tabs/progress-observation.js";
|
|
4
6
|
import { DamageAwareTerminalAdapter, } from "../../integrations/pi/tui-runtime/damage-aware-terminal.js";
|
|
5
|
-
import { PiTuiRuntimeAdapter } from "../../integrations/pi/tui-runtime/adapter.js";
|
|
7
|
+
import { PiTuiRuntimeAdapter, legacyKeyInput } from "../../integrations/pi/tui-runtime/adapter.js";
|
|
6
8
|
import { classifyPiTuiInput } from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
|
|
7
9
|
import { pinnedLayoutRoot, } from "./session-shell-root.js";
|
|
10
|
+
/** The size and render request a Pi component reads from the terminal it is shown on, read on every call. */
|
|
11
|
+
export function componentRuntime(terminal) {
|
|
12
|
+
return {
|
|
13
|
+
getColumns: () => terminal.viewport().columns,
|
|
14
|
+
getRows: () => terminal.viewport().rows,
|
|
15
|
+
requestRender: () => terminal.requestRender(),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
8
18
|
/** The terminal a session's shell options call for: its layout, TUI mode, cursor, and presentation seams. */
|
|
9
19
|
export function sessionTerminalHostOptions(options) {
|
|
10
20
|
const { backend, sessionLayout } = options.engine;
|
|
@@ -47,6 +57,8 @@ export class OwnedUiTerminalHost {
|
|
|
47
57
|
this.#customViewport = options.layout === "custom-viewport";
|
|
48
58
|
this.#quitOutro = options.quitOutro;
|
|
49
59
|
const input = options.input;
|
|
60
|
+
const fixtureControl = residentFixtureControl();
|
|
61
|
+
const progressObserver = residentProgressObserver();
|
|
50
62
|
let damageTerminal;
|
|
51
63
|
const surface = {
|
|
52
64
|
render: width => this.#active?.render(width) ?? [],
|
|
@@ -72,6 +84,13 @@ export class OwnedUiTerminalHost {
|
|
|
72
84
|
inspectHyperlinks: readVisibleHyperlinks,
|
|
73
85
|
onResize: () => this.#active?.noteImmediatePresentation(),
|
|
74
86
|
onHyperlinkCleanupRequired: () => this.runtime?.requestRender(true),
|
|
87
|
+
...(fixtureControl === null ? {} : {
|
|
88
|
+
allowWrite: () => !fixtureControl.stopped("child-render-write"),
|
|
89
|
+
writeChunks: data => fixtureControl.fragmentChildWrite(data),
|
|
90
|
+
}),
|
|
91
|
+
...(progressObserver === null ? {} : {
|
|
92
|
+
onWrite: ({ bytes, fragments, transaction, frameId, cause }) => progressObserver.childRenderWrite(bytes, fragments, transaction, frameId, cause),
|
|
93
|
+
}),
|
|
75
94
|
});
|
|
76
95
|
return damageTerminal;
|
|
77
96
|
},
|
|
@@ -337,7 +356,8 @@ export class OwnedUiTerminalHost {
|
|
|
337
356
|
callbacks.closed(rendered);
|
|
338
357
|
};
|
|
339
358
|
removeInterruptWatch = runtime.addInputListener(data => {
|
|
340
|
-
|
|
359
|
+
// Compatibility: a kitty-keyboard child reports Ctrl+C as a CSI-u sequence rather than the byte.
|
|
360
|
+
if (!attached() || !data.includes(INTERRUPT) && legacyKeyInput(data) !== INTERRUPT)
|
|
341
361
|
return undefined;
|
|
342
362
|
// Protocol: route hosts decide whether one interrupt closes their app. Raw-input forwarding
|
|
343
363
|
// is required because Pi handles Ctrl+C before the fullscreen overlay receives normal input.
|
|
@@ -395,8 +415,10 @@ export class OwnedUiTerminalHost {
|
|
|
395
415
|
const { events, rest } = parseMouseInput(data);
|
|
396
416
|
for (const event of events)
|
|
397
417
|
surface.handleMouse(event);
|
|
398
|
-
|
|
399
|
-
|
|
418
|
+
// Invariant: owned screens see legacy key bytes whether the terminal reports legacy or kitty keys.
|
|
419
|
+
const key = rest.length > 0 ? legacyKeyInput(rest) : "";
|
|
420
|
+
if (key.length > 0)
|
|
421
|
+
surface.handleInput(key);
|
|
400
422
|
if (surface.isClosed()) {
|
|
401
423
|
closeSurface(true);
|
|
402
424
|
return;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { OwnedUiSessionViewModel } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { TranscriptViewportFrame, TranscriptViewportFrameInput, TranscriptViewportTheme } from "../../ui/components/transcript-viewport.js";
|
|
3
|
+
import type { PiShellEditorPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
4
|
+
import type { DockChrome } from "./dock-chrome.js";
|
|
5
|
+
import type { InputSurfaceSwitch } from "./input-surface-switch.js";
|
|
6
|
+
import type { PromptChipStore } from "./prompt-chips.js";
|
|
7
|
+
import type { SessionViewportController } from "./session-viewport-controller.js";
|
|
8
|
+
import type { TranscriptDocumentLayout } from "./transcript-document.js";
|
|
9
|
+
/** The dock's rows and where its input and footer sit inside them. */
|
|
10
|
+
export interface DockLayout {
|
|
11
|
+
readonly rows: readonly string[];
|
|
12
|
+
readonly inputOffset: number;
|
|
13
|
+
readonly editorOffset: number;
|
|
14
|
+
readonly inputRows: number;
|
|
15
|
+
readonly footerRows: number;
|
|
16
|
+
/** Exact status, warning, error, command-result, and notice rows; queued and structural rows stay excluded. */
|
|
17
|
+
readonly copyableMessageRows: NonNullable<TranscriptViewportFrameInput["copyableDockRows"]>;
|
|
18
|
+
}
|
|
19
|
+
/** What a layout reads from the shell root to compose one frame. */
|
|
20
|
+
export interface ShellLayoutPorts {
|
|
21
|
+
readonly viewport: SessionViewportController;
|
|
22
|
+
readonly input: InputSurfaceSwitch;
|
|
23
|
+
readonly editor: Pick<PiShellEditorPort, "getText">;
|
|
24
|
+
readonly promptChips: Pick<PromptChipStore, "atomicRanges">;
|
|
25
|
+
readonly dockChrome: Pick<DockChrome, "renderCopyAcknowledgement" | "renderReleaseBanner" | "locateReleaseClose">;
|
|
26
|
+
readonly theme: TranscriptViewportTheme;
|
|
27
|
+
readonly onFrame?: (frame: TranscriptViewportFrame) => void;
|
|
28
|
+
rows(): number;
|
|
29
|
+
dock(width: number): DockLayout;
|
|
30
|
+
document(width: number): TranscriptDocumentLayout;
|
|
31
|
+
queued(width: number): readonly string[];
|
|
32
|
+
liveStatus(width: number): readonly string[];
|
|
33
|
+
diagnostics(): OwnedUiSessionViewModel["diagnostics"];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* How one session's root composes a frame. The root picks one layout at construction and never
|
|
37
|
+
* consults the layout mode again on the render path.
|
|
38
|
+
*/
|
|
39
|
+
export interface ShellLayout {
|
|
40
|
+
render(width: number): readonly string[];
|
|
41
|
+
/** Visible content changed outside a render, so the next frame may not reuse the last one. */
|
|
42
|
+
invalidate(): void;
|
|
43
|
+
/** What the last composed frame represented, for payload-free evidence; undefined before one exists. */
|
|
44
|
+
composed(): {
|
|
45
|
+
readonly viewportRevision: number;
|
|
46
|
+
readonly pointerPosition: TranscriptViewportFrameInput["pointerPosition"];
|
|
47
|
+
} | undefined;
|
|
48
|
+
compositions(): {
|
|
49
|
+
readonly full: number;
|
|
50
|
+
readonly dockOnly: number;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** The pinned comparison profile: the whole document above the dock; the terminal host scrolls it. */
|
|
54
|
+
export declare class PinnedLayout implements ShellLayout {
|
|
55
|
+
#private;
|
|
56
|
+
constructor(ports: ShellLayoutPorts);
|
|
57
|
+
render(width: number): readonly string[];
|
|
58
|
+
invalidate(): void;
|
|
59
|
+
composed(): undefined;
|
|
60
|
+
compositions(): {
|
|
61
|
+
readonly full: number;
|
|
62
|
+
readonly dockOnly: number;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** The pinned comparison profile: the whole document above the dock; the terminal host scrolls it. */
|
|
2
|
+
export class PinnedLayout {
|
|
3
|
+
#ports;
|
|
4
|
+
constructor(ports) {
|
|
5
|
+
this.#ports = ports;
|
|
6
|
+
}
|
|
7
|
+
render(width) {
|
|
8
|
+
this.#ports.viewport.setEditorPointerFrame(undefined);
|
|
9
|
+
return [...this.#ports.document(width).rows, ...this.#ports.dock(width).rows];
|
|
10
|
+
}
|
|
11
|
+
invalidate() { }
|
|
12
|
+
composed() {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
compositions() {
|
|
16
|
+
return { full: 0, dockOnly: 0 };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { OwnedUiEvent, OwnedUiPromptSuggestionIdentity, OwnedUiSessionViewModel, SuggestionDecision } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { ContextualPromptSuggestionController, ContextualPromptSuggestionSurface } from "./prompt-suggestion-controller.js";
|
|
3
|
+
import type { OwnedUiSessionShellRoot } from "./session-shell-root.js";
|
|
4
|
+
type ResponseEvent = Extract<OwnedUiEvent, {
|
|
5
|
+
readonly type: "assistant-message-completed" | "agent-run-settled";
|
|
6
|
+
}>;
|
|
7
|
+
/** The provider/model key a suggestion identity and the session view are compared by; empty without a model. */
|
|
8
|
+
export declare function suggestionModelKey(view: Pick<OwnedUiSessionViewModel, "activeModel">): string;
|
|
9
|
+
/**
|
|
10
|
+
* Why a completed response cannot seed a suggestion, checked in order; `prepareBlockReason` is asked
|
|
11
|
+
* only when the response itself qualifies.
|
|
12
|
+
*/
|
|
13
|
+
export declare function responseSuggestionDecision(event: ResponseEvent, prepareBlockReason: () => SuggestionDecision): SuggestionDecision;
|
|
14
|
+
/** Hands one completed or settled response to the controller: skipped without a model, otherwise considered or settled. */
|
|
15
|
+
export declare function routeResponseToSuggestions(controller: Pick<ContextualPromptSuggestionController, "skip" | "consider" | "settle"> | null, event: ResponseEvent, prepareBlockReason: () => SuggestionDecision): void;
|
|
16
|
+
export interface SuggestionPresentationState {
|
|
17
|
+
readonly disposed: boolean;
|
|
18
|
+
readonly view: Pick<OwnedUiSessionViewModel, "sessionId" | "activeModel">;
|
|
19
|
+
readonly sessionGeneration: number;
|
|
20
|
+
}
|
|
21
|
+
/** Why a prepared suggestion cannot be shown now: a released shell, a different session or model, or the root's own reason. */
|
|
22
|
+
export declare function suggestionPresentationBlockReason(identity: OwnedUiPromptSuggestionIdentity, state: SuggestionPresentationState, rootBlockReason: () => SuggestionDecision): SuggestionDecision;
|
|
23
|
+
/** The controller's view of the shell: ghost text in the root's editor, gated by `blockReason`. */
|
|
24
|
+
export declare function promptSuggestionSurface(root: Pick<OwnedUiSessionShellRoot, "canPresentPromptSuggestion" | "setPromptSuggestion">, blockReason: (identity: OwnedUiPromptSuggestionIdentity) => SuggestionDecision, requestRender: () => void): ContextualPromptSuggestionSurface;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** The provider/model key a suggestion identity and the session view are compared by; empty without a model. */
|
|
2
|
+
export function suggestionModelKey(view) {
|
|
3
|
+
return view.activeModel === null ? "" : `${view.activeModel.providerId}/${view.activeModel.modelId}`;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Why a completed response cannot seed a suggestion, checked in order; `prepareBlockReason` is asked
|
|
7
|
+
* only when the response itself qualifies.
|
|
8
|
+
*/
|
|
9
|
+
export function responseSuggestionDecision(event, prepareBlockReason) {
|
|
10
|
+
if (!event.successful)
|
|
11
|
+
return "failed-response";
|
|
12
|
+
if (event.toolContinuation || event.stopReason === "toolUse")
|
|
13
|
+
return "tool-continuation";
|
|
14
|
+
if (event.stopReason !== "stop")
|
|
15
|
+
return "incomplete-response";
|
|
16
|
+
if (event.assistantMessageCount < 2)
|
|
17
|
+
return "early-conversation";
|
|
18
|
+
return prepareBlockReason();
|
|
19
|
+
}
|
|
20
|
+
/** Hands one completed or settled response to the controller: skipped without a model, otherwise considered or settled. */
|
|
21
|
+
export function routeResponseToSuggestions(controller, event, prepareBlockReason) {
|
|
22
|
+
const identity = {
|
|
23
|
+
sessionId: event.sessionId,
|
|
24
|
+
sessionGeneration: event.sessionGeneration,
|
|
25
|
+
runSequence: event.runSequence,
|
|
26
|
+
responseSequence: event.responseSequence,
|
|
27
|
+
model: event.model,
|
|
28
|
+
};
|
|
29
|
+
if (event.model === null) {
|
|
30
|
+
controller?.skip(identity, "no-model");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const known = { ...identity, model: event.model };
|
|
34
|
+
const decision = responseSuggestionDecision(event, prepareBlockReason);
|
|
35
|
+
if (event.type === "assistant-message-completed")
|
|
36
|
+
controller?.consider(known, decision);
|
|
37
|
+
else
|
|
38
|
+
controller?.settle(known, decision);
|
|
39
|
+
}
|
|
40
|
+
/** Why a prepared suggestion cannot be shown now: a released shell, a different session or model, or the root's own reason. */
|
|
41
|
+
export function suggestionPresentationBlockReason(identity, state, rootBlockReason) {
|
|
42
|
+
if (state.disposed)
|
|
43
|
+
return "disposed";
|
|
44
|
+
if (identity.sessionId !== state.view.sessionId || identity.sessionGeneration !== state.sessionGeneration
|
|
45
|
+
|| suggestionModelKey(state.view) !== `${identity.model.providerId}/${identity.model.modelId}`)
|
|
46
|
+
return "stale-identity";
|
|
47
|
+
return rootBlockReason();
|
|
48
|
+
}
|
|
49
|
+
/** The controller's view of the shell: ghost text in the root's editor, gated by `blockReason`. */
|
|
50
|
+
export function promptSuggestionSurface(root, blockReason, requestRender) {
|
|
51
|
+
return {
|
|
52
|
+
canPresent: identity => blockReason(identity) === null,
|
|
53
|
+
presentationBlockReason: blockReason,
|
|
54
|
+
present: text => {
|
|
55
|
+
if (!root.canPresentPromptSuggestion())
|
|
56
|
+
return false;
|
|
57
|
+
root.setPromptSuggestion(text);
|
|
58
|
+
return true;
|
|
59
|
+
},
|
|
60
|
+
clear: () => root.setPromptSuggestion(null),
|
|
61
|
+
requestRender,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { OwnedUiSessionViewModel, OwnedUiViewportSettings } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { TranscriptPromptAnchor } from "../../ui/components/transcript-viewport.js";
|
|
3
|
+
import type { PiShellTranscriptComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
4
|
+
type TranscriptBlock = OwnedUiSessionViewModel["transcript"][number];
|
|
5
|
+
export interface TranscriptDocumentLayout {
|
|
6
|
+
readonly rows: readonly string[];
|
|
7
|
+
readonly promptAnchors: readonly TranscriptPromptAnchor[];
|
|
8
|
+
readonly liveTailStartRow: number | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Why the document's caches must drop. Layout-only reasons keep each block's rendered rows; the
|
|
12
|
+
* others also drop every block's rows because what a block draws has changed without its revision.
|
|
13
|
+
*/
|
|
14
|
+
export type TranscriptInvalidation = "editor-padding" | "diagnostics" | "workflow-status" | "extension-header" | "viewport-config" | "extension-renderers" | "block-presentation" | "tools-expanded" | "repaint";
|
|
15
|
+
/** What the document reads from the shell around it on every uncached layout. */
|
|
16
|
+
export interface TranscriptDocumentChrome {
|
|
17
|
+
diagnostics(): OwnedUiSessionViewModel["diagnostics"];
|
|
18
|
+
/** The extension header's rows when one is set, else the built-in header's rows for this layout. */
|
|
19
|
+
headerRows(width: number): readonly string[];
|
|
20
|
+
/** The loaded-resources listing the pinned layout shows above the transcript. */
|
|
21
|
+
resourceRows(width: number): readonly string[];
|
|
22
|
+
/** An extension header may animate, so a document under one is never cached. */
|
|
23
|
+
hasExtensionHeader(): boolean;
|
|
24
|
+
thinkingVisible(): boolean;
|
|
25
|
+
timeFormat(): OwnedUiViewportSettings["timeFormat"];
|
|
26
|
+
}
|
|
27
|
+
export interface TranscriptDocumentOptions {
|
|
28
|
+
readonly customViewport: boolean;
|
|
29
|
+
readonly cwd: string;
|
|
30
|
+
/** Creates the component for a newly seen block; its change callback should call `blockChanged`. */
|
|
31
|
+
mount(block: TranscriptBlock): PiShellTranscriptComponentPort;
|
|
32
|
+
readonly chrome: TranscriptDocumentChrome;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The only owner of the transcript's blocks, their order (including anchored workflow output), the
|
|
36
|
+
* per-block rendered rows, and the per-width document layouts. Every cache drop names its reason.
|
|
37
|
+
*/
|
|
38
|
+
export declare class TranscriptDocument {
|
|
39
|
+
#private;
|
|
40
|
+
constructor(options: TranscriptDocumentOptions);
|
|
41
|
+
/** Block component renders since construction, for rendering evidence. */
|
|
42
|
+
get renderCount(): number;
|
|
43
|
+
get lastId(): string | undefined;
|
|
44
|
+
component(id: string): PiShellTranscriptComponentPort | undefined;
|
|
45
|
+
components(): IterableIterator<PiShellTranscriptComponentPort>;
|
|
46
|
+
anchorOf(id: string): number | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Applies one block: its component is created or updated in place and the order grows
|
|
49
|
+
* only when the block is new. A streamed chunk costs one component update rather than a
|
|
50
|
+
* walk of the whole transcript.
|
|
51
|
+
*/
|
|
52
|
+
apply(block: TranscriptBlock): void;
|
|
53
|
+
/** Replaces the whole transcript with the view's blocks, keeping anchored workflow output in place. */
|
|
54
|
+
sync(blocks: OwnedUiSessionViewModel["transcript"]): void;
|
|
55
|
+
/** Appends workflow output anchored after the transcript's first `anchor` blocks. */
|
|
56
|
+
appendAnchored(id: string, component: PiShellTranscriptComponentPort, anchor: number): void;
|
|
57
|
+
/** Disposes every anchored workflow output and drops it from the order. */
|
|
58
|
+
removeAnchored(): void;
|
|
59
|
+
/** One block's component drew something new: drop its rows and every layout that contains them. */
|
|
60
|
+
blockChanged(id: string): void;
|
|
61
|
+
invalidate(reason: TranscriptInvalidation): void;
|
|
62
|
+
/** A new session binding owns new mounts even when it reuses semantic invocation ids. */
|
|
63
|
+
reset(): void;
|
|
64
|
+
/** Disposes every component; anchors and blocks are left for a shell that is going away. */
|
|
65
|
+
dispose(): void;
|
|
66
|
+
layout(width: number): TranscriptDocumentLayout;
|
|
67
|
+
/** The transcript as plain rows for the parent terminal after a fullscreen leave. */
|
|
68
|
+
exitTranscript(width: number): string;
|
|
69
|
+
}
|
|
70
|
+
/** The release, command, and optional changelog carried by the adapter's `release-update` diagnostic. */
|
|
71
|
+
export declare function parseReleaseUpdateDiagnostic(message: string): {
|
|
72
|
+
version: string;
|
|
73
|
+
command: string;
|
|
74
|
+
changelogUrl: string | null;
|
|
75
|
+
} | null;
|
|
76
|
+
/** Web URLs use link blue; file targets retain A1's cyan interactive accent. */
|
|
77
|
+
export declare function nativeTranscriptLinkColor(text: string, target: string): string;
|
|
78
|
+
export {};
|