@vibecook/ghosttea-react 0.11.1 → 0.12.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 +27 -0
- package/dist/TerminalSurface.d.ts.map +1 -1
- package/dist/TerminalSurface.js +31 -4
- package/dist/TerminalSurface.js.map +1 -1
- package/dist/appearance/AppearanceSettings.d.ts +3 -2
- package/dist/appearance/AppearanceSettings.d.ts.map +1 -1
- package/dist/appearance/AppearanceSettings.js +3 -2
- package/dist/appearance/AppearanceSettings.js.map +1 -1
- package/dist/appearance/BackdropBlurControl.d.ts +5 -0
- package/dist/appearance/BackdropBlurControl.d.ts.map +1 -0
- package/dist/appearance/BackdropBlurControl.js +42 -0
- package/dist/appearance/BackdropBlurControl.js.map +1 -0
- package/dist/appearance/types.d.ts +6 -0
- package/dist/appearance/types.d.ts.map +1 -1
- package/dist/link-input.d.ts +18 -0
- package/dist/link-input.d.ts.map +1 -0
- package/dist/link-input.js +27 -0
- package/dist/link-input.js.map +1 -0
- package/dist/renderers/background-geometry.d.ts +16 -0
- package/dist/renderers/background-geometry.d.ts.map +1 -0
- package/dist/renderers/background-geometry.js +20 -0
- package/dist/renderers/background-geometry.js.map +1 -0
- package/dist/renderers/types.d.ts +2 -0
- package/dist/renderers/types.d.ts.map +1 -1
- package/dist/renderers/types.js.map +1 -1
- package/dist/renderers/webgpu-renderer.d.ts.map +1 -1
- package/dist/renderers/webgpu-renderer.js +10 -2
- package/dist/renderers/webgpu-renderer.js.map +1 -1
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +50 -6
- package/dist/runtime.js.map +1 -1
- package/dist/styles.css +13 -0
- package/dist/terminal-render.worker.js +71 -9
- package/dist/terminal-render.worker.js.map +3 -3
- package/dist/use-terminal-links.d.ts +17 -0
- package/dist/use-terminal-links.d.ts.map +1 -0
- package/dist/use-terminal-links.js +101 -0
- package/dist/use-terminal-links.js.map +1 -0
- package/dist/worker-messages.d.ts +5 -0
- package/dist/worker-messages.d.ts.map +1 -1
- package/dist/workspace/Workspace.d.ts +6 -3
- package/dist/workspace/Workspace.d.ts.map +1 -1
- package/dist/workspace/Workspace.js +18 -9
- package/dist/workspace/Workspace.js.map +1 -1
- package/dist/workspace/index.d.ts +2 -2
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/pane-focus.d.ts +8 -0
- package/dist/workspace/pane-focus.d.ts.map +1 -0
- package/dist/workspace/pane-focus.js +24 -0
- package/dist/workspace/pane-focus.js.map +1 -0
- package/dist/workspace/pane-layout.d.ts +2 -1
- package/dist/workspace/pane-layout.d.ts.map +1 -1
- package/dist/workspace/pane-layout.js +29 -2
- package/dist/workspace/pane-layout.js.map +1 -1
- package/package.json +4 -4
package/dist/runtime.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { terminalLinkUrl } from "@vibecook/ghosttea-protocol";
|
|
1
2
|
import { ControlClient } from "@vibecook/ghosttea";
|
|
2
3
|
import { DEFAULT_ROUTED_PROTOCOL_LIMITS, PROTOCOL_MAJOR, PROTOCOL_MINOR, SESSION_SCROLLBACK_PROTOCOL_MINOR, STRUCTURED_ERROR_PROTOCOL_MINOR, isRoutedSessionAttachGrant, isRoutedTerminalOpenTicket, isValidScrollbackBytes, } from "@vibecook/ghosttea-protocol";
|
|
3
4
|
import { FRAME_MAGIC, FrameFlag } from "@vibecook/ghosttea-frame";
|
|
@@ -110,6 +111,7 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
110
111
|
#performanceRequestId = 1;
|
|
111
112
|
#performanceRequests = new Map();
|
|
112
113
|
#counterRequests = new Map();
|
|
114
|
+
#linksByHandle = new Map();
|
|
113
115
|
#disposed = false;
|
|
114
116
|
constructor(options) {
|
|
115
117
|
super();
|
|
@@ -155,6 +157,10 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
155
157
|
else if (data.type === "clipboard-write") {
|
|
156
158
|
this.#platform.writeClipboard(data.text);
|
|
157
159
|
}
|
|
160
|
+
else if (data.type === "link-targets") {
|
|
161
|
+
this.#linksByHandle.set(data.sessionHandle, data.links.filter((link) => terminalLinkUrl(link.uri) !== null));
|
|
162
|
+
this.dispatchEvent(new CustomEvent("link-targets", { detail: { sessionHandle: data.sessionHandle } }));
|
|
163
|
+
}
|
|
158
164
|
else if (data.type === "scrollbar-state") {
|
|
159
165
|
this.#scrollbarByHandle.set(data.sessionHandle, data.scrollbar);
|
|
160
166
|
this.dispatchEvent(new CustomEvent("scrollbar-state", {
|
|
@@ -1804,6 +1810,29 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
1804
1810
|
this.#routedByActivation.delete(entry.state.activationId);
|
|
1805
1811
|
this.#routedGeometry.delete(sessionId);
|
|
1806
1812
|
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Detach one of our views and let the seat go with it.
|
|
1815
|
+
*
|
|
1816
|
+
* The daemon clears the resize controller when its holder detaches, but a
|
|
1817
|
+
* local session announces control only through the legacy `control-changed`
|
|
1818
|
+
* frame, which cannot say "no controller": the clear never reaches this
|
|
1819
|
+
* client, and a pane that remounts (a split re-parents its surface) would
|
|
1820
|
+
* see its own previous incarnation on the record forever and never claim.
|
|
1821
|
+
* Our own detach is the one clear this client can predict, so the record is
|
|
1822
|
+
* cleared here at the same revision and the session's remaining views get
|
|
1823
|
+
* their one look at the empty seat (§4.2.3).
|
|
1824
|
+
*/
|
|
1825
|
+
#detachView(sessionId, viewId) {
|
|
1826
|
+
this.#control?.notify({ type: "detach-session", sessionId, viewId });
|
|
1827
|
+
const control = this.#controlBySession.get(sessionId);
|
|
1828
|
+
if (!control?.controller || control.controller.viewId !== viewId)
|
|
1829
|
+
return;
|
|
1830
|
+
this.#controlBySession.set(sessionId, { controller: null, revision: control.revision });
|
|
1831
|
+
for (const other of this.#viewIdsForSession(sessionId)) {
|
|
1832
|
+
if (other !== viewId)
|
|
1833
|
+
this.#maybeReclaim(other);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1807
1836
|
#createMountLease(mounted) {
|
|
1808
1837
|
let disposed = false;
|
|
1809
1838
|
return {
|
|
@@ -1829,7 +1858,7 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
1829
1858
|
if (this.#routedHost)
|
|
1830
1859
|
this.#releaseRoutedView(mounted.sessionId, mounted.viewId);
|
|
1831
1860
|
else
|
|
1832
|
-
this.#
|
|
1861
|
+
this.#detachView(mounted.sessionId, mounted.viewId);
|
|
1833
1862
|
this.#views.delete(mounted.viewId);
|
|
1834
1863
|
this.#focusByView.delete(mounted.viewId);
|
|
1835
1864
|
}
|
|
@@ -2269,6 +2298,16 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
2269
2298
|
setEffects(sessionHandle, effects, surfaceId) {
|
|
2270
2299
|
this.#postWorker({ type: "effects", sessionHandle, ...(surfaceId ? { surfaceId } : {}), effects });
|
|
2271
2300
|
}
|
|
2301
|
+
links(sessionHandle) {
|
|
2302
|
+
return this.#platform.openExternal
|
|
2303
|
+
? (this.#linksByHandle.get(sessionHandle) ?? []).filter((link) => link.explicit || this.#configSnapshot?.renderer.linkUrl !== false)
|
|
2304
|
+
: [];
|
|
2305
|
+
}
|
|
2306
|
+
async openLink(uri) {
|
|
2307
|
+
const url = terminalLinkUrl(uri);
|
|
2308
|
+
if (url)
|
|
2309
|
+
await this.#platform.openExternal?.(url);
|
|
2310
|
+
}
|
|
2272
2311
|
setSelection(sessionHandle, selection, surfaceId) {
|
|
2273
2312
|
this.#postWorker({ type: "selection", sessionHandle, ...(surfaceId ? { surfaceId } : {}), selection });
|
|
2274
2313
|
}
|
|
@@ -2369,9 +2408,12 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
2369
2408
|
}
|
|
2370
2409
|
return;
|
|
2371
2410
|
}
|
|
2372
|
-
// The legacy protocol has no release verb
|
|
2373
|
-
//
|
|
2374
|
-
|
|
2411
|
+
// The legacy protocol has no release verb, so the daemon keeps this view
|
|
2412
|
+
// seated. Dropping the request is what closes every resize path; the epoch
|
|
2413
|
+
// stays, because it is still the seat's truth and a later explicit claim
|
|
2414
|
+
// resumes on it. Clearing it here would leave the view with the record in
|
|
2415
|
+
// its own name and no epoch: the funnel's one-claim-per-attachment guard
|
|
2416
|
+
// refuses that claim, and a pane hidden by a zoom never resizes again.
|
|
2375
2417
|
}
|
|
2376
2418
|
setViewInputPolicy(viewId, readWrite) {
|
|
2377
2419
|
const view = this.#views.get(viewId);
|
|
@@ -2480,6 +2522,7 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
2480
2522
|
this.#sessionMountReferences.delete(handle);
|
|
2481
2523
|
const subscriptionChanged = this.#subscribedSessionHandles.delete(handle);
|
|
2482
2524
|
this.#cancelMetadataRefresh(handle);
|
|
2525
|
+
this.#linksByHandle.delete(handle);
|
|
2483
2526
|
this.#mouseTrackingByHandle.delete(handle);
|
|
2484
2527
|
this.#scrollbarByHandle.delete(handle);
|
|
2485
2528
|
for (const mounted of [...this.#mountedEntries]) {
|
|
@@ -2494,7 +2537,7 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
2494
2537
|
this.#postWorker({ type: "unmount", surfaceId: mounted.viewId });
|
|
2495
2538
|
this.#mountGenerationBySurface.delete(mounted.viewId);
|
|
2496
2539
|
if (detachViews)
|
|
2497
|
-
this.#
|
|
2540
|
+
this.#detachView(mounted.sessionId, mounted.viewId);
|
|
2498
2541
|
this.#views.delete(mounted.viewId);
|
|
2499
2542
|
this.#focusByView.delete(mounted.viewId);
|
|
2500
2543
|
}
|
|
@@ -2505,7 +2548,7 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
2505
2548
|
if (view.sessionId === sessionId) {
|
|
2506
2549
|
view.pendingInput.length = 0;
|
|
2507
2550
|
if (detachViews)
|
|
2508
|
-
this.#
|
|
2551
|
+
this.#detachView(sessionId, viewId);
|
|
2509
2552
|
this.#views.delete(viewId);
|
|
2510
2553
|
this.#focusByView.delete(viewId);
|
|
2511
2554
|
}
|
|
@@ -2615,6 +2658,7 @@ export class GhostteaTerminalRuntime extends EventTarget {
|
|
|
2615
2658
|
this.#recoveredSessions.clear();
|
|
2616
2659
|
this.#focusByView.clear();
|
|
2617
2660
|
this.#mountGenerationBySurface.clear();
|
|
2661
|
+
this.#linksByHandle.clear();
|
|
2618
2662
|
this.#mouseTrackingByHandle.clear();
|
|
2619
2663
|
this.#scrollbarByHandle.clear();
|
|
2620
2664
|
this.#subscribedSessionHandles.clear();
|