@tutti-os/workspace-terminal 0.0.1
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/LICENSE +202 -0
- package/README.md +57 -0
- package/dist/chunk-56B5GYMU.js +607 -0
- package/dist/chunk-56B5GYMU.js.map +1 -0
- package/dist/chunk-65BWWZQV.js +109 -0
- package/dist/chunk-65BWWZQV.js.map +1 -0
- package/dist/chunk-FEJT6FJ4.js +1722 -0
- package/dist/chunk-FEJT6FJ4.js.map +1 -0
- package/dist/contracts/index.d.ts +167 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/feature-sh6KDO7B.d.ts +32 -0
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.js +13 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +39 -0
- package/dist/react/index.js +13 -0
- package/dist/react/index.js.map +1 -0
- package/dist/styles/terminal.css +303 -0
- package/dist/workbench/index.d.ts +59 -0
- package/dist/workbench/index.js +317 -0
- package/dist/workbench/index.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createTerminalNodeI18nRuntime
|
|
3
|
+
} from "./chunk-65BWWZQV.js";
|
|
4
|
+
|
|
5
|
+
// src/core/sessionDiagnostics.ts
|
|
6
|
+
function createTerminalSurfaceDiagnostics(input) {
|
|
7
|
+
return {
|
|
8
|
+
dispose() {
|
|
9
|
+
input.diagnostics.log("dispose", resolveContext(input));
|
|
10
|
+
},
|
|
11
|
+
mount() {
|
|
12
|
+
input.diagnostics.log("mount", resolveContext(input));
|
|
13
|
+
},
|
|
14
|
+
outputSync({
|
|
15
|
+
contentEpoch,
|
|
16
|
+
nextCommittedBytes,
|
|
17
|
+
plan,
|
|
18
|
+
previousCommittedBytes,
|
|
19
|
+
rawBytes,
|
|
20
|
+
writeBytes
|
|
21
|
+
}) {
|
|
22
|
+
input.diagnostics.log("surface-output-sync", {
|
|
23
|
+
...resolveContext(input),
|
|
24
|
+
contentEpoch,
|
|
25
|
+
nextCommittedBytes,
|
|
26
|
+
plan,
|
|
27
|
+
previousCommittedBytes,
|
|
28
|
+
rawBytes,
|
|
29
|
+
writeBytes
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
outputWritten({
|
|
33
|
+
bufferCursorX,
|
|
34
|
+
bufferCursorY,
|
|
35
|
+
bufferLength,
|
|
36
|
+
bytes,
|
|
37
|
+
canvasClientHeight,
|
|
38
|
+
canvasClientWidth,
|
|
39
|
+
canvasCount,
|
|
40
|
+
cols,
|
|
41
|
+
containerClientHeight,
|
|
42
|
+
containerClientWidth,
|
|
43
|
+
cursorLinePreview,
|
|
44
|
+
firstLinePreview,
|
|
45
|
+
helperChildCount,
|
|
46
|
+
mode,
|
|
47
|
+
remainingChunkCount,
|
|
48
|
+
renderDimensionsReady,
|
|
49
|
+
rowContainerChildCount,
|
|
50
|
+
rowContainerTextPreview,
|
|
51
|
+
rows,
|
|
52
|
+
screenChildCount,
|
|
53
|
+
screenClientHeight,
|
|
54
|
+
screenClientWidth,
|
|
55
|
+
screenDisplay,
|
|
56
|
+
screenOpacity,
|
|
57
|
+
screenVisibility,
|
|
58
|
+
serializedBytes,
|
|
59
|
+
xtermClientHeight,
|
|
60
|
+
xtermClientWidth,
|
|
61
|
+
xtermDisplay,
|
|
62
|
+
xtermOpacity,
|
|
63
|
+
xtermVisibility
|
|
64
|
+
}) {
|
|
65
|
+
input.diagnostics.log("surface-output-written", {
|
|
66
|
+
...resolveContext(input),
|
|
67
|
+
bufferCursorX,
|
|
68
|
+
bufferCursorY,
|
|
69
|
+
bufferLength,
|
|
70
|
+
bytes,
|
|
71
|
+
canvasClientHeight,
|
|
72
|
+
canvasClientWidth,
|
|
73
|
+
canvasCount,
|
|
74
|
+
cols,
|
|
75
|
+
containerClientHeight,
|
|
76
|
+
containerClientWidth,
|
|
77
|
+
cursorLinePreview,
|
|
78
|
+
firstLinePreview,
|
|
79
|
+
helperChildCount,
|
|
80
|
+
mode,
|
|
81
|
+
remainingChunkCount,
|
|
82
|
+
renderDimensionsReady,
|
|
83
|
+
rowContainerChildCount,
|
|
84
|
+
rowContainerTextPreview,
|
|
85
|
+
rows,
|
|
86
|
+
screenChildCount,
|
|
87
|
+
screenClientHeight,
|
|
88
|
+
screenClientWidth,
|
|
89
|
+
screenDisplay,
|
|
90
|
+
screenOpacity,
|
|
91
|
+
screenVisibility,
|
|
92
|
+
serializedBytes,
|
|
93
|
+
xtermClientHeight,
|
|
94
|
+
xtermClientWidth,
|
|
95
|
+
xtermDisplay,
|
|
96
|
+
xtermOpacity,
|
|
97
|
+
xtermVisibility
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
resize({ cols, rows }) {
|
|
101
|
+
input.diagnostics.log("resize", {
|
|
102
|
+
...resolveContext(input),
|
|
103
|
+
cols,
|
|
104
|
+
rows
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function createTerminalCloseDiagnostics(input) {
|
|
110
|
+
return {
|
|
111
|
+
confirmed() {
|
|
112
|
+
input.diagnostics.log("close-confirmed", {
|
|
113
|
+
sessionId: input.sessionId
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
requested() {
|
|
117
|
+
input.diagnostics.log("close-requested", {
|
|
118
|
+
sessionId: input.sessionId
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function createTerminalSessionRecoveryDiagnostics(input) {
|
|
124
|
+
return {
|
|
125
|
+
attachComplete() {
|
|
126
|
+
input.diagnostics.log("attach-complete", resolveContext(input));
|
|
127
|
+
},
|
|
128
|
+
attachError() {
|
|
129
|
+
input.diagnostics.log("attach-error", resolveContext(input));
|
|
130
|
+
},
|
|
131
|
+
attachStart(afterSeq) {
|
|
132
|
+
input.diagnostics.log("attach-start", {
|
|
133
|
+
...resolveContext(input),
|
|
134
|
+
afterSeq
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
hydrationComplete(replayChunkCount) {
|
|
138
|
+
input.diagnostics.log("hydration-complete", {
|
|
139
|
+
...resolveContext(input),
|
|
140
|
+
replayChunkCount
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
hydrationGap({ fromSeq, toSeq }) {
|
|
144
|
+
input.diagnostics.log("hydration-gap", {
|
|
145
|
+
...resolveContext(input),
|
|
146
|
+
fromSeq,
|
|
147
|
+
toSeq
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
hydrationStart() {
|
|
151
|
+
input.diagnostics.log("hydration-start", resolveContext(input));
|
|
152
|
+
},
|
|
153
|
+
outputProjected({
|
|
154
|
+
contentEpoch,
|
|
155
|
+
previewHead,
|
|
156
|
+
previewTail,
|
|
157
|
+
rawBytes,
|
|
158
|
+
source,
|
|
159
|
+
writeBytes
|
|
160
|
+
}) {
|
|
161
|
+
input.diagnostics.log("output-projected", {
|
|
162
|
+
...resolveContext(input),
|
|
163
|
+
contentEpoch,
|
|
164
|
+
previewHead,
|
|
165
|
+
previewTail,
|
|
166
|
+
rawBytes,
|
|
167
|
+
source,
|
|
168
|
+
writeBytes
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
snapshotComplete({ toSeq, truncated }) {
|
|
172
|
+
input.diagnostics.log("snapshot-complete", {
|
|
173
|
+
...resolveContext(input),
|
|
174
|
+
toSeq,
|
|
175
|
+
truncated
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
snapshotStart() {
|
|
179
|
+
input.diagnostics.log("snapshot-start", resolveContext(input));
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function resolveContext(input) {
|
|
184
|
+
return {
|
|
185
|
+
nodeId: input.nodeId,
|
|
186
|
+
sessionId: input.sessionId
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/core/sessionProjection.ts
|
|
191
|
+
function isTerminalSessionEndedStatus(status) {
|
|
192
|
+
return status === "exited" || status === "failed";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/core/closeFlow.ts
|
|
196
|
+
async function closeTerminalSession({
|
|
197
|
+
confirm,
|
|
198
|
+
feature,
|
|
199
|
+
sessionId,
|
|
200
|
+
status
|
|
201
|
+
}) {
|
|
202
|
+
if (!sessionId || status && isTerminalSessionEndedStatus(status)) {
|
|
203
|
+
return "closed";
|
|
204
|
+
}
|
|
205
|
+
const closeDiagnostics = createTerminalCloseDiagnostics({
|
|
206
|
+
diagnostics: feature.diagnostics,
|
|
207
|
+
sessionId
|
|
208
|
+
});
|
|
209
|
+
closeDiagnostics.requested();
|
|
210
|
+
const guard = await feature.closeGuard.check({ sessionId });
|
|
211
|
+
if (isTerminalSessionEndedStatus(guard.status)) {
|
|
212
|
+
closeDiagnostics.confirmed();
|
|
213
|
+
return "closed";
|
|
214
|
+
}
|
|
215
|
+
if (guard.requiresConfirmation) {
|
|
216
|
+
const confirmed = await confirm?.(guard);
|
|
217
|
+
if (!confirmed) {
|
|
218
|
+
return "kept-open";
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
await feature.launchService.terminate({ sessionId });
|
|
222
|
+
closeDiagnostics.confirmed();
|
|
223
|
+
return "closed";
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/core/feature.ts
|
|
227
|
+
var defaultTerminalNodeLimits = {
|
|
228
|
+
maxScrollbackLines: 1e4,
|
|
229
|
+
maxWriteBatchBytes: 64 * 1024,
|
|
230
|
+
snapshotChunkBytes: 256 * 1024
|
|
231
|
+
};
|
|
232
|
+
var noopTerminalDiagnostics = {
|
|
233
|
+
log() {
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
var defaultResolveTerminalTheme = () => ({});
|
|
238
|
+
function createTerminalNodeFeature(input) {
|
|
239
|
+
return {
|
|
240
|
+
closeGuard: input.closeGuard,
|
|
241
|
+
diagnostics: input.diagnostics ?? noopTerminalDiagnostics,
|
|
242
|
+
dropInput: input.dropInput,
|
|
243
|
+
i18n: createTerminalNodeI18nRuntime(input.i18n),
|
|
244
|
+
launchService: input.launchService,
|
|
245
|
+
limits: {
|
|
246
|
+
...defaultTerminalNodeLimits,
|
|
247
|
+
...input.limits
|
|
248
|
+
},
|
|
249
|
+
linkHandler: input.linkHandler,
|
|
250
|
+
outputTransform: input.outputTransform,
|
|
251
|
+
resolveTheme: input.resolveTheme ?? defaultResolveTerminalTheme,
|
|
252
|
+
transport: input.transport
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/core/attachmentController.ts
|
|
257
|
+
function createTerminalAttachmentController(input) {
|
|
258
|
+
let attached = false;
|
|
259
|
+
let attachPromise = null;
|
|
260
|
+
let detachIssued = false;
|
|
261
|
+
let detachPromise = null;
|
|
262
|
+
let detachRequested = false;
|
|
263
|
+
const issueDetach = async () => {
|
|
264
|
+
if (detachIssued || !attached) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
detachIssued = true;
|
|
268
|
+
attached = false;
|
|
269
|
+
await input.transport.detach({
|
|
270
|
+
clientId: input.clientId,
|
|
271
|
+
sessionId: input.sessionId
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
return {
|
|
275
|
+
attach(afterSeq) {
|
|
276
|
+
if (attachPromise) {
|
|
277
|
+
return attachPromise;
|
|
278
|
+
}
|
|
279
|
+
if (attached) {
|
|
280
|
+
return Promise.resolve();
|
|
281
|
+
}
|
|
282
|
+
attachPromise = input.transport.attach({
|
|
283
|
+
afterSeq,
|
|
284
|
+
clientId: input.clientId,
|
|
285
|
+
sessionId: input.sessionId
|
|
286
|
+
}).then(async () => {
|
|
287
|
+
attached = true;
|
|
288
|
+
attachPromise = null;
|
|
289
|
+
if (detachRequested) {
|
|
290
|
+
await issueDetach();
|
|
291
|
+
}
|
|
292
|
+
}).catch((error) => {
|
|
293
|
+
attachPromise = null;
|
|
294
|
+
throw error;
|
|
295
|
+
});
|
|
296
|
+
return attachPromise;
|
|
297
|
+
},
|
|
298
|
+
async detach() {
|
|
299
|
+
detachRequested = true;
|
|
300
|
+
if (detachPromise) {
|
|
301
|
+
return detachPromise;
|
|
302
|
+
}
|
|
303
|
+
detachPromise = Promise.resolve(attachPromise).catch(() => void 0).then(async () => {
|
|
304
|
+
await issueDetach();
|
|
305
|
+
}).finally(() => {
|
|
306
|
+
attachPromise = null;
|
|
307
|
+
detachIssued = false;
|
|
308
|
+
detachPromise = null;
|
|
309
|
+
detachRequested = false;
|
|
310
|
+
});
|
|
311
|
+
return detachPromise;
|
|
312
|
+
},
|
|
313
|
+
markDetached() {
|
|
314
|
+
attached = false;
|
|
315
|
+
attachPromise = null;
|
|
316
|
+
detachIssued = false;
|
|
317
|
+
detachPromise = null;
|
|
318
|
+
detachRequested = false;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/core/inputQueue.ts
|
|
324
|
+
function createBufferedTerminalInputQueue() {
|
|
325
|
+
const entries = [];
|
|
326
|
+
return {
|
|
327
|
+
enqueue(data, encoding = "utf8") {
|
|
328
|
+
if (data.length === 0) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
entries.push({ data, encoding });
|
|
332
|
+
},
|
|
333
|
+
async flush(writer) {
|
|
334
|
+
const queued = entries.splice(0);
|
|
335
|
+
for (const entry of queued) {
|
|
336
|
+
await writer(entry);
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
reset() {
|
|
340
|
+
entries.length = 0;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
async function writeQueuedTerminalInput(input) {
|
|
345
|
+
await input.queue.flush(
|
|
346
|
+
(entry) => input.transport.write({
|
|
347
|
+
data: entry.data,
|
|
348
|
+
encoding: entry.encoding,
|
|
349
|
+
provenance: "user",
|
|
350
|
+
sessionId: input.sessionId
|
|
351
|
+
})
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/core/linkDetection.ts
|
|
356
|
+
var pathCandidatePattern = /(?<path>(?:~|\.{1,2}|\/)[^\s"'`<>|:([\]]+|[A-Za-z0-9_.-]+\/[^\s"'`<>|:([\]]+)(?<suffix>(?::(?<lineColon>\d+)(?::(?<columnColon>\d+))?)|(?:\((?<lineParen>\d+)(?:,\s*(?<columnParen>\d+))?\))|(?:\[(?<lineBracket>\d+)(?:,\s*(?<columnBracket>\d+))?\]))?/g;
|
|
357
|
+
function detectTerminalFileLinks(text) {
|
|
358
|
+
const links = [];
|
|
359
|
+
pathCandidatePattern.lastIndex = 0;
|
|
360
|
+
let match = pathCandidatePattern.exec(text);
|
|
361
|
+
while (match) {
|
|
362
|
+
const groups = match.groups ?? {};
|
|
363
|
+
const rawPath = groups.path ?? "";
|
|
364
|
+
const suffix = groups.suffix ?? "";
|
|
365
|
+
const candidateText = `${rawPath}${suffix}`;
|
|
366
|
+
const trimmed = trimTerminalPathCandidate(rawPath);
|
|
367
|
+
const trimAmount = rawPath.length - trimmed.length;
|
|
368
|
+
if (isTerminalPathCandidate(trimmed, text, match.index)) {
|
|
369
|
+
const line = parsePositiveInteger(
|
|
370
|
+
groups.lineColon ?? groups.lineParen ?? groups.lineBracket
|
|
371
|
+
);
|
|
372
|
+
const column = parsePositiveInteger(
|
|
373
|
+
groups.columnColon ?? groups.columnParen ?? groups.columnBracket
|
|
374
|
+
);
|
|
375
|
+
links.push({
|
|
376
|
+
column,
|
|
377
|
+
index: match.index,
|
|
378
|
+
line,
|
|
379
|
+
path: trimmed,
|
|
380
|
+
text: candidateText.slice(0, candidateText.length - trimAmount)
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
match = pathCandidatePattern.exec(text);
|
|
384
|
+
}
|
|
385
|
+
return links;
|
|
386
|
+
}
|
|
387
|
+
function toTerminalLinkTarget(link) {
|
|
388
|
+
return {
|
|
389
|
+
column: link.column,
|
|
390
|
+
line: link.line,
|
|
391
|
+
path: link.path
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function trimTerminalPathCandidate(value) {
|
|
395
|
+
let result = value.trim();
|
|
396
|
+
while (/[),.;:!?]$/.test(result) && !looksLikeFileExtension(result)) {
|
|
397
|
+
result = result.slice(0, -1);
|
|
398
|
+
}
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
function looksLikeFileExtension(value) {
|
|
402
|
+
return /\.[A-Za-z0-9]{1,8}$/.test(value);
|
|
403
|
+
}
|
|
404
|
+
function isTerminalPathCandidate(value, sourceText, index) {
|
|
405
|
+
if (value.length === 0) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
if (/^\d+(?::\d+)*$/.test(value)) {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
if (value.startsWith("//") || sourceText[index - 1] === ":") {
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
if (value.startsWith("node:")) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.includes("/");
|
|
421
|
+
}
|
|
422
|
+
function parsePositiveInteger(value) {
|
|
423
|
+
if (!value) {
|
|
424
|
+
return void 0;
|
|
425
|
+
}
|
|
426
|
+
const parsed = Number.parseInt(value, 10);
|
|
427
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/core/screenStateCache.ts
|
|
431
|
+
function createTerminalScreenStateCache() {
|
|
432
|
+
const screenStateByNodeId = /* @__PURE__ */ new Map();
|
|
433
|
+
const invalidatedSessionIdByNodeId = /* @__PURE__ */ new Map();
|
|
434
|
+
const get = (nodeId, sessionId) => {
|
|
435
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
436
|
+
const normalizedSessionId = normalizeId(sessionId);
|
|
437
|
+
if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
if (invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId) {
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
const cached = screenStateByNodeId.get(normalizedNodeId);
|
|
444
|
+
if (!cached || cached.sessionId !== normalizedSessionId) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
return cached;
|
|
448
|
+
};
|
|
449
|
+
const peek = (nodeId) => {
|
|
450
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
451
|
+
if (normalizedNodeId.length === 0) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
return screenStateByNodeId.get(normalizedNodeId) ?? null;
|
|
455
|
+
};
|
|
456
|
+
const set = (nodeId, state) => {
|
|
457
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
458
|
+
const normalizedSessionId = normalizeId(state.sessionId);
|
|
459
|
+
if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0 || state.serialized.length === 0) {
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
if (invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId) {
|
|
463
|
+
invalidatedSessionIdByNodeId.delete(normalizedNodeId);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
invalidatedSessionIdByNodeId.delete(normalizedNodeId);
|
|
467
|
+
screenStateByNodeId.set(normalizedNodeId, {
|
|
468
|
+
cols: normalizeDimension(state.cols, 80),
|
|
469
|
+
rawSnapshot: state.rawSnapshot,
|
|
470
|
+
rows: normalizeDimension(state.rows, 24),
|
|
471
|
+
serialized: state.serialized,
|
|
472
|
+
sessionId: normalizedSessionId
|
|
473
|
+
});
|
|
474
|
+
};
|
|
475
|
+
const remove = (nodeId, sessionId) => {
|
|
476
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
477
|
+
const normalizedSessionId = normalizeId(sessionId);
|
|
478
|
+
if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const cached = screenStateByNodeId.get(normalizedNodeId);
|
|
482
|
+
if (cached?.sessionId === normalizedSessionId) {
|
|
483
|
+
screenStateByNodeId.delete(normalizedNodeId);
|
|
484
|
+
}
|
|
485
|
+
if (invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId) {
|
|
486
|
+
invalidatedSessionIdByNodeId.delete(normalizedNodeId);
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
const invalidate = (nodeId, sessionId) => {
|
|
490
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
491
|
+
const normalizedSessionId = normalizeId(sessionId);
|
|
492
|
+
if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
screenStateByNodeId.delete(normalizedNodeId);
|
|
496
|
+
invalidatedSessionIdByNodeId.set(normalizedNodeId, normalizedSessionId);
|
|
497
|
+
};
|
|
498
|
+
const isInvalidated = (nodeId, sessionId) => {
|
|
499
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
500
|
+
const normalizedSessionId = normalizeId(sessionId);
|
|
501
|
+
if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
return invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId;
|
|
505
|
+
};
|
|
506
|
+
const clearInvalidation = (nodeId, sessionId) => {
|
|
507
|
+
const normalizedNodeId = normalizeId(nodeId);
|
|
508
|
+
const normalizedSessionId = normalizeId(sessionId);
|
|
509
|
+
if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (invalidatedSessionIdByNodeId.get(normalizedNodeId) !== normalizedSessionId) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
invalidatedSessionIdByNodeId.delete(normalizedNodeId);
|
|
516
|
+
};
|
|
517
|
+
const clear = () => {
|
|
518
|
+
screenStateByNodeId.clear();
|
|
519
|
+
invalidatedSessionIdByNodeId.clear();
|
|
520
|
+
};
|
|
521
|
+
return {
|
|
522
|
+
clear,
|
|
523
|
+
clearInvalidation,
|
|
524
|
+
get,
|
|
525
|
+
invalidate,
|
|
526
|
+
isInvalidated,
|
|
527
|
+
peek,
|
|
528
|
+
remove,
|
|
529
|
+
set
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function normalizeId(value) {
|
|
533
|
+
return value.trim();
|
|
534
|
+
}
|
|
535
|
+
function normalizeDimension(value, fallback) {
|
|
536
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/core/stringOverlap.ts
|
|
540
|
+
function resolveSuffixPrefixOverlap(left, right) {
|
|
541
|
+
if (left.length === 0 || right.length === 0) {
|
|
542
|
+
return 0;
|
|
543
|
+
}
|
|
544
|
+
const max = Math.min(left.length, right.length);
|
|
545
|
+
const leftTail = left.slice(-max);
|
|
546
|
+
const rightPrefix = right.slice(0, max);
|
|
547
|
+
const combined = `${rightPrefix}\0${leftTail}`;
|
|
548
|
+
const prefix = new Uint32Array(combined.length);
|
|
549
|
+
let cursor = 0;
|
|
550
|
+
for (let index = 1; index < combined.length; index += 1) {
|
|
551
|
+
while (cursor > 0 && combined[index] !== combined[cursor]) {
|
|
552
|
+
cursor = prefix[cursor - 1] ?? 0;
|
|
553
|
+
}
|
|
554
|
+
if (combined[index] === combined[cursor]) {
|
|
555
|
+
cursor += 1;
|
|
556
|
+
prefix[index] = cursor;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return prefix[combined.length - 1] ?? 0;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// src/core/scrollback.ts
|
|
563
|
+
var defaultMaxTerminalScrollbackChars = 4e5;
|
|
564
|
+
function truncateTerminalScrollback(snapshot, options) {
|
|
565
|
+
const maxChars = normalizeMaxChars(options?.maxChars);
|
|
566
|
+
if (snapshot.length <= maxChars) {
|
|
567
|
+
return snapshot;
|
|
568
|
+
}
|
|
569
|
+
return snapshot.slice(-maxChars);
|
|
570
|
+
}
|
|
571
|
+
function resolveTerminalScrollbackDelta(previous, next, options) {
|
|
572
|
+
const previousSnapshot = truncateTerminalScrollback(previous, options);
|
|
573
|
+
const nextSnapshot = truncateTerminalScrollback(next, options);
|
|
574
|
+
if (previousSnapshot.length === 0) {
|
|
575
|
+
return nextSnapshot;
|
|
576
|
+
}
|
|
577
|
+
if (nextSnapshot.length === 0 || previousSnapshot === nextSnapshot) {
|
|
578
|
+
return "";
|
|
579
|
+
}
|
|
580
|
+
if (previousSnapshot.includes(nextSnapshot)) {
|
|
581
|
+
return "";
|
|
582
|
+
}
|
|
583
|
+
const overlap = resolveSuffixPrefixOverlap(previousSnapshot, nextSnapshot);
|
|
584
|
+
return nextSnapshot.slice(overlap);
|
|
585
|
+
}
|
|
586
|
+
function normalizeMaxChars(value) {
|
|
587
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : defaultMaxTerminalScrollbackChars;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
export {
|
|
591
|
+
createTerminalAttachmentController,
|
|
592
|
+
createTerminalSurfaceDiagnostics,
|
|
593
|
+
createTerminalCloseDiagnostics,
|
|
594
|
+
createTerminalSessionRecoveryDiagnostics,
|
|
595
|
+
isTerminalSessionEndedStatus,
|
|
596
|
+
closeTerminalSession,
|
|
597
|
+
defaultTerminalNodeLimits,
|
|
598
|
+
createTerminalNodeFeature,
|
|
599
|
+
createBufferedTerminalInputQueue,
|
|
600
|
+
writeQueuedTerminalInput,
|
|
601
|
+
detectTerminalFileLinks,
|
|
602
|
+
toTerminalLinkTarget,
|
|
603
|
+
createTerminalScreenStateCache,
|
|
604
|
+
truncateTerminalScrollback,
|
|
605
|
+
resolveTerminalScrollbackDelta
|
|
606
|
+
};
|
|
607
|
+
//# sourceMappingURL=chunk-56B5GYMU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/sessionDiagnostics.ts","../src/core/sessionProjection.ts","../src/core/closeFlow.ts","../src/core/feature.ts","../src/core/attachmentController.ts","../src/core/inputQueue.ts","../src/core/linkDetection.ts","../src/core/screenStateCache.ts","../src/core/stringOverlap.ts","../src/core/scrollback.ts"],"sourcesContent":["import type { TerminalDiagnostics } from \"../contracts/index.ts\";\n\nexport interface TerminalCloseDiagnostics {\n confirmed(): void;\n requested(): void;\n}\n\nexport interface TerminalSurfaceDiagnostics {\n dispose(): void;\n mount(): void;\n outputSync(input: {\n contentEpoch: number;\n nextCommittedBytes: number;\n plan: \"append\" | \"replace\" | \"reset\" | \"skip\";\n previousCommittedBytes: number;\n rawBytes: number;\n writeBytes: number;\n }): void;\n outputWritten(input: {\n bufferCursorX: number;\n bufferCursorY: number;\n bufferLength: number;\n bytes: number;\n canvasClientHeight: number;\n canvasClientWidth: number;\n canvasCount: number;\n cols: number;\n containerClientHeight: number;\n containerClientWidth: number;\n cursorLinePreview: string;\n firstLinePreview: string;\n helperChildCount: number;\n mode: \"append\" | \"cache\" | \"replace\" | \"reset\";\n remainingChunkCount: number;\n renderDimensionsReady: boolean;\n rowContainerChildCount: number;\n rowContainerTextPreview: string;\n rows: number;\n screenChildCount: number;\n screenClientHeight: number;\n screenClientWidth: number;\n screenDisplay: string;\n screenOpacity: string;\n screenVisibility: string;\n serializedBytes: number;\n xtermClientHeight: number;\n xtermClientWidth: number;\n xtermDisplay: string;\n xtermOpacity: string;\n xtermVisibility: string;\n }): void;\n resize(input: { cols: number; rows: number }): void;\n}\n\nexport interface TerminalSessionRecoveryDiagnostics {\n attachComplete(): void;\n attachError(): void;\n attachStart(afterSeq: number | null): void;\n hydrationComplete(replayChunkCount: number): void;\n hydrationGap(input: { fromSeq: number; toSeq: number }): void;\n hydrationStart(): void;\n outputProjected(input: {\n contentEpoch: number;\n previewHead: string;\n previewTail: string;\n rawBytes: number;\n source: \"replay\" | \"snapshot\";\n writeBytes: number;\n }): void;\n snapshotComplete(input: { toSeq: number | null; truncated: boolean }): void;\n snapshotStart(): void;\n}\n\nexport function createTerminalSurfaceDiagnostics(input: {\n diagnostics: TerminalDiagnostics;\n nodeId: string;\n sessionId: string;\n}): TerminalSurfaceDiagnostics {\n return {\n dispose() {\n input.diagnostics.log(\"dispose\", resolveContext(input));\n },\n mount() {\n input.diagnostics.log(\"mount\", resolveContext(input));\n },\n outputSync({\n contentEpoch,\n nextCommittedBytes,\n plan,\n previousCommittedBytes,\n rawBytes,\n writeBytes\n }) {\n input.diagnostics.log(\"surface-output-sync\", {\n ...resolveContext(input),\n contentEpoch,\n nextCommittedBytes,\n plan,\n previousCommittedBytes,\n rawBytes,\n writeBytes\n });\n },\n outputWritten({\n bufferCursorX,\n bufferCursorY,\n bufferLength,\n bytes,\n canvasClientHeight,\n canvasClientWidth,\n canvasCount,\n cols,\n containerClientHeight,\n containerClientWidth,\n cursorLinePreview,\n firstLinePreview,\n helperChildCount,\n mode,\n remainingChunkCount,\n renderDimensionsReady,\n rowContainerChildCount,\n rowContainerTextPreview,\n rows,\n screenChildCount,\n screenClientHeight,\n screenClientWidth,\n screenDisplay,\n screenOpacity,\n screenVisibility,\n serializedBytes,\n xtermClientHeight,\n xtermClientWidth,\n xtermDisplay,\n xtermOpacity,\n xtermVisibility\n }) {\n input.diagnostics.log(\"surface-output-written\", {\n ...resolveContext(input),\n bufferCursorX,\n bufferCursorY,\n bufferLength,\n bytes,\n canvasClientHeight,\n canvasClientWidth,\n canvasCount,\n cols,\n containerClientHeight,\n containerClientWidth,\n cursorLinePreview,\n firstLinePreview,\n helperChildCount,\n mode,\n remainingChunkCount,\n renderDimensionsReady,\n rowContainerChildCount,\n rowContainerTextPreview,\n rows,\n screenChildCount,\n screenClientHeight,\n screenClientWidth,\n screenDisplay,\n screenOpacity,\n screenVisibility,\n serializedBytes,\n xtermClientHeight,\n xtermClientWidth,\n xtermDisplay,\n xtermOpacity,\n xtermVisibility\n });\n },\n resize({ cols, rows }) {\n input.diagnostics.log(\"resize\", {\n ...resolveContext(input),\n cols,\n rows\n });\n }\n };\n}\n\nexport function createTerminalCloseDiagnostics(input: {\n diagnostics: TerminalDiagnostics;\n sessionId: string;\n}): TerminalCloseDiagnostics {\n return {\n confirmed() {\n input.diagnostics.log(\"close-confirmed\", {\n sessionId: input.sessionId\n });\n },\n requested() {\n input.diagnostics.log(\"close-requested\", {\n sessionId: input.sessionId\n });\n }\n };\n}\n\nexport function createTerminalSessionRecoveryDiagnostics(input: {\n diagnostics: TerminalDiagnostics;\n nodeId: string;\n sessionId: string;\n}): TerminalSessionRecoveryDiagnostics {\n return {\n attachComplete() {\n input.diagnostics.log(\"attach-complete\", resolveContext(input));\n },\n attachError() {\n input.diagnostics.log(\"attach-error\", resolveContext(input));\n },\n attachStart(afterSeq) {\n input.diagnostics.log(\"attach-start\", {\n ...resolveContext(input),\n afterSeq\n });\n },\n hydrationComplete(replayChunkCount) {\n input.diagnostics.log(\"hydration-complete\", {\n ...resolveContext(input),\n replayChunkCount\n });\n },\n hydrationGap({ fromSeq, toSeq }) {\n input.diagnostics.log(\"hydration-gap\", {\n ...resolveContext(input),\n fromSeq,\n toSeq\n });\n },\n hydrationStart() {\n input.diagnostics.log(\"hydration-start\", resolveContext(input));\n },\n outputProjected({\n contentEpoch,\n previewHead,\n previewTail,\n rawBytes,\n source,\n writeBytes\n }) {\n input.diagnostics.log(\"output-projected\", {\n ...resolveContext(input),\n contentEpoch,\n previewHead,\n previewTail,\n rawBytes,\n source,\n writeBytes\n });\n },\n snapshotComplete({ toSeq, truncated }) {\n input.diagnostics.log(\"snapshot-complete\", {\n ...resolveContext(input),\n toSeq,\n truncated\n });\n },\n snapshotStart() {\n input.diagnostics.log(\"snapshot-start\", resolveContext(input));\n }\n };\n}\n\nfunction resolveContext(input: { nodeId: string; sessionId: string }) {\n return {\n nodeId: input.nodeId,\n sessionId: input.sessionId\n };\n}\n","import type {\n TerminalNodeExternalState,\n TerminalSessionStatus\n} from \"../contracts/index.ts\";\n\nexport const terminalSessionLostMessage = \"Terminal session was lost.\";\n\nexport interface TerminalSessionStatusProjection {\n lastError: string | null;\n status: TerminalSessionStatus;\n}\n\nexport function createTerminalSessionExitProjection(): TerminalSessionStatusProjection {\n return {\n lastError: null,\n status: \"exited\"\n };\n}\n\nexport function createTerminalSessionFailedProjection(\n lastError = terminalSessionLostMessage\n): TerminalSessionStatusProjection {\n return {\n lastError,\n status: \"failed\"\n };\n}\n\nexport function applyTerminalSessionStatusProjection<\n THostMetadata extends Record<string, unknown> = Record<string, unknown>\n>(\n current: TerminalNodeExternalState<THostMetadata>,\n projection: TerminalSessionStatusProjection,\n now: () => string = () => new Date().toISOString()\n): TerminalNodeExternalState<THostMetadata> {\n if (\n current.endedAt &&\n isTerminalSessionEndedStatus(current.status) &&\n !isTerminalSessionEndedStatus(projection.status)\n ) {\n return current;\n }\n\n return {\n ...current,\n endedAt: isTerminalSessionEndedStatus(projection.status)\n ? (current.endedAt ?? now())\n : current.endedAt,\n lastError: projection.lastError,\n status: projection.status\n };\n}\n\nexport function applyTerminalSessionTitleProjection<\n THostMetadata extends Record<string, unknown> = Record<string, unknown>\n>(\n current: TerminalNodeExternalState<THostMetadata>,\n title: string\n): TerminalNodeExternalState<THostMetadata> {\n return {\n ...current,\n title\n };\n}\n\nexport function isTerminalSessionEndedStatus(\n status: TerminalSessionStatus\n): boolean {\n return status === \"exited\" || status === \"failed\";\n}\n","import type {\n TerminalCloseGuardResult,\n TerminalLaunchService,\n TerminalSessionStatus\n} from \"../contracts/index.ts\";\nimport { createTerminalCloseDiagnostics } from \"./sessionDiagnostics.ts\";\nimport type { TerminalNodeFeature } from \"./feature.ts\";\nimport { isTerminalSessionEndedStatus } from \"./sessionProjection.ts\";\n\nexport type TerminalCloseConfirmation = (\n guard: TerminalCloseGuardResult\n) => Promise<boolean> | boolean;\n\nexport type TerminalCloseResult = \"closed\" | \"kept-open\";\n\nexport interface CloseTerminalSessionInput {\n confirm?: TerminalCloseConfirmation;\n feature: Pick<TerminalNodeFeature, \"closeGuard\" | \"diagnostics\"> & {\n launchService: Pick<TerminalLaunchService, \"terminate\">;\n };\n sessionId: string | null | undefined;\n status?: TerminalSessionStatus | null | undefined;\n}\n\nexport async function closeTerminalSession({\n confirm,\n feature,\n sessionId,\n status\n}: CloseTerminalSessionInput): Promise<TerminalCloseResult> {\n if (!sessionId || (status && isTerminalSessionEndedStatus(status))) {\n return \"closed\";\n }\n\n const closeDiagnostics = createTerminalCloseDiagnostics({\n diagnostics: feature.diagnostics,\n sessionId\n });\n\n closeDiagnostics.requested();\n const guard = await feature.closeGuard.check({ sessionId });\n if (isTerminalSessionEndedStatus(guard.status)) {\n closeDiagnostics.confirmed();\n return \"closed\";\n }\n if (guard.requiresConfirmation) {\n const confirmed = await confirm?.(guard);\n if (!confirmed) {\n return \"kept-open\";\n }\n }\n\n await feature.launchService.terminate({ sessionId });\n closeDiagnostics.confirmed();\n return \"closed\";\n}\n","import type { I18nRuntime } from \"@tutti-os/ui-i18n-runtime\";\nimport {\n createTerminalNodeI18nRuntime,\n type TerminalNodeI18nRuntime\n} from \"../i18n/terminalNodeI18n.ts\";\nimport type {\n TerminalCloseGuardService,\n TerminalDiagnostics,\n TerminalDropInputResolver,\n TerminalLaunchService,\n TerminalLinkHandler,\n TerminalNodeLimits,\n TerminalOutputTransform,\n TerminalThemeResolver,\n TerminalTransport\n} from \"../contracts/index.ts\";\n\nexport interface TerminalNodeFeature {\n closeGuard: TerminalCloseGuardService;\n diagnostics: TerminalDiagnostics;\n dropInput?: TerminalDropInputResolver;\n i18n: TerminalNodeI18nRuntime;\n launchService: TerminalLaunchService;\n limits: TerminalNodeLimits;\n linkHandler?: TerminalLinkHandler;\n outputTransform?: TerminalOutputTransform;\n resolveTheme: TerminalThemeResolver;\n transport: TerminalTransport;\n}\n\nexport interface CreateTerminalNodeFeatureInput {\n closeGuard: TerminalCloseGuardService;\n diagnostics?: TerminalDiagnostics;\n dropInput?: TerminalDropInputResolver;\n i18n?: I18nRuntime<string>;\n launchService: TerminalLaunchService;\n limits?: Partial<TerminalNodeLimits>;\n linkHandler?: TerminalLinkHandler;\n outputTransform?: TerminalOutputTransform;\n resolveTheme?: TerminalThemeResolver;\n transport: TerminalTransport;\n}\n\nexport const defaultTerminalNodeLimits: TerminalNodeLimits = {\n maxScrollbackLines: 10_000,\n maxWriteBatchBytes: 64 * 1024,\n snapshotChunkBytes: 256 * 1024\n};\n\nconst noopTerminalDiagnostics: TerminalDiagnostics = {\n log() {\n return undefined;\n }\n};\n\nconst defaultResolveTerminalTheme: TerminalThemeResolver = () => ({});\n\nexport function createTerminalNodeFeature(\n input: CreateTerminalNodeFeatureInput\n): TerminalNodeFeature {\n return {\n closeGuard: input.closeGuard,\n diagnostics: input.diagnostics ?? noopTerminalDiagnostics,\n dropInput: input.dropInput,\n i18n: createTerminalNodeI18nRuntime(input.i18n),\n launchService: input.launchService,\n limits: {\n ...defaultTerminalNodeLimits,\n ...input.limits\n },\n linkHandler: input.linkHandler,\n outputTransform: input.outputTransform,\n resolveTheme: input.resolveTheme ?? defaultResolveTerminalTheme,\n transport: input.transport\n };\n}\n","import type { TerminalTransport } from \"../contracts/index.ts\";\n\nexport interface TerminalAttachmentController {\n attach(afterSeq?: number): Promise<void>;\n detach(): Promise<void>;\n markDetached(): void;\n}\n\nexport function createTerminalAttachmentController(input: {\n clientId: string;\n sessionId: string;\n transport: Pick<TerminalTransport, \"attach\" | \"detach\">;\n}): TerminalAttachmentController {\n let attached = false;\n let attachPromise: Promise<void> | null = null;\n let detachIssued = false;\n let detachPromise: Promise<void> | null = null;\n let detachRequested = false;\n\n const issueDetach = async () => {\n if (detachIssued || !attached) {\n return;\n }\n detachIssued = true;\n attached = false;\n await input.transport.detach({\n clientId: input.clientId,\n sessionId: input.sessionId\n });\n };\n\n return {\n attach(afterSeq) {\n if (attachPromise) {\n return attachPromise;\n }\n if (attached) {\n return Promise.resolve();\n }\n\n attachPromise = input.transport\n .attach({\n afterSeq,\n clientId: input.clientId,\n sessionId: input.sessionId\n })\n .then(async () => {\n attached = true;\n attachPromise = null;\n if (detachRequested) {\n await issueDetach();\n }\n })\n .catch((error: unknown) => {\n attachPromise = null;\n throw error;\n });\n\n return attachPromise;\n },\n async detach() {\n detachRequested = true;\n if (detachPromise) {\n return detachPromise;\n }\n detachPromise = Promise.resolve(attachPromise)\n .catch(() => undefined)\n .then(async () => {\n await issueDetach();\n })\n .finally(() => {\n attachPromise = null;\n detachIssued = false;\n detachPromise = null;\n detachRequested = false;\n });\n return detachPromise;\n },\n markDetached() {\n attached = false;\n attachPromise = null;\n detachIssued = false;\n detachPromise = null;\n detachRequested = false;\n }\n };\n}\n","import type {\n TerminalTransport,\n TerminalWriteEncoding\n} from \"../contracts/index.ts\";\n\nexport interface QueuedTerminalInput {\n data: string;\n encoding: TerminalWriteEncoding;\n}\n\nexport interface BufferedTerminalInputQueue {\n enqueue(data: string, encoding?: TerminalWriteEncoding): void;\n flush(writer: (entry: QueuedTerminalInput) => Promise<void>): Promise<void>;\n reset(): void;\n}\n\nexport function createBufferedTerminalInputQueue(): BufferedTerminalInputQueue {\n const entries: QueuedTerminalInput[] = [];\n\n return {\n enqueue(data, encoding = \"utf8\") {\n if (data.length === 0) {\n return;\n }\n entries.push({ data, encoding });\n },\n async flush(writer) {\n const queued = entries.splice(0);\n for (const entry of queued) {\n await writer(entry);\n }\n },\n reset() {\n entries.length = 0;\n }\n };\n}\n\nexport async function writeQueuedTerminalInput(input: {\n queue: BufferedTerminalInputQueue;\n sessionId: string;\n transport: Pick<TerminalTransport, \"write\">;\n}): Promise<void> {\n await input.queue.flush((entry) =>\n input.transport.write({\n data: entry.data,\n encoding: entry.encoding,\n provenance: \"user\",\n sessionId: input.sessionId\n })\n );\n}\n","import type { TerminalLinkTarget } from \"../contracts/index.ts\";\n\nexport interface DetectedTerminalFileLink {\n column?: number;\n index: number;\n line?: number;\n path: string;\n text: string;\n}\n\nconst pathCandidatePattern =\n /(?<path>(?:~|\\.{1,2}|\\/)[^\\s\"'`<>|:([\\]]+|[A-Za-z0-9_.-]+\\/[^\\s\"'`<>|:([\\]]+)(?<suffix>(?::(?<lineColon>\\d+)(?::(?<columnColon>\\d+))?)|(?:\\((?<lineParen>\\d+)(?:,\\s*(?<columnParen>\\d+))?\\))|(?:\\[(?<lineBracket>\\d+)(?:,\\s*(?<columnBracket>\\d+))?\\]))?/g;\n\nexport function detectTerminalFileLinks(\n text: string\n): DetectedTerminalFileLink[] {\n const links: DetectedTerminalFileLink[] = [];\n pathCandidatePattern.lastIndex = 0;\n\n let match = pathCandidatePattern.exec(text);\n while (match) {\n const groups = match.groups ?? {};\n const rawPath = groups.path ?? \"\";\n const suffix = groups.suffix ?? \"\";\n const candidateText = `${rawPath}${suffix}`;\n const trimmed = trimTerminalPathCandidate(rawPath);\n const trimAmount = rawPath.length - trimmed.length;\n\n if (isTerminalPathCandidate(trimmed, text, match.index)) {\n const line = parsePositiveInteger(\n groups.lineColon ?? groups.lineParen ?? groups.lineBracket\n );\n const column = parsePositiveInteger(\n groups.columnColon ?? groups.columnParen ?? groups.columnBracket\n );\n links.push({\n column,\n index: match.index,\n line,\n path: trimmed,\n text: candidateText.slice(0, candidateText.length - trimAmount)\n });\n }\n\n match = pathCandidatePattern.exec(text);\n }\n\n return links;\n}\n\nexport function toTerminalLinkTarget(\n link: DetectedTerminalFileLink\n): TerminalLinkTarget {\n return {\n column: link.column,\n line: link.line,\n path: link.path\n };\n}\n\nfunction trimTerminalPathCandidate(value: string): string {\n let result = value.trim();\n while (/[),.;:!?]$/.test(result) && !looksLikeFileExtension(result)) {\n result = result.slice(0, -1);\n }\n return result;\n}\n\nfunction looksLikeFileExtension(value: string): boolean {\n return /\\.[A-Za-z0-9]{1,8}$/.test(value);\n}\n\nfunction isTerminalPathCandidate(\n value: string,\n sourceText: string,\n index: number\n): boolean {\n if (value.length === 0) {\n return false;\n }\n if (/^\\d+(?::\\d+)*$/.test(value)) {\n return false;\n }\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(value)) {\n return false;\n }\n if (value.startsWith(\"//\") || sourceText[index - 1] === \":\") {\n return false;\n }\n if (value.startsWith(\"node:\")) {\n return false;\n }\n return (\n value.startsWith(\"/\") ||\n value.startsWith(\"./\") ||\n value.startsWith(\"../\") ||\n value.startsWith(\"~/\") ||\n value.includes(\"/\")\n );\n}\n\nfunction parsePositiveInteger(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number.parseInt(value, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n}\n","export interface CachedTerminalScreenState {\n cols: number;\n rawSnapshot: string;\n rows: number;\n serialized: string;\n sessionId: string;\n}\n\nexport interface TerminalScreenStateCache {\n clear(): void;\n clearInvalidation(nodeId: string, sessionId: string): void;\n get(nodeId: string, sessionId: string): CachedTerminalScreenState | null;\n invalidate(nodeId: string, sessionId: string): void;\n isInvalidated(nodeId: string, sessionId: string): boolean;\n peek(nodeId: string): CachedTerminalScreenState | null;\n remove(nodeId: string, sessionId: string): void;\n set(nodeId: string, state: CachedTerminalScreenState): void;\n}\n\nexport function createTerminalScreenStateCache(): TerminalScreenStateCache {\n const screenStateByNodeId = new Map<string, CachedTerminalScreenState>();\n const invalidatedSessionIdByNodeId = new Map<string, string>();\n\n const get = (\n nodeId: string,\n sessionId: string\n ): CachedTerminalScreenState | null => {\n const normalizedNodeId = normalizeId(nodeId);\n const normalizedSessionId = normalizeId(sessionId);\n\n if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {\n return null;\n }\n\n if (\n invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId\n ) {\n return null;\n }\n\n const cached = screenStateByNodeId.get(normalizedNodeId);\n if (!cached || cached.sessionId !== normalizedSessionId) {\n return null;\n }\n\n return cached;\n };\n\n const peek = (nodeId: string): CachedTerminalScreenState | null => {\n const normalizedNodeId = normalizeId(nodeId);\n if (normalizedNodeId.length === 0) {\n return null;\n }\n\n return screenStateByNodeId.get(normalizedNodeId) ?? null;\n };\n\n const set = (nodeId: string, state: CachedTerminalScreenState): void => {\n const normalizedNodeId = normalizeId(nodeId);\n const normalizedSessionId = normalizeId(state.sessionId);\n\n if (\n normalizedNodeId.length === 0 ||\n normalizedSessionId.length === 0 ||\n state.serialized.length === 0\n ) {\n return;\n }\n\n if (\n invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId\n ) {\n invalidatedSessionIdByNodeId.delete(normalizedNodeId);\n return;\n }\n\n invalidatedSessionIdByNodeId.delete(normalizedNodeId);\n screenStateByNodeId.set(normalizedNodeId, {\n cols: normalizeDimension(state.cols, 80),\n rawSnapshot: state.rawSnapshot,\n rows: normalizeDimension(state.rows, 24),\n serialized: state.serialized,\n sessionId: normalizedSessionId\n });\n };\n\n const remove = (nodeId: string, sessionId: string): void => {\n const normalizedNodeId = normalizeId(nodeId);\n const normalizedSessionId = normalizeId(sessionId);\n\n if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {\n return;\n }\n\n const cached = screenStateByNodeId.get(normalizedNodeId);\n if (cached?.sessionId === normalizedSessionId) {\n screenStateByNodeId.delete(normalizedNodeId);\n }\n\n if (\n invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId\n ) {\n invalidatedSessionIdByNodeId.delete(normalizedNodeId);\n }\n };\n\n const invalidate = (nodeId: string, sessionId: string): void => {\n const normalizedNodeId = normalizeId(nodeId);\n const normalizedSessionId = normalizeId(sessionId);\n\n if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {\n return;\n }\n\n screenStateByNodeId.delete(normalizedNodeId);\n invalidatedSessionIdByNodeId.set(normalizedNodeId, normalizedSessionId);\n };\n\n const isInvalidated = (nodeId: string, sessionId: string): boolean => {\n const normalizedNodeId = normalizeId(nodeId);\n const normalizedSessionId = normalizeId(sessionId);\n\n if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {\n return false;\n }\n\n return (\n invalidatedSessionIdByNodeId.get(normalizedNodeId) === normalizedSessionId\n );\n };\n\n const clearInvalidation = (nodeId: string, sessionId: string): void => {\n const normalizedNodeId = normalizeId(nodeId);\n const normalizedSessionId = normalizeId(sessionId);\n\n if (normalizedNodeId.length === 0 || normalizedSessionId.length === 0) {\n return;\n }\n\n if (\n invalidatedSessionIdByNodeId.get(normalizedNodeId) !== normalizedSessionId\n ) {\n return;\n }\n\n invalidatedSessionIdByNodeId.delete(normalizedNodeId);\n };\n\n const clear = (): void => {\n screenStateByNodeId.clear();\n invalidatedSessionIdByNodeId.clear();\n };\n\n return {\n clear,\n clearInvalidation,\n get,\n invalidate,\n isInvalidated,\n peek,\n remove,\n set\n };\n}\n\nfunction normalizeId(value: string): string {\n return value.trim();\n}\n\nfunction normalizeDimension(value: number, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0\n ? Math.floor(value)\n : fallback;\n}\n","export function resolveSuffixPrefixOverlap(\n left: string,\n right: string\n): number {\n if (left.length === 0 || right.length === 0) {\n return 0;\n }\n\n const max = Math.min(left.length, right.length);\n const leftTail = left.slice(-max);\n const rightPrefix = right.slice(0, max);\n const combined = `${rightPrefix}\\u0000${leftTail}`;\n const prefix = new Uint32Array(combined.length);\n let cursor = 0;\n\n for (let index = 1; index < combined.length; index += 1) {\n while (cursor > 0 && combined[index] !== combined[cursor]) {\n cursor = prefix[cursor - 1] ?? 0;\n }\n\n if (combined[index] === combined[cursor]) {\n cursor += 1;\n prefix[index] = cursor;\n }\n }\n\n return prefix[combined.length - 1] ?? 0;\n}\n","import { resolveSuffixPrefixOverlap } from \"./stringOverlap.ts\";\n\nexport const defaultMaxTerminalScrollbackChars = 400_000;\n\nexport interface TerminalScrollbackOptions {\n maxChars?: number;\n}\n\nexport function truncateTerminalScrollback(\n snapshot: string,\n options?: TerminalScrollbackOptions\n): string {\n const maxChars = normalizeMaxChars(options?.maxChars);\n if (snapshot.length <= maxChars) {\n return snapshot;\n }\n\n return snapshot.slice(-maxChars);\n}\n\nexport function resolveTerminalScrollbackDelta(\n previous: string,\n next: string,\n options?: TerminalScrollbackOptions\n): string {\n const previousSnapshot = truncateTerminalScrollback(previous, options);\n const nextSnapshot = truncateTerminalScrollback(next, options);\n\n if (previousSnapshot.length === 0) {\n return nextSnapshot;\n }\n\n if (nextSnapshot.length === 0 || previousSnapshot === nextSnapshot) {\n return \"\";\n }\n\n if (previousSnapshot.includes(nextSnapshot)) {\n return \"\";\n }\n\n const overlap = resolveSuffixPrefixOverlap(previousSnapshot, nextSnapshot);\n return nextSnapshot.slice(overlap);\n}\n\nexport function mergeTerminalScrollbackSnapshots(\n persisted: string,\n live: string,\n options?: TerminalScrollbackOptions\n): string {\n const persistedSnapshot = truncateTerminalScrollback(persisted, options);\n const liveSnapshot = truncateTerminalScrollback(live, options);\n\n if (persistedSnapshot.length === 0) {\n return liveSnapshot;\n }\n\n if (liveSnapshot.length === 0) {\n return persistedSnapshot;\n }\n\n if (persistedSnapshot === liveSnapshot) {\n return liveSnapshot;\n }\n\n if (liveSnapshot.includes(persistedSnapshot)) {\n return liveSnapshot;\n }\n\n if (persistedSnapshot.includes(liveSnapshot)) {\n return persistedSnapshot;\n }\n\n const overlap = resolveSuffixPrefixOverlap(persistedSnapshot, liveSnapshot);\n return truncateTerminalScrollback(\n `${persistedSnapshot}${liveSnapshot.slice(overlap)}`,\n options\n );\n}\n\nfunction normalizeMaxChars(value: number | undefined): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0\n ? Math.floor(value)\n : defaultMaxTerminalScrollbackChars;\n}\n"],"mappings":"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","names":[]}
|