@zhongqian97-code/ecode 0.5.56 → 0.5.58

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.js CHANGED
@@ -814,7 +814,7 @@ if (rawArgs[0] === "web") {
814
814
  webAutoApprove = true;
815
815
  }
816
816
  }
817
- const { buildServer, generateAccessToken } = await import("./web-XPP3PJJZ.js");
817
+ const { buildServer, generateAccessToken } = await import("./web-3CS3TO2E.js");
818
818
  const token = finalConfig.webToken ?? generateAccessToken();
819
819
  const manager = new SessionManager(finalConfig);
820
820
  const __webDirname = dirname(fileURLToPath(import.meta.url));
@@ -923,7 +923,7 @@ Node.js 16/18 \u8BF7\u4F7F\u7528 --web \u6216 --pipe \u6A21\u5F0F\u3002
923
923
  );
924
924
  process.exit(1);
925
925
  }
926
- const { App, React, render, createStdinFilter } = await import("./ui-YEBPUMP7.js");
926
+ const { App, React, render, createStdinFilter } = await import("./ui-STSJVDXD.js");
927
927
  const stdinFilter = process.stdin.isTTY ? createStdinFilter(process.stdin) : process.stdin;
928
928
  render(
929
929
  React.createElement(App, { config: finalConfig, version: VERSION, autoMode, registry, trustedSkillDirs, initialMessages, stdinFilter }),
@@ -200,6 +200,7 @@ function StatusBar({
200
200
  import { Box as Box2, Text as Text2 } from "ink";
201
201
 
202
202
  // src/ui/messageLines.ts
203
+ import stringWidth from "string-width";
203
204
  var TOOL_RESULT_MAX_LINES = 3;
204
205
  function wrapText(text, terminalWidth) {
205
206
  const logicalLines = text.split("\n");
@@ -210,9 +211,20 @@ function wrapText(text, terminalWidth) {
210
211
  result.push("");
211
212
  continue;
212
213
  }
213
- for (let i = 0; i < line.length; i += terminalWidth) {
214
- result.push(line.slice(i, i + terminalWidth));
214
+ let chunk = "";
215
+ let chunkW = 0;
216
+ for (const ch of line) {
217
+ const w = stringWidth(ch);
218
+ if (chunkW + w > terminalWidth && chunk.length > 0) {
219
+ result.push(chunk);
220
+ chunk = ch;
221
+ chunkW = w;
222
+ } else {
223
+ chunk += ch;
224
+ chunkW += w;
225
+ }
215
226
  }
227
+ if (chunk.length > 0) result.push(chunk);
216
228
  }
217
229
  return result;
218
230
  }
@@ -853,6 +865,28 @@ ${blocks.join("\n\n")}`;
853
865
  ${contextSection}` : contextSection;
854
866
  }
855
867
 
868
+ // src/ui/mouseCoords.ts
869
+ var STATUS_BAR_ROWS = 1;
870
+ function computeVisibleWindow(totalLines, scrollOffset, historyMaxHeight) {
871
+ const end = Math.max(0, Math.min(totalLines, totalLines - scrollOffset));
872
+ const initialStart = Math.max(0, end - historyMaxHeight);
873
+ const hasScrollIndicator = initialStart > 0 && historyMaxHeight > 1;
874
+ const start = hasScrollIndicator ? Math.max(0, end - (historyMaxHeight - 1)) : initialStart;
875
+ const visibleCount = (hasScrollIndicator ? 1 : 0) + (end - start);
876
+ return { start, end, visibleCount, hasScrollIndicator };
877
+ }
878
+ function mouseRowToLineIndex(opts) {
879
+ if (opts.visibleCount <= 0) return null;
880
+ const bottomRows = STATUS_BAR_ROWS + opts.skillAcRows + opts.fileAcRows + opts.selectedItemsRows + opts.inputRows;
881
+ const innerBoxHeight = opts.terminalRows - bottomRows;
882
+ const chTopRow = innerBoxHeight - opts.visibleCount;
883
+ const chBottomRow = innerBoxHeight - 1;
884
+ if (opts.mouseRow < chTopRow || opts.mouseRow > chBottomRow) return null;
885
+ const indicatorOffset = opts.hasScrollIndicator ? 1 : 0;
886
+ if (opts.mouseRow < chTopRow + indicatorOffset) return null;
887
+ return opts.mouseRow - chTopRow - indicatorOffset;
888
+ }
889
+
856
890
  // src/ui/App.tsx
857
891
  import { homedir as homedir2 } from "os";
858
892
  import { join as join5 } from "path";
@@ -2439,6 +2473,12 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2439
2473
  historyMaxHeightRef.current = historyMaxHeight;
2440
2474
  const selectionStateRef = useRef2(selectionState);
2441
2475
  selectionStateRef.current = selectionState;
2476
+ const inputRowsRef = useRef2(1);
2477
+ const skillAcRowsRef = useRef2(0);
2478
+ const fileAcRowsRef = useRef2(0);
2479
+ const selectedItemsRowsRef = useRef2(0);
2480
+ const terminalRowsRef = useRef2((stdout == null ? void 0 : stdout.rows) ?? 24);
2481
+ terminalRowsRef.current = (stdout == null ? void 0 : stdout.rows) ?? 24;
2442
2482
  const pendingConfirmRef = useRef2(null);
2443
2483
  const abortControllerRef = useRef2(null);
2444
2484
  const llmRef = useRef2(llmClient ?? createProvider(resolveActiveProfile(config)));
@@ -2520,13 +2560,22 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2520
2560
  }
2521
2561
  return;
2522
2562
  }
