sisyphi 1.1.0 → 1.1.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/tui.js CHANGED
@@ -396,7 +396,7 @@ function autoExpandCycle(state2) {
396
396
  }
397
397
 
398
398
  // src/tui/app.ts
399
- import { readFileSync as readFileSync2, existsSync as existsSync2, readdirSync } from "fs";
399
+ import { readFileSync as readFileSync2, existsSync as existsSync2, readdirSync, statSync } from "fs";
400
400
  import { join as join3 } from "path";
401
401
 
402
402
  // src/tui/lib/tree.ts
@@ -582,30 +582,32 @@ function wrapText(text, width) {
582
582
  result.push(rawLine);
583
583
  continue;
584
584
  }
585
- let remaining = rawLine;
586
- while (stringWidth(remaining) > width) {
587
- let breakAt = -1;
588
- let estimate = Math.min(remaining.length, width);
589
- for (let i = estimate; i >= 0; i--) {
590
- if (remaining[i] === " " && stringWidth(remaining.slice(0, i)) <= width) {
591
- breakAt = i;
592
- break;
593
- }
594
- }
595
- if (breakAt <= 0) {
596
- breakAt = remaining.length;
597
- for (let i = 1; i <= remaining.length; i++) {
598
- if (stringWidth(remaining.slice(0, i)) > width) {
599
- breakAt = i - 1;
600
- break;
601
- }
585
+ let lineStart = 0;
586
+ let lastSpace = -1;
587
+ let displayWidth = 0;
588
+ for (let i = 0; i < rawLine.length; i++) {
589
+ const charWidth = stringWidth(rawLine[i]);
590
+ displayWidth += charWidth;
591
+ if (rawLine[i] === " ") lastSpace = i;
592
+ if (displayWidth > width) {
593
+ let breakAt;
594
+ if (lastSpace > lineStart) {
595
+ breakAt = lastSpace;
596
+ result.push(rawLine.slice(lineStart, breakAt));
597
+ lineStart = breakAt + 1;
598
+ while (lineStart < rawLine.length && rawLine[lineStart] === " ") lineStart++;
599
+ } else {
600
+ breakAt = Math.max(lineStart + 1, i);
601
+ result.push(rawLine.slice(lineStart, breakAt));
602
+ lineStart = breakAt;
602
603
  }
603
- if (breakAt <= 0) breakAt = 1;
604
+ displayWidth = stringWidth(rawLine.slice(lineStart, i + 1));
605
+ lastSpace = -1;
604
606
  }
605
- result.push(remaining.slice(0, breakAt));
606
- remaining = remaining.slice(breakAt).trimStart();
607
607
  }
608
- if (remaining) result.push(remaining);
608
+ if (lineStart < rawLine.length) {
609
+ result.push(rawLine.slice(lineStart));
610
+ }
609
611
  }
610
612
  return result;
611
613
  }
@@ -2887,6 +2889,8 @@ var latestNodes = [];
2887
2889
  var cachedContextFilePath = null;
2888
2890
  var cachedContextFileContent = null;
2889
2891
  var prevFrame = [];
2892
+ var cachedLogSessionId = null;
2893
+ var cachedLogFiles = /* @__PURE__ */ new Map();
2890
2894
  function getAgentForNode(node, agents) {
2891
2895
  if (!node) return null;
2892
2896
  if (node.type === "agent" || node.type === "report") {
@@ -2955,12 +2959,29 @@ function startApp(state2, cleanup2) {
2955
2959
  try {
2956
2960
  const ld = logsDir(state2.cwd, state2.selectedSessionId);
2957
2961
  if (existsSync2(ld)) {
2962
+ if (state2.selectedSessionId !== cachedLogSessionId) {
2963
+ cachedLogFiles = /* @__PURE__ */ new Map();
2964
+ cachedLogSessionId = state2.selectedSessionId;
2965
+ }
2958
2966
  const files = readdirSync(ld).filter((f) => f.startsWith("cycle-")).sort();
2967
+ const fileSet = new Set(files);
2968
+ for (const key of cachedLogFiles.keys()) {
2969
+ if (!fileSet.has(key)) cachedLogFiles.delete(key);
2970
+ }
2971
+ for (const f of files) {
2972
+ const filePath = join3(ld, f);
2973
+ const mtime = statSync(filePath).mtimeMs;
2974
+ const cached = cachedLogFiles.get(f);
2975
+ if (!cached || cached.mtime !== mtime) {
2976
+ const match = f.match(/cycle-(\d+)\.md$/);
2977
+ const cycle = match ? parseInt(match[1], 10) : 0;
2978
+ const content = readFileSync2(filePath, "utf-8");
2979
+ cachedLogFiles.set(f, { mtime, cycle, content });
2980
+ }
2981
+ }
2959
2982
  logsCycles = files.map((f) => {
2960
- const match = f.match(/cycle-(\d+)\.md$/);
2961
- const cycle = match ? parseInt(match[1], 10) : 0;
2962
- const content = readFileSync2(join3(ld, f), "utf-8");
2963
- return { cycle, content };
2983
+ const entry = cachedLogFiles.get(f);
2984
+ return { cycle: entry.cycle, content: entry.content };
2964
2985
  });
2965
2986
  logsContent = logsCycles.map((c) => c.content).join("\n");
2966
2987
  }
@@ -3150,10 +3171,10 @@ function startApp(state2, cleanup2) {
3150
3171
  }
3151
3172
  };
3152
3173
  setRenderFunction(render);
3153
- startKeypressListener((input, key) => {
3174
+ const stopKeypress = startKeypressListener((input, key) => {
3154
3175
  handleKeypress(input, key, state2, inputActions);
3155
3176
  });
3156
- onResize(() => {
3177
+ const stopResize = onResize(() => {
3157
3178
  const stdoutRows = process.stdout.rows;
3158
3179
  const stdoutCols = process.stdout.columns;
3159
3180
  state2.rows = typeof stdoutRows === "number" && stdoutRows > 0 ? stdoutRows : 24;
@@ -3162,7 +3183,16 @@ function startApp(state2, cleanup2) {
3162
3183
  requestRender();
3163
3184
  });
3164
3185
  void poll();
3165
- setInterval(() => void poll(), 2500);
3186
+ const pollInterval = setInterval(() => void poll(), 2500);
3187
+ const origCleanup = inputActions.cleanup;
3188
+ inputActions.cleanup = () => {
3189
+ clearInterval(pollInterval);
3190
+ stopKeypress();
3191
+ stopResize();
3192
+ state2.detailScroll.destroy();
3193
+ state2.logsScroll.destroy();
3194
+ origCleanup();
3195
+ };
3166
3196
  requestRender();
3167
3197
  }
3168
3198