@simon_he/vue-tui 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -361,7 +361,7 @@ __export(path_suggest_exports, {
361
361
  });
362
362
  function isNodeLike() {
363
363
  var _a2;
364
- const proc = import_node_process3.default;
364
+ const proc = import_node_process4.default;
365
365
  return typeof ((_a2 = proc == null ? void 0 : proc.versions) == null ? void 0 : _a2.node) === "string";
366
366
  }
367
367
  function loadGitignoreRulesAsync(workspaceAbs) {
@@ -559,16 +559,16 @@ async function suggestPaths2(options) {
559
559
  }
560
560
  function resolveUserPath2(workspaceAbs, input) {
561
561
  var _a2;
562
- const env = ((_a2 = import_node_process3.default) == null ? void 0 : _a2.env) ?? {};
562
+ const env = ((_a2 = import_node_process4.default) == null ? void 0 : _a2.env) ?? {};
563
563
  return resolveUserPath(workspaceAbs, input, {
564
564
  homeDir: String(env.HOME || env.USERPROFILE || "")
565
565
  });
566
566
  }
567
- var import_node_process3, DEFAULT_IGNORED_SEGMENTS, EMPTY_GITIGNORE_RULES, gitignoreRulesCache, gitignoreRulesLoading;
567
+ var import_node_process4, DEFAULT_IGNORED_SEGMENTS, EMPTY_GITIGNORE_RULES, gitignoreRulesCache, gitignoreRulesLoading;
568
568
  var init_path_suggest = __esm({
569
569
  "src/cli/path-suggest.ts"() {
570
570
  "use strict";
571
- import_node_process3 = __toESM(require("process"), 1);
571
+ import_node_process4 = __toESM(require("process"), 1);
572
572
  init_path();
573
573
  init_path_suggest_core();
574
574
  init_path_suggest_core();
@@ -638,6 +638,7 @@ __export(src_exports, {
638
638
  defaultTInputHostPlugin: () => defaultTInputHostPlugin,
639
639
  detectTerminalColorCapability: () => detectTerminalColorCapability,
640
640
  formatInlineCellLine: () => formatInlineCellLine,
641
+ getCliLatencyProfiler: () => getCliLatencyProfiler,
641
642
  getStdoutRendererMetrics: () => getStdoutRendererMetrics,
642
643
  lintJsonText: () => lintJsonText,
643
644
  normalizeNewlines: () => normalizeNewlines,
@@ -1017,7 +1018,359 @@ function ansiColors(level) {
1017
1018
  }
1018
1019
 
1019
1020
  // src/cli/input.ts
1020
- var import_node_process2 = __toESM(require("process"), 1);
1021
+ var import_node_process3 = __toESM(require("process"), 1);
1022
+
1023
+ // src/observability/cli-latency.ts
1024
+ var import_node_fs = require("fs");
1025
+ var import_node_process = __toESM(require("process"), 1);
1026
+ var EVENT_OP_ID = Symbol("dimcode.cliLatencyOpId");
1027
+ var DEFAULT_LOG_PATH = "/tmp/dimcode-cli-latency.jsonl";
1028
+ var INVALIDATE_ASSOCIATION_WINDOW_MS = 32;
1029
+ var MAX_OP_AGE_MS = 5e3;
1030
+ var nextOpId = 1;
1031
+ var singleton;
1032
+ function now() {
1033
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
1034
+ }
1035
+ function diffMs(end, start) {
1036
+ if (end == null || start == null)
1037
+ return null;
1038
+ return Math.max(0, end - start);
1039
+ }
1040
+ function parseEnabled(value) {
1041
+ const raw = String(value ?? "").trim().toLowerCase();
1042
+ return raw === "1" || raw === "true" || raw === "yes";
1043
+ }
1044
+ function isTrackedEventType(type) {
1045
+ return type === "keydown" || type === "beforeinput" || type === "input" || type === "paste";
1046
+ }
1047
+ function defineOpId(target, id) {
1048
+ try {
1049
+ Object.defineProperty(target, EVENT_OP_ID, {
1050
+ configurable: true,
1051
+ enumerable: false,
1052
+ writable: true,
1053
+ value: id
1054
+ });
1055
+ } catch {
1056
+ }
1057
+ }
1058
+ function readOpId(target) {
1059
+ const value = target == null ? void 0 : target[EVENT_OP_ID];
1060
+ return typeof value === "number" ? value : null;
1061
+ }
1062
+ function createDisabledProfiler() {
1063
+ return null;
1064
+ }
1065
+ function createProfiler() {
1066
+ var _a2, _b2, _c;
1067
+ const env = ((_a2 = import_node_process.default) == null ? void 0 : _a2.env) ?? {};
1068
+ if (!parseEnabled(env.DIMCODE_PROFILE_INPUT_LATENCY))
1069
+ return createDisabledProfiler();
1070
+ const logPath = String(
1071
+ env.DIMCODE_PROFILE_INPUT_LATENCY_LOG_PATH ?? DEFAULT_LOG_PATH
1072
+ ).trim() || DEFAULT_LOG_PATH;
1073
+ const ops = /* @__PURE__ */ new Map();
1074
+ const pendingCommitIds = /* @__PURE__ */ new Set();
1075
+ const pendingWriteIds = /* @__PURE__ */ new Set();
1076
+ let currentDispatchOpId = null;
1077
+ let lastDispatchOpId = null;
1078
+ let lastDispatchEndedAt = null;
1079
+ let currentFlushIds = [];
1080
+ let lastRawInputAt = null;
1081
+ const emit = (record) => {
1082
+ try {
1083
+ (0, import_node_fs.appendFileSync)(logPath, `${JSON.stringify(record)}
1084
+ `);
1085
+ } catch {
1086
+ }
1087
+ };
1088
+ const cleanupOp = (id) => {
1089
+ ops.delete(id);
1090
+ pendingCommitIds.delete(id);
1091
+ pendingWriteIds.delete(id);
1092
+ if (currentDispatchOpId === id)
1093
+ currentDispatchOpId = null;
1094
+ if (lastDispatchOpId === id) {
1095
+ lastDispatchOpId = null;
1096
+ lastDispatchEndedAt = null;
1097
+ }
1098
+ if (currentFlushIds.includes(id))
1099
+ currentFlushIds = currentFlushIds.filter((value) => value !== id);
1100
+ };
1101
+ const flushOp = (op, outcome) => {
1102
+ const totalStart = op.rawInputAt ?? op.stdinDispatchAt ?? op.dispatchStartAt;
1103
+ emit({
1104
+ ts: op.createdAtIso,
1105
+ id: op.id,
1106
+ event: {
1107
+ type: op.eventType,
1108
+ key: op.key,
1109
+ code: op.code,
1110
+ defaultPrevented: op.defaultPrevented,
1111
+ parser: op.parser
1112
+ },
1113
+ operation: op.operation,
1114
+ stages: {
1115
+ rawInputAt: op.rawInputAt,
1116
+ stdinDispatchAt: op.stdinDispatchAt,
1117
+ dispatchStartAt: op.dispatchStartAt,
1118
+ dispatchEndAt: op.dispatchEndAt,
1119
+ invalidateAt: op.invalidateAt,
1120
+ flushStartAt: op.flushStartAt,
1121
+ flushEndAt: op.flushEndAt,
1122
+ commitAt: op.commitAt,
1123
+ stdoutRenderStartAt: op.stdoutRenderStartAt,
1124
+ writeStartAt: op.writeStartAt,
1125
+ writeEndAt: op.writeEndAt
1126
+ },
1127
+ timingsMs: {
1128
+ inputParseWait: diffMs(op.stdinDispatchAt, op.rawInputAt),
1129
+ eventDispatch: diffMs(op.dispatchEndAt, op.dispatchStartAt),
1130
+ dispatchToInvalidate: diffMs(op.invalidateAt, op.dispatchEndAt),
1131
+ dispatchToFlush: diffMs(op.flushStartAt, op.dispatchEndAt),
1132
+ flushToCommitDone: diffMs(op.flushEndAt, op.flushStartAt),
1133
+ commitToRender: diffMs(op.stdoutRenderStartAt, op.commitAt),
1134
+ renderToWriteStart: diffMs(op.writeStartAt, op.stdoutRenderStartAt),
1135
+ write: op.writeDurationMs,
1136
+ totalToWrite: diffMs(op.writeEndAt, totalStart)
1137
+ },
1138
+ scheduler: {
1139
+ invalidatePriority: op.invalidatePriority,
1140
+ invalidatePlane: op.invalidatePlane,
1141
+ commitSync: op.commitSync,
1142
+ commitPlaneCount: op.commitPlaneCount,
1143
+ commitDirtyRows: op.commitDirtyRows,
1144
+ stdoutQueuedDelayMs: op.stdoutQueuedDelayMs,
1145
+ writeMode: op.writeMode,
1146
+ writeBytes: op.writeBytes
1147
+ },
1148
+ outcome
1149
+ });
1150
+ cleanupOp(op.id);
1151
+ };
1152
+ const expireOldOps = () => {
1153
+ const currentTime = now();
1154
+ for (const op of ops.values()) {
1155
+ if (currentTime - op.createdAt < MAX_OP_AGE_MS)
1156
+ continue;
1157
+ flushOp(op, op.writeEndAt != null ? "completed" : "timeout");
1158
+ }
1159
+ };
1160
+ const flushPendingOps = (outcome) => {
1161
+ for (const op of Array.from(ops.values()))
1162
+ flushOp(op, op.writeEndAt != null ? "completed" : outcome);
1163
+ };
1164
+ const ensureOp = (event) => {
1165
+ const type = String((event == null ? void 0 : event.type) ?? "");
1166
+ if (!isTrackedEventType(type))
1167
+ return null;
1168
+ const existingId = readOpId(event);
1169
+ if (existingId != null) {
1170
+ return ops.get(existingId) ?? null;
1171
+ }
1172
+ const id = nextOpId++;
1173
+ const op = {
1174
+ id,
1175
+ createdAt: now(),
1176
+ createdAtIso: (/* @__PURE__ */ new Date()).toISOString(),
1177
+ eventType: type,
1178
+ key: String((event == null ? void 0 : event.key) ?? ""),
1179
+ code: String((event == null ? void 0 : event.code) ?? ""),
1180
+ operation: null,
1181
+ rawInputAt: null,
1182
+ stdinDispatchAt: null,
1183
+ dispatchStartAt: null,
1184
+ dispatchEndAt: null,
1185
+ invalidateAt: null,
1186
+ invalidatePriority: null,
1187
+ invalidatePlane: null,
1188
+ flushStartAt: null,
1189
+ flushEndAt: null,
1190
+ commitAt: null,
1191
+ commitSync: null,
1192
+ commitPlaneCount: null,
1193
+ commitDirtyRows: null,
1194
+ stdoutQueuedDelayMs: null,
1195
+ stdoutRenderStartAt: null,
1196
+ writeStartAt: null,
1197
+ writeEndAt: null,
1198
+ writeDurationMs: null,
1199
+ writeMode: null,
1200
+ writeBytes: null,
1201
+ defaultPrevented: null,
1202
+ parser: null
1203
+ };
1204
+ ops.set(id, op);
1205
+ defineOpId(event, id);
1206
+ expireOldOps();
1207
+ return op;
1208
+ };
1209
+ const forIds = (ids, fn) => {
1210
+ for (const id of ids) {
1211
+ const op = ops.get(id);
1212
+ if (!op)
1213
+ continue;
1214
+ fn(op);
1215
+ }
1216
+ };
1217
+ const resolveActiveOp = () => {
1218
+ if (currentDispatchOpId != null)
1219
+ return ops.get(currentDispatchOpId) ?? null;
1220
+ if (lastDispatchOpId != null && lastDispatchEndedAt != null && now() - lastDispatchEndedAt <= INVALIDATE_ASSOCIATION_WINDOW_MS) {
1221
+ return ops.get(lastDispatchOpId) ?? null;
1222
+ }
1223
+ return null;
1224
+ };
1225
+ (_c = (_b2 = import_node_process.default) == null ? void 0 : _b2.once) == null ? void 0 : _c.call(_b2, "exit", () => {
1226
+ flushPendingOps("process-exit");
1227
+ });
1228
+ return {
1229
+ enabled: true,
1230
+ recordRawInput(_info) {
1231
+ lastRawInputAt = now();
1232
+ expireOldOps();
1233
+ },
1234
+ recordStdinDispatch(event, info) {
1235
+ const op = ensureOp(event);
1236
+ if (!op)
1237
+ return;
1238
+ if (op.rawInputAt == null && lastRawInputAt != null)
1239
+ op.rawInputAt = lastRawInputAt;
1240
+ if (op.stdinDispatchAt == null)
1241
+ op.stdinDispatchAt = now();
1242
+ if (!op.parser && (info == null ? void 0 : info.parser))
1243
+ op.parser = String(info.parser);
1244
+ },
1245
+ recordEventDispatchStart(event) {
1246
+ const op = ensureOp(event);
1247
+ if (!op)
1248
+ return;
1249
+ currentDispatchOpId = op.id;
1250
+ if (op.dispatchStartAt == null)
1251
+ op.dispatchStartAt = now();
1252
+ },
1253
+ recordEventDispatchEnd(event, info) {
1254
+ const op = ensureOp(event);
1255
+ if (!op)
1256
+ return;
1257
+ op.defaultPrevented = Boolean(info.defaultPrevented);
1258
+ if (op.dispatchEndAt == null)
1259
+ op.dispatchEndAt = now();
1260
+ currentDispatchOpId = currentDispatchOpId === op.id ? null : currentDispatchOpId;
1261
+ lastDispatchOpId = op.id;
1262
+ lastDispatchEndedAt = op.dispatchEndAt;
1263
+ },
1264
+ recordSchedulerInvalidate(info) {
1265
+ const op = resolveActiveOp();
1266
+ if (!op)
1267
+ return;
1268
+ if (op.invalidateAt == null)
1269
+ op.invalidateAt = now();
1270
+ if (!op.invalidatePriority && (info == null ? void 0 : info.priority))
1271
+ op.invalidatePriority = String(info.priority);
1272
+ if (!op.invalidatePlane && (info == null ? void 0 : info.plane))
1273
+ op.invalidatePlane = String(info.plane);
1274
+ pendingCommitIds.add(op.id);
1275
+ },
1276
+ recordFlushStart(info) {
1277
+ currentFlushIds = Array.from(pendingCommitIds);
1278
+ if (!currentFlushIds.length)
1279
+ return;
1280
+ const flushTime = now();
1281
+ forIds(currentFlushIds, (op) => {
1282
+ if (op.flushStartAt == null)
1283
+ op.flushStartAt = flushTime;
1284
+ if (op.commitSync == null && (info == null ? void 0 : info.sync) != null)
1285
+ op.commitSync = Boolean(info.sync);
1286
+ if (op.commitPlaneCount == null && Array.isArray(info == null ? void 0 : info.activePlanes)) {
1287
+ op.commitPlaneCount = info.activePlanes.length;
1288
+ }
1289
+ });
1290
+ },
1291
+ recordFlushEnd() {
1292
+ if (!currentFlushIds.length)
1293
+ return;
1294
+ const flushTime = now();
1295
+ forIds(currentFlushIds, (op) => {
1296
+ if (op.flushEndAt == null)
1297
+ op.flushEndAt = flushTime;
1298
+ });
1299
+ currentFlushIds = [];
1300
+ },
1301
+ recordCommit(info) {
1302
+ if (!pendingCommitIds.size)
1303
+ return;
1304
+ const commitTime = now();
1305
+ const ids = Array.from(pendingCommitIds);
1306
+ pendingCommitIds.clear();
1307
+ forIds(ids, (op) => {
1308
+ if (op.flushEndAt == null && op.flushStartAt != null)
1309
+ op.flushEndAt = commitTime;
1310
+ if (op.commitAt == null)
1311
+ op.commitAt = commitTime;
1312
+ op.commitSync = (info == null ? void 0 : info.sync) == null ? op.commitSync : Boolean(info.sync);
1313
+ op.commitPlaneCount = Array.isArray(info == null ? void 0 : info.planes) ? info.planes.length : op.commitPlaneCount;
1314
+ op.commitDirtyRows = Array.isArray(info == null ? void 0 : info.dirtyRows) ? info.dirtyRows.length : (info == null ? void 0 : info.dirtyRows) === null ? null : op.commitDirtyRows;
1315
+ pendingWriteIds.add(op.id);
1316
+ });
1317
+ },
1318
+ recordStdoutQueued(delayMs) {
1319
+ if (!pendingWriteIds.size)
1320
+ return;
1321
+ forIds(pendingWriteIds, (op) => {
1322
+ if (op.stdoutQueuedDelayMs == null)
1323
+ op.stdoutQueuedDelayMs = Math.max(0, delayMs);
1324
+ });
1325
+ },
1326
+ recordStdoutRenderStart() {
1327
+ if (!pendingWriteIds.size)
1328
+ return;
1329
+ const renderTime = now();
1330
+ forIds(pendingWriteIds, (op) => {
1331
+ if (op.stdoutRenderStartAt == null)
1332
+ op.stdoutRenderStartAt = renderTime;
1333
+ });
1334
+ },
1335
+ recordStdoutNoOutput() {
1336
+ if (!pendingWriteIds.size)
1337
+ return;
1338
+ const ids = Array.from(pendingWriteIds);
1339
+ pendingWriteIds.clear();
1340
+ forIds(ids, (op) => flushOp(op, "no-output"));
1341
+ },
1342
+ recordStdoutWrite(info) {
1343
+ if (!pendingWriteIds.size)
1344
+ return;
1345
+ const writeEndTime = now();
1346
+ const ids = Array.from(pendingWriteIds);
1347
+ pendingWriteIds.clear();
1348
+ forIds(ids, (op) => {
1349
+ op.writeEndAt = writeEndTime;
1350
+ op.writeDurationMs = Math.max(0, info.durationMs);
1351
+ op.writeStartAt = writeEndTime - op.writeDurationMs;
1352
+ op.writeMode = String(info.mode ?? "");
1353
+ op.writeBytes = Math.max(0, Math.floor(info.bytes));
1354
+ flushOp(op, "completed");
1355
+ });
1356
+ },
1357
+ markOperation(operation) {
1358
+ const nextOperation = String(operation ?? "").trim();
1359
+ if (!nextOperation)
1360
+ return;
1361
+ const op = resolveActiveOp();
1362
+ if (!op)
1363
+ return;
1364
+ op.operation = nextOperation;
1365
+ }
1366
+ };
1367
+ }
1368
+ function getCliLatencyProfiler() {
1369
+ if (singleton !== void 0)
1370
+ return singleton;
1371
+ singleton = createProfiler();
1372
+ return singleton;
1373
+ }
1021
1374
 
1022
1375
  // src/utils/newlines.ts
1023
1376
  function normalizeNewlines(text) {
@@ -1474,13 +1827,13 @@ function parseLegacySequence(sequence) {
1474
1827
  }
1475
1828
 
1476
1829
  // src/cli/parse-mouse.ts
1477
- var import_node_fs = require("fs");
1478
- var import_node_process = __toESM(require("process"), 1);
1830
+ var import_node_fs2 = require("fs");
1831
+ var import_node_process2 = __toESM(require("process"), 1);
1479
1832
  function parseMouseSgr(sequence) {
1480
1833
  var _a2;
1481
1834
  if (!sequence.startsWith("\x1B[<"))
1482
1835
  return { handled: false, event: null };
1483
- const env = ((_a2 = import_node_process.default) == null ? void 0 : _a2.env) ?? {};
1836
+ const env = ((_a2 = import_node_process2.default) == null ? void 0 : _a2.env) ?? {};
1484
1837
  const invertWheel = String(env.DIMCODE_WHEEL_INVERT ?? env.VUE_TUI_WHEEL_INVERT ?? "") === "1";
1485
1838
  const mouseDebugEnabled = String(env.DIMCODE_MOUSE_DEBUG ?? env.VUE_TUI_MOUSE_DEBUG ?? "") === "1";
1486
1839
  const mouseDebugPath = String(
@@ -1490,7 +1843,7 @@ function parseMouseSgr(sequence) {
1490
1843
  if (!mouseDebugEnabled)
1491
1844
  return;
1492
1845
  try {
1493
- (0, import_node_fs.appendFileSync)(mouseDebugPath, `${msg}
1846
+ (0, import_node_fs2.appendFileSync)(mouseDebugPath, `${msg}
1494
1847
  `);
1495
1848
  } catch {
1496
1849
  }
@@ -1619,6 +1972,7 @@ var import_node_events = require("events");
1619
1972
  var ESC3 = "\x1B";
1620
1973
  var BRACKETED_PASTE_START = "\x1B[200~";
1621
1974
  var BRACKETED_PASTE_END = "\x1B[201~";
1975
+ var ESC_CONTINUATION_RESCUE_WINDOW_MS = 64;
1622
1976
  function looksLikeQuotedPathPaste(value) {
1623
1977
  if (!value)
1624
1978
  return false;
@@ -1741,11 +2095,19 @@ function extractCompleteSequences(buffer) {
1741
2095
  }
1742
2096
  return { sequences, remainder: "" };
1743
2097
  }
2098
+ function looksLikeSplitEscapeContinuation(value) {
2099
+ const first = value[0];
2100
+ if (first !== "[" && first !== "]" && first !== "P" && first !== "_" && first !== "O") {
2101
+ return false;
2102
+ }
2103
+ return isCompleteSequence(`${ESC3}${value}`) !== "not-escape";
2104
+ }
1744
2105
  var StdinBuffer = class extends import_node_events.EventEmitter {
1745
2106
  buffer = "";
1746
2107
  timeout = null;
1747
2108
  timeoutMs;
1748
2109
  escTimeoutMs;
2110
+ pendingEscContinuationAt = null;
1749
2111
  pasteMode = false;
1750
2112
  pasteBuffer = "";
1751
2113
  constructor(options = {}) {
@@ -1769,6 +2131,12 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
1769
2131
  } else {
1770
2132
  str = data;
1771
2133
  }
2134
+ if (this.pendingEscContinuationAt != null) {
2135
+ const canRescue = Date.now() - this.pendingEscContinuationAt <= ESC_CONTINUATION_RESCUE_WINDOW_MS;
2136
+ this.pendingEscContinuationAt = null;
2137
+ if (canRescue && looksLikeSplitEscapeContinuation(str))
2138
+ str = `${ESC3}${str}`;
2139
+ }
1772
2140
  if (str.length === 0 && this.buffer.length === 0) {
1773
2141
  this.emit("data", "");
1774
2142
  return;
@@ -1830,7 +2198,10 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
1830
2198
  if (this.buffer.length > 0) {
1831
2199
  const timeoutMs = this.buffer === ESC3 ? this.escTimeoutMs : this.timeoutMs;
1832
2200
  this.timeout = setTimeout(() => {
2201
+ const rescuableLoneEsc = this.buffer === ESC3;
1833
2202
  const flushed = this.flush();
2203
+ if (rescuableLoneEsc && flushed.length === 1 && flushed[0] === ESC3)
2204
+ this.pendingEscContinuationAt = Date.now();
1834
2205
  for (const sequence of flushed)
1835
2206
  this.emit("data", sequence);
1836
2207
  }, timeoutMs);
@@ -1853,6 +2224,7 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
1853
2224
  this.timeout = null;
1854
2225
  }
1855
2226
  this.buffer = "";
2227
+ this.pendingEscContinuationAt = null;
1856
2228
  this.pasteMode = false;
1857
2229
  this.pasteBuffer = "";
1858
2230
  }
@@ -1865,6 +2237,10 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
1865
2237
  };
1866
2238
 
1867
2239
  // src/cli/input.ts
2240
+ var KITTY_KEYBOARD_PROTOCOL_ENABLE = "\x1B[>1u";
2241
+ var KITTY_KEYBOARD_PROTOCOL_DISABLE = "\x1B[<u";
2242
+ var XTERM_MODIFY_OTHER_KEYS_ENABLE = "\x1B[>4;2m";
2243
+ var XTERM_MODIFY_OTHER_KEYS_DISABLE = "\x1B[>4n";
1868
2244
  function isPrintable(ch) {
1869
2245
  if (ch.length === 0)
1870
2246
  return false;
@@ -1888,13 +2264,64 @@ function ctrlKeyFromChar(ch) {
1888
2264
  return String.fromCharCode(code + 96);
1889
2265
  return null;
1890
2266
  }
2267
+ function isUnhandledCtrlC(event) {
2268
+ return event.type === "keydown" && (event.key === "c" || event.key === "C") && event.ctrlKey === true && event.metaKey !== true && event.altKey !== true && event.shiftKey !== true;
2269
+ }
2270
+ function parseKeyboardProtocol(value) {
2271
+ const normalized = String(value ?? "").trim().toLowerCase();
2272
+ if (normalized === "auto" || normalized === "kitty" || normalized === "xterm" || normalized === "off") {
2273
+ return normalized;
2274
+ }
2275
+ return null;
2276
+ }
2277
+ function detectKeyboardProtocol(env) {
2278
+ const termProgram = String(env.TERM_PROGRAM ?? "").trim().toLowerCase();
2279
+ const term = String(env.TERM ?? "").trim().toLowerCase();
2280
+ const hasKittyProtocolTerminal = "GHOSTTY_RESOURCES_DIR" in env || "WEZTERM_PANE" in env || "KITTY_WINDOW_ID" in env || "KITTY_INSTALLATION_DIR" in env || "ALACRITTY_WINDOW_ID" in env || "ALACRITTY_LOG" in env || termProgram.includes("ghostty") || termProgram.includes("wezterm") || termProgram.includes("kitty") || termProgram.includes("alacritty");
2281
+ if (hasKittyProtocolTerminal)
2282
+ return "kitty";
2283
+ const isScreenLike = "TMUX" in env || term.includes("screen") || term.includes("tmux");
2284
+ const hasXtermKeyboardTerminal = termProgram.includes("iterm") || termProgram.includes("apple_terminal") || termProgram.includes("vscode") || term.includes("xterm") && !isScreenLike;
2285
+ return hasXtermKeyboardTerminal ? "xterm" : "off";
2286
+ }
2287
+ function resolveKeyboardProtocol(options) {
2288
+ var _a2;
2289
+ const configured = parseKeyboardProtocol(options.keyboardProtocol) ?? "auto";
2290
+ if (configured !== "auto")
2291
+ return configured;
2292
+ const envOverride = parseKeyboardProtocol((_a2 = options.env) == null ? void 0 : _a2.DIMCODE_KEYBOARD_PROTOCOL);
2293
+ if (envOverride && envOverride !== "auto")
2294
+ return envOverride;
2295
+ return detectKeyboardProtocol(options.env ?? {});
2296
+ }
2297
+ function getKeyboardProtocolSequences(protocol) {
2298
+ if (protocol === "kitty") {
2299
+ return {
2300
+ enable: KITTY_KEYBOARD_PROTOCOL_ENABLE,
2301
+ disable: KITTY_KEYBOARD_PROTOCOL_DISABLE
2302
+ };
2303
+ }
2304
+ if (protocol === "xterm") {
2305
+ return {
2306
+ enable: XTERM_MODIFY_OTHER_KEYS_ENABLE,
2307
+ disable: XTERM_MODIFY_OTHER_KEYS_DISABLE
2308
+ };
2309
+ }
2310
+ return null;
2311
+ }
1891
2312
  function createStdinDriver(options) {
1892
- const stdin = options.stdin ?? import_node_process2.default.stdin;
1893
- const stdout = options.stdout ?? import_node_process2.default.stdout;
2313
+ const stdin = options.stdin ?? import_node_process3.default.stdin;
2314
+ const stdout = options.stdout ?? import_node_process3.default.stdout;
1894
2315
  if (!stdin || !stdout)
1895
2316
  throw new Error("createStdinDriver requires Node process.stdin/stdout");
2317
+ const env = options.env ?? import_node_process3.default.env ?? {};
1896
2318
  const enableMouse = options.enableMouse ?? true;
1897
2319
  const enableMouseMotion = options.enableMouseMotion ?? false;
2320
+ const keyboardProtocol = resolveKeyboardProtocol({
2321
+ keyboardProtocol: options.keyboardProtocol,
2322
+ env
2323
+ });
2324
+ const keyboardProtocolSequences = getKeyboardProtocolSequences(keyboardProtocol);
1898
2325
  let disposed = false;
1899
2326
  let swallowNextLF = false;
1900
2327
  let lastMouseDown = null;
@@ -1903,61 +2330,69 @@ function createStdinDriver(options) {
1903
2330
  timeout: 50,
1904
2331
  // When mouse tracking is enabled, CSI mouse reports are frequent and we really want to avoid
1905
2332
  // leaking "[<...;...;...M" into focused inputs if the leading ESC gets chunk-split.
1906
- // Keep this low to reduce perceived latency for plain Esc while still covering split CSI.
1907
- escTimeout: enableMouse ? 80 : 20
2333
+ // Keep this well below one frame so plain Esc remains responsive while the
2334
+ // stdin buffer rescue path still covers delayed CSI continuations.
2335
+ escTimeout: enableMouse ? 8 : 6
1908
2336
  });
1909
- const handlePlainChar = (ch) => {
2337
+ const latency = getCliLatencyProfiler();
2338
+ const dispatchEvent = (event, parser) => {
1910
2339
  var _a2;
2340
+ latency == null ? void 0 : latency.recordStdinDispatch(event, { parser });
2341
+ const prevented = Boolean(options.dispatch(event));
2342
+ if (isUnhandledCtrlC(event) && !prevented)
2343
+ (_a2 = options.onExit) == null ? void 0 : _a2.call(options);
2344
+ return prevented;
2345
+ };
2346
+ const handlePlainChar = (ch) => {
1911
2347
  if (swallowNextLF) {
1912
2348
  swallowNextLF = false;
1913
2349
  if (ch === "\n")
1914
2350
  return;
1915
2351
  }
1916
2352
  if (ch === "") {
1917
- const prevented = Boolean(
1918
- options.dispatch(keyEvent("c", "", { ctrlKey: true }))
1919
- );
1920
- if (!prevented)
1921
- (_a2 = options.onExit) == null ? void 0 : _a2.call(options);
2353
+ dispatchEvent(keyEvent("c", "", { ctrlKey: true }), "plain");
1922
2354
  return;
1923
2355
  }
1924
2356
  if (ch === "\r") {
1925
2357
  swallowNextLF = true;
1926
- options.dispatch(keyEvent("Enter", "Enter"));
2358
+ dispatchEvent(keyEvent("Enter", "Enter"), "plain");
1927
2359
  return;
1928
2360
  }
1929
2361
  if (ch === "\n") {
1930
- options.dispatch({
1931
- type: "input",
1932
- data: "\n",
1933
- inputType: "insertLineBreak",
1934
- text: "\n"
1935
- });
2362
+ dispatchEvent(
2363
+ {
2364
+ type: "input",
2365
+ data: "\n",
2366
+ inputType: "insertLineBreak",
2367
+ text: "\n"
2368
+ },
2369
+ "plain"
2370
+ );
1936
2371
  return;
1937
2372
  }
1938
2373
  const ctrlKey = ctrlKeyFromChar(ch);
1939
2374
  if (ctrlKey) {
1940
2375
  if (ctrlKey === "i") {
1941
- options.dispatch(keyEvent("Tab", "Tab"));
2376
+ dispatchEvent(keyEvent("Tab", "Tab"), "plain");
1942
2377
  return;
1943
2378
  }
1944
2379
  if (ctrlKey === "h") {
1945
- options.dispatch(keyEvent("Backspace", "Backspace"));
2380
+ dispatchEvent(keyEvent("Backspace", "Backspace"), "plain");
1946
2381
  return;
1947
2382
  }
1948
- options.dispatch(keyEvent(ctrlKey, "", { ctrlKey: true }));
2383
+ dispatchEvent(keyEvent(ctrlKey, "", { ctrlKey: true }), "plain");
1949
2384
  return;
1950
2385
  }
1951
2386
  if (ch === "\x7F") {
1952
- options.dispatch(keyEvent("Backspace", "Backspace"));
2387
+ dispatchEvent(keyEvent("Backspace", "Backspace"), "plain");
1953
2388
  return;
1954
2389
  }
1955
2390
  if (ch === " ") {
1956
- options.dispatch(keyEvent("Tab", "Tab"));
2391
+ dispatchEvent(keyEvent("Tab", "Tab"), "plain");
1957
2392
  return;
1958
2393
  }
1959
2394
  if (isPrintable(ch))
1960
- options.dispatch(keyEvent(ch));
2395
+ dispatchEvent(keyEvent(ch), "plain");
1961
2396
  };
1962
2397
  const handleMouseEvent = (event) => {
1963
2398
  const ev = event;
@@ -2039,22 +2474,22 @@ function createStdinDriver(options) {
2039
2474
  const kitty = parseKittySequence(sequence);
2040
2475
  if (kitty.handled) {
2041
2476
  if (kitty.event)
2042
- options.dispatch(kitty.event);
2477
+ dispatchEvent(kitty.event, "kitty");
2043
2478
  return;
2044
2479
  }
2045
2480
  const legacy = parseLegacySequence(sequence);
2046
2481
  if (legacy.handled) {
2047
2482
  if (legacy.event)
2048
- options.dispatch(legacy.event);
2483
+ dispatchEvent(legacy.event, "legacy");
2049
2484
  return;
2050
2485
  }
2051
2486
  if (sequence.startsWith("\x1B")) {
2052
2487
  if (sequence.length === 2 && isPrintable(sequence[1])) {
2053
- options.dispatch(keyEvent(sequence[1], "", { altKey: true }));
2488
+ dispatchEvent(keyEvent(sequence[1], "", { altKey: true }), "alt");
2054
2489
  return;
2055
2490
  }
2056
2491
  if (sequence === "\x1B") {
2057
- options.dispatch(keyEvent("Escape", "Escape"));
2492
+ dispatchEvent(keyEvent("Escape", "Escape"), "escape");
2058
2493
  return;
2059
2494
  }
2060
2495
  return;
@@ -2066,7 +2501,7 @@ function createStdinDriver(options) {
2066
2501
  stdinBuffer.on("paste", (data) => {
2067
2502
  const pastedText = normalizeNewlines(data);
2068
2503
  if (pastedText)
2069
- options.dispatch({ type: "paste", text: pastedText });
2504
+ dispatchEvent({ type: "paste", text: pastedText }, "paste");
2070
2505
  });
2071
2506
  const decodeBytes = (bytes) => {
2072
2507
  if (bytes.length === 1 && bytes[0] > 127) {
@@ -2081,6 +2516,7 @@ function createStdinDriver(options) {
2081
2516
  const onData = (chunk) => {
2082
2517
  if (disposed)
2083
2518
  return;
2519
+ latency == null ? void 0 : latency.recordRawInput();
2084
2520
  if (typeof chunk === "string") {
2085
2521
  stdinBuffer.process(chunk);
2086
2522
  return;
@@ -2111,6 +2547,8 @@ function createStdinDriver(options) {
2111
2547
  if (stdout.isTTY) {
2112
2548
  stdout.write("\x1B[?2004h");
2113
2549
  stdout.write("\x1B[?1004h");
2550
+ if (keyboardProtocolSequences)
2551
+ stdout.write(keyboardProtocolSequences.enable);
2114
2552
  if (enableMouse) {
2115
2553
  stdout.write("\x1B[?1007h");
2116
2554
  if (enableMouseMotion)
@@ -2140,6 +2578,8 @@ function createStdinDriver(options) {
2140
2578
  if (stdout.isTTY) {
2141
2579
  stdout.write("\x1B[?2004l");
2142
2580
  stdout.write("\x1B[?1004l");
2581
+ if (keyboardProtocolSequences)
2582
+ stdout.write(keyboardProtocolSequences.disable);
2143
2583
  if (enableMouse) {
2144
2584
  stdout.write("\x1B[?1007l");
2145
2585
  if (enableMouseMotion)
@@ -4111,7 +4551,7 @@ function createTerminal(opts) {
4111
4551
  }
4112
4552
 
4113
4553
  // src/create-terminal-app.ts
4114
- var import_node_process7 = __toESM(require("process"), 1);
4554
+ var import_node_process8 = __toESM(require("process"), 1);
4115
4555
  var import_vue4 = require("vue");
4116
4556
 
4117
4557
  // src/cli/headless-renderer.ts
@@ -4213,8 +4653,8 @@ function createHeadlessRoot() {
4213
4653
  }
4214
4654
 
4215
4655
  // src/events/manager/cli-event-manager.ts
4216
- var import_node_fs2 = require("fs");
4217
- var import_node_process4 = __toESM(require("process"), 1);
4656
+ var import_node_fs3 = require("fs");
4657
+ var import_node_process5 = __toESM(require("process"), 1);
4218
4658
  function contains(rect, x, y) {
4219
4659
  return x >= rect.x && y >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h;
4220
4660
  }
@@ -4227,7 +4667,7 @@ function area(rect) {
4227
4667
  function isVisible(node) {
4228
4668
  return node.visible !== false;
4229
4669
  }
4230
- function now() {
4670
+ function now2() {
4231
4671
  return typeof performance !== "undefined" ? performance.now() : Date.now();
4232
4672
  }
4233
4673
  function rectRowRange(rect) {
@@ -4249,6 +4689,7 @@ function createCliEventManager(options) {
4249
4689
  let hoverPath = [];
4250
4690
  const record = options == null ? void 0 : options.record;
4251
4691
  const onFocusChange = options == null ? void 0 : options.onFocusChange;
4692
+ const latency = getCliLatencyProfiler();
4252
4693
  const MODAL_FOCUS_Z_THRESHOLD = 100;
4253
4694
  const MODAL_ROOT_MIN_AREA = 40;
4254
4695
  function focusLockTarget() {
@@ -4430,7 +4871,7 @@ function createCliEventManager(options) {
4430
4871
  bubbles: true,
4431
4872
  cancelable: true,
4432
4873
  defaultPrevented: false,
4433
- timeStamp: now(),
4874
+ timeStamp: now2(),
4434
4875
  __stopped: false,
4435
4876
  stopPropagation() {
4436
4877
  this.__stopped = true;
@@ -4454,10 +4895,10 @@ function createCliEventManager(options) {
4454
4895
  handler(event);
4455
4896
  } catch (err) {
4456
4897
  try {
4457
- const env = (_a2 = import_node_process4.default) == null ? void 0 : _a2.env;
4898
+ const env = (_a2 = import_node_process5.default) == null ? void 0 : _a2.env;
4458
4899
  if ((env == null ? void 0 : env.DIMCODE_DEBUG) === "1") {
4459
4900
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, -1);
4460
- (0, import_node_fs2.appendFileSync)(
4901
+ (0, import_node_fs3.appendFileSync)(
4461
4902
  "/tmp/goatchain-debug.log",
4462
4903
  `[${timestamp}] [EVENT-MGR] ERROR in handler ${node.id}.${handlerKey}: ${err}
4463
4904
  `
@@ -4691,57 +5132,67 @@ function createCliEventManager(options) {
4691
5132
  },
4692
5133
  dispatch(event) {
4693
5134
  record == null ? void 0 : record(event);
4694
- if (event.type === "keydown" || event.type === "keyup") {
4695
- return dispatchToFocused(event.type, event);
4696
- }
4697
- if (event.type === "pointerdown" || event.type === "pointermove" || event.type === "pointerup" || event.type === "click" || event.type === "dblclick" || event.type === "contextmenu" || event.type === "wheel") {
4698
- if (event.type === "pointerdown") {
4699
- const list = candidatesAt(event.cellX, event.cellY);
4700
- const target = pickTarget(list);
4701
- if (target == null ? void 0 : target.focusable)
4702
- setFocus(target.id);
4703
- capturedId = (target == null ? void 0 : target.id) ?? null;
4704
- updateHover(target, event);
4705
- dispatchPointerEvent("pointerdown", event, target);
4706
- return false;
4707
- }
4708
- if (event.type === "pointermove" && capturedId) {
4709
- const target = nodes.get(capturedId) ?? null;
4710
- if (!target)
4711
- return false;
4712
- updateHover(target, event);
4713
- const path = ancestorsForTarget(target);
4714
- const ev = buildPointerEvent("pointermove", path, event);
4715
- dispatchWithPhases("pointermove", path, target, ev);
4716
- return ev.defaultPrevented;
4717
- }
4718
- if (event.type === "pointermove") {
4719
- const list = candidatesAt(event.cellX, event.cellY);
4720
- const target = pickTarget(list);
4721
- updateHover(target, event);
4722
- dispatchPointerEvent("pointermove", event, target);
4723
- return false;
5135
+ latency == null ? void 0 : latency.recordEventDispatchStart(event);
5136
+ let prevented = false;
5137
+ try {
5138
+ if (event.type === "keydown" || event.type === "keyup") {
5139
+ prevented = dispatchToFocused(event.type, event);
5140
+ return prevented;
4724
5141
  }
4725
- if (event.type === "pointerup" && capturedId) {
4726
- const target = nodes.get(capturedId) ?? null;
4727
- const path = target ? ancestorsForTarget(target) : [];
4728
- const ev = buildPointerEvent("pointerup", path, event);
4729
- dispatchWithPhases("pointerup", path, target, ev);
4730
- capturedId = null;
4731
- return ev.defaultPrevented;
5142
+ if (event.type === "pointerdown" || event.type === "pointermove" || event.type === "pointerup" || event.type === "click" || event.type === "dblclick" || event.type === "contextmenu" || event.type === "wheel") {
5143
+ if (event.type === "pointerdown") {
5144
+ const list = candidatesAt(event.cellX, event.cellY);
5145
+ const target = pickTarget(list);
5146
+ if (target == null ? void 0 : target.focusable)
5147
+ setFocus(target.id);
5148
+ capturedId = (target == null ? void 0 : target.id) ?? null;
5149
+ updateHover(target, event);
5150
+ dispatchPointerEvent("pointerdown", event, target);
5151
+ return prevented;
5152
+ }
5153
+ if (event.type === "pointermove" && capturedId) {
5154
+ const target = nodes.get(capturedId) ?? null;
5155
+ if (!target)
5156
+ return prevented;
5157
+ updateHover(target, event);
5158
+ const path = ancestorsForTarget(target);
5159
+ const ev = buildPointerEvent("pointermove", path, event);
5160
+ dispatchWithPhases("pointermove", path, target, ev);
5161
+ prevented = ev.defaultPrevented;
5162
+ return prevented;
5163
+ }
5164
+ if (event.type === "pointermove") {
5165
+ const list = candidatesAt(event.cellX, event.cellY);
5166
+ const target = pickTarget(list);
5167
+ updateHover(target, event);
5168
+ dispatchPointerEvent("pointermove", event, target);
5169
+ return prevented;
5170
+ }
5171
+ if (event.type === "pointerup" && capturedId) {
5172
+ const target = nodes.get(capturedId) ?? null;
5173
+ const path = target ? ancestorsForTarget(target) : [];
5174
+ const ev = buildPointerEvent("pointerup", path, event);
5175
+ dispatchWithPhases("pointerup", path, target, ev);
5176
+ capturedId = null;
5177
+ prevented = ev.defaultPrevented;
5178
+ return prevented;
5179
+ }
5180
+ if (event.type === "pointerup") {
5181
+ dispatchPointerEvent("pointerup", event);
5182
+ capturedId = null;
5183
+ return prevented;
5184
+ }
5185
+ dispatchPointerEvent(event.type, event);
5186
+ return prevented;
4732
5187
  }
4733
- if (event.type === "pointerup") {
4734
- dispatchPointerEvent("pointerup", event);
4735
- capturedId = null;
4736
- return false;
5188
+ if (event.type === "beforeinput" || event.type === "input" || event.type === "compositionstart" || event.type === "compositionupdate" || event.type === "compositionend" || event.type === "paste") {
5189
+ prevented = dispatchToFocusedText(event.type, event);
5190
+ return prevented;
4737
5191
  }
4738
- dispatchPointerEvent(event.type, event);
4739
- return false;
4740
- }
4741
- if (event.type === "beforeinput" || event.type === "input" || event.type === "compositionstart" || event.type === "compositionupdate" || event.type === "compositionend" || event.type === "paste") {
4742
- return dispatchToFocusedText(event.type, event);
5192
+ return prevented;
5193
+ } finally {
5194
+ latency == null ? void 0 : latency.recordEventDispatchEnd(event, { defaultPrevented: prevented });
4743
5195
  }
4744
- return false;
4745
5196
  },
4746
5197
  debugNodes() {
4747
5198
  return Array.from(nodes.values()).map((n) => ({
@@ -4776,7 +5227,7 @@ function containsRect2(outer, inner) {
4776
5227
  function area2(rect) {
4777
5228
  return Math.max(0, rect.w) * Math.max(0, rect.h);
4778
5229
  }
4779
- function now2() {
5230
+ function now3() {
4780
5231
  return typeof performance !== "undefined" ? performance.now() : Date.now();
4781
5232
  }
4782
5233
  function rectRowRange2(rect) {
@@ -4799,9 +5250,9 @@ function createEventManager(container, metrics2, options) {
4799
5250
  let hoverPath = [];
4800
5251
  let lastPointerMoveEvent = null;
4801
5252
  const rawRecord = options == null ? void 0 : options.record;
4802
- const recordStart = now2();
5253
+ const recordStart = now3();
4803
5254
  const record = rawRecord ? (event) => {
4804
- rawRecord({ ...event, time: now2() - recordStart });
5255
+ rawRecord({ ...event, time: now3() - recordStart });
4805
5256
  } : void 0;
4806
5257
  const onFocusChange = options == null ? void 0 : options.onFocusChange;
4807
5258
  const textInputTarget = (options == null ? void 0 : options.textInputTarget) ?? null;
@@ -5025,7 +5476,7 @@ function createEventManager(container, metrics2, options) {
5025
5476
  bubbles: true,
5026
5477
  cancelable: true,
5027
5478
  defaultPrevented: false,
5028
- timeStamp: now2(),
5479
+ timeStamp: now3(),
5029
5480
  __stopped: false,
5030
5481
  stopPropagation() {
5031
5482
  this.__stopped = true;
@@ -5895,15 +6346,15 @@ function createTraceStore(opts) {
5895
6346
  }
5896
6347
 
5897
6348
  // src/observability/tui-profiler.ts
5898
- var import_node_fs3 = require("fs");
5899
- var import_node_process5 = __toESM(require("process"), 1);
6349
+ var import_node_fs4 = require("fs");
6350
+ var import_node_process6 = __toESM(require("process"), 1);
5900
6351
  function defaultNow() {
5901
6352
  const p = globalThis.performance;
5902
6353
  if (p && typeof p.now === "function")
5903
6354
  return p.now();
5904
6355
  return Date.now();
5905
6356
  }
5906
- function parseEnabled(v) {
6357
+ function parseEnabled2(v) {
5907
6358
  return String(v ?? "").trim() === "1";
5908
6359
  }
5909
6360
  function parseLogFormat(v) {
@@ -5928,8 +6379,8 @@ function formatClockTime(ms) {
5928
6379
  }
5929
6380
  function createTuiProfiler(name) {
5930
6381
  var _a2, _b2;
5931
- const env = (_a2 = import_node_process5.default) == null ? void 0 : _a2.env;
5932
- if (!parseEnabled(env == null ? void 0 : env.DIMCODE_PROFILE_TUI))
6382
+ const env = (_a2 = import_node_process6.default) == null ? void 0 : _a2.env;
6383
+ if (!parseEnabled2(env == null ? void 0 : env.DIMCODE_PROFILE_TUI))
5933
6384
  return null;
5934
6385
  const format = parseLogFormat(env == null ? void 0 : env.DIMCODE_PROFILE_TUI_FORMAT);
5935
6386
  const logDest = parseLogDest(env == null ? void 0 : env.DIMCODE_PROFILE_TUI_LOG_DEST);
@@ -5952,8 +6403,8 @@ function createTuiProfiler(name) {
5952
6403
  const invalidatePlaneCounts = /* @__PURE__ */ new Map();
5953
6404
  const renderPlaneCounts = /* @__PURE__ */ new Map();
5954
6405
  const logEveryMs = Number((env == null ? void 0 : env.DIMCODE_PROFILE_TUI_LOG_EVERY_MS) ?? 1e3);
5955
- const now3 = defaultNow;
5956
- let lastLogAt = now3();
6406
+ const now4 = defaultNow;
6407
+ let lastLogAt = now4();
5957
6408
  function incrementPlaneCount(target, key) {
5958
6409
  const normalized = String(key ?? "all").trim() || "all";
5959
6410
  target.set(normalized, (target.get(normalized) ?? 0) + 1);
@@ -5962,7 +6413,7 @@ function createTuiProfiler(name) {
5962
6413
  const dest = logDest;
5963
6414
  if ((dest === "file" || dest === "both") && logPath) {
5964
6415
  try {
5965
- (0, import_node_fs3.appendFileSync)(logPath, `${line}
6416
+ (0, import_node_fs4.appendFileSync)(logPath, `${line}
5966
6417
  `);
5967
6418
  } catch {
5968
6419
  }
@@ -5972,7 +6423,7 @@ function createTuiProfiler(name) {
5972
6423
  }
5973
6424
  }
5974
6425
  function flushLog() {
5975
- const at = now3();
6426
+ const at = now4();
5976
6427
  const elapsed = at - lastLogAt;
5977
6428
  if (elapsed <= 0)
5978
6429
  return;
@@ -6054,7 +6505,7 @@ function createTuiProfiler(name) {
6054
6505
  );
6055
6506
  (_b2 = timer.unref) == null ? void 0 : _b2.call(timer);
6056
6507
  return {
6057
- now: now3,
6508
+ now: now4,
6058
6509
  recordInvalidate(info) {
6059
6510
  invalidates++;
6060
6511
  incrementPlaneCount(invalidatePlaneCounts, (info == null ? void 0 : info.plane) ?? "all");
@@ -6445,15 +6896,15 @@ var RenderStackKey = Symbol(
6445
6896
  );
6446
6897
 
6447
6898
  // src/core/debug-logger.ts
6448
- var import_node_fs4 = require("fs");
6449
- var import_node_process6 = __toESM(require("process"), 1);
6899
+ var import_node_fs5 = require("fs");
6900
+ var import_node_process7 = __toESM(require("process"), 1);
6450
6901
  var LOG_FILE = "/tmp/goatchain-debug.log";
6451
6902
  var enabled = false;
6452
6903
  function createDebugLogger(enable = false) {
6453
6904
  enabled = enable;
6454
6905
  if (enabled) {
6455
6906
  try {
6456
- (0, import_node_fs4.writeFileSync)(
6907
+ (0, import_node_fs5.writeFileSync)(
6457
6908
  LOG_FILE,
6458
6909
  `=== GoatChain Debug Log Started at ${(/* @__PURE__ */ new Date()).toISOString()} ===
6459
6910
 
@@ -6486,13 +6937,13 @@ function write(data) {
6486
6937
  if (!enabled)
6487
6938
  return;
6488
6939
  try {
6489
- (0, import_node_fs4.appendFileSync)(LOG_FILE, data);
6940
+ (0, import_node_fs5.appendFileSync)(LOG_FILE, data);
6490
6941
  } catch {
6491
6942
  }
6492
6943
  }
6493
6944
  function isDebugEnabled() {
6494
6945
  var _a2;
6495
- const env = (_a2 = import_node_process6.default) == null ? void 0 : _a2.env;
6946
+ const env = (_a2 = import_node_process7.default) == null ? void 0 : _a2.env;
6496
6947
  return (env == null ? void 0 : env.DIMCODE_DEBUG) === "1" || (env == null ? void 0 : env.DEBUG) === "1";
6497
6948
  }
6498
6949
 
@@ -7347,6 +7798,7 @@ function createTerminalApp(options) {
7347
7798
  const trace = createTraceStore({
7348
7799
  enabled: Boolean(globalThis.__VT_DEBUG_TRACE__)
7349
7800
  });
7801
+ const latency = getCliLatencyProfiler();
7350
7802
  const profiler = createTuiProfiler("cli-scheduler");
7351
7803
  const events = createCliEventManager({
7352
7804
  record: (event) => {
@@ -7361,7 +7813,8 @@ function createTerminalApp(options) {
7361
7813
  }
7362
7814
  });
7363
7815
  const render = createRenderManager(terminal);
7364
- const offCommit = terminal.on("commit", ({ dirtyRows, planes }) => {
7816
+ const offCommit = terminal.on("commit", ({ dirtyRows, planes, sync }) => {
7817
+ latency == null ? void 0 : latency.recordCommit({ dirtyRows, planes, sync });
7365
7818
  if (!trace.enabled.value)
7366
7819
  return;
7367
7820
  trace.push({
@@ -7382,8 +7835,7 @@ function createTerminalApp(options) {
7382
7835
  let pendingInvalidateAfterFlush = false;
7383
7836
  let pendingInvalidateAllPlanes = false;
7384
7837
  const pendingInvalidatePlanes = /* @__PURE__ */ new Set();
7385
- const env = ((_a2 = import_node_process7.default) == null ? void 0 : _a2.env) ?? {};
7386
- const isGhostty = "GHOSTTY_RESOURCES_DIR" in env;
7838
+ const env = ((_a2 = import_node_process8.default) == null ? void 0 : _a2.env) ?? {};
7387
7839
  const throttleMs = (() => {
7388
7840
  const raw = env.DIMCODE_TUI_THROTTLE_MS;
7389
7841
  if (!raw)
@@ -7393,9 +7845,9 @@ function createTerminalApp(options) {
7393
7845
  })();
7394
7846
  const frameThrottleMs = (() => {
7395
7847
  var _a3, _b2;
7396
- if (!((_b2 = (_a3 = import_node_process7.default) == null ? void 0 : _a3.stdout) == null ? void 0 : _b2.isTTY))
7848
+ if (!((_b2 = (_a3 = import_node_process8.default) == null ? void 0 : _a3.stdout) == null ? void 0 : _b2.isTTY))
7397
7849
  return 0;
7398
- return isGhostty ? 24 : 16;
7850
+ return 16;
7399
7851
  })();
7400
7852
  function queueInvalidatePlane(plane) {
7401
7853
  if (!plane) {
@@ -7425,11 +7877,16 @@ function createTerminalApp(options) {
7425
7877
  scheduled = false;
7426
7878
  flushing = true;
7427
7879
  const activePlanes = takeActivePlanes();
7428
- render.render({ activePlanes });
7429
- terminal.commit({ planes: activePlanes, sync });
7430
- flushing = false;
7431
- lastFlushAtMs = Date.now();
7432
- scheduledAtMs = 0;
7880
+ latency == null ? void 0 : latency.recordFlushStart({ sync, activePlanes });
7881
+ try {
7882
+ render.render({ activePlanes });
7883
+ terminal.commit({ planes: activePlanes, sync });
7884
+ } finally {
7885
+ latency == null ? void 0 : latency.recordFlushEnd();
7886
+ flushing = false;
7887
+ lastFlushAtMs = Date.now();
7888
+ scheduledAtMs = 0;
7889
+ }
7433
7890
  if (pendingInvalidateAfterFlush) {
7434
7891
  pendingInvalidateAfterFlush = false;
7435
7892
  flush(true);
@@ -7455,9 +7912,9 @@ function createTerminalApp(options) {
7455
7912
  }
7456
7913
  clearScheduledTimer();
7457
7914
  scheduledAtMs = nowMs;
7458
- if (typeof import_node_process7.default.nextTick === "function") {
7915
+ if (typeof import_node_process8.default.nextTick === "function") {
7459
7916
  ;
7460
- import_node_process7.default.nextTick(() => {
7917
+ import_node_process8.default.nextTick(() => {
7461
7918
  flush();
7462
7919
  });
7463
7920
  } else if (typeof globalThis.setImmediate === "function") {
@@ -7483,12 +7940,16 @@ function createTerminalApp(options) {
7483
7940
  function invalidate(options2) {
7484
7941
  if (disposed)
7485
7942
  return;
7943
+ const priority = (options2 == null ? void 0 : options2.priority) ?? "normal";
7944
+ latency == null ? void 0 : latency.recordSchedulerInvalidate({
7945
+ priority,
7946
+ plane: (options2 == null ? void 0 : options2.plane) ?? null
7947
+ });
7486
7948
  if (flushing) {
7487
7949
  queueInvalidatePlane(options2 == null ? void 0 : options2.plane);
7488
7950
  pendingInvalidateAfterFlush = true;
7489
7951
  return;
7490
7952
  }
7491
- const priority = (options2 == null ? void 0 : options2.priority) ?? "normal";
7492
7953
  queueInvalidatePlane(options2 == null ? void 0 : options2.plane);
7493
7954
  profiler == null ? void 0 : profiler.recordInvalidate({ plane: (options2 == null ? void 0 : options2.plane) ?? null });
7494
7955
  if (priority === "high") {
@@ -7695,7 +8156,7 @@ function recordStdoutFrame(info) {
7695
8156
 
7696
8157
  // src/renderer/cli/stdout-renderer.ts
7697
8158
  var import_node_buffer2 = require("buffer");
7698
- var import_node_process8 = __toESM(require("process"), 1);
8159
+ var import_node_process9 = __toESM(require("process"), 1);
7699
8160
  var debugLog = null;
7700
8161
  function getDebugLog() {
7701
8162
  if (!debugLog) {
@@ -7733,7 +8194,7 @@ function parseWriteMode(raw) {
7733
8194
  }
7734
8195
  function createStdoutRenderer(terminal, options) {
7735
8196
  var _a2, _b2, _c, _d;
7736
- const output = (options == null ? void 0 : options.output) ?? import_node_process8.default.stdout;
8197
+ const output = (options == null ? void 0 : options.output) ?? import_node_process9.default.stdout;
7737
8198
  if (!output)
7738
8199
  throw new Error("createStdoutRenderer requires a Node stdout-like output");
7739
8200
  const out = output;
@@ -7744,26 +8205,27 @@ function createStdoutRenderer(terminal, options) {
7744
8205
  let palette = options == null ? void 0 : options.palette;
7745
8206
  const trackResize = (options == null ? void 0 : options.trackResize) ?? true;
7746
8207
  const getImeAnchor = options == null ? void 0 : options.getImeAnchor;
8208
+ const cliLatency = getCliLatencyProfiler();
7747
8209
  const profiler = createTuiProfiler("stdout-renderer");
7748
8210
  function resolveUseSyncOutput() {
7749
8211
  var _a3;
7750
8212
  if ((options == null ? void 0 : options.useSyncOutput) != null)
7751
8213
  return options.useSyncOutput;
7752
- const env2 = ((_a3 = import_node_process8.default) == null ? void 0 : _a3.env) ?? {};
8214
+ const env2 = ((_a3 = import_node_process9.default) == null ? void 0 : _a3.env) ?? {};
7753
8215
  const envValue = env2.DIMCODE_SYNC_OUTPUT;
7754
8216
  if (envValue != null) {
7755
8217
  const v = String(envValue).trim().toLowerCase();
7756
8218
  return v === "1" || v === "true" || v === "yes";
7757
8219
  }
7758
- const term = String(env2.TERM ?? "").toLowerCase();
7759
- const termProgram = String(env2.TERM_PROGRAM ?? "").toLowerCase();
8220
+ const term2 = String(env2.TERM ?? "").toLowerCase();
8221
+ const termProgram2 = String(env2.TERM_PROGRAM ?? "").toLowerCase();
7760
8222
  const termProgramVersion = env2.TERM_PROGRAM_VERSION;
7761
8223
  const isGhostty2 = "GHOSTTY_RESOURCES_DIR" in env2;
7762
- const isProblematicTerminal = isGhostty2 || termProgram.includes("apple_terminal") || term.includes("screen") && !term.includes("tmux");
8224
+ const isProblematicTerminal = isGhostty2 || termProgram2.includes("apple_terminal") || term2.includes("screen") && !term2.includes("tmux");
7763
8225
  if (isProblematicTerminal) {
7764
8226
  return false;
7765
8227
  }
7766
- const isGoodTerminal = termProgram.includes("iterm") && termProgramVersion && compareVersion(String(termProgramVersion), "3.5.0") >= 0;
8228
+ const isGoodTerminal = termProgram2.includes("iterm") && termProgramVersion && compareVersion(String(termProgramVersion), "3.5.0") >= 0;
7767
8229
  if (isGoodTerminal) {
7768
8230
  return true;
7769
8231
  }
@@ -7782,8 +8244,8 @@ function createStdoutRenderer(terminal, options) {
7782
8244
  return 0;
7783
8245
  }
7784
8246
  const useSyncOutput = resolveUseSyncOutput();
7785
- const isGhostty = "GHOSTTY_RESOURCES_DIR" in (((_a2 = import_node_process8.default) == null ? void 0 : _a2.env) ?? {});
7786
- const env = ((_b2 = import_node_process8.default) == null ? void 0 : _b2.env) ?? {};
8247
+ const isGhostty = "GHOSTTY_RESOURCES_DIR" in (((_a2 = import_node_process9.default) == null ? void 0 : _a2.env) ?? {});
8248
+ const env = ((_b2 = import_node_process9.default) == null ? void 0 : _b2.env) ?? {};
7787
8249
  const forcedWriteMode = parseWriteMode(
7788
8250
  env.DIMCODE_TUI_WRITE_MODE ?? env.VUE_TUI_WRITE_MODE
7789
8251
  );
@@ -7810,8 +8272,11 @@ function createStdoutRenderer(terminal, options) {
7810
8272
  return Math.min(1, Math.max(0.05, n));
7811
8273
  return 0.6;
7812
8274
  })();
7813
- const disableCursorPos = isGhostty && ((_d = (_c = import_node_process8.default) == null ? void 0 : _c.env) == null ? void 0 : _d.DIMCODE_DISABLE_CURSOR_POS) === "1";
7814
- const isVscodeTerminal = String(env.TERM_PROGRAM ?? "").trim().toLowerCase() === "vscode" || "VSCODE_PID" in env || "VSCODE_IPC_HOOK_CLI" in env;
8275
+ const disableCursorPos = isGhostty && ((_d = (_c = import_node_process9.default) == null ? void 0 : _c.env) == null ? void 0 : _d.DIMCODE_DISABLE_CURSOR_POS) === "1";
8276
+ const termProgram = String(env.TERM_PROGRAM ?? "").trim().toLowerCase();
8277
+ const term = String(env.TERM ?? "").trim().toLowerCase();
8278
+ const isVscodeTerminal = termProgram === "vscode" || "VSCODE_PID" in env || "VSCODE_IPC_HOOK_CLI" in env;
8279
+ const useConservativeDirtyRowRendering = out.isTTY !== false && !isVscodeTerminal && (isGhostty || "KITTY_WINDOW_ID" in env || "ALACRITTY_WINDOW_ID" in env || "ALACRITTY_LOG" in env || "WEZTERM_PANE" in env || "WEZTERM_EXECUTABLE" in env || termProgram.includes("kitty") || termProgram.includes("alacritty") || termProgram.includes("wezterm") || term.includes("kitty") || term.includes("alacritty"));
7815
8280
  const enableOsc8Links = (() => {
7816
8281
  if (!out.isTTY)
7817
8282
  return false;
@@ -7835,7 +8300,7 @@ function createStdoutRenderer(terminal, options) {
7835
8300
  let accumulatedDirtyMax = -1;
7836
8301
  let accumulatedScrollOperations = null;
7837
8302
  let accumulatedSkipUnchangedDirtyRows = true;
7838
- const MIN_FRAME_MS = !out.isTTY ? 0 : isGhostty ? 24 : 16;
8303
+ const MIN_FRAME_MS = !out.isTTY ? 0 : 16;
7839
8304
  function clampCellToViewport(cell, size) {
7840
8305
  const maxX = Math.max(0, Math.floor(size.cols) - 1);
7841
8306
  const maxY = Math.max(0, Math.floor(size.rows) - 1);
@@ -7850,11 +8315,11 @@ function createStdoutRenderer(terminal, options) {
7850
8315
  const opt = (options == null ? void 0 : options.colorMode) ?? "auto";
7851
8316
  if (opt !== "auto")
7852
8317
  return opt;
7853
- const env2 = ((_a3 = import_node_process8.default) == null ? void 0 : _a3.env) ?? {};
8318
+ const env2 = ((_a3 = import_node_process9.default) == null ? void 0 : _a3.env) ?? {};
7854
8319
  return detectTerminalColorCapability({
7855
8320
  env: env2,
7856
8321
  isTTY: Boolean(out.isTTY),
7857
- platform: String(((_b3 = import_node_process8.default) == null ? void 0 : _b3.platform) ?? "")
8322
+ platform: String(((_b3 = import_node_process9.default) == null ? void 0 : _b3.platform) ?? "")
7858
8323
  }).mode;
7859
8324
  }
7860
8325
  const colorMode = resolveColorMode();
@@ -8344,6 +8809,7 @@ function createStdoutRenderer(terminal, options) {
8344
8809
  }
8345
8810
  if (disposed)
8346
8811
  return;
8812
+ cliLatency == null ? void 0 : cliLatency.recordStdoutRenderStart();
8347
8813
  pendingRender = false;
8348
8814
  accumulatedAllRows = false;
8349
8815
  accumulatedDirtyBits = null;
@@ -8425,6 +8891,9 @@ function createStdoutRenderer(terminal, options) {
8425
8891
  outRows.sort((a, b) => a - b);
8426
8892
  return outRows;
8427
8893
  })();
8894
+ if (fpPrevValid && rowsToRender) {
8895
+ currentFP.set(prevFP);
8896
+ }
8428
8897
  const frameParts = [];
8429
8898
  frameParts.push(!isGhostty && useSyncOutput ? SYNC_START : "");
8430
8899
  frameParts.push("\x1B[?7l");
@@ -8580,6 +9049,14 @@ function createStdoutRenderer(terminal, options) {
8580
9049
  ])
8581
9050
  ).sort((a, b) => a - b);
8582
9051
  const overlayPartialRowSet = overlayPartialRows.length ? new Set(overlayPartialRows) : null;
9052
+ const overlayTouchedRowSet = (() => {
9053
+ if (!overlayRowSet && !overlayPartialRowSet)
9054
+ return null;
9055
+ return /* @__PURE__ */ new Set([
9056
+ ...overlayRowSet ? Array.from(overlayRowSet) : [],
9057
+ ...overlayPartialRowSet ? Array.from(overlayPartialRowSet) : []
9058
+ ]);
9059
+ })();
8583
9060
  let explicitScrollOperations = normalizedScrollOperations;
8584
9061
  let hiddenExplicitDirtyRows = null;
8585
9062
  let allowInferredScrollRegions = true;
@@ -8700,12 +9177,12 @@ function createStdoutRenderer(terminal, options) {
8700
9177
  const explicitDirtyRows = Array.from(explicitRowsToRender).sort(
8701
9178
  (a, b) => a - b
8702
9179
  );
8703
- const overlayDirtyRows = overlayRowSet ? explicitDirtyRows.filter((y) => overlayRowSet.has(y)) : [];
9180
+ const overlayDirtyRows = overlayTouchedRowSet ? explicitDirtyRows.filter((y) => overlayTouchedRowSet.has(y)) : [];
8704
9181
  const paintedExplicitRows = [];
8705
9182
  for (const y of explicitDirtyRows) {
8706
9183
  const row = terminal.getRow(y);
8707
- const overlayRow = overlayRowSet == null ? void 0 : overlayRowSet.has(y);
8708
- if (overlayRow) {
9184
+ const overlayRow = overlayTouchedRowSet == null ? void 0 : overlayTouchedRowSet.has(y);
9185
+ if (overlayRow || useConservativeDirtyRowRendering) {
8709
9186
  fingerprintRow(row, y, size.cols);
8710
9187
  renderRow2(y, row);
8711
9188
  paintedExplicitRows.push(y);
@@ -8808,10 +9285,10 @@ function createStdoutRenderer(terminal, options) {
8808
9285
  ) : shift.extraDirtyRows;
8809
9286
  for (const y of extraDirtyRows) {
8810
9287
  const row = terminal.getRow(y);
8811
- const overlayRow = overlayRowSet == null ? void 0 : overlayRowSet.has(y);
8812
- if (overlayRow) {
8813
- renderRow2(y, row);
9288
+ const overlayRow = overlayTouchedRowSet == null ? void 0 : overlayTouchedRowSet.has(y);
9289
+ if (overlayRow || useConservativeDirtyRowRendering) {
8814
9290
  fingerprintRow(row, y, size.cols);
9291
+ renderRow2(y, row);
8815
9292
  continue;
8816
9293
  }
8817
9294
  const span = resolveChangedSpanAgainstReference(row, y, size.cols);
@@ -8863,7 +9340,7 @@ function createStdoutRenderer(terminal, options) {
8863
9340
  renderRow2(y, row);
8864
9341
  }
8865
9342
  } else {
8866
- const overlayDirtyRows = overlayRowSet ? rowsToRender.filter((y) => overlayRowSet.has(y)) : [];
9343
+ const overlayDirtyRows = overlayTouchedRowSet ? rowsToRender.filter((y) => overlayTouchedRowSet.has(y)) : [];
8867
9344
  if (isDebugEnabled()) {
8868
9345
  getDebugLog().render(
8869
9346
  ` Partial render: ${rowsToRender.length} dirty rows: [${rowsToRender.join(", ")}]${overlayDirtyRows.length ? ` (overlay-full-row: [${overlayDirtyRows.join(", ")}])` : ""}`
@@ -8872,8 +9349,8 @@ function createStdoutRenderer(terminal, options) {
8872
9349
  for (const y of rowsToRender) {
8873
9350
  const row = terminal.getRow(y);
8874
9351
  fingerprintRow(row, y, size.cols);
8875
- const overlayRow = overlayRowSet == null ? void 0 : overlayRowSet.has(y);
8876
- if (overlayRow) {
9352
+ const overlayRow = overlayTouchedRowSet == null ? void 0 : overlayTouchedRowSet.has(y);
9353
+ if (overlayRow || useConservativeDirtyRowRendering) {
8877
9354
  renderRow2(y, row);
8878
9355
  continue;
8879
9356
  }
@@ -8927,6 +9404,7 @@ function createStdoutRenderer(terminal, options) {
8927
9404
  if (!hasFrameOutput) {
8928
9405
  if (isDebugEnabled())
8929
9406
  getDebugLog().render(" No-op frame skipped");
9407
+ cliLatency == null ? void 0 : cliLatency.recordStdoutNoOutput();
8930
9408
  return;
8931
9409
  }
8932
9410
  if (enableOsc8Links && activeStyle.href)
@@ -9087,6 +9565,11 @@ function createStdoutRenderer(terminal, options) {
9087
9565
  mode: writeMode === "sync" ? "sync" : writeMode === "chunked" ? "chunked" : "stream"
9088
9566
  });
9089
9567
  }
9568
+ cliLatency == null ? void 0 : cliLatency.recordStdoutWrite({
9569
+ durationMs: writeMs,
9570
+ bytes: frame.length,
9571
+ mode: writeMode === "sync" ? "sync" : writeMode === "chunked" ? "chunked" : "stream"
9572
+ });
9090
9573
  }
9091
9574
  if (isDebugEnabled()) {
9092
9575
  const totalTime = (performance.now() - renderStart).toFixed(2);
@@ -9206,11 +9689,13 @@ function createStdoutRenderer(terminal, options) {
9206
9689
  mergeScrollOperations(scrollOperations);
9207
9690
  accumulatedSkipUnchangedDirtyRows && (accumulatedSkipUnchangedDirtyRows = skipUnchangedDirtyRows);
9208
9691
  }
9692
+ const now4 = Date.now();
9693
+ const elapsed = now4 - lastFrameTime;
9694
+ const queuedDelayMs = Math.max(0, MIN_FRAME_MS - elapsed);
9209
9695
  if (pendingRender && !sync) {
9696
+ cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(queuedDelayMs);
9210
9697
  return;
9211
9698
  }
9212
- const now3 = Date.now();
9213
- const elapsed = now3 - lastFrameTime;
9214
9699
  if (sync) {
9215
9700
  if (pendingRender) {
9216
9701
  pendingRender = false;
@@ -9221,12 +9706,14 @@ function createStdoutRenderer(terminal, options) {
9221
9706
  }
9222
9707
  const rows = buildAccumulatedRows();
9223
9708
  const pendingScrolls = buildAccumulatedScrollOperations();
9709
+ cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(0);
9224
9710
  doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
9225
9711
  return;
9226
9712
  }
9227
9713
  if (elapsed >= MIN_FRAME_MS) {
9228
9714
  const rows = buildAccumulatedRows();
9229
9715
  const pendingScrolls = buildAccumulatedScrollOperations();
9716
+ cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(0);
9230
9717
  doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
9231
9718
  } else {
9232
9719
  pendingRender = true;
@@ -9239,7 +9726,8 @@ function createStdoutRenderer(terminal, options) {
9239
9726
  const pendingScrolls = buildAccumulatedScrollOperations();
9240
9727
  doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
9241
9728
  }
9242
- }, MIN_FRAME_MS - elapsed);
9729
+ }, queuedDelayMs);
9730
+ cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(queuedDelayMs);
9243
9731
  }
9244
9732
  }
9245
9733
  terminal.setFingerprintFn((ch, style) => {
@@ -9260,7 +9748,7 @@ function createStdoutRenderer(terminal, options) {
9260
9748
  }
9261
9749
  render(dirtyRows, sync, scrollOperations, true);
9262
9750
  });
9263
- const resizeSource = (options == null ? void 0 : options.output) ?? import_node_process8.default.stdout;
9751
+ const resizeSource = (options == null ? void 0 : options.output) ?? import_node_process9.default.stdout;
9264
9752
  const canTrackResize = Boolean(
9265
9753
  trackResize && out.isTTY && typeof (resizeSource == null ? void 0 : resizeSource.on) === "function"
9266
9754
  );
@@ -9528,6 +10016,12 @@ var rowCache = /* @__PURE__ */ new WeakMap();
9528
10016
  function segmentsToKey(segments) {
9529
10017
  return segments.map((s) => `${s.key}:${s.text}:${s.cols}:${s.wide}`).join("|");
9530
10018
  }
10019
+ function isPlainStyle(style) {
10020
+ return !style.fg && !style.bg && !style.bold && !style.dim && !style.italic && !style.underline && !style.inverse && !style.href;
10021
+ }
10022
+ function isTransparentBlankRow(segments) {
10023
+ return segments.length === 1 && isPlainStyle(segments[0].style) && segments[0].text.trim().length === 0;
10024
+ }
9531
10025
  function renderRow(terminal, metrics2, wideScaleX, y, lineEl) {
9532
10026
  const segments = computeRowSegments(terminal, y);
9533
10027
  const newKey = segmentsToKey(segments);
@@ -9535,6 +10029,10 @@ function renderRow(terminal, metrics2, wideScaleX, y, lineEl) {
9535
10029
  if (cachedKey === newKey)
9536
10030
  return;
9537
10031
  rowCache.set(lineEl, newKey);
10032
+ if (isTransparentBlankRow(segments)) {
10033
+ lineEl.replaceChildren();
10034
+ return;
10035
+ }
9538
10036
  const fragment = document.createDocumentFragment();
9539
10037
  for (const seg of segments) {
9540
10038
  const span = document.createElement("span");
@@ -9557,6 +10055,7 @@ function createDomRenderer(terminal, container) {
9557
10055
  container.style.whiteSpace = "pre";
9558
10056
  container.style.display = "inline-block";
9559
10057
  container.style.overflow = "hidden";
10058
+ container.style.position = "relative";
9560
10059
  container.style.userSelect = "text";
9561
10060
  container.style.outline = "none";
9562
10061
  container.style.contain = "layout style";
@@ -9564,21 +10063,105 @@ function createDomRenderer(terminal, container) {
9564
10063
  installAnsiPaletteCssVars(container);
9565
10064
  let metrics2 = measureCell(container);
9566
10065
  let wideScaleX = 1;
9567
- let lineEls = [];
10066
+ const planeLayers = /* @__PURE__ */ new Map();
9568
10067
  let raf = 0;
9569
- const pending = /* @__PURE__ */ new Set();
10068
+ const pending = /* @__PURE__ */ new Map();
9570
10069
  let disposed = false;
10070
+ function applyPlaneOffset(plane, offsetPx) {
10071
+ const layer = planeLayers.get(plane);
10072
+ if (!layer)
10073
+ return;
10074
+ const next = Number.isFinite(offsetPx) ? offsetPx : 0;
10075
+ if (layer.offsetPx === next)
10076
+ return;
10077
+ layer.offsetPx = next;
10078
+ layer.contentEl.style.transform = next ? `translateY(${next}px)` : "translateY(0px)";
10079
+ }
10080
+ function applyPlaneViewport(plane, viewport) {
10081
+ const layer = planeLayers.get(plane);
10082
+ if (!layer)
10083
+ return;
10084
+ const totalHeight = terminal.size().rows * metrics2.cellHeight;
10085
+ if (!viewport) {
10086
+ layer.viewportTopPx = 0;
10087
+ layer.viewportHeightPx = null;
10088
+ layer.el.style.clipPath = "none";
10089
+ return;
10090
+ }
10091
+ const topPx = Math.max(
10092
+ 0,
10093
+ Math.min(totalHeight, Math.floor(viewport.topPx))
10094
+ );
10095
+ const heightPx = Math.max(
10096
+ 0,
10097
+ Math.min(totalHeight - topPx, Math.floor(viewport.heightPx))
10098
+ );
10099
+ layer.viewportTopPx = topPx;
10100
+ layer.viewportHeightPx = heightPx;
10101
+ if (topPx === 0 && heightPx >= totalHeight) {
10102
+ layer.el.style.clipPath = "none";
10103
+ return;
10104
+ }
10105
+ const bottomPx = Math.max(0, totalHeight - topPx - heightPx);
10106
+ layer.el.style.clipPath = `inset(${topPx}px 0px ${bottomPx}px 0px)`;
10107
+ }
9571
10108
  function rebuildLines() {
9572
10109
  const { rows, cols } = terminal.size();
9573
10110
  container.style.width = `${cols * metrics2.cellWidth}px`;
9574
10111
  container.style.height = `${rows * metrics2.cellHeight}px`;
9575
10112
  const fragment = document.createDocumentFragment();
9576
- lineEls = Array.from({ length: rows }, () => {
9577
- const line = document.createElement("div");
9578
- line.style.cssText = `height:${metrics2.cellHeight}px;width:${cols * metrics2.cellWidth}px;overflow:hidden;contain:layout style`;
9579
- fragment.appendChild(line);
9580
- return line;
9581
- });
10113
+ for (let i = 0; i < TERMINAL_RENDER_PLANES.length; i++) {
10114
+ const plane = TERMINAL_RENDER_PLANES[i];
10115
+ const planeTerminal = getPlaneTerminal(terminal, plane);
10116
+ let layer = planeLayers.get(plane);
10117
+ if (!layer) {
10118
+ const el = document.createElement("div");
10119
+ const contentEl = document.createElement("div");
10120
+ el.dataset.vtPlane = plane;
10121
+ el.style.pointerEvents = "none";
10122
+ contentEl.style.position = "absolute";
10123
+ contentEl.style.left = "0";
10124
+ contentEl.style.top = "0";
10125
+ layer = {
10126
+ el,
10127
+ contentEl,
10128
+ lines: [],
10129
+ offsetPx: 0,
10130
+ terminal: planeTerminal,
10131
+ viewportTopPx: 0,
10132
+ viewportHeightPx: null
10133
+ };
10134
+ planeLayers.set(plane, layer);
10135
+ }
10136
+ layer.terminal = planeTerminal;
10137
+ layer.el.style.position = "absolute";
10138
+ layer.el.style.left = "0";
10139
+ layer.el.style.top = "0";
10140
+ layer.el.style.width = `${cols * metrics2.cellWidth}px`;
10141
+ layer.el.style.height = `${rows * metrics2.cellHeight}px`;
10142
+ layer.el.style.overflow = "hidden";
10143
+ layer.el.style.zIndex = String(i);
10144
+ layer.contentEl.style.width = `${cols * metrics2.cellWidth}px`;
10145
+ layer.contentEl.style.height = `${rows * metrics2.cellHeight}px`;
10146
+ applyPlaneOffset(plane, layer.offsetPx);
10147
+ applyPlaneViewport(
10148
+ plane,
10149
+ layer.viewportHeightPx == null ? null : {
10150
+ topPx: layer.viewportTopPx,
10151
+ heightPx: layer.viewportHeightPx
10152
+ }
10153
+ );
10154
+ const lineFragment = document.createDocumentFragment();
10155
+ layer.lines = Array.from({ length: rows }, () => {
10156
+ const line = document.createElement("div");
10157
+ line.style.cssText = `height:${metrics2.cellHeight}px;width:${cols * metrics2.cellWidth}px;overflow:hidden;contain:layout style`;
10158
+ lineFragment.appendChild(line);
10159
+ return line;
10160
+ });
10161
+ layer.contentEl.replaceChildren(lineFragment);
10162
+ layer.el.replaceChildren(layer.contentEl);
10163
+ fragment.appendChild(layer.el);
10164
+ }
9582
10165
  container.replaceChildren(fragment);
9583
10166
  }
9584
10167
  function refresh() {
@@ -9587,28 +10170,54 @@ function createDomRenderer(terminal, container) {
9587
10170
  wideScaleX = wideW > 0 ? Math.max(1, Math.min(2, metrics2.cellWidth * 2 / wideW)) : 1;
9588
10171
  rebuildLines();
9589
10172
  const size = terminal.size();
9590
- for (let y = 0; y < size.rows; y++)
9591
- renderRow(terminal, metrics2, wideScaleX, y, lineEls[y]);
10173
+ for (const plane of TERMINAL_RENDER_PLANES) {
10174
+ const layer = planeLayers.get(plane);
10175
+ if (!layer)
10176
+ continue;
10177
+ for (let y = 0; y < size.rows; y++)
10178
+ renderRow(layer.terminal, metrics2, wideScaleX, y, layer.lines[y]);
10179
+ }
9592
10180
  }
9593
10181
  function flushPending() {
9594
10182
  raf = 0;
9595
10183
  if (disposed)
9596
10184
  return;
9597
- for (const y of pending) {
9598
- const line = lineEls[y];
9599
- if (line)
9600
- renderRow(terminal, metrics2, wideScaleX, y, line);
10185
+ for (const plane of TERMINAL_RENDER_PLANES) {
10186
+ const layer = planeLayers.get(plane);
10187
+ const rows = pending.get(plane);
10188
+ if (!layer || !(rows == null ? void 0 : rows.size))
10189
+ continue;
10190
+ for (const y of rows) {
10191
+ const line = layer.lines[y];
10192
+ if (line)
10193
+ renderRow(layer.terminal, metrics2, wideScaleX, y, line);
10194
+ }
10195
+ rows.clear();
9601
10196
  }
9602
- pending.clear();
9603
10197
  }
9604
- const offCommit = terminal.on("commit", ({ dirtyRows }) => {
10198
+ const offCommit = terminal.on("commit", ({ dirtyRows, planes }) => {
10199
+ const activePlanes = (planes == null ? void 0 : planes.length) ? planes : TERMINAL_RENDER_PLANES;
9605
10200
  if (dirtyRows === null) {
9606
10201
  const size = terminal.size();
9607
- for (let y = 0; y < size.rows; y++)
9608
- pending.add(y);
10202
+ for (const plane of activePlanes) {
10203
+ let rows = pending.get(plane);
10204
+ if (!rows) {
10205
+ rows = /* @__PURE__ */ new Set();
10206
+ pending.set(plane, rows);
10207
+ }
10208
+ for (let y = 0; y < size.rows; y++)
10209
+ rows.add(y);
10210
+ }
9609
10211
  } else {
9610
- for (const y of dirtyRows)
9611
- pending.add(y);
10212
+ for (const plane of activePlanes) {
10213
+ let rows = pending.get(plane);
10214
+ if (!rows) {
10215
+ rows = /* @__PURE__ */ new Set();
10216
+ pending.set(plane, rows);
10217
+ }
10218
+ for (const y of dirtyRows)
10219
+ rows.add(y);
10220
+ }
9612
10221
  }
9613
10222
  if (!raf) {
9614
10223
  raf = -1;
@@ -9637,16 +10246,23 @@ function createDomRenderer(terminal, container) {
9637
10246
  if (raf > 0)
9638
10247
  cancelAnimationFrame(raf);
9639
10248
  pending.clear();
10249
+ planeLayers.clear();
9640
10250
  container.replaceChildren();
10251
+ },
10252
+ setPlaneOffset(plane, offsetPx) {
10253
+ applyPlaneOffset(plane, offsetPx);
10254
+ },
10255
+ setPlaneViewport(plane, viewport) {
10256
+ applyPlaneViewport(plane, viewport);
9641
10257
  }
9642
10258
  };
9643
10259
  }
9644
10260
 
9645
10261
  // src/runtime/index.ts
9646
- var import_node_process9 = __toESM(require("process"), 1);
10262
+ var import_node_process10 = __toESM(require("process"), 1);
9647
10263
  function isNodeLike2() {
9648
10264
  var _a2, _b2;
9649
- return typeof ((_b2 = (_a2 = import_node_process9.default) == null ? void 0 : _a2.versions) == null ? void 0 : _b2.node) === "string";
10265
+ return typeof ((_b2 = (_a2 = import_node_process10.default) == null ? void 0 : _a2.versions) == null ? void 0 : _b2.node) === "string";
9650
10266
  }
9651
10267
  function detectEnv() {
9652
10268
  const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
@@ -11125,6 +11741,7 @@ function mentionIndexAt2(value, mentionToken, index) {
11125
11741
  return countMentionTokens2(value, mentionToken, index);
11126
11742
  }
11127
11743
  function createPromptMentionPlugin(options = {}) {
11744
+ const latency = getCliLatencyProfiler();
11128
11745
  return {
11129
11746
  name: "promptMention",
11130
11747
  install: (ctx) => {
@@ -11287,6 +11904,12 @@ function createPromptMentionPlugin(options = {}) {
11287
11904
  query: ctx0.query
11288
11905
  });
11289
11906
  if (handled !== false) {
11907
+ const value = ctx.getValue();
11908
+ const before2 = value.slice(0, ctx0.tokenStart);
11909
+ const after2 = value.slice(ctx0.tokenEnd);
11910
+ const nextValue2 = `${before2}${after2}`;
11911
+ ctx.pushUndoSnapshot(nextValue2);
11912
+ ctx.applyEdit(nextValue2, ctx0.tokenStart);
11290
11913
  promptMention.promptSuppressedKey.value = ctx0.key;
11291
11914
  ctx.scheduler.invalidate();
11292
11915
  return;
@@ -11330,8 +11953,17 @@ function createPromptMentionPlugin(options = {}) {
11330
11953
  var _a2, _b2, _c, _d;
11331
11954
  if (!promptMention.promptVisible.value)
11332
11955
  return false;
11956
+ const markPromptOperation = (suffix) => {
11957
+ const ctx0 = promptMention.activeContext.value;
11958
+ const mentionTrigger = getProps().mentionTrigger || "@";
11959
+ const skillTrigger = getProps().skillTrigger || "";
11960
+ const tokenText = String((ctx0 == null ? void 0 : ctx0.tokenText) ?? "");
11961
+ const scope = tokenText.startsWith(mentionTrigger) ? "prompt.mention" : skillTrigger && tokenText.startsWith(skillTrigger) ? "prompt.skill" : "prompt.command";
11962
+ latency == null ? void 0 : latency.markOperation(`${scope}.${suffix}`);
11963
+ };
11333
11964
  const len = promptMention.promptMatches.value.length;
11334
11965
  if (e.key === "ArrowDown") {
11966
+ markPromptOperation("navigate.next");
11335
11967
  e.preventDefault();
11336
11968
  if (len <= 0) {
11337
11969
  promptMention.promptActive.value = 0;
@@ -11348,6 +11980,7 @@ function createPromptMentionPlugin(options = {}) {
11348
11980
  return true;
11349
11981
  }
11350
11982
  if (e.key === "ArrowUp") {
11983
+ markPromptOperation("navigate.prev");
11351
11984
  e.preventDefault();
11352
11985
  if (len <= 0) {
11353
11986
  promptMention.promptActive.value = 0;
@@ -11383,11 +12016,13 @@ function createPromptMentionPlugin(options = {}) {
11383
12016
  const candidate = String(((_c = match == null ? void 0 : match.item) == null ? void 0 : _c.value) ?? "");
11384
12017
  if (!typed || !candidate.startsWith(typed))
11385
12018
  return false;
12019
+ markPromptOperation("accept");
11386
12020
  e.preventDefault();
11387
12021
  acceptPrompt(promptMention.promptActive.value);
11388
12022
  return true;
11389
12023
  }
11390
12024
  if (e.key === "Tab" && (isMention || isSkill)) {
12025
+ markPromptOperation("accept");
11391
12026
  e.preventDefault();
11392
12027
  if (len === 0)
11393
12028
  return true;
@@ -11404,11 +12039,13 @@ function createPromptMentionPlugin(options = {}) {
11404
12039
  }
11405
12040
  if (len === 0)
11406
12041
  return false;
12042
+ markPromptOperation("accept");
11407
12043
  e.preventDefault();
11408
12044
  acceptPrompt(promptMention.promptActive.value);
11409
12045
  return true;
11410
12046
  }
11411
12047
  if (e.key === "Escape") {
12048
+ markPromptOperation("dismiss");
11412
12049
  e.preventDefault();
11413
12050
  promptMention.promptSuppressedKey.value = ((_d = promptMention.activeContext.value) == null ? void 0 : _d.key) ?? null;
11414
12051
  ctx.scheduler.invalidate();
@@ -17327,8 +17964,8 @@ function normalizeDelta(deltaY, mode = "auto") {
17327
17964
  return deltaY;
17328
17965
  return deltaY / PIXELS_PER_LINE;
17329
17966
  }
17330
- function accelFactor(now3, lastAt) {
17331
- const dt = now3 - lastAt;
17967
+ function accelFactor(now4, lastAt) {
17968
+ const dt = now4 - lastAt;
17332
17969
  if (!Number.isFinite(dt) || dt <= 0 || dt > ACCEL_WINDOW_MS)
17333
17970
  return 1;
17334
17971
  const t = 1 - dt / ACCEL_WINDOW_MS;
@@ -17339,24 +17976,29 @@ function createWheelScrollState() {
17339
17976
  accumulator: 0,
17340
17977
  lastAt: 0,
17341
17978
  lastEdgeDir: 0,
17342
- lastEdgeAt: 0
17979
+ lastEdgeAt: 0,
17980
+ lastLineUnitDir: 0
17343
17981
  };
17344
17982
  }
17345
- function applyWheelScroll(state, deltaY, scrollTop, maxTop, now3 = Date.now(), deltaMode = "auto") {
17983
+ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now4 = Date.now(), deltaMode = "auto", options = {}) {
17346
17984
  if (!Number.isFinite(deltaY) || deltaY === 0 || maxTop <= 0) {
17347
17985
  if (maxTop <= 0) {
17348
17986
  state.accumulator = 0;
17349
17987
  state.lastEdgeDir = 0;
17350
17988
  state.lastEdgeAt = 0;
17989
+ state.lastLineUnitDir = 0;
17351
17990
  }
17352
17991
  return { nextTop: scrollTop, dir: 0, lines: 0 };
17353
17992
  }
17354
- const dt = state.lastAt ? now3 - state.lastAt : Infinity;
17993
+ const dt = state.lastAt ? now4 - state.lastAt : Infinity;
17355
17994
  const lineUnits = isLineUnitDelta(deltaY, deltaMode);
17356
- if (lineUnits && dt !== Infinity && dt >= 0 && dt < MIN_TICK_INTERVAL_MS)
17995
+ const inputDir = Math.sign(normalizeDelta(deltaY, deltaMode));
17996
+ if (lineUnits && dt !== Infinity && dt >= 0 && dt < MIN_TICK_INTERVAL_MS && inputDir === state.lastLineUnitDir) {
17357
17997
  return { nextTop: scrollTop, dir: 0, lines: 0 };
17358
- const accel = lineUnits ? 1 : state.lastAt ? accelFactor(now3, state.lastAt) : 1;
17359
- state.lastAt = now3;
17998
+ }
17999
+ state.lastLineUnitDir = lineUnits ? inputDir : 0;
18000
+ const accel = lineUnits ? 1 : options.disableAcceleration ? 1 : state.lastAt ? accelFactor(now4, state.lastAt) : 1;
18001
+ state.lastAt = now4;
17360
18002
  state.accumulator += normalizeDelta(deltaY, deltaMode) * accel;
17361
18003
  const lines = Math.trunc(state.accumulator);
17362
18004
  if (lines === 0)
@@ -17367,11 +18009,11 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now3 = Date.now(), d
17367
18009
  const atBottom = scrollTop >= maxTop;
17368
18010
  if (dir < 0 && atTop || dir > 0 && atBottom) {
17369
18011
  state.lastEdgeDir = dir;
17370
- state.lastEdgeAt = now3;
18012
+ state.lastEdgeAt = now4;
17371
18013
  state.accumulator = 0;
17372
18014
  return { nextTop: scrollTop, dir: 0, lines: 0 };
17373
18015
  }
17374
- if (state.lastEdgeDir !== 0 && now3 - state.lastEdgeAt < EDGE_BOUNCE_MS && dir === -state.lastEdgeDir && (atTop || atBottom)) {
18016
+ if (state.lastEdgeDir !== 0 && now4 - state.lastEdgeAt < EDGE_BOUNCE_MS && dir === -state.lastEdgeDir && (atTop || atBottom)) {
17375
18017
  return { nextTop: scrollTop, dir: 0, lines: 0 };
17376
18018
  }
17377
18019
  const unclamped = scrollTop + lines;
@@ -19426,6 +20068,7 @@ var TRouterView = (0, import_vue32.defineComponent)({
19426
20068
  defaultTInputHostPlugin,
19427
20069
  detectTerminalColorCapability,
19428
20070
  formatInlineCellLine,
20071
+ getCliLatencyProfiler,
19429
20072
  getStdoutRendererMetrics,
19430
20073
  lintJsonText,
19431
20074
  normalizeNewlines,