[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
139
electron/bridges/emitTerminalSessionData.cjs
Normal file
139
electron/bridges/emitTerminalSessionData.cjs
Normal file
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
|
||||
const { trackEmitted } = require("./terminalFlowAck.cjs");
|
||||
const {
|
||||
attachTerminalOutputPerfMeta,
|
||||
createTerminalOutputPerfMeta,
|
||||
logTerminalOutputPerf,
|
||||
} = require("./terminalPerformanceDiagnostics.cjs");
|
||||
|
||||
let getSession = null;
|
||||
let outputChannel = null;
|
||||
let onSessionActivity = null;
|
||||
/** @type {Set<(sessionId: string, data: string) => void>} */
|
||||
const dataTaps = new Set();
|
||||
const emitPerfLogStateBySession = new Map();
|
||||
const MAX_EMIT_PERF_SESSION_STATES = 512;
|
||||
|
||||
function retainTerminalSessionPerformanceState(key, state) {
|
||||
emitPerfLogStateBySession.delete(key);
|
||||
emitPerfLogStateBySession.set(key, state);
|
||||
while (emitPerfLogStateBySession.size > MAX_EMIT_PERF_SESSION_STATES) {
|
||||
const oldestKey = emitPerfLogStateBySession.keys().next().value;
|
||||
if (oldestKey === undefined) break;
|
||||
emitPerfLogStateBySession.delete(oldestKey);
|
||||
}
|
||||
}
|
||||
|
||||
function clearTerminalSessionPerformanceState(sessionId) {
|
||||
if (!sessionId) return;
|
||||
emitPerfLogStateBySession.delete(sessionId);
|
||||
}
|
||||
|
||||
function configureTerminalSessionDataEmitter(options = {}) {
|
||||
getSession = typeof options.getSession === "function" ? options.getSession : null;
|
||||
outputChannel = options.outputChannel || null;
|
||||
onSessionActivity = typeof options.onSessionActivity === "function"
|
||||
? options.onSessionActivity
|
||||
: null;
|
||||
}
|
||||
|
||||
function addTerminalDataTap(listener) {
|
||||
if (typeof listener !== "function") return () => {};
|
||||
dataTaps.add(listener);
|
||||
return () => dataTaps.delete(listener);
|
||||
}
|
||||
|
||||
function getEmitPerfLogDetails(sessionId, terminalPerf, options = {}) {
|
||||
if (!terminalPerf) return null;
|
||||
const key = sessionId || "__unknown__";
|
||||
const now = Date.now();
|
||||
const state = emitPerfLogStateBySession.get(key) || {
|
||||
lastLoggedAt: 0,
|
||||
batchChunks: 0,
|
||||
batchChars: 0,
|
||||
batchLineFeeds: 0,
|
||||
};
|
||||
|
||||
state.batchChunks += 1;
|
||||
state.batchChars += terminalPerf.chars;
|
||||
state.batchLineFeeds += terminalPerf.lineFeeds;
|
||||
|
||||
const shouldLog =
|
||||
state.lastLoggedAt === 0
|
||||
|| state.batchChars >= 512 * 1024
|
||||
|| state.batchLineFeeds >= 200
|
||||
|| now - state.lastLoggedAt >= 1000;
|
||||
|
||||
if (!shouldLog) {
|
||||
retainTerminalSessionPerformanceState(key, state);
|
||||
return null;
|
||||
}
|
||||
|
||||
const details = {
|
||||
id: terminalPerf.id,
|
||||
sessionId,
|
||||
chars: terminalPerf.chars,
|
||||
lineFeeds: terminalPerf.lineFeeds,
|
||||
batchChunks: state.batchChunks,
|
||||
batchChars: state.batchChars,
|
||||
batchLineFeeds: state.batchLineFeeds,
|
||||
cols: options?.cols,
|
||||
rows: options?.rows,
|
||||
};
|
||||
|
||||
retainTerminalSessionPerformanceState(key, {
|
||||
lastLoggedAt: now,
|
||||
batchChunks: 0,
|
||||
batchChars: 0,
|
||||
batchLineFeeds: 0,
|
||||
});
|
||||
return details;
|
||||
}
|
||||
|
||||
function emitTerminalSessionData(contents, sessionId, data, options = {}) {
|
||||
const currentSession = getSession && sessionId ? getSession(sessionId) : null;
|
||||
if (options.session && currentSession !== options.session) return false;
|
||||
if (sessionId && data && onSessionActivity) {
|
||||
try {
|
||||
onSessionActivity({ sessionId, phase: "touch" });
|
||||
} catch {
|
||||
// Session activity tracking is best-effort and must not break output.
|
||||
}
|
||||
}
|
||||
if (currentSession && sessionId && data) {
|
||||
trackEmitted(currentSession, typeof data === "string" ? data.length : 0, sessionId);
|
||||
}
|
||||
if (sessionId && data) {
|
||||
for (const tap of dataTaps) {
|
||||
try {
|
||||
tap(sessionId, data);
|
||||
} catch (err) {
|
||||
console.warn("[emitTerminalSessionData] tap failed", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
const terminalPerf = createTerminalOutputPerfMeta(sessionId, data);
|
||||
const meta = attachTerminalOutputPerfMeta(options?.meta, terminalPerf);
|
||||
const emitPerfDetails = getEmitPerfLogDetails(sessionId, terminalPerf, options);
|
||||
if (emitPerfDetails) {
|
||||
logTerminalOutputPerf("backend-emit", emitPerfDetails);
|
||||
}
|
||||
if (outputChannel?.send?.(sessionId, data, meta)) return true;
|
||||
const generation = options.session?._terminalSessionGeneration;
|
||||
contents?.send("netcatty:data", {
|
||||
sessionId,
|
||||
data,
|
||||
...(meta ? { meta } : {}),
|
||||
...(Number.isSafeInteger(generation) ? { _terminalSessionGeneration: generation } : {}),
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
configureTerminalSessionDataEmitter,
|
||||
emitTerminalSessionData,
|
||||
addTerminalDataTap,
|
||||
clearTerminalSessionPerformanceState,
|
||||
_getTerminalSessionPerformanceStateCountForTests: () => emitPerfLogStateBySession.size,
|
||||
};
|
||||
Reference in New Issue
Block a user