@floegence/floeterm-terminal-web 0.14.1 → 0.15.0
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 +78 -445
- package/dist/core/TerminalInputBridge.d.ts +7 -3
- package/dist/core/TerminalInputBridge.d.ts.map +1 -1
- package/dist/core/TerminalInputBridge.js +63 -4
- package/dist/core/TerminalInputBridge.js.map +1 -1
- package/dist/entries/live.d.ts +4 -4
- package/dist/entries/live.d.ts.map +1 -1
- package/dist/entries/live.js +2 -2
- package/dist/entries/live.js.map +1 -1
- package/dist/entries/semantic.d.ts +9 -0
- package/dist/entries/semantic.d.ts.map +1 -0
- package/dist/entries/semantic.js +5 -0
- package/dist/entries/semantic.js.map +1 -0
- package/dist/entries/sessions.d.ts +1 -1
- package/dist/entries/sessions.d.ts.map +1 -1
- package/dist/index.d.ts +4 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -16
- package/dist/index.js.map +1 -1
- package/dist/live/client.d.ts +4 -6
- package/dist/live/client.d.ts.map +1 -1
- package/dist/live/client.js +19 -72
- package/dist/live/client.js.map +1 -1
- package/dist/live/codec.d.ts +8 -21
- package/dist/live/codec.d.ts.map +1 -1
- package/dist/live/codec.js +79 -111
- package/dist/live/codec.js.map +1 -1
- package/dist/live/transport.d.ts +38 -18
- package/dist/live/transport.d.ts.map +1 -1
- package/dist/live/transport.js +59 -133
- package/dist/live/transport.js.map +1 -1
- package/dist/semantic/RendererSurface.d.ts +65 -0
- package/dist/semantic/RendererSurface.d.ts.map +1 -0
- package/dist/semantic/RendererSurface.js +566 -0
- package/dist/semantic/RendererSurface.js.map +1 -0
- package/dist/semantic/presentation.d.ts +97 -0
- package/dist/semantic/presentation.d.ts.map +1 -0
- package/dist/semantic/presentation.js +102 -0
- package/dist/semantic/presentation.js.map +1 -0
- package/dist/types.d.ts +13 -494
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -37
- package/dist/types.js.map +1 -1
- package/package.json +11 -19
- package/dist/checkpoint/GhosttyCheckpoint.worker.d.ts +0 -2
- package/dist/checkpoint/GhosttyCheckpoint.worker.d.ts.map +0 -1
- package/dist/checkpoint/GhosttyCheckpoint.worker.js +0 -9
- package/dist/checkpoint/GhosttyCheckpoint.worker.js.map +0 -1
- package/dist/checkpoint/GhosttyCheckpointActor.d.ts +0 -44
- package/dist/checkpoint/GhosttyCheckpointActor.d.ts.map +0 -1
- package/dist/checkpoint/GhosttyCheckpointActor.js +0 -284
- package/dist/checkpoint/GhosttyCheckpointActor.js.map +0 -1
- package/dist/checkpoint/GhosttyCheckpointEngine.d.ts +0 -62
- package/dist/checkpoint/GhosttyCheckpointEngine.d.ts.map +0 -1
- package/dist/checkpoint/GhosttyCheckpointEngine.js +0 -175
- package/dist/checkpoint/GhosttyCheckpointEngine.js.map +0 -1
- package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.d.ts +0 -31
- package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.d.ts.map +0 -1
- package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.js +0 -112
- package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.js.map +0 -1
- package/dist/core/PagedTerminalOutputCoordinator.d.ts +0 -130
- package/dist/core/PagedTerminalOutputCoordinator.d.ts.map +0 -1
- package/dist/core/PagedTerminalOutputCoordinator.js +0 -1213
- package/dist/core/PagedTerminalOutputCoordinator.js.map +0 -1
- package/dist/core/TerminalCore.d.ts +0 -286
- package/dist/core/TerminalCore.d.ts.map +0 -1
- package/dist/core/TerminalCore.js +0 -3566
- package/dist/core/TerminalCore.js.map +0 -1
- package/dist/core/TerminalOutputPipeline.d.ts +0 -86
- package/dist/core/TerminalOutputPipeline.d.ts.map +0 -1
- package/dist/core/TerminalOutputPipeline.js +0 -511
- package/dist/core/TerminalOutputPipeline.js.map +0 -1
- package/dist/core/TerminalRenderScheduler.d.ts +0 -45
- package/dist/core/TerminalRenderScheduler.d.ts.map +0 -1
- package/dist/core/TerminalRenderScheduler.js +0 -145
- package/dist/core/TerminalRenderScheduler.js.map +0 -1
- package/dist/core/TerminalScrollbarOverlay.d.ts +0 -63
- package/dist/core/TerminalScrollbarOverlay.d.ts.map +0 -1
- package/dist/core/TerminalScrollbarOverlay.js +0 -493
- package/dist/core/TerminalScrollbarOverlay.js.map +0 -1
- package/dist/entries/history.d.ts +0 -4
- package/dist/entries/history.d.ts.map +0 -1
- package/dist/entries/history.js +0 -2
- package/dist/entries/history.js.map +0 -1
- package/dist/entries/preload.d.ts +0 -3
- package/dist/entries/preload.d.ts.map +0 -1
- package/dist/entries/preload.js +0 -2
- package/dist/entries/preload.js.map +0 -1
- package/dist/fabric/BeamtermFabricRenderer.d.ts +0 -67
- package/dist/fabric/BeamtermFabricRenderer.d.ts.map +0 -1
- package/dist/fabric/BeamtermFabricRenderer.js +0 -659
- package/dist/fabric/BeamtermFabricRenderer.js.map +0 -1
- package/dist/fabric/TerminalFabricCoordinator.d.ts +0 -40
- package/dist/fabric/TerminalFabricCoordinator.d.ts.map +0 -1
- package/dist/fabric/TerminalFabricCoordinator.js +0 -141
- package/dist/fabric/TerminalFabricCoordinator.js.map +0 -1
- package/dist/fabric/TerminalLiveFabric.d.ts +0 -44
- package/dist/fabric/TerminalLiveFabric.d.ts.map +0 -1
- package/dist/fabric/TerminalLiveFabric.js +0 -117
- package/dist/fabric/TerminalLiveFabric.js.map +0 -1
- package/dist/fabric/types.d.ts +0 -152
- package/dist/fabric/types.d.ts.map +0 -1
- package/dist/fabric/types.js +0 -2
- package/dist/fabric/types.js.map +0 -1
- package/dist/internal/BeamtermResourceLoader.d.ts +0 -3
- package/dist/internal/BeamtermResourceLoader.d.ts.map +0 -1
- package/dist/internal/BeamtermResourceLoader.js +0 -14
- package/dist/internal/BeamtermResourceLoader.js.map +0 -1
- package/dist/internal/GhosttyCompatibilityVersion.d.ts +0 -2
- package/dist/internal/GhosttyCompatibilityVersion.d.ts.map +0 -1
- package/dist/internal/GhosttyCompatibilityVersion.js +0 -2
- package/dist/internal/GhosttyCompatibilityVersion.js.map +0 -1
- package/dist/internal/GhosttyScrollbackCompat.d.ts +0 -16
- package/dist/internal/GhosttyScrollbackCompat.d.ts.map +0 -1
- package/dist/internal/GhosttyScrollbackCompat.js +0 -43
- package/dist/internal/GhosttyScrollbackCompat.js.map +0 -1
- package/dist/internal/GhosttyScrollbarCompat.d.ts +0 -12
- package/dist/internal/GhosttyScrollbarCompat.d.ts.map +0 -1
- package/dist/internal/GhosttyScrollbarCompat.js +0 -160
- package/dist/internal/GhosttyScrollbarCompat.js.map +0 -1
- package/dist/internal/SequenceBuffer.d.ts +0 -19
- package/dist/internal/SequenceBuffer.d.ts.map +0 -1
- package/dist/internal/SequenceBuffer.js +0 -83
- package/dist/internal/SequenceBuffer.js.map +0 -1
- package/dist/internal/TerminalInitializationScheduler.d.ts +0 -38
- package/dist/internal/TerminalInitializationScheduler.d.ts.map +0 -1
- package/dist/internal/TerminalInitializationScheduler.js +0 -112
- package/dist/internal/TerminalInitializationScheduler.js.map +0 -1
- package/dist/internal/TerminalResourceLoader.d.ts +0 -40
- package/dist/internal/TerminalResourceLoader.d.ts.map +0 -1
- package/dist/internal/TerminalResourceLoader.js +0 -165
- package/dist/internal/TerminalResourceLoader.js.map +0 -1
- package/dist/internal/UnicodeSafeUrlProvider.d.ts +0 -17
- package/dist/internal/UnicodeSafeUrlProvider.d.ts.map +0 -1
- package/dist/internal/UnicodeSafeUrlProvider.js +0 -32
- package/dist/internal/UnicodeSafeUrlProvider.js.map +0 -1
- package/dist/internal/scheduleUiTurn.d.ts +0 -5
- package/dist/internal/scheduleUiTurn.d.ts.map +0 -1
- package/dist/internal/scheduleUiTurn.js +0 -37
- package/dist/internal/scheduleUiTurn.js.map +0 -1
- package/dist/manager/TerminalInstanceController.d.ts +0 -88
- package/dist/manager/TerminalInstanceController.d.ts.map +0 -1
- package/dist/manager/TerminalInstanceController.js +0 -1076
- package/dist/manager/TerminalInstanceController.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -3
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -11
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/history.d.ts +0 -2
- package/dist/utils/history.d.ts.map +0 -1
- package/dist/utils/history.js +0 -12
- package/dist/utils/history.js.map +0 -1
- package/dist/utils/xtermAutoResponseFilter.d.ts +0 -2
- package/dist/utils/xtermAutoResponseFilter.d.ts.map +0 -1
- package/dist/utils/xtermAutoResponseFilter.js +0 -109
- package/dist/utils/xtermAutoResponseFilter.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,486 +1,119 @@
|
|
|
1
|
-
# terminal-web
|
|
1
|
+
# @floegence/floeterm-terminal-web
|
|
2
2
|
|
|
3
|
-
Framework-neutral
|
|
3
|
+
Framework-neutral browser components for FloeTerm's semantic terminal protocol.
|
|
4
4
|
|
|
5
|
-
The
|
|
5
|
+
The package does not contain a VT parser, Ghostty WASM, a raw replay/checkpoint
|
|
6
|
+
pipeline, or a WebGL terminal renderer. `terminal-go` owns terminal state and emits
|
|
7
|
+
complete immutable Presentations. The browser owns only view-local rendering and
|
|
8
|
+
interaction.
|
|
6
9
|
|
|
7
10
|
## Install
|
|
8
11
|
|
|
9
12
|
```bash
|
|
10
|
-
npm
|
|
13
|
+
npm install @floegence/floeterm-terminal-web@0.15.0
|
|
11
14
|
```
|
|
12
15
|
|
|
13
|
-
##
|
|
16
|
+
## Exports
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
| Subpath | API |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| `./semantic` | `RendererSurface`, `TerminalInputBridge`, validators, semantic types, themes |
|
|
21
|
+
| `./live` | semantic WebSocket codec, client, transport, lifecycle and geometry events |
|
|
22
|
+
| `./sessions` | session coordinator and display-only metadata normalization |
|
|
23
|
+
| `.` | semantic aggregation plus shell-integration parsing utilities |
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
import { createTerminalInstance } from '@floegence/floeterm-terminal-web';
|
|
19
|
-
|
|
20
|
-
const controller = createTerminalInstance({
|
|
21
|
-
sessionId: 'session-1',
|
|
22
|
-
isActive: true,
|
|
23
|
-
transport: myTransport,
|
|
24
|
-
eventSource: myEventSource,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const unsubscribe = controller.subscribe((snapshot) => {
|
|
28
|
-
console.log(snapshot.connection.state, snapshot.loadingMessage);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
await controller.mount(container);
|
|
32
|
-
|
|
33
|
-
// Later:
|
|
34
|
-
controller.actions.copySelection('command');
|
|
35
|
-
unsubscribe();
|
|
36
|
-
controller.dispose();
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Use `TerminalCore` directly when the host product owns its own session lifecycle, paging, shell integration, or workbench coordination:
|
|
40
|
-
|
|
41
|
-
```ts
|
|
42
|
-
import { TerminalCore, getDefaultTerminalConfig } from '@floegence/floeterm-terminal-web';
|
|
43
|
-
|
|
44
|
-
const core = new TerminalCore(
|
|
45
|
-
container,
|
|
46
|
-
getDefaultTerminalConfig('dark', { clipboard: { copyOnSelect: false } }),
|
|
47
|
-
{
|
|
48
|
-
onData: data => transport.sendInput(sessionId, data),
|
|
49
|
-
onResize: size => transport.resize(sessionId, size.cols, size.rows),
|
|
50
|
-
},
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
await core.initialize();
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Session catalogs can carry independent `executionContext`, `workState`,
|
|
57
|
-
`foregroundCommand`, and `outputActivity` snapshots. The coordinator fences
|
|
58
|
-
each dimension by its own monotonic revision. `TerminalShellIntegrationParser`
|
|
59
|
-
filters strict `FloetermContext=v1` and `FloetermWork=v1` metadata from renderer
|
|
60
|
-
display data while returning ordered structured events; standard OSC title and
|
|
61
|
-
OSC 7 controls remain untouched so replay preserves normal terminal semantics.
|
|
62
|
-
Hosts must treat every context value as untrusted presentation metadata.
|
|
63
|
-
|
|
64
|
-
Floeterm projects one renderer-neutral DOM scrollbar for both canvas and WebGL terminals while Ghostty remains the only scrollback and viewport owner:
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
const core = new TerminalCore(container, {
|
|
68
|
-
rendererType: 'webgl',
|
|
69
|
-
fit: { scrollbarReservePx: 15 },
|
|
70
|
-
scrollbar: {
|
|
71
|
-
visibility: 'persistent', // "auto" by default, or "hidden"
|
|
72
|
-
minThumbPx: 24,
|
|
73
|
-
ariaLabel: 'Terminal history',
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Keep a long-lived Core aligned with a runtime locale change.
|
|
78
|
-
core.setScrollbarOptions({ ariaLabel: localizedTerminalHistoryLabel });
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The scrollbar uses a 12px visual and fine-pointer rail. Reserve at least 12px when the last terminal column must remain fully unobstructed; the default 15px reserve provides a stable gutter. An explicit `scrollbarReservePx: 0` remains supported as an overlay mode and may cover the rightmost 12px. The visual overlay itself never owns pointer hit testing: Floeterm captures fine-pointer track and thumb gestures at the viewport boundary, while wheel and touch events continue to target Ghostty's terminal surface exactly once. `persistent` automatically behaves as `auto` on coarse-pointer-only devices. Mixed-pointer devices keep mouse and pen interaction without creating a dead touch strip.
|
|
82
|
-
|
|
83
|
-
Floeterm follows Ghostty's default `keystroke, no-output` viewport policy. New output follows automatically while the viewport is already at the bottom. After a user scrolls into history, incoming output preserves that reading anchor; keyboard or text input, the End key, or an explicit scrollbar action returns to the latest output. Terminal-generated responses and mouse protocol events do not count as user input.
|
|
84
|
-
|
|
85
|
-
`auto` reveals on terminal wheel activity, keyboard focus, or fine-pointer movement into the right-edge rail, then fades after 1,200ms of inactivity. `persistent` remains visible on fine-pointer layouts and `hidden` removes the control from pointer, tab, and accessibility access. Alternate-screen programs and empty buffers also hide it. Theme-derived idle and hover/focus colors meet 3:1 and 4.5:1 contrast targets. Drag color targets 7:1; when that ratio is mathematically impossible against the configured background, Floeterm chooses whichever of black or white provides the highest available contrast. Forced-colors and reduced-motion preferences are honored.
|
|
86
|
-
|
|
87
|
-
After a host-owned layout transition or history recovery, request an explicit
|
|
88
|
-
presentation fence before declaring the terminal surface ready:
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
await core.forceResizeAndWaitForPresentation();
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The fence performs a fresh resize, requires a complete Beamterm frame, finishes
|
|
95
|
-
the submitted WebGL work, and resolves after that frame has crossed a browser
|
|
96
|
-
paint opportunity. Concurrent callers before the frame is submitted share the
|
|
97
|
-
same work; a caller arriving after submission requests a newer frame. This is an
|
|
98
|
-
explicit recovery/lifecycle operation, not a replacement for ordinary demand
|
|
99
|
-
rendering.
|
|
100
|
-
|
|
101
|
-
Hosts can preload the dynamic Ghostty module, WASM, and renderer resources before a terminal surface is visible without creating a `TerminalCore`:
|
|
102
|
-
|
|
103
|
-
```ts
|
|
104
|
-
import { preloadTerminalResources } from '@floegence/floeterm-terminal-web/preload';
|
|
105
|
-
|
|
106
|
-
await preloadTerminalResources({ signal });
|
|
107
|
-
await core.initialize({ priority: 'interactive', signal });
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Resource loading is single-flight and retryable after a real import or WASM initialization failure. Caller cancellation only stops that caller from waiting; it does not interrupt shared resource initialization. Core initialization is globally bounded, gives queued interactive work priority over background work, and shares the actual ready promise across duplicate calls.
|
|
111
|
-
|
|
112
|
-
Use the lightweight subpath exports when the host needs session metadata or renderer-neutral history before loading the full terminal feature:
|
|
25
|
+
## Render a Presentation
|
|
113
26
|
|
|
114
27
|
```ts
|
|
115
28
|
import {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
`TerminalSessionsCoordinator` treats `pollMs: 0` as a real periodic-poll disable. Subscribing still performs one best-effort initial reconcile, and explicit `refresh()` calls remain available to a host-owned lifecycle coordinator.
|
|
123
|
-
|
|
124
|
-
Session snapshots may include independent `foregroundCommand` and
|
|
125
|
-
`outputActivity` metadata. The coordinator normalizes missing metadata to
|
|
126
|
-
`unknown` and merges each field only when its own revision is newer, so a stale
|
|
127
|
-
list response cannot overwrite a newer output boundary. `outputActivity.phase`
|
|
128
|
-
is `streaming` while a running command is producing visible display payload and
|
|
129
|
-
becomes `settled` after the configured quiet interval. `settled` does not mean
|
|
130
|
-
that the command, Agent turn, or task completed successfully.
|
|
131
|
-
|
|
132
|
-
`classifyTerminalAgentCli` maps an already-sanitized foreground basename to an
|
|
133
|
-
audited strict identity for Codex, Claude Code, OpenCode, Kimi Code, Gemini CLI,
|
|
134
|
-
Qwen Code, GitHub Copilot CLI, Cline, Roo Code, Mistral Vibe, Cursor
|
|
135
|
-
Agent, Junie CLI, Kiro CLI, OpenHands, Pi, TRAE Agent, or Kilo Code. Matching is
|
|
136
|
-
case-insensitive and accepts one Windows executable suffix (`.exe`, `.cmd`, or
|
|
137
|
-
`.bat`), but deliberately rejects paths, arguments, wrappers, partial matches,
|
|
138
|
-
Unicode guesses, and overlong values. The root package exports the same helper.
|
|
139
|
-
The lightweight sessions entry does not load TerminalCore or renderer code.
|
|
140
|
-
|
|
141
|
-
Hosts that own output projection can reuse the bounded shell parser instead of
|
|
142
|
-
maintaining a product-specific OSC implementation:
|
|
143
|
-
|
|
144
|
-
```ts
|
|
145
|
-
import { TerminalShellIntegrationParser } from '@floegence/floeterm-terminal-web';
|
|
146
|
-
|
|
147
|
-
const parser = new TerminalShellIntegrationParser();
|
|
148
|
-
const { displayData, events, tokens } = parser.parse(chunk);
|
|
149
|
-
core.write(displayData);
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
When the host has an authoritative PTY hostname, pass it explicitly as
|
|
153
|
-
`new TerminalShellIntegrationParser({ localHostname })` to reject same-host
|
|
154
|
-
remote hints. The parser never infers the PTY host from the browser page origin.
|
|
155
|
-
|
|
156
|
-
The parser recognizes OSC 633 prompt/command/cwd markers and Floeterm's safe
|
|
157
|
-
program label. Recognized metadata is removed from display output, unknown OSC
|
|
158
|
-
sequences are preserved, fragmented input is bounded, and program labels are
|
|
159
|
-
limited to a 64-byte ASCII allowlist. The label never contains command
|
|
160
|
-
arguments or environment values. `tokens` preserves the original order of
|
|
161
|
-
display segments and recognized events, allowing hosts to attribute output to
|
|
162
|
-
the foreground revision that was active at that exact byte boundary.
|
|
163
|
-
|
|
164
|
-
## Notes
|
|
165
|
-
|
|
166
|
-
- You must provide a `TerminalTransport` and `TerminalEventSource` for the managed controller.
|
|
167
|
-
- Each `TerminalCore` owns an isolated `@floegence/ghostty-web` WASM runtime; consumers must not provide or share a Ghostty runtime.
|
|
168
|
-
- `scrollback` is measured in terminal buffer rows, including separately wrapped rows, and accepts integers from 1 through 10,000. Within the supported geometry, Floeterm preserves at least the requested number of buffer rows; it does not trim to an exact physical row count. Floeterm maps that contract to a bounded byte budget for the exact pinned `@floegence/ghostty-web@0.5.0-rc.0` release, which currently interprets the value as bytes. The 81,920,000-byte cap limits Ghostty's scrollback arena, not the total memory of a WASM runtime. The mapping is temporary and must be reviewed and removed or updated with any Ghostty upgrade.
|
|
169
|
-
- Supported terminal geometry is limited to 500 columns. Explicit dimensions above that limit fail, while automatic fitting reports at most 500 columns.
|
|
170
|
-
- Consumer dependency overrides for `@floegence/ghostty-web` are unsupported. Floeterm's compatibility guard requires the exact package pin so an upstream behavior change cannot silently apply the row-to-byte mapping twice or reactivate the native canvas scrollbar beneath the renderer-neutral DOM control.
|
|
171
|
-
- `TerminalCore` bridges the hidden textarea used by `ghostty-web`, so soft-keyboard and composition input continue to work on touch devices.
|
|
172
|
-
- The hidden terminal input is mounted in the document viewport plane and anchored from rendered cursor geometry, so native IME candidate windows stay aligned without expanding transformed terminal hosts.
|
|
173
|
-
- Programmatic terminal focus uses no-scroll focus by default, keeping embedded terminals stable inside scaled, projected, or otherwise transformed host surfaces.
|
|
174
|
-
- Explicit terminal copy is handled through shared selection-copy APIs, so keyboard shortcuts, native app menus, and product context menus can reuse the same selection logic.
|
|
175
|
-
- `TerminalCore` exposes runtime appearance updates, shell bell/title events, custom terminal link providers, buffer line reads, and touch-scroll helpers without requiring consumers to reach into private runtime objects.
|
|
176
|
-
- Multiple live `TerminalCore` instances share one render scheduler, so large terminal grids coalesce demand-driven canvas work into browser frames.
|
|
177
|
-
|
|
178
|
-
## Paged History And Live Recovery
|
|
179
|
-
|
|
180
|
-
Hosts with cursor-paged history APIs can use the framework-neutral coordinator instead of maintaining a second live-output queue:
|
|
181
|
-
|
|
182
|
-
```ts
|
|
183
|
-
const output = createPagedTerminalOutputCoordinator({
|
|
184
|
-
fetchPage: ({ startSequence, endSequence, historyGeneration, cursor, signal }) =>
|
|
185
|
-
transport.historyPage(sessionId, {
|
|
186
|
-
startSequence,
|
|
187
|
-
endSequence,
|
|
188
|
-
historyGeneration,
|
|
189
|
-
cursor,
|
|
190
|
-
signal,
|
|
191
|
-
}),
|
|
192
|
-
write: data => new Promise(resolve => core.write(data, resolve)),
|
|
193
|
-
writeHistory: data => new Promise(resolve => core.writeHistory(data, resolve)),
|
|
194
|
-
clear: () => core.clear(),
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
void output.attach(1);
|
|
198
|
-
const baseline = await output.waitForBaseline();
|
|
199
|
-
if (!baseline.baselineReady) {
|
|
200
|
-
throw baseline.failure;
|
|
201
|
-
}
|
|
202
|
-
events.onData(sessionId, chunk => output.pushLive(chunk));
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
History pages must explicitly include `coveredThroughSequence`, including the valid empty-history value `0`. A missing or malformed value produces a structured contract failure instead of guessing from the last returned chunk. The first page may also provide `snapshotEndSequence`, `firstRetainedSequence`, and `historyGeneration`; pass the snapshot end and generation through each later request.
|
|
206
|
-
|
|
207
|
-
History chunks must also carry the PTY geometry that produced their bytes:
|
|
208
|
-
`geometryGeneration`, `cols`, and `rows`. The coordinator validates that tuple,
|
|
209
|
-
keeps generations monotonic, splits writes at geometry changes, and invokes
|
|
210
|
-
`applyHistoryGeometry` immediately before each history batch. Hosts that replay
|
|
211
|
-
history into a fixed-grid renderer must use that hook to set the recorded
|
|
212
|
-
dimensions; omitting or conflicting geometry fails the replay contract rather
|
|
213
|
-
than silently interpreting historical cursor movement at the current grid.
|
|
214
|
-
|
|
215
|
-
If a page reports `historyReset` or changes `historyGeneration` while catch-up is running, the coordinator atomically clears the obsolete baseline, preserves retained live output, and restarts from the new generation. Hosts must not merge pages from different generations or reinterpret the expected coverage reset as a malformed regression.
|
|
216
|
-
|
|
217
|
-
`baselineReady` becomes true only after the complete fixed history snapshot has been source-sequence merged with retained live output and the final history writer completion has fired. After that fence, catch-up retries preserve baseline readiness and do not need to block input. Structured failures distinguish initial replay from background catch-up and expose stable codes without requiring error-string parsing.
|
|
218
|
-
|
|
219
|
-
Use `TerminalCore.writeHistory` for history batches. Its auto-response suppression is scoped to that parser write and ends at its completion callback, so later live output and user input use normal terminal behavior.
|
|
220
|
-
|
|
221
|
-
Running sessions can prepare bounded history before a visible terminal exists. Preparation does not create a Core, attach a session, resize a PTY, or subscribe to live output:
|
|
222
|
-
|
|
223
|
-
```ts
|
|
224
|
-
const preparedHistory = await preparePagedTerminalHistory({
|
|
225
|
-
fetchPage: request => transport.historyPage(sessionId, request),
|
|
226
|
-
maxBytes: 4 * 1024 * 1024,
|
|
227
|
-
signal,
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
const attachGeneration = output.beginAttach(0);
|
|
231
|
-
const attach = await transport.attachWithHistoryBoundary(sessionId, cols, rows);
|
|
232
|
-
await output.completeAttach(attachGeneration, attach.historyBoundarySequence, {
|
|
233
|
-
preparedHistory,
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
const baseline = await output.waitForBaseline();
|
|
237
|
-
if (baseline.preparedHistoryOutcome?.status === 'accepted') {
|
|
238
|
-
console.log('prepared history used', { rebased: baseline.preparedHistoryOutcome.rebased });
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
Prepared history is renderer-neutral and pins `historyGeneration`, `firstRetainedSequence`, and `snapshotEndSequence`. The visible attach validates those boundaries, replays the seed once, and fetches only the missing delta. A generation reset, retention advance, stale fence, or malformed seed discards it and falls back to the normal full recovery path. The baseline snapshot reports `accepted`, `rejected`, or `not-provided` plus a `rebased` flag, so hosts do not need to infer seed use from fetched byte counts.
|
|
243
|
-
|
|
244
|
-
`preparePagedTerminalHistory` requires those three metadata fields on every prepared page and passes the remaining retained-byte budget as `request.maxBytes` so transports can bound each page as well. The helper always enforces its retained seed budget after a page returns; adapters should honor the request hint to keep peak response memory bounded too.
|
|
245
|
-
|
|
246
|
-
## Restorable In-Memory Snapshots
|
|
247
|
-
|
|
248
|
-
Adaptive host worksets can release inactive renderers without closing their PTY sessions:
|
|
249
|
-
|
|
250
|
-
```ts
|
|
251
|
-
await output.pause();
|
|
252
|
-
const snapshot = core.captureRestorableSnapshot({
|
|
253
|
-
coveredThroughSequence: output.getSnapshot().coveredThroughSequence,
|
|
254
|
-
});
|
|
255
|
-
const estimate = core.getResourceEstimate();
|
|
256
|
-
|
|
257
|
-
core.dispose(); // The host-owned PTY and output coordinator remain alive.
|
|
29
|
+
RendererSurface,
|
|
30
|
+
getThemeColors,
|
|
31
|
+
validatePresentation,
|
|
32
|
+
} from '@floegence/floeterm-terminal-web/semantic';
|
|
258
33
|
|
|
259
|
-
const
|
|
260
|
-
|
|
34
|
+
const renderer = new RendererSurface(canvas, error => showInlineError(error));
|
|
35
|
+
renderer.setPalette(getThemeColors('tokyoNight'));
|
|
36
|
+
renderer.apply(validatePresentation(payload));
|
|
261
37
|
```
|
|
262
38
|
|
|
263
|
-
`
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
## Responsive Resize
|
|
39
|
+
`RendererSurface` owns one 2D canvas. It keeps the latest immutable Presentation,
|
|
40
|
+
rejects sequence or geometry regressions, follows host CSS bounds, tracks DPR changes,
|
|
41
|
+
fills every backing pixel before painting cells/graphics/cursor, and never stretches
|
|
42
|
+
the authoritative cell grid to an observer viewport.
|
|
268
43
|
|
|
269
|
-
|
|
44
|
+
Themes are view-local. Changing the palette repaints the latest Presentation without
|
|
45
|
+
requesting output, resizing the PTY, or affecting another view. Explicit ANSI/RGB
|
|
46
|
+
colors stay semantic; only default foreground/background/cursor fallbacks change.
|
|
270
47
|
|
|
271
|
-
|
|
272
|
-
const core = new TerminalCore(container, {
|
|
273
|
-
responsive: {
|
|
274
|
-
fitOnFocus: true,
|
|
275
|
-
emitResizeOnFocus: true,
|
|
276
|
-
notifyResizeOnlyWhenFocused: true,
|
|
277
|
-
},
|
|
278
|
-
});
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
For an active fixed-grid view that is becoming interactive after history recovery,
|
|
282
|
-
measure host capacity without changing the shared PTY grid, then submit that
|
|
283
|
-
capacity through the host transport:
|
|
48
|
+
## Input and IME
|
|
284
49
|
|
|
285
50
|
```ts
|
|
286
|
-
|
|
287
|
-
const hostDimensions = core.measureHostDimensions();
|
|
288
|
-
```
|
|
51
|
+
import { TerminalInputBridge } from '@floegence/floeterm-terminal-web/semantic';
|
|
289
52
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
Passive mirrors of a remote PTY can render with the session owner's current dimensions:
|
|
297
|
-
|
|
298
|
-
```ts
|
|
299
|
-
const core = new TerminalCore(container, {
|
|
300
|
-
fixedDimensions: { cols: 100, rows: 30 },
|
|
53
|
+
const bridge = new TerminalInputBridge({
|
|
54
|
+
inputHost,
|
|
55
|
+
inputElement: textarea,
|
|
56
|
+
onData: data => sendInput(data),
|
|
57
|
+
syncInputGeometry: () => positionTextarea(renderer.getCursorClientRect()),
|
|
301
58
|
});
|
|
302
|
-
|
|
303
|
-
core.setFixedDimensions(null);
|
|
304
|
-
core.forceResize();
|
|
305
59
|
```
|
|
306
60
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
transport,
|
|
313
|
-
eventSource,
|
|
314
|
-
isActive: true,
|
|
315
|
-
config: {
|
|
316
|
-
responsive: {
|
|
317
|
-
reportHostDimensionsWithFixedGrid: true,
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
});
|
|
321
|
-
```
|
|
61
|
+
The textarea must remain editable and positioned in the visible terminal viewport.
|
|
62
|
+
Composition preedit is never sent to the PTY. The final Unicode composition commit is
|
|
63
|
+
sent exactly once across Chrome/Safari event orderings. Physical keys, paste,
|
|
64
|
+
dead-key/emoji input, copy shortcuts, focus, and controller ownership remain separate
|
|
65
|
+
from composition state.
|
|
322
66
|
|
|
323
|
-
The
|
|
67
|
+
The cursor rectangle uses CSS pixels. Canvas backing DPR is not multiplied into the
|
|
68
|
+
IME anchor.
|
|
324
69
|
|
|
325
|
-
|
|
70
|
+
## Semantic Live Transport
|
|
326
71
|
|
|
327
72
|
```ts
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
Hosts with overlay scrollbars can remove the default ghostty-web scrollbar reserve:
|
|
338
|
-
|
|
339
|
-
```ts
|
|
340
|
-
const core = new TerminalCore(container, {
|
|
341
|
-
fit: {
|
|
342
|
-
scrollbarReservePx: 0,
|
|
343
|
-
},
|
|
344
|
-
});
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
## Clipboard
|
|
348
|
-
|
|
349
|
-
By default, upstream mouse selection keeps the `ghostty-web` behavior and copies immediately on selection. Consumers that want explicit copy commands only can disable that side effect:
|
|
350
|
-
|
|
351
|
-
```ts
|
|
352
|
-
const core = new TerminalCore(container, {
|
|
353
|
-
clipboard: {
|
|
354
|
-
copyOnSelect: false,
|
|
355
|
-
},
|
|
73
|
+
import {
|
|
74
|
+
createSemanticTerminalLiveTransport,
|
|
75
|
+
} from '@floegence/floeterm-terminal-web/live';
|
|
76
|
+
|
|
77
|
+
const { transport, eventSource } = createSemanticTerminalLiveTransport({
|
|
78
|
+
connectionId,
|
|
79
|
+
openStream,
|
|
80
|
+
control,
|
|
81
|
+
onError: reportError,
|
|
356
82
|
});
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
With `copyOnSelect: false`, `TerminalCore` keeps selection explicit:
|
|
360
|
-
|
|
361
|
-
- `core.hasSelection()` reports whether the terminal currently owns a copyable selection.
|
|
362
|
-
- `core.copySelection()` writes the current terminal selection to the clipboard.
|
|
363
|
-
- `Cmd+C` / `Ctrl+C` copies only when the terminal currently has a selection. Without a selection, `Ctrl+C` remains terminal input and produces the standard interrupt control byte; `Cmd+C` is not converted into terminal input.
|
|
364
|
-
|
|
365
|
-
The managed controller exposes the same helpers through `controller.actions`.
|
|
366
|
-
|
|
367
|
-
## Link Providers And Buffer Reads
|
|
368
83
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
import { TerminalCore, type TerminalLinkProvider } from '@floegence/floeterm-terminal-web';
|
|
373
|
-
|
|
374
|
-
const linkProvider: TerminalLinkProvider = {
|
|
375
|
-
provideLinks(y, callback) {
|
|
376
|
-
const line = core.readBufferLine(y);
|
|
377
|
-
void line;
|
|
378
|
-
callback(undefined);
|
|
379
|
-
},
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
const core = new TerminalCore(container, {}, {
|
|
383
|
-
onBell: () => console.log('bell'),
|
|
384
|
-
onTitleChange: title => console.log('title', title),
|
|
84
|
+
await transport.attach(sessionId, cols, rows);
|
|
85
|
+
const stop = eventSource.onTerminalPresentation(sessionId, value => {
|
|
86
|
+
renderer.apply(validatePresentation(value));
|
|
385
87
|
});
|
|
386
|
-
|
|
387
|
-
await core.initialize();
|
|
388
|
-
core.registerLinkProvider(linkProvider);
|
|
389
88
|
```
|
|
390
89
|
|
|
391
|
-
|
|
90
|
+
The transport carries attach, structured input, canonical resize settlement,
|
|
91
|
+
Presentation, geometry, and lifecycle frames. It does not carry raw PTY output.
|
|
92
|
+
Unknown input is not replayed after a disconnect. A new transport generation does not
|
|
93
|
+
write through an old connection.
|
|
392
94
|
|
|
393
|
-
##
|
|
95
|
+
## Session Metadata
|
|
394
96
|
|
|
395
|
-
|
|
97
|
+
The `./sessions` entry is independent of rendering. It normalizes session list,
|
|
98
|
+
foreground command, output activity, execution context, and semantic work metadata.
|
|
99
|
+
These values are display-only and must not be used for authorization.
|
|
396
100
|
|
|
397
|
-
|
|
398
|
-
const touch = core.getTouchScrollRuntime();
|
|
399
|
-
|
|
400
|
-
if (touch?.isAlternateScreen()) {
|
|
401
|
-
touch.sendAlternateScreenInput('\x1B[A');
|
|
402
|
-
} else {
|
|
403
|
-
touch?.scrollLines(-3);
|
|
404
|
-
}
|
|
405
|
-
```
|
|
101
|
+
## Lifecycle
|
|
406
102
|
|
|
407
|
-
|
|
103
|
+
Dispose each view's subscriptions, input bridge, renderer, and live transport. Disposal
|
|
104
|
+
cancels RAF/blink/DPR/font listeners and releases graphics bitmaps without detaching or
|
|
105
|
+
resizing another view.
|
|
408
106
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
```ts
|
|
412
|
-
const suspend = core.beginVisualSuspend({ reason: 'workbench_widget_drag' });
|
|
413
|
-
|
|
414
|
-
try {
|
|
415
|
-
// Move, zoom, or resize the host surface.
|
|
416
|
-
} finally {
|
|
417
|
-
suspend.dispose();
|
|
418
|
-
}
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
While suspended, `write()` continues to update terminal state. Rendering, fit, full repaint, and overlay refresh requests are coalesced and reconciled when the final nested suspend handle is disposed.
|
|
422
|
-
|
|
423
|
-
## Multi-Terminal Render Scheduling
|
|
424
|
-
|
|
425
|
-
`TerminalCore` keeps ghostty-web rendering demand-driven and routes visible terminal repaints through a shared scheduler. Demo or profiling surfaces can inspect the scheduler without reaching into private instances:
|
|
426
|
-
|
|
427
|
-
```ts
|
|
428
|
-
import { getTerminalRenderSchedulerStats } from '@floegence/floeterm-terminal-web';
|
|
429
|
-
|
|
430
|
-
const stats = getTerminalRenderSchedulerStats();
|
|
431
|
-
console.log(stats.lastFrameRendered, stats.pending);
|
|
432
|
-
```
|
|
107
|
+
## Development
|
|
433
108
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
import { getThemeColors } from '@floegence/floeterm-terminal-web';
|
|
442
|
-
|
|
443
|
-
core.setAppearance({
|
|
444
|
-
theme: getThemeColors('light'),
|
|
445
|
-
fontSize: 14,
|
|
446
|
-
fontFamily: '"Iosevka Term", monospace',
|
|
447
|
-
presentationScale: 1,
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
core.setFontFamily('"Iosevka Term", monospace');
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
## Built-in Theme Catalog
|
|
454
|
-
|
|
455
|
-
Floeterm 0.8.0 publishes 20 immutable built-in theme definitions. Hosts can use
|
|
456
|
-
the same stable catalog for validation, previews, and terminal rendering:
|
|
457
|
-
|
|
458
|
-
```ts
|
|
459
|
-
import {
|
|
460
|
-
TERMINAL_THEME_DEFINITIONS,
|
|
461
|
-
getThemeColors,
|
|
462
|
-
normalizeTerminalThemeName,
|
|
463
|
-
} from '@floegence/floeterm-terminal-web';
|
|
464
|
-
|
|
465
|
-
const selected = normalizeTerminalThemeName(persistedValue, 'dark');
|
|
466
|
-
const colors = getThemeColors(selected);
|
|
467
|
-
const lightThemes = TERMINAL_THEME_DEFINITIONS.filter(
|
|
468
|
-
(theme) => theme.appearance === 'light',
|
|
469
|
-
);
|
|
109
|
+
```bash
|
|
110
|
+
npm ci
|
|
111
|
+
npm run lint
|
|
112
|
+
npm test
|
|
113
|
+
npm run test:browser
|
|
114
|
+
npm run build
|
|
115
|
+
npm run check:package-artifact
|
|
470
116
|
```
|
|
471
117
|
|
|
472
|
-
The
|
|
473
|
-
|
|
474
|
-
third-party license details ship in `THEME_PROVENANCE.json` and
|
|
475
|
-
`THIRD_PARTY_THEME_NOTICES.md`. The package also includes
|
|
476
|
-
`THEME_QUALITY_EVIDENCE.json` with the catalog thresholds, measured results,
|
|
477
|
-
and Signal Safe color-vision simulation evidence.
|
|
478
|
-
|
|
479
|
-
### 0.8.0 migration
|
|
480
|
-
|
|
481
|
-
- `TerminalThemeName` now includes the full catalog; exhaustive switches must
|
|
482
|
-
handle the new IDs.
|
|
483
|
-
- `getThemeColors()` keeps its function name but returns the exact readonly
|
|
484
|
-
`TerminalThemeColors` type instead of a mutable `Record<string, string>`.
|
|
485
|
-
- `light`, `solarizedDark`, and `monokai` add `cursorAccent` equal to their
|
|
486
|
-
existing background. All other legacy fields and values are unchanged.
|
|
118
|
+
The package-artifact check installs the packed tarball into a fresh consumer and
|
|
119
|
+
rejects removed parser, checkpoint, renderer, and WASM contracts.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger, TerminalCopySelectionResult, TerminalCopySelectionSource, TerminalFocusOptions } from '../types.js';
|
|
2
2
|
export declare const resolveTerminalInputElement: (inputHost: HTMLElement) => HTMLTextAreaElement | null;
|
|
3
|
-
type
|
|
3
|
+
export type TerminalInputBridgeOptions = {
|
|
4
4
|
inputHost: HTMLElement;
|
|
5
5
|
inputElement: HTMLTextAreaElement;
|
|
6
6
|
onData: (data: string) => void;
|
|
@@ -18,6 +18,7 @@ export declare class TerminalInputBridge {
|
|
|
18
18
|
private readonly copySelection;
|
|
19
19
|
private readonly syncInputGeometry;
|
|
20
20
|
private isComposing;
|
|
21
|
+
private pendingCompositionCommit;
|
|
21
22
|
private ignoreNextInput;
|
|
22
23
|
private suppressionToken;
|
|
23
24
|
private ephemeralStateResetTimer;
|
|
@@ -30,11 +31,13 @@ export declare class TerminalInputBridge {
|
|
|
30
31
|
private readonly compositionStartListener;
|
|
31
32
|
private readonly compositionEndListener;
|
|
32
33
|
private readonly focusListener;
|
|
34
|
+
private readonly blurListener;
|
|
33
35
|
private readonly inputHostFocusInListener;
|
|
34
36
|
private readonly inputHostPointerDownListener;
|
|
35
37
|
private inputFocusClaimTimer;
|
|
36
|
-
constructor(options:
|
|
38
|
+
constructor(options: TerminalInputBridgeOptions);
|
|
37
39
|
focus(options?: TerminalFocusOptions): void;
|
|
40
|
+
syncGeometry(): void;
|
|
38
41
|
dispose(): void;
|
|
39
42
|
private attach;
|
|
40
43
|
private handleInputHostFocusIn;
|
|
@@ -44,6 +47,7 @@ export declare class TerminalInputBridge {
|
|
|
44
47
|
private handleInput;
|
|
45
48
|
private handleCompositionStart;
|
|
46
49
|
private handleCompositionEnd;
|
|
50
|
+
private consumeCompositionCommitBeforeInput;
|
|
47
51
|
containsTarget(target: Node): boolean;
|
|
48
52
|
tryHandleDocumentCopyShortcut(event: KeyboardEvent): boolean;
|
|
49
53
|
tryHandleDocumentCopyEvent(event: ClipboardEvent): boolean;
|
|
@@ -52,10 +56,10 @@ export declare class TerminalInputBridge {
|
|
|
52
56
|
private patchTerminalFocusHost;
|
|
53
57
|
private requestSelectionCopy;
|
|
54
58
|
private clearInputValue;
|
|
59
|
+
private resetCompositionState;
|
|
55
60
|
private emitData;
|
|
56
61
|
private scheduleEphemeralStateReset;
|
|
57
62
|
private clearEphemeralStateResetTimer;
|
|
58
63
|
private clearInputFocusClaimTimer;
|
|
59
64
|
}
|
|
60
|
-
export {};
|
|
61
65
|
//# sourceMappingURL=TerminalInputBridge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalInputBridge.d.ts","sourceRoot":"","sources":["../../src/core/TerminalInputBridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAsLrB,eAAO,MAAM,2BAA2B,GAAI,WAAW,WAAW,KAAG,mBAAmB,GAAG,IAG1F,CAAC;AAEF,
|
|
1
|
+
{"version":3,"file":"TerminalInputBridge.d.ts","sourceRoot":"","sources":["../../src/core/TerminalInputBridge.ts"],"names":[],"mappings":"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"}
|