mocode-ai 0.5.2 → 0.5.3

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.
@@ -131,6 +131,11 @@ export function sliceFromEnd(offset, count) {
131
131
  export function totalRows() {
132
132
  return rows.length + (hasCurrent ? 1 : 0);
133
133
  }
134
+ /** 已提交行数(不含 hasCurrent 空行)。供续写位校正:breakRow 后 hasCurrent=true 时光标已在
135
+ * rows.length+1 位,若用 totalRows()+1 会多跳 1 行(2 空行 bug)。 */
136
+ export function committedRows() {
137
+ return rows.length;
138
+ }
134
139
  /** 取绝对行索引(0-based,含当前行)的原始自洽行;越界返 null。供鼠标选区文本提取。 */
135
140
  export function lineAt(abs) {
136
141
  const all = snapshot();
package/dist/ui/layout.js CHANGED
@@ -191,13 +191,15 @@ export function contentWrite(s) {
191
191
  const bottom = g.contentBottom;
192
192
  // resize 后 contentRow 可能过时(拖终端框):
193
193
  // - 缩小:contentRow > 新 bottom → 钳到新 bottom
194
- // - 放大:contentRow < 新 bottom 且回尾 → 推进到 min(total+1, bottom)
195
- // total+1 是合法「待写位」(所有行已 breakRow 提交、光标在新空行);用 total 会把续写位拉回到
194
+ // - 放大:contentRow < 新 bottom 且回尾 → 推进到 min(committed+1, bottom)
195
+ // committed+1 是合法「待写位」(所有行已 breakRow 提交、光标在新空行);用 committed 会把续写位拉回到
196
196
  // 最后一行 banner/content 上,首次 contentWrite 覆盖 banner(首条消息「插到 logo 下面」bug)。
197
+ // 注意:不能用 totalRows()+1——breakRow 后 hasCurrent=true,totalRows 已含当前空行,再 +1 会多跳一行,
198
+ // 导致 onDone 摘要行等写 \n 后的 contentWrite 入口多跳 1 行(2 空行 bug)。
197
199
  if (contentRow > bottom)
198
200
  contentRow = bottom;
199
201
  else if (scrollOffset === 0 && contentRow < bottom) {
200
- contentRow = Math.min(content.totalRows() + 1, bottom);
202
+ contentRow = Math.min(content.committedRows() + 1, bottom);
201
203
  }
202
204
  const startRow = contentRow;
203
205
  const startCol = contentCol;
@@ -1422,11 +1424,13 @@ export function paintLiveAtCursor(text) {
1422
1424
  // 首次 contentWrite 覆盖 banner(首条消息「插到 logo 下面」bug)。
1423
1425
  // 否则 cup 到旧行号→帧画在屏幕中间(旧 bottom 位置),而非内容末尾/最底部。
1424
1426
  const g = getGeo();
1425
- const total = content.totalRows();
1427
+ const committed = content.committedRows();
1426
1428
  if (contentRow > g.contentBottom)
1427
1429
  contentRow = g.contentBottom;
1428
1430
  if (scrollOffset === 0 && contentRow < g.contentBottom) {
1429
- contentRow = Math.min(total + 1, g.contentBottom);
1431
+ // committed+1 而非 total+1:breakRow 后 hasCurrent=true,totalRows 已含当前空行,+1 会多跳一行
1432
+ // (contentWrite 入口的同类逻辑已同步修正,见上方注释)。
1433
+ contentRow = Math.min(committed + 1, g.contentBottom);
1430
1434
  }
1431
1435
  let out = '';
1432
1436
  if (frameRow && (frameRow !== contentRow || frameCol !== contentCol)) {
@@ -1859,13 +1863,14 @@ export function enterAltScreen() {
1859
1863
  // 重画 repaintViewport 防抖(下面 timer),避免连续拖动闪烁;但行号/区域必须立即正确。
1860
1864
  const g = getGeo(footerH);
1861
1865
  const total = content.totalRows();
1866
+ const committed = content.committedRows();
1862
1867
  // 缩小:contentRow > 新 bottom → 钳到新 bottom
1863
1868
  if (contentRow > g.contentBottom)
1864
1869
  contentRow = g.contentBottom;
1865
- // 放大:contentRow < 新 bottom 且回尾(offset=0)→ 推进到 min(total+1, bottom)
1866
- // total+1 是合法「待写位」;用 total 会把续写位拉回最后一行,首次 contentWrite 覆盖 banner
1870
+ // 放大:contentRow < 新 bottom 且回尾(offset=0)→ 推进到 min(committed+1, bottom)
1871
+ // committed+1 是合法「待写位」;用 total+1 hasCurrent=true(breakRow 后)时会多跳一行。
1867
1872
  if (scrollOffset === 0 && contentRow < g.contentBottom) {
1868
- contentRow = Math.min(total + 1, g.contentBottom);
1873
+ contentRow = Math.min(committed + 1, g.contentBottom);
1869
1874
  }
1870
1875
  if (frameRow && frameRow > g.contentBottom)
1871
1876
  frameRow = g.contentBottom;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocode-ai",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "终端编码 agent:LLM + tool-call 循环 + 流式输出(含思考)+ 16 个工具,接任意 OpenAI 兼容后端。",
5
5
  "type": "module",
6
6
  "bin": {