@kontextmind/kxm 0.7.176 → 0.7.177

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.
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.176",
14
+ "version": "0.7.177",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.176",
3
+ "version": "0.7.177",
4
4
  "description": "KXM local-first multi-agent orchestration and operator dashboard",
5
5
  "type": "module",
6
6
  "author": "KontextMind",
@@ -78,7 +78,7 @@
78
78
  },
79
79
  "dependencies": {
80
80
  "@anthropic-ai/claude-agent-sdk": "0.3.289",
81
- "@earendil-works/pi-tui": "0.87.1",
81
+ "@earendil-works/pi-tui": "1.0.2",
82
82
  "@modelcontextprotocol/sdk": "1.32.0",
83
83
  "yaml": "^2.9.0"
84
84
  },
@@ -95,7 +95,7 @@
95
95
  }
96
96
  },
97
97
  "devDependencies": {
98
- "@earendil-works/pi-coding-agent": "0.87.1",
98
+ "@earendil-works/pi-coding-agent": "1.0.2",
99
99
  "@modelcontextprotocol/sdk": "1.32.0",
100
100
  "@playwright/test": "1.63.0",
101
101
  "@types/node": "26.6.4",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "kxm",
4
4
  "displayName": "KXM",
5
- "version": "0.7.176",
5
+ "version": "0.7.177",
6
6
  "description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
7
7
  "author": {
8
8
  "name": "KontextMind",
@@ -43129,8 +43129,12 @@ function finalizeTruncatedResult(prefix, prefixWidth, ellipsis, ellipsisWidth, m
43129
43129
  return pad2 ? result + " ".repeat(Math.max(0, maxWidth - visibleWidth2)) : result;
43130
43130
  }
43131
43131
  function graphemeWidth(segment) {
43132
- if (segment === " ") {
43133
- return 3;
43132
+ if (segment.length === 1) {
43133
+ const code = segment.charCodeAt(0);
43134
+ if (code >= 32 && code <= 126)
43135
+ return 1;
43136
+ if (code === 9)
43137
+ return 3;
43134
43138
  }
43135
43139
  if (terminalSpacingMarkRegex.test(segment)) {
43136
43140
  return [...segment].length;
@@ -43174,8 +43178,9 @@ function visibleWidth(str) {
43174
43178
  if (str.length === 0) {
43175
43179
  return 0;
43176
43180
  }
43177
- if (isPrintableAscii(str)) {
43178
- return str.length;
43181
+ const asciiWidth = asciiVisibleWidth(str);
43182
+ if (asciiWidth !== -1) {
43183
+ return asciiWidth;
43179
43184
  }
43180
43185
  const cached = widthCache.get(str);
43181
43186
  if (cached !== void 0) {
@@ -43185,19 +43190,22 @@ function visibleWidth(str) {
43185
43190
  if (str.includes(" ")) {
43186
43191
  clean = clean.replace(/\t/g, " ");
43187
43192
  }
43188
- if (clean.includes("\x1B")) {
43193
+ let escapeIndex = clean.indexOf("\x1B");
43194
+ if (escapeIndex !== -1) {
43189
43195
  let stripped = "";
43190
- let i = 0;
43191
- while (i < clean.length) {
43192
- const ansi = extractAnsiCode(clean, i);
43193
- if (ansi) {
43194
- i += ansi.length;
43195
- continue;
43196
+ let copyFrom = 0;
43197
+ while (escapeIndex !== -1) {
43198
+ const length = ansiCodeLength(clean, escapeIndex);
43199
+ if (length > 0) {
43200
+ stripped += clean.slice(copyFrom, escapeIndex);
43201
+ escapeIndex += length;
43202
+ copyFrom = escapeIndex;
43203
+ } else {
43204
+ escapeIndex++;
43196
43205
  }
43197
- stripped += clean[i];
43198
- i++;
43206
+ escapeIndex = clean.indexOf("\x1B", escapeIndex);
43199
43207
  }
43200
- clean = stripped;
43208
+ clean = stripped + clean.slice(copyFrom);
43201
43209
  }
43202
43210
  let width = 0;
43203
43211
  for (const { segment } of graphemeSegmenter.segment(clean)) {
@@ -43301,40 +43309,54 @@ function normalizeTerminalOutput(str) {
43301
43309
  return result;
43302
43310
  }
43303
43311
  function extractAnsiCode(str, pos) {
43304
- if (pos >= str.length || str[pos] !== "\x1B")
43305
- return null;
43312
+ const length = ansiCodeLength(str, pos);
43313
+ return length > 0 ? { code: str.substring(pos, pos + length), length } : null;
43314
+ }
43315
+ function asciiVisibleWidth(str) {
43316
+ let width = 0;
43317
+ let i = 0;
43318
+ while (i < str.length) {
43319
+ const code = str.charCodeAt(i);
43320
+ if (code >= 32 && code <= 126) {
43321
+ width++;
43322
+ i++;
43323
+ } else if (code === 9) {
43324
+ width += 3;
43325
+ i++;
43326
+ } else if (code === 27) {
43327
+ const length = ansiCodeLength(str, i);
43328
+ if (length === 0)
43329
+ return -1;
43330
+ i += length;
43331
+ } else {
43332
+ return -1;
43333
+ }
43334
+ }
43335
+ return width;
43336
+ }
43337
+ function ansiCodeLength(str, pos) {
43338
+ if (pos >= str.length || str.charCodeAt(pos) !== 27)
43339
+ return 0;
43306
43340
  const next = str[pos + 1];
43307
43341
  if (next === "[") {
43308
- let j2 = pos + 2;
43309
- while (j2 < str.length && !/[mGKHJ]/.test(str[j2]))
43310
- j2++;
43311
- if (j2 < str.length)
43312
- return { code: str.substring(pos, j2 + 1), length: j2 + 1 - pos };
43313
- return null;
43314
- }
43315
- if (next === "]") {
43316
- let j2 = pos + 2;
43317
- while (j2 < str.length) {
43318
- if (str[j2] === "\x07")
43319
- return { code: str.substring(pos, j2 + 1), length: j2 + 1 - pos };
43320
- if (str[j2] === "\x1B" && str[j2 + 1] === "\\")
43321
- return { code: str.substring(pos, j2 + 2), length: j2 + 2 - pos };
43322
- j2++;
43342
+ for (let j2 = pos + 2; j2 < str.length; j2++) {
43343
+ const c = str.charCodeAt(j2);
43344
+ if (c === 109 || c === 71 || c === 75 || c === 72 || c === 74)
43345
+ return j2 + 1 - pos;
43323
43346
  }
43324
- return null;
43347
+ return 0;
43325
43348
  }
43326
- if (next === "_") {
43327
- let j2 = pos + 2;
43328
- while (j2 < str.length) {
43329
- if (str[j2] === "\x07")
43330
- return { code: str.substring(pos, j2 + 1), length: j2 + 1 - pos };
43331
- if (str[j2] === "\x1B" && str[j2 + 1] === "\\")
43332
- return { code: str.substring(pos, j2 + 2), length: j2 + 2 - pos };
43333
- j2++;
43349
+ if (next === "]" || next === "_") {
43350
+ for (let j2 = pos + 2; j2 < str.length; j2++) {
43351
+ const c = str.charCodeAt(j2);
43352
+ if (c === 7)
43353
+ return j2 + 1 - pos;
43354
+ if (c === 27 && str[j2 + 1] === "\\")
43355
+ return j2 + 2 - pos;
43334
43356
  }
43335
- return null;
43357
+ return 0;
43336
43358
  }
43337
- return null;
43359
+ return 0;
43338
43360
  }
43339
43361
  function parseOsc8Hyperlink(ansiCode) {
43340
43362
  if (!ansiCode.startsWith("\x1B]8;")) {
@@ -43578,15 +43600,16 @@ var AnsiCodeTracker = class {
43578
43600
  }
43579
43601
  };
43580
43602
  function updateTrackerFromText(text, tracker) {
43581
- let i = 0;
43582
- while (i < text.length) {
43583
- const ansiResult = extractAnsiCode(text, i);
43584
- if (ansiResult) {
43585
- tracker.process(ansiResult.code);
43586
- i += ansiResult.length;
43603
+ let i = text.indexOf("\x1B");
43604
+ while (i !== -1) {
43605
+ const length = ansiCodeLength(text, i);
43606
+ if (length > 0) {
43607
+ tracker.process(text.substring(i, i + length));
43608
+ i += length;
43587
43609
  } else {
43588
43610
  i++;
43589
43611
  }
43612
+ i = text.indexOf("\x1B", i);
43590
43613
  }
43591
43614
  }
43592
43615
  function getActiveBackgroundAnsi(text) {
@@ -43594,6 +43617,10 @@ function getActiveBackgroundAnsi(text) {
43594
43617
  updateTrackerFromText(text, tracker);
43595
43618
  return tracker.getActiveBackgroundCode();
43596
43619
  }
43620
+ function* graphemeSegments(text) {
43621
+ for (const { segment } of graphemeSegmenter.segment(text))
43622
+ yield segment;
43623
+ }
43597
43624
  function splitIntoTokensWithAnsi(text) {
43598
43625
  const tokens = [];
43599
43626
  let current = "";
@@ -43615,13 +43642,17 @@ function splitIntoTokensWithAnsi(text) {
43615
43642
  i += ansiResult.length;
43616
43643
  continue;
43617
43644
  }
43618
- let end = i;
43619
- while (end < text.length && !extractAnsiCode(text, end)) {
43620
- end++;
43645
+ let end = text.indexOf("\x1B", i + 1);
43646
+ while (end !== -1 && ansiCodeLength(text, end) === 0) {
43647
+ end = text.indexOf("\x1B", end + 1);
43621
43648
  }
43622
- for (const { segment } of graphemeSegmenter.segment(text.slice(i, end))) {
43649
+ if (end === -1)
43650
+ end = text.length;
43651
+ const chunk = text.slice(i, end);
43652
+ const ascii = isPrintableAscii(chunk);
43653
+ for (const segment of ascii ? chunk : graphemeSegments(chunk)) {
43623
43654
  const segmentIsSpace = segment === " ";
43624
- if (!segmentIsSpace && cjkBreakRegex.test(segment)) {
43655
+ if (!ascii && !segmentIsSpace && cjkBreakRegex.test(segment)) {
43625
43656
  flushCurrent();
43626
43657
  const token = pendingAnsi + segment;
43627
43658
  pendingAnsi = "";
@@ -43655,6 +43686,10 @@ function splitIntoTokensWithAnsi(text) {
43655
43686
  }
43656
43687
  return tokens;
43657
43688
  }
43689
+ function flattenLines(lines) {
43690
+ for (const line of lines)
43691
+ Number(line);
43692
+ }
43658
43693
  function wrapTextWithAnsi(text, width) {
43659
43694
  if (!text) {
43660
43695
  return [""];
@@ -43927,9 +43962,10 @@ function sliceWithWidth(line, startCol, length, strict = false) {
43927
43962
  while (i < line.length) {
43928
43963
  const ansi = extractAnsiCode(line, i);
43929
43964
  if (ansi) {
43930
- if (currentCol >= startCol && currentCol < endCol)
43931
- result += ansi.code;
43932
- else if (currentCol < startCol)
43965
+ if (currentCol >= startCol && currentCol < endCol) {
43966
+ result += pendingAnsi + ansi.code;
43967
+ pendingAnsi = "";
43968
+ } else if (currentCol < startCol)
43933
43969
  pendingAnsi += ansi.code;
43934
43970
  i += ansi.length;
43935
43971
  continue;
@@ -44016,8 +44052,19 @@ function extractSegments(line, beforeEnd, afterStart, afterLen, strictAfter = fa
44016
44052
  // node_modules/@earendil-works/pi-tui/dist/autocomplete.js
44017
44053
  var tokenStartRegex = new RegExp(`${autocompleteBoundaryRegex.source}$`, "u");
44018
44054
 
44055
+ // node_modules/@earendil-works/pi-tui/dist/oklab.js
44056
+ var K1 = 0.206;
44057
+ var K2 = 0.03;
44058
+ var K3 = (1 + K1) / (1 + K2);
44059
+
44060
+ // node_modules/@earendil-works/pi-tui/dist/colors.js
44061
+ var NUMBER_PATTERN = String.raw`[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?`;
44062
+ var OKLCH_PATTERN = new RegExp(`^oklch\\(\\s*(${NUMBER_PATTERN})(%)?\\s+(${NUMBER_PATTERN})\\s+(${NUMBER_PATTERN})(?:deg)?\\s*\\)$`, "i");
44063
+ var OKHSL_PATTERN = new RegExp(`^okhsl\\(\\s*(${NUMBER_PATTERN})(?:deg)?\\s+(${NUMBER_PATTERN})(%)?\\s+(${NUMBER_PATTERN})(%)?\\s*\\)$`, "i");
44064
+ var GRAY_VALUES = Array.from({ length: 24 }, (_2, index) => 8 + index * 10);
44065
+
44019
44066
  // node_modules/@earendil-works/pi-tui/dist/tui.js
44020
- import { performance } from "node:perf_hooks";
44067
+ import { performance as performance2 } from "node:perf_hooks";
44021
44068
 
44022
44069
  // node_modules/@earendil-works/pi-tui/dist/keys.js
44023
44070
  var _kittyProtocolActive = false;
@@ -44729,17 +44776,18 @@ function parseOscHexChannel(channel) {
44729
44776
  }
44730
44777
  return Math.round(parseInt(channel, 16) / max * 255);
44731
44778
  }
44732
- var OSC11_BACKGROUND_COLOR_RESPONSE_PATTERN = /^\x1b\]11;([^\x07\x1b]*)(?:\x07|\x1b\\)$/i;
44779
+ var OSC_COLOR_RESPONSE_PATTERN = /^\x1b\](?:(1[01])|4;(\d{1,3}));([^\x07\x1b]*)(?:\x07|\x1b\\)$/i;
44733
44780
  var COLOR_SCHEME_REPORT_PATTERN = /^(?:\x1b\[\?997;(1|2)n)+$/;
44734
- function isOsc11BackgroundColorResponse(data) {
44735
- return OSC11_BACKGROUND_COLOR_RESPONSE_PATTERN.test(data);
44736
- }
44737
- function parseOsc11BackgroundColor(data) {
44738
- const match = data.match(OSC11_BACKGROUND_COLOR_RESPONSE_PATTERN);
44781
+ function parseOscColorResponse(data) {
44782
+ const match = data.match(OSC_COLOR_RESPONSE_PATTERN);
44739
44783
  if (!match) {
44740
44784
  return void 0;
44741
44785
  }
44742
- const value = match[1].trim();
44786
+ const target = match[1] === "10" ? "foreground" : match[1] === "11" ? "background" : Number.parseInt(match[2], 10);
44787
+ return { target, rgb: parseOscColorValue(match[3]) };
44788
+ }
44789
+ function parseOscColorValue(rawValue) {
44790
+ const value = rawValue.trim();
44743
44791
  if (value.startsWith("#")) {
44744
44792
  const hex = value.slice(1);
44745
44793
  if (/^[0-9a-f]{6}$/i.test(hex)) {
@@ -44796,7 +44844,7 @@ function detectCapabilitiesFromEnvironment(tmuxForwardsHyperlink) {
44796
44844
  const terminalEmulator = process.env.TERMINAL_EMULATOR?.toLowerCase() || "";
44797
44845
  const term = process.env.TERM?.toLowerCase() || "";
44798
44846
  const colorTerm = process.env.COLORTERM?.toLowerCase() || "";
44799
- const hasTrueColorHint = colorTerm === "truecolor" || colorTerm === "24bit";
44847
+ const hasTrueColorHint = colorTerm === "truecolor" || colorTerm === "24bit" || term.endsWith("-direct");
44800
44848
  const isWindowsConsole = process.platform === "win32";
44801
44849
  if (process.env.TMUX || term.startsWith("tmux")) {
44802
44850
  return { images: null, trueColor: hasTrueColorHint, hyperlinks: tmuxForwardsHyperlink() };
@@ -44880,12 +44928,23 @@ function deleteAllKittyPlacements() {
44880
44928
  return "\x1B_Ga=d,d=a,q=2\x1B\\";
44881
44929
  }
44882
44930
  var kittyImageMetadata = /* @__PURE__ */ new Map();
44931
+ function getRegisteredKittyImageMetadataFromControls(controls) {
44932
+ const imageId = /(?:^|,)i=(\d+)(?:,|$)/.exec(controls)?.[1];
44933
+ return imageId === void 0 ? void 0 : kittyImageMetadata.get(Number.parseInt(imageId, 10));
44934
+ }
44883
44935
  function getRegisteredKittyImageMetadata(line) {
44884
44936
  const controls = /\x1b_G([^;]*);/.exec(line)?.[1];
44885
- if (!controls)
44937
+ return controls === void 0 ? void 0 : getRegisteredKittyImageMetadataFromControls(controls);
44938
+ }
44939
+ function getExplicitKittyImageRows(controls) {
44940
+ const value = /(?:^|,)r=(\d+)(?:,|$)/.exec(controls)?.[1];
44941
+ if (value === void 0)
44886
44942
  return void 0;
44887
- const imageId = /(?:^|,)i=(\d+)(?:,|$)/.exec(controls)?.[1];
44888
- return imageId === void 0 ? void 0 : kittyImageMetadata.get(Number.parseInt(imageId, 10));
44943
+ const rows = Number.parseInt(value, 10);
44944
+ return rows > 0 ? rows : void 0;
44945
+ }
44946
+ function getKittyImageRowsFromControls(controls, fallbackRows) {
44947
+ return getExplicitKittyImageRows(controls) ?? fallbackRows;
44889
44948
  }
44890
44949
  function getKittyImageMetadata(line) {
44891
44950
  const metadata = getRegisteredKittyImageMetadata(line);
@@ -44918,10 +44977,21 @@ var KITTY_PLACEMENT_CONTROL_KEYS = /* @__PURE__ */ new Set([
44918
44977
  "H",
44919
44978
  "V"
44920
44979
  ]);
44980
+ function getKittyImagePlacementRows(line) {
44981
+ const controls = /\x1b_G([^;]*);/.exec(line)?.[1];
44982
+ if (controls === void 0)
44983
+ return void 0;
44984
+ const explicitRows = getExplicitKittyImageRows(controls);
44985
+ if (explicitRows !== void 0)
44986
+ return explicitRows;
44987
+ return getRegisteredKittyImageMetadataFromControls(controls)?.rows;
44988
+ }
44921
44989
  function getKittyImagePlacement(line) {
44922
44990
  const match = /\x1b_G([^;]*);/.exec(line);
44923
- const metadata = getRegisteredKittyImageMetadata(line);
44924
- if (!match || !metadata)
44991
+ if (!match)
44992
+ return void 0;
44993
+ const metadata = getRegisteredKittyImageMetadataFromControls(match[1]);
44994
+ if (!metadata)
44925
44995
  return void 0;
44926
44996
  let commandStart = match.index;
44927
44997
  let commandControls = match[1];
@@ -44948,6 +45018,7 @@ function getKittyImagePlacement(line) {
44948
45018
  transmissionGeneration: metadata.transmissionGeneration,
44949
45019
  transmissionBytes: transmissionEnd - match.index,
44950
45020
  estimatedDecodedBytes: metadata.widthPx * metadata.heightPx * 4,
45021
+ rows: getKittyImageRowsFromControls(match[1], metadata.rows),
44951
45022
  sequence,
44952
45023
  replacementLine: `${line.slice(0, match.index)}${sequence}${line.slice(transmissionEnd)}`
44953
45024
  };
@@ -44973,8 +45044,10 @@ function dispatchMouseEvent(component, event) {
44973
45044
  const result = component.handleMouse?.(event);
44974
45045
  if (!result)
44975
45046
  return void 0;
44976
- if ("target" in result)
44977
- return result;
45047
+ if ("target" in result) {
45048
+ const forwarded = result;
45049
+ return forwarded.focus && component.handleInput ? { ...forwarded, focusTarget: component } : forwarded;
45050
+ }
44978
45051
  if (!result.handled && !result.capture && !result.focus)
44979
45052
  return void 0;
44980
45053
  return {
@@ -44999,6 +45072,10 @@ function retargetMouseEvent(event, target) {
44999
45072
  height: target.height
45000
45073
  };
45001
45074
  }
45075
+ var TERMINAL_PALETTE_SIZE = 16;
45076
+ var TERMINAL_COLOR_REPLY_COUNT = 2 + TERMINAL_PALETTE_SIZE;
45077
+ var TERMINAL_COLOR_QUERY = `\x1B]10;?\x07\x1B]11;?\x07${Array.from({ length: TERMINAL_PALETTE_SIZE }, (_2, index) => `\x1B]4;${index};?\x07`).join("")}\x1B[c`;
45078
+ var DEVICE_ATTRIBUTES_RESPONSE_PATTERN = /^\x1b\[\?[\d;]*c$/;
45002
45079
  function isFocusable(component) {
45003
45080
  return component !== null && "focused" in component;
45004
45081
  }
@@ -45100,8 +45177,11 @@ var TuiBase = class _TuiBase extends Container {
45100
45177
  clearOnShrink = false;
45101
45178
  fullRedrawCount = 0;
45102
45179
  stopped = false;
45103
- pendingOsc11BackgroundReplies = 0;
45104
- pendingOsc11BackgroundQueries = [];
45180
+ /**
45181
+ * Color queries waiting for their DA1 reply, oldest first. Terminals answer in order, so color
45182
+ * replies belong to the oldest one. Queries stay here after a timeout to collect late replies.
45183
+ */
45184
+ pendingTerminalColorQueries = [];
45105
45185
  terminalColorSchemeListeners = /* @__PURE__ */ new Set();
45106
45186
  terminalColorSchemeNotificationsEnabled = false;
45107
45187
  /** Directory for debug/crash logs. When undefined, debug logging is disabled and crash dumps fall back to the OS temp directory. */
@@ -45143,7 +45223,7 @@ var TuiBase = class _TuiBase extends Container {
45143
45223
  return;
45144
45224
  this.showHardwareCursor = enabled;
45145
45225
  if (!enabled) {
45146
- this.terminal.hideCursor();
45226
+ this.hideTerminalCursor();
45147
45227
  }
45148
45228
  this.requestRender();
45149
45229
  }
@@ -45279,7 +45359,7 @@ var TuiBase = class _TuiBase extends Container {
45279
45359
  if (!options?.nonCapturing && this.isOverlayVisible(entry)) {
45280
45360
  this.setFocus(component);
45281
45361
  }
45282
- this.terminal.hideCursor();
45362
+ this.hideTerminalCursor();
45283
45363
  this.requestRender();
45284
45364
  return {
45285
45365
  hide: () => {
@@ -45293,7 +45373,7 @@ var TuiBase = class _TuiBase extends Container {
45293
45373
  this.setFocus(topVisible?.component ?? entry.preFocus);
45294
45374
  }
45295
45375
  if (this.overlayStack.length === 0)
45296
- this.terminal.hideCursor();
45376
+ this.hideTerminalCursor();
45297
45377
  this.requestRender();
45298
45378
  }
45299
45379
  },
@@ -45372,9 +45452,14 @@ var TuiBase = class _TuiBase extends Container {
45372
45452
  this.setFocus(topVisible?.component ?? overlay.preFocus);
45373
45453
  }
45374
45454
  if (this.overlayStack.length === 0)
45375
- this.terminal.hideCursor();
45455
+ this.hideTerminalCursor();
45376
45456
  this.requestRender();
45377
45457
  }
45458
+ /** Hide the cursor while running. After stop(), the shell owns the cursor and it must stay visible. */
45459
+ hideTerminalCursor() {
45460
+ if (!this.stopped)
45461
+ this.terminal.hideCursor();
45462
+ }
45378
45463
  /** Check if there are any visible overlays */
45379
45464
  hasOverlay() {
45380
45465
  return this.overlayStack.some((o) => this.isOverlayVisible(o));
@@ -45499,7 +45584,7 @@ var TuiBase = class _TuiBase extends Container {
45499
45584
  this.resetRenderState();
45500
45585
  this.renderRequested = false;
45501
45586
  this.cancelRenderTimer();
45502
- this.lastRenderAt = performance.now();
45587
+ this.lastRenderAt = performance2.now();
45503
45588
  this.doRender();
45504
45589
  }
45505
45590
  requestRender(force = false) {
@@ -45525,7 +45610,7 @@ var TuiBase = class _TuiBase extends Container {
45525
45610
  return;
45526
45611
  this.cancelRenderTimer();
45527
45612
  this.renderRequested = false;
45528
- this.lastRenderAt = performance.now();
45613
+ this.lastRenderAt = performance2.now();
45529
45614
  this.doRender();
45530
45615
  });
45531
45616
  }
@@ -45539,7 +45624,7 @@ var TuiBase = class _TuiBase extends Container {
45539
45624
  if (this.stopped || this.renderTimer || !this.renderRequested) {
45540
45625
  return;
45541
45626
  }
45542
- const elapsed = performance.now() - this.lastRenderAt;
45627
+ const elapsed = performance2.now() - this.lastRenderAt;
45543
45628
  const delay = Math.max(0, _TuiBase.MIN_RENDER_INTERVAL_MS - elapsed);
45544
45629
  this.renderTimer = setTimeout(() => {
45545
45630
  this.renderTimer = void 0;
@@ -45547,7 +45632,7 @@ var TuiBase = class _TuiBase extends Container {
45547
45632
  return;
45548
45633
  }
45549
45634
  this.renderRequested = false;
45550
- this.lastRenderAt = performance.now();
45635
+ this.lastRenderAt = performance2.now();
45551
45636
  this.doRender();
45552
45637
  if (this.renderRequested) {
45553
45638
  this.scheduleRender();
@@ -45555,7 +45640,7 @@ var TuiBase = class _TuiBase extends Container {
45555
45640
  }, delay);
45556
45641
  }
45557
45642
  handleTerminalInput(data) {
45558
- if (this.consumeOsc11BackgroundResponse(data)) {
45643
+ if (this.consumeTerminalColorResponse(data)) {
45559
45644
  return;
45560
45645
  }
45561
45646
  if (this.consumeTerminalColorSchemeReport(data)) {
@@ -45615,27 +45700,48 @@ var TuiBase = class _TuiBase extends Container {
45615
45700
  this.requestImmediateRender();
45616
45701
  }
45617
45702
  }
45618
- consumeOsc11BackgroundResponse(data) {
45619
- if (this.pendingOsc11BackgroundReplies <= 0) {
45703
+ consumeTerminalColorResponse(data) {
45704
+ const query = this.pendingTerminalColorQueries[0];
45705
+ if (!query) {
45620
45706
  return false;
45621
45707
  }
45622
- if (!isOsc11BackgroundColorResponse(data)) {
45708
+ if (DEVICE_ATTRIBUTES_RESPONSE_PATTERN.test(data)) {
45709
+ this.pendingTerminalColorQueries.shift();
45710
+ this.completeTerminalColorQuery(query);
45711
+ return true;
45712
+ }
45713
+ const response = parseOscColorResponse(data);
45714
+ if (!response) {
45623
45715
  return false;
45624
45716
  }
45625
- const rgb = parseOsc11BackgroundColor(data);
45626
- this.pendingOsc11BackgroundReplies -= 1;
45627
- const query = this.pendingOsc11BackgroundQueries.shift();
45628
- if (query && !query.settled) {
45629
- query.settled = true;
45630
- if (query.timer) {
45631
- clearTimeout(query.timer);
45632
- query.timer = void 0;
45633
- }
45634
- query.resolve?.(rgb);
45635
- query.resolve = void 0;
45717
+ const { target, rgb } = response;
45718
+ const key = String(target);
45719
+ if (!query.deliver || query.replied.has(key)) {
45720
+ return true;
45721
+ }
45722
+ query.replied.add(key);
45723
+ if (target === "foreground") {
45724
+ query.foreground = rgb;
45725
+ } else if (target === "background") {
45726
+ query.background = rgb;
45727
+ } else if (target < TERMINAL_PALETTE_SIZE) {
45728
+ query.palette[target] = rgb;
45729
+ }
45730
+ if (query.replied.size === TERMINAL_COLOR_REPLY_COUNT) {
45731
+ this.completeTerminalColorQuery(query);
45636
45732
  }
45637
45733
  return true;
45638
45734
  }
45735
+ terminalColorQueryResult(query) {
45736
+ const palette = query.palette.every((color) => color !== void 0) ? query.palette : void 0;
45737
+ return { foreground: query.foreground, background: query.background, palette };
45738
+ }
45739
+ completeTerminalColorQuery(query) {
45740
+ const deliver = query.deliver;
45741
+ query.deliver = void 0;
45742
+ clearTimeout(query.timer);
45743
+ deliver?.(this.terminalColorQueryResult(query));
45744
+ }
45639
45745
  consumeTerminalColorSchemeReport(data) {
45640
45746
  const scheme = parseTerminalColorSchemeReport(data);
45641
45747
  if (!scheme) {
@@ -45844,56 +45950,27 @@ var TuiBase = class _TuiBase extends Container {
45844
45950
  return null;
45845
45951
  }
45846
45952
  /**
45847
- * Query the terminal's default background color with OSC 11 (`ESC ] 11 ; ? BEL`).
45848
- * @param timeoutMs Query timeout in milliseconds.
45849
- * @returns Promise containing the parsed RGB color, or undefined if it times out or fails to parse.
45953
+ * Query the terminal's theme colors: the default foreground (OSC 10), the default background
45954
+ * (OSC 11), and ANSI colors 0-15 (OSC 4), followed by a DA1 request that marks the end of the
45955
+ * replies. Resolves when the DA1 reply or all color replies arrive, or when the timeout expires.
45956
+ * Colors the terminal did not report are undefined; the palette is only set when all 16 arrived.
45957
+ * @param timeoutMs Query timeout in milliseconds, for terminals that do not answer DA1 either.
45958
+ * @param onLateReply Receives the replies if the query completes after the timeout, e.g. over slow links.
45850
45959
  */
45851
- queryTerminalBackgroundColor({ timeoutMs }) {
45960
+ queryTerminalColors({ timeoutMs, onLateReply }) {
45852
45961
  return new Promise((resolve35) => {
45853
45962
  const query = {
45854
- settled: false,
45855
- resolve: resolve35,
45963
+ palette: Array.from({ length: TERMINAL_PALETTE_SIZE }, () => void 0),
45964
+ replied: /* @__PURE__ */ new Set(),
45965
+ deliver: resolve35,
45856
45966
  timer: void 0
45857
45967
  };
45858
45968
  query.timer = setTimeout(() => {
45859
- if (query.settled) {
45860
- return;
45861
- }
45862
- query.settled = true;
45863
- query.timer = void 0;
45864
- query.resolve?.(void 0);
45865
- query.resolve = void 0;
45969
+ query.deliver = onLateReply;
45970
+ resolve35(this.terminalColorQueryResult(query));
45866
45971
  }, timeoutMs);
45867
- this.pendingOsc11BackgroundQueries.push(query);
45868
- this.pendingOsc11BackgroundReplies += 1;
45869
- this.terminal.write("\x1B]11;?\x07");
45870
- });
45871
- }
45872
- /**
45873
- * Query the terminal's color-scheme preference with DSR (`CSI ? 996 n`).
45874
- * Terminals that support the color palette notification protocol reply with
45875
- * `CSI ? 997 ; 1 n` for dark or `CSI ? 997 ; 2 n` for light.
45876
- */
45877
- queryTerminalColorScheme({ timeoutMs }) {
45878
- return new Promise((resolve35) => {
45879
- let settled = false;
45880
- let timer;
45881
- let unsubscribe = () => {
45882
- };
45883
- const settle = (scheme) => {
45884
- if (settled)
45885
- return;
45886
- settled = true;
45887
- if (timer) {
45888
- clearTimeout(timer);
45889
- timer = void 0;
45890
- }
45891
- unsubscribe();
45892
- resolve35(scheme);
45893
- };
45894
- unsubscribe = this.onTerminalColorSchemeChange(settle);
45895
- timer = setTimeout(() => settle(void 0), timeoutMs);
45896
- this.terminal.write("\x1B[?996n");
45972
+ this.pendingTerminalColorQueries.push(query);
45973
+ this.terminal.write(TERMINAL_COLOR_QUERY);
45897
45974
  });
45898
45975
  }
45899
45976
  };
@@ -45977,7 +46054,7 @@ var Box = class {
45977
46054
  const lines = child.render(contentWidth);
45978
46055
  mouseChildren.push({ component: child, height: lines.length });
45979
46056
  for (const line of lines) {
45980
- childLines.push(leftPad + line);
46057
+ childLines.push(line);
45981
46058
  }
45982
46059
  }
45983
46060
  this.mouseLayout = { width: contentWidth, children: mouseChildren };
@@ -45993,11 +46070,12 @@ var Box = class {
45993
46070
  result.push(this.applyBg("", width));
45994
46071
  }
45995
46072
  for (const line of childLines) {
45996
- result.push(this.applyBg(line, width));
46073
+ result.push(this.applyBg(leftPad + line, width));
45997
46074
  }
45998
46075
  for (let i = 0; i < this.paddingY; i++) {
45999
46076
  result.push(this.applyBg("", width));
46000
46077
  }
46078
+ flattenLines(result);
46001
46079
  this.cache = { childLines, width, bgSample, lines: result };
46002
46080
  return result;
46003
46081
  }
@@ -46005,10 +46083,7 @@ var Box = class {
46005
46083
  const visLen = visibleWidth(line);
46006
46084
  const padNeeded = Math.max(0, width - visLen);
46007
46085
  const padded = line + " ".repeat(padNeeded);
46008
- if (this.bgFn) {
46009
- return applyBackgroundToLine(padded, width, this.bgFn);
46010
- }
46011
- return padded;
46086
+ return this.bgFn ? this.bgFn(padded) : padded;
46012
46087
  }
46013
46088
  };
46014
46089
 
@@ -46312,6 +46387,7 @@ var Text = class {
46312
46387
  emptyLines.push(line);
46313
46388
  }
46314
46389
  const result = [...emptyLines, ...contentLines, ...emptyLines];
46390
+ flattenLines(result);
46315
46391
  this.cachedText = this.text;
46316
46392
  this.cachedWidth = width;
46317
46393
  this.cachedLines = result;
@@ -46443,6 +46519,7 @@ function findWordForward(text, cursor2, options) {
46443
46519
  var graphemeSegmenter2 = getGraphemeSegmenter();
46444
46520
  var wordSegmenter3 = getWordSegmenter();
46445
46521
  var unquotedAutocompleteSuffixRegex = new RegExp(`(?:(?!${autocompleteSeparatorRegex.source}).)*`, "u");
46522
+ var autocompleteTokenStartSource = `${autocompleteBoundaryRegex.source}[([{<\`]*`;
46446
46523
 
46447
46524
  // node_modules/@earendil-works/pi-tui/dist/layout-node.js
46448
46525
  var LAYOUT_NODE = /* @__PURE__ */ Symbol.for("@earendil-works/pi-tui/layout-node");
@@ -47733,6 +47810,8 @@ var ProcessTerminal = class {
47733
47810
  _kittyProtocolActive = false;
47734
47811
  _modifyOtherKeysActive = false;
47735
47812
  keyboardProtocolPushed = false;
47813
+ /** DA1 replies owed to keyboard protocol queries. Later DA1 replies answer other queries and are forwarded. */
47814
+ pendingKeyboardProtocolDeviceAttributes = 0;
47736
47815
  keyboardProtocolNegotiationBuffer = "";
47737
47816
  keyboardProtocolBufferFlushTimer;
47738
47817
  stdinBuffer;
@@ -47784,15 +47863,15 @@ var ProcessTerminal = class {
47784
47863
  setupStdinBuffer() {
47785
47864
  this.stdinBuffer = new StdinBuffer({ escapeTimeout: resolveEscapeTimeoutMs() });
47786
47865
  this.stdinBuffer.on("data", (sequence) => {
47787
- const negotiationSequence = this.readKeyboardProtocolNegotiationSequence(sequence);
47788
- if (negotiationSequence === "pending") {
47866
+ const negotiation = this.readKeyboardProtocolNegotiationSequence(sequence);
47867
+ if (negotiation === "pending") {
47789
47868
  this.scheduleKeyboardProtocolNegotiationBufferFlush();
47790
47869
  return;
47791
47870
  }
47792
- if (this.handleKeyboardProtocolNegotiationSequence(negotiationSequence)) {
47871
+ if (negotiation && this.handleKeyboardProtocolNegotiationSequence(negotiation.parsed)) {
47793
47872
  return;
47794
47873
  }
47795
- this.forwardInputSequence(sequence);
47874
+ this.forwardInputSequence(negotiation?.sequence ?? sequence);
47796
47875
  });
47797
47876
  this.stdinBuffer.on("paste", (content) => {
47798
47877
  if (this.inputHandler) {
@@ -47820,13 +47899,17 @@ var ProcessTerminal = class {
47820
47899
  this.setupStdinBuffer();
47821
47900
  process.stdin.on("data", this.stdinDataHandler);
47822
47901
  this.keyboardProtocolPushed = true;
47902
+ this.pendingKeyboardProtocolDeviceAttributes += 1;
47823
47903
  this.clearKeyboardProtocolNegotiationBuffer();
47824
47904
  process.stdout.write(KITTY_KEYBOARD_PROTOCOL_QUERY);
47825
47905
  }
47826
47906
  handleKeyboardProtocolNegotiationSequence(negotiationSequence) {
47827
- if (!negotiationSequence)
47828
- return false;
47829
47907
  this.clearKeyboardProtocolNegotiationBuffer();
47908
+ if (negotiationSequence.type === "device-attributes") {
47909
+ if (this.pendingKeyboardProtocolDeviceAttributes === 0)
47910
+ return false;
47911
+ this.pendingKeyboardProtocolDeviceAttributes -= 1;
47912
+ }
47830
47913
  if (negotiationSequence.type === "kitty-flags") {
47831
47914
  if (negotiationSequence.flags !== 0) {
47832
47915
  this.disableModifyOtherKeys();
@@ -47844,13 +47927,14 @@ var ProcessTerminal = class {
47844
47927
  }
47845
47928
  return true;
47846
47929
  }
47930
+ /** Returns the parsed negotiation reply with its full (possibly reassembled) sequence. */
47847
47931
  readKeyboardProtocolNegotiationSequence(sequence) {
47848
47932
  if (this.keyboardProtocolNegotiationBuffer) {
47849
47933
  const bufferedSequence = this.keyboardProtocolNegotiationBuffer + sequence;
47850
47934
  const negotiationSequence2 = parseKeyboardProtocolNegotiationSequence(bufferedSequence);
47851
47935
  if (negotiationSequence2) {
47852
47936
  this.clearKeyboardProtocolNegotiationBuffer();
47853
- return negotiationSequence2;
47937
+ return { parsed: negotiationSequence2, sequence: bufferedSequence };
47854
47938
  }
47855
47939
  if (isKeyboardProtocolNegotiationSequencePrefix(bufferedSequence)) {
47856
47940
  this.setKeyboardProtocolNegotiationBuffer(bufferedSequence);
@@ -47860,7 +47944,7 @@ var ProcessTerminal = class {
47860
47944
  }
47861
47945
  const negotiationSequence = parseKeyboardProtocolNegotiationSequence(sequence);
47862
47946
  if (negotiationSequence)
47863
- return negotiationSequence;
47947
+ return { parsed: negotiationSequence, sequence };
47864
47948
  if (isKeyboardProtocolNegotiationSequencePrefix(sequence)) {
47865
47949
  this.setKeyboardProtocolNegotiationBuffer(sequence);
47866
47950
  return "pending";
@@ -48677,6 +48761,61 @@ function getScrollViewsAt(frame, x2, y2) {
48677
48761
  return result.map((entry) => entry.scrollView);
48678
48762
  }
48679
48763
 
48764
+ // node_modules/@earendil-works/pi-tui/dist/wheel-scroll.js
48765
+ var BURST_GAP_MS = 5;
48766
+ var GESTURE_GAP_MS = 200;
48767
+ var REFERENCE_GAP_MS = 100;
48768
+ var MAX_AUTO_LINES = 6;
48769
+ function terminalAcceleratesWheel() {
48770
+ const env = process.env;
48771
+ return process.platform === "darwin" && env.SSH_CONNECTION === void 0 && env.SSH_CLIENT === void 0 && env.SSH_TTY === void 0;
48772
+ }
48773
+ var WheelScrollAccelerator = class {
48774
+ lines;
48775
+ accelerate;
48776
+ lastTime = Number.NEGATIVE_INFINITY;
48777
+ lastDirection = 0;
48778
+ averageGap;
48779
+ carry = 0;
48780
+ constructor(lines = "auto", accelerate = !terminalAcceleratesWheel()) {
48781
+ this.lines = lines;
48782
+ this.accelerate = accelerate;
48783
+ }
48784
+ setLines(lines) {
48785
+ this.lines = lines;
48786
+ this.reset();
48787
+ }
48788
+ /** Return the positive line count for a wheel event in `direction` at time `now` (milliseconds). */
48789
+ next(direction, now) {
48790
+ if (this.lines !== "auto")
48791
+ return Number.isFinite(this.lines) ? Math.max(1, Math.floor(this.lines)) : 1;
48792
+ if (!this.accelerate)
48793
+ return 1;
48794
+ const gap = now - this.lastTime;
48795
+ const sameGesture = direction === this.lastDirection && gap <= GESTURE_GAP_MS;
48796
+ this.lastTime = now;
48797
+ this.lastDirection = direction;
48798
+ if (!sameGesture) {
48799
+ this.averageGap = void 0;
48800
+ this.carry = 0;
48801
+ return 1;
48802
+ }
48803
+ if (gap < BURST_GAP_MS)
48804
+ return 1;
48805
+ this.averageGap = this.averageGap === void 0 ? gap : (this.averageGap + gap) / 2;
48806
+ const lines = Math.min(MAX_AUTO_LINES, Math.max(1, REFERENCE_GAP_MS / this.averageGap)) + this.carry;
48807
+ const whole = Math.floor(lines);
48808
+ this.carry = lines - whole;
48809
+ return whole;
48810
+ }
48811
+ reset() {
48812
+ this.lastTime = Number.NEGATIVE_INFINITY;
48813
+ this.lastDirection = 0;
48814
+ this.averageGap = void 0;
48815
+ this.carry = 0;
48816
+ }
48817
+ };
48818
+
48680
48819
  // node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js
48681
48820
  var ENTER_ALT_SCREEN = "\x1B[?1049h";
48682
48821
  var EXIT_ALT_SCREEN = "\x1B[?1049l";
@@ -48736,7 +48875,7 @@ var TuiAltScreen = class extends TuiBase {
48736
48875
  mousePressPoint;
48737
48876
  mousePressMoved = false;
48738
48877
  lastComponentClick;
48739
- wheelScrollLines;
48878
+ wheelScroll;
48740
48879
  mouseEnabled;
48741
48880
  searchMatchStyle;
48742
48881
  searchCurrentMatchStyle;
@@ -48758,7 +48897,7 @@ var TuiAltScreen = class extends TuiBase {
48758
48897
  };
48759
48898
  this.implicitScrollView = new ScrollView(this.implicitDocument, { follow: "end", primary: true });
48760
48899
  this.flashes = new AltScreenFlashContainer(() => this.requestRender());
48761
- this.wheelScrollLines = Math.max(1, Math.floor(options.wheelScrollLines ?? 1));
48900
+ this.wheelScroll = new WheelScrollAccelerator(options.wheelScrollLines ?? 1);
48762
48901
  this.mouseEnabled = options.mouse ?? true;
48763
48902
  this.searchMatchStyle = options.searchMatchStyle ?? ((text) => `\x1B[4m${text}\x1B[24m`);
48764
48903
  this.searchCurrentMatchStyle = options.searchCurrentMatchStyle ?? ((text) => `\x1B[1;7m${text}\x1B[22;27m`);
@@ -48776,6 +48915,9 @@ var TuiAltScreen = class extends TuiBase {
48776
48915
  get isFollowingOutput() {
48777
48916
  return this.getPrimaryScrollView().isFollowingEnd;
48778
48917
  }
48918
+ setWheelScrollLines(lines) {
48919
+ this.wheelScroll.setLines(lines);
48920
+ }
48779
48921
  getCopyOnSelect() {
48780
48922
  return this.copyOnSelect;
48781
48923
  }
@@ -48793,6 +48935,10 @@ var TuiAltScreen = class extends TuiBase {
48793
48935
  return false;
48794
48936
  return this.copyTextToClipboard(text);
48795
48937
  }
48938
+ /** The lines of the last rendered frame, one per terminal row, as written to the terminal. */
48939
+ getScreenLines() {
48940
+ return [...this.previousScreen];
48941
+ }
48796
48942
  setLayoutRoot(component) {
48797
48943
  if (this.layoutRoot === component)
48798
48944
  return;
@@ -49135,9 +49281,9 @@ var TuiAltScreen = class extends TuiBase {
49135
49281
  return { consume: true };
49136
49282
  const wheelEvent = this.parseWheelEvent(data);
49137
49283
  if (wheelEvent) {
49138
- const event = this.createMouseEvent("wheel", wheelEvent.button, wheelEvent.x, wheelEvent.y, {
49139
- wheelDelta: wheelEvent.direction * this.getWheelScrollLines(wheelEvent.button)
49140
- });
49284
+ const lines = this.wheelScroll.next(wheelEvent.direction, performance.now());
49285
+ const wheelDelta = wheelEvent.direction * ((wheelEvent.button & 8) !== 0 ? lines * ALT_WHEEL_SCROLL_MULTIPLIER : lines);
49286
+ const event = this.createMouseEvent("wheel", wheelEvent.button, wheelEvent.x, wheelEvent.y, { wheelDelta });
49141
49287
  const overlay = this.dispatchMouseToOverlay(event);
49142
49288
  const result = overlay.result ?? (overlay.hit ? void 0 : this.dispatchMouseToLayout(event));
49143
49289
  if (result) {
@@ -49147,7 +49293,7 @@ var TuiAltScreen = class extends TuiBase {
49147
49293
  }
49148
49294
  if (this.shouldDeferViewportInputToOverlay())
49149
49295
  return void 0;
49150
- this.routeWheel(wheelEvent);
49296
+ this.routeWheel(wheelEvent, wheelDelta);
49151
49297
  return { consume: true };
49152
49298
  }
49153
49299
  const mouseEvent = this.parseSgrMouseEvent(data);
@@ -49410,11 +49556,8 @@ var TuiAltScreen = class extends TuiBase {
49410
49556
  }
49411
49557
  return void 0;
49412
49558
  }
49413
- getWheelScrollLines(button) {
49414
- return (button & 8) !== 0 ? this.wheelScrollLines * ALT_WHEEL_SCROLL_MULTIPLIER : this.wheelScrollLines;
49415
- }
49416
- routeWheel(event) {
49417
- let remaining = event.direction * this.getWheelScrollLines(event.button);
49559
+ routeWheel(event, delta) {
49560
+ let remaining = delta;
49418
49561
  const seen = /* @__PURE__ */ new Set();
49419
49562
  for (const scrollView of this.currentLayout ? getScrollViewsAt(this.currentLayout, event.x, event.y) : []) {
49420
49563
  seen.add(scrollView);
@@ -50035,7 +50178,20 @@ var TuiAltScreen = class extends TuiBase {
50035
50178
  return sliceByColumn(line, 0, width, true);
50036
50179
  });
50037
50180
  const fullRedraw = this.previousScreen.length === 0 || this.previousScreenWidth !== width || this.previousScreenHeight !== height;
50038
- const imagesNeedRedraw = screen.some((line, row) => line !== this.previousScreen[row] && (isImageLine(line) || isImageLine(this.previousScreen[row] ?? "")));
50181
+ const changedRows = screen.map((line, row) => line !== this.previousScreen[row]);
50182
+ const imageAnchorsNeedRedraw = screen.some((line, row) => changedRows[row] && (isImageLine(line) || isImageLine(this.previousScreen[row] ?? "")));
50183
+ const isWezTerm = Boolean(process.env.WEZTERM_PANE) || process.env.TERM_PROGRAM?.toLowerCase() === "wezterm";
50184
+ const imageCellsNeedRedraw = !imageAnchorsNeedRedraw && isWezTerm && this.imageProtocol === "kitty" && changedRows.some(Boolean) && screen.some((line, row) => {
50185
+ const placementRows = getKittyImagePlacementRows(line);
50186
+ if (placementRows === void 0)
50187
+ return false;
50188
+ for (let coveredRow = row; coveredRow < row + placementRows; coveredRow++) {
50189
+ if (changedRows[coveredRow])
50190
+ return true;
50191
+ }
50192
+ return false;
50193
+ });
50194
+ const imagesNeedRedraw = imageAnchorsNeedRedraw || imageCellsNeedRedraw;
50039
50195
  const redrawImages = fullRedraw || imagesNeedRedraw;
50040
50196
  const hadUploadedKittyImages = this.uploadedKittyImages.size > 0;
50041
50197
  const preparedKittyScreen = redrawImages && this.imageProtocol === "kitty" ? this.prepareKittyScreen(screen) : { lines: screen, evictedImageDeletion: "" };
@@ -50051,18 +50207,33 @@ var TuiAltScreen = class extends TuiBase {
50051
50207
  buffer += deleteAllKittyPlacements();
50052
50208
  }
50053
50209
  buffer += preparedKittyScreen.evictedImageDeletion;
50054
- const clearRowsBeforeKittyImages = redrawImages && this.imageProtocol === "kitty" && screen.some(isImageLine) && (Boolean(process.env.WEZTERM_PANE) || process.env.TERM_PROGRAM?.toLowerCase() === "wezterm");
50055
- if (clearRowsBeforeKittyImages) {
50210
+ const drawKittyImagesLast = redrawImages && this.imageProtocol === "kitty" && screen.some(isImageLine) && isWezTerm;
50211
+ if (drawKittyImagesLast) {
50056
50212
  for (let row = 0; row < height; row++) {
50057
50213
  if (!fullRedraw && !imagesNeedRedraw && screen[row] === this.previousScreen[row])
50058
50214
  continue;
50059
50215
  buffer += `\x1B[${row + 1};1H\x1B[2K`;
50060
50216
  }
50061
- }
50062
- for (let row = 0; row < height; row++) {
50063
- if (!fullRedraw && !imagesNeedRedraw && screen[row] === this.previousScreen[row])
50064
- continue;
50065
- buffer += `\x1B[${row + 1};1H${clearRowsBeforeKittyImages ? "" : "\x1B[2K"}${preparedKittyScreen.lines[row] ?? ""}`;
50217
+ for (let row = 0; row < height; row++) {
50218
+ if (!fullRedraw && !imagesNeedRedraw && screen[row] === this.previousScreen[row])
50219
+ continue;
50220
+ if (isImageLine(preparedKittyScreen.lines[row] ?? ""))
50221
+ continue;
50222
+ buffer += `\x1B[${row + 1};1H${preparedKittyScreen.lines[row] ?? ""}`;
50223
+ }
50224
+ for (let row = 0; row < height; row++) {
50225
+ if (!fullRedraw && !imagesNeedRedraw && screen[row] === this.previousScreen[row])
50226
+ continue;
50227
+ if (!isImageLine(preparedKittyScreen.lines[row] ?? ""))
50228
+ continue;
50229
+ buffer += `\x1B[${row + 1};1H${preparedKittyScreen.lines[row] ?? ""}`;
50230
+ }
50231
+ } else {
50232
+ for (let row = 0; row < height; row++) {
50233
+ if (!fullRedraw && !imagesNeedRedraw && screen[row] === this.previousScreen[row])
50234
+ continue;
50235
+ buffer += `\x1B[${row + 1};1H\x1B[2K${preparedKittyScreen.lines[row] ?? ""}`;
50236
+ }
50066
50237
  }
50067
50238
  if (cursorPos) {
50068
50239
  buffer += `\x1B[${cursorPos.row + 1};${Math.min(width, cursorPos.col) + 1}H`;
@@ -25461,7 +25461,7 @@ function sessionTokenFixHint(policy) {
25461
25461
  }
25462
25462
 
25463
25463
  // plugins/kxm/src/mcp-server.ts
25464
- var VERSION = "0.7.176";
25464
+ var VERSION = "0.7.177";
25465
25465
  var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
25466
25466
  var inbox = /* @__PURE__ */ new Map();
25467
25467
  var notifiedInbox = /* @__PURE__ */ new Set();
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin",
3
- "version": "0.7.176",
3
+ "version": "0.7.177",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -11,7 +11,7 @@ import { deliverInboxNotification } from "./inbox.ts";
11
11
  import type { HubEvent, MessageRecord } from "./protocol.ts";
12
12
  import { sessionTokenFixHint } from "./session-token-hint.ts";
13
13
 
14
- const VERSION = "0.7.176";
14
+ const VERSION = "0.7.177";
15
15
  const CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
16
16
  const inbox = new Map<string, MessageRecord>();
17
17
  const notifiedInbox = new Set<string>();