2523
- const totalL = totalLinesRef.current;
2524
- const scrollOff = scrollOffsetRef.current;
2525
- const histH = historyMaxHeightRef.current;
2526
- const visibleCount = Math.min(Math.max(0, totalL - scrollOff), histH);
2527
- const contentStartRow = histH - visibleCount;
2528
- const lineIdx = e.row - contentStartRow;
2529
- if (lineIdx < 0 || lineIdx >= visibleCount) return;
2563
+ const window = computeVisibleWindow(
2564
+ totalLinesRef.current,
2565
+ scrollOffsetRef.current,
2566
+ historyMaxHeightRef.current
2567
+ );
2568
+ const lineIdx = mouseRowToLineIndex({
2569
+ mouseRow: e.row,
2570
+ terminalRows: terminalRowsRef.current,
2571
+ inputRows: inputRowsRef.current,
2572
+ skillAcRows: skillAcRowsRef.current,
2573
+ fileAcRows: fileAcRowsRef.current,
2574
+ selectedItemsRows: selectedItemsRowsRef.current,
2575
+ visibleCount: window.visibleCount,
2576
+ hasScrollIndicator: window.hasScrollIndicator
2577
+ });
2578
+ if (lineIdx === null) return;
2530
2579
  const pt = { row: lineIdx, col: e.col };
2531
2580
  if (e.type === "leftDown") setSelectionState(startSelection(selectionStateRef.current, pt));
2532
2581
  else if (e.type === "leftDrag") setSelectionState(updateSelection(selectionStateRef.current, pt));
@@ -2541,11 +2590,8 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2541
2590
  if (selectionState.dragging || !selectionState.anchor || !selectionState.focus) return;
2542
2591
  const visible = messages.filter((m) => m.role !== "system");
2543
2592
  const allLines = visible.flatMap((msg) => messageToLines(msg, expandTools, (stdout == null ? void 0 : stdout.columns) ?? 0));
2544
- const totalL = allLines.length;
2545
- const end = Math.max(0, Math.min(totalL, totalL - scrollOffset));
2546
- const histH = historyMaxHeight;
2547
- const start = Math.max(0, end - histH);
2548
- const lineTexts = allLines.slice(start, end).map((l) => l.text);
2593
+ const window = computeVisibleWindow(allLines.length, scrollOffset, historyMaxHeight);
2594
+ const lineTexts = allLines.slice(window.start, window.end).map((l) => l.text);
2549
2595
  const text = extractSelectedText(lineTexts, selectionState);
2550
2596
  if (text && stdout) {
2551
2597
  const b64 = Buffer.from(text, "utf8").toString("base64");
@@ -2999,6 +3045,7 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2999
3045
  } else {
3000
3046
  historyIndexRef.current = -1;
3001
3047
  }
3048
+ inputRowsRef.current = Math.max(1, text.split("\n").length);
3002
3049
  if (status !== "awaiting_confirm") {
3003
3050
  setAcState((prev) => handleInputChange(prev, text));
3004
3051
  setFileAcState((prev) => handleInputChange2(prev, text));
@@ -3006,6 +3053,10 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
3006
3053
  }, [status]);
3007
3054
  const skillSuggestions = registry ? computeSuggestions(registry.list(), acState) : [];
3008
3055
  const acOpen = isOpen(acState, skillSuggestions);
3056
+ const facOpen = isOpen2(fileAcState, fileSuggestions);
3057
+ skillAcRowsRef.current = acOpen ? skillSuggestions.length + 2 : 0;
3058
+ fileAcRowsRef.current = facOpen ? fileSuggestions.length + 2 : 0;
3059
+ selectedItemsRowsRef.current = selectedItems.length > 0 ? 1 : 0;
3009
3060
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: "100%", children: [
3010
3061
  /* @__PURE__ */ jsx6(Box6, { flexGrow: 1, flexDirection: "column", justifyContent: "flex-end", children: /* @__PURE__ */ jsx6(
3011
3062
  ConversationHistory,
@@ -3041,7 +3092,7 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
3041
3092
  {
3042
3093
  suggestions: fileSuggestions,
3043
3094
  selectedIndex: fileAcState.selectedIndex,
3044
- isOpen: isOpen2(fileAcState, fileSuggestions)
3095
+ isOpen: facOpen
3045
3096
  }
3046
3097
  ),
3047
3098
  selectedItems.length > 0 && /* @__PURE__ */ jsx6(Box6, { paddingLeft: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "cyan", dimColor: true, children: [
@@ -221,6 +221,15 @@ function generateAdminHtml(version) {
221
221
  font-size: 12px;
222
222
  overflow: hidden;
223
223
  margin: 4px 0;
224
+ /* #messages \u662F flex column \u5BB9\u5668\uFF0Cflex item \u9ED8\u8BA4 flex-shrink:1\u3002
225
+ * .tool-box \u6709 overflow:hidden \u4F1A\u8BA9 min-height \u9ED8\u8BA4\u5F52 0\uFF08CSS Flexbox \u89C4\u8303\uFF09\uFF0C
226
+ * \u7D2F\u79EF\u591A\u4E2A tool-box \u65F6\u6574\u5217\u88AB\u6324\u538B\uFF0Cbody \u88AB\u88C1\u6389\u5BFC\u81F4"\u6846\u9AD8\u5EA6\u53D8\u6210\u4E00\u6761\u7EBF"\u3002
227
+ * flex-shrink:0 \u5F3A\u5236\u4FDD\u7559\u81EA\u7136\u9AD8\u5EA6\uFF0C\u7531 #messages \u7684 overflow-y:auto \u6EDA\u52A8\u3002 */
228
+ flex-shrink: 0;
229
+ }
230
+ .thinking-block,
231
+ .msg {
232
+ flex-shrink: 0;
224
233
  }
225
234
  .tool-box-header {
226
235
  background: #21262d;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhongqian97-code/ecode",
3
- "version": "0.5.56",
3
+ "version": "0.5.58",
4
4
  "description": "A minimal Claude Code clone with REPL interface and bash tool calling",
5
5
  "type": "module",
6
6
  "author": "zhongqian97-code",
@@ -49,7 +49,8 @@
49
49
  "fastify": "^5.8.5",
50
50
  "ink": "^7.0.2",
51
51
  "openai": "^4.0.0",
52
- "react": "^19.2.5"
52
+ "react": "^19.2.5",
53
+ "string-width": "^8.2.1"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@playwright/test": "^1.60.0",