mocode-ai 1.5.13 → 1.6.0
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/agent/spawn.js +2 -1
- package/dist/tools/jev-client.js +1 -3
- package/dist/ui/batch.js +25 -16
- package/package.json +1 -1
package/dist/agent/spawn.js
CHANGED
|
@@ -172,7 +172,8 @@ export async function spawnAgent(opts) {
|
|
|
172
172
|
const childIndex = parentId ? batch.getGroupChildIndex(opts.callId) : undefined;
|
|
173
173
|
liveBatchId = batch.beginBatch(t('subagent.running'), {
|
|
174
174
|
parentId,
|
|
175
|
-
|
|
175
|
+
// 子批摘要行缩进 = 两层 entry 缩进(随 ENTRY_INDENT 联动,不硬编码空格数)。
|
|
176
|
+
indent: parentId ? batch.SUB_BATCH_INDENT : undefined,
|
|
176
177
|
groupChildIndex: childIndex,
|
|
177
178
|
running: true,
|
|
178
179
|
});
|
package/dist/tools/jev-client.js
CHANGED
|
@@ -157,9 +157,7 @@ export async function askJev(request) {
|
|
|
157
157
|
inheritPrevious = finiteProbability(inheritAnswer.noul);
|
|
158
158
|
}
|
|
159
159
|
const usage = record.usage && typeof record.usage === 'object' ? record.usage : {};
|
|
160
|
-
const inputTokens = typeof usage.input_tokens === 'number' && Number.isFinite(usage.input_tokens)
|
|
161
|
-
? usage.input_tokens
|
|
162
|
-
: undefined;
|
|
160
|
+
const inputTokens = typeof usage.input_tokens === 'number' && Number.isFinite(usage.input_tokens) ? usage.input_tokens : undefined;
|
|
163
161
|
return {
|
|
164
162
|
ok: true,
|
|
165
163
|
probabilities,
|
package/dist/ui/batch.js
CHANGED
|
@@ -413,7 +413,7 @@ function buildSummaryLine(record, live = false) {
|
|
|
413
413
|
/** 把 batch 的详情行展开成自洽行数组(供 layout.contentInsertAfter 走 mid-buffer 插入)。
|
|
414
414
|
* 每行末尾必须以 \x1B[0m 收尾(SGR 自洽模型),行内允许含 SGR(行末 reset 不影响行内样式),
|
|
415
415
|
* 但**绝不**带 \n——rows[] 是行数组,不是流输出。 */
|
|
416
|
-
function buildEntryDetailLines(e, indent =
|
|
416
|
+
function buildEntryDetailLines(e, indent = DETAIL_INDENT) {
|
|
417
417
|
const lines = [];
|
|
418
418
|
if (e.diffBlock) {
|
|
419
419
|
// diff 块多行文本(由 renderFileChange 渲染);按 \n 拆成物理行,
|
|
@@ -478,8 +478,16 @@ const CARET_COLLAPSED = '▸';
|
|
|
478
478
|
const CARET_EXPANDED = '▾';
|
|
479
479
|
/** 无详情可展开时占位,保持与 "▸ " 同宽,让工具名列对齐。 */
|
|
480
480
|
const CARET_NONE = ' ';
|
|
481
|
-
/**
|
|
482
|
-
|
|
481
|
+
/** 第一层(工具调用行)相对摘要行的前导缩进:2 空格。
|
|
482
|
+
* 曾为 4 空格——摘要行(`◆ 探索 …`)与工具调用行之间留白过大,工具名被推得过右(用户实测反馈);
|
|
483
|
+
* 子批再叠 8 空格后层级被拉散。收成 2 空格后每层固定递进 2 列,层级仍清晰但不空旷。 */
|
|
484
|
+
const ENTRY_INDENT = ' ';
|
|
485
|
+
/** 子 agent 批摘要行的缩进(= 两层 entry 缩进)。
|
|
486
|
+
* 子批摘要挂在父批的 entry 行之下,是第二层;硬编码会与 ENTRY_INDENT 脱钩,
|
|
487
|
+
* 故由 ENTRY_INDENT 推得。 */
|
|
488
|
+
export const SUB_BATCH_INDENT = ENTRY_INDENT + ENTRY_INDENT;
|
|
489
|
+
/** 详情行缩进:5 空格(对齐 entry 行的 " ▸ " 之后再右移一列,形成层次)。 */
|
|
490
|
+
const DETAIL_INDENT = ' ';
|
|
483
491
|
/**
|
|
484
492
|
* 详情行结果标记:·(U+00B7 MIDDLE DOT, Latin-1 Supplement, **EAW = Narrow**)。
|
|
485
493
|
* 比 ▸/▾ 更稳——Narrow 是 Unicode 层面的硬保证,不依赖字体对 Ambiguous 的取舍。
|
|
@@ -504,7 +512,7 @@ function buildEntryLine(b, index, extraIndent = '', cols = maxCols) {
|
|
|
504
512
|
const result = e.resultSummary ? ` ${ui.gray}↳ ${e.resultSummary}${ui.reset}` : '';
|
|
505
513
|
const caret = entryCaret(e, b.expandedEntries.has(index));
|
|
506
514
|
const failure = e.failed ? `${ui.red}×${ui.reset} ` : '';
|
|
507
|
-
return sanitizeRow(`${extraIndent}
|
|
515
|
+
return sanitizeRow(`${extraIndent}${ENTRY_INDENT}${caret}${failure}${ui.accent}${e.name}${ui.reset} ${ui.dim}${e.callSummary}${ui.reset}${result}`, cols);
|
|
508
516
|
}
|
|
509
517
|
/** 第一层只展示有哪些调用及其简短结果,不展开完整输出。extraIndent 供子批嵌套加深缩进。
|
|
510
518
|
* fromIndex:运行态追加渲染时只产出 entries[fromIndex, ...) 的行(已渲染的不能重复输出)。 */
|
|
@@ -515,9 +523,11 @@ export function buildExpandedLines(b, extraIndent = '', fromIndex = 0, cols = ma
|
|
|
515
523
|
out.push(buildEntryLine(b, i, extraIndent, cols));
|
|
516
524
|
return out;
|
|
517
525
|
}
|
|
518
|
-
/** 详情行缩进(
|
|
519
|
-
|
|
520
|
-
|
|
526
|
+
/** 详情行缩进(随批层级联动):批量缩进 + 5 空格。
|
|
527
|
+
* 5 = ENTRY_INDENT(2) + caret 宽(2) + 1,即相对 entry 行的工具名右移一列形成层次。
|
|
528
|
+
* 必须跟随 b.indent——否则子批(挂在父批下、entry 行更深)的详情行会跑回父层左侧(错位)。 */
|
|
529
|
+
function entryDetailIndent(indent) {
|
|
530
|
+
return indent + DETAIL_INDENT;
|
|
521
531
|
}
|
|
522
532
|
/** 在 batch 收尾时(onToolBatchEnd):写摘要行 + 登记 summaryAbsIdx;若已展开(回放场景)立即插详情。 */
|
|
523
533
|
export function endBatch(id, layout) {
|
|
@@ -684,7 +694,7 @@ export function refreshBatchExpanded(id, layout) {
|
|
|
684
694
|
let anchor = b.summaryAbsIdx + b.renderedCount;
|
|
685
695
|
for (const j of b.expandedEntries) {
|
|
686
696
|
if (j < b.renderedCount) {
|
|
687
|
-
anchor += buildEntryDetailLines(b.entries[j], entryDetailIndent(b.
|
|
697
|
+
anchor += buildEntryDetailLines(b.entries[j], entryDetailIndent(b.indent ?? '')).length;
|
|
688
698
|
}
|
|
689
699
|
}
|
|
690
700
|
if (b.groupParent) {
|
|
@@ -694,8 +704,7 @@ export function refreshBatchExpanded(id, layout) {
|
|
|
694
704
|
continue;
|
|
695
705
|
// entry 行自身(含其二层明细)的块末位置
|
|
696
706
|
const end = b.expandedEntries.has(target.entryIndex)
|
|
697
|
-
? idx +
|
|
698
|
-
buildEntryDetailLines(b.entries[target.entryIndex], entryDetailIndent(b.entries, target.entryIndex)).length
|
|
707
|
+
? idx + buildEntryDetailLines(b.entries[target.entryIndex], entryDetailIndent(b.indent ?? '')).length
|
|
699
708
|
: idx;
|
|
700
709
|
if (end > maxIdx)
|
|
701
710
|
maxIdx = end;
|
|
@@ -706,7 +715,7 @@ export function refreshBatchExpanded(id, layout) {
|
|
|
706
715
|
if (expandedBatches.has(child.id)) {
|
|
707
716
|
childEnd += child.renderedCount;
|
|
708
717
|
for (const j of child.expandedEntries) {
|
|
709
|
-
childEnd += buildEntryDetailLines(child.entries[j], entryDetailIndent(child.
|
|
718
|
+
childEnd += buildEntryDetailLines(child.entries[j], entryDetailIndent(child.indent ?? '')).length;
|
|
710
719
|
}
|
|
711
720
|
}
|
|
712
721
|
if (childEnd > maxIdx)
|
|
@@ -780,7 +789,7 @@ export function expandSingleEntryFully(id, layout) {
|
|
|
780
789
|
const b = batches.get(id);
|
|
781
790
|
if (!b || b.entries.length !== 1 || expandedBatches.has(id))
|
|
782
791
|
return;
|
|
783
|
-
const lines = [...buildExpandedLines(b), ...buildEntryDetailLines(b.entries[0], entryDetailIndent(b.
|
|
792
|
+
const lines = [...buildExpandedLines(b), ...buildEntryDetailLines(b.entries[0], entryDetailIndent(b.indent ?? ''))];
|
|
784
793
|
// keepViewport=false:这是 agent 产出后的**自动**展开,属于「新内容」而非用户点击的回看式展开,
|
|
785
794
|
// 视口必须跟随屏底(同其它工具输出 / 子 agent 实时嵌套)。传 true 会让视口锚定在摘要行、
|
|
786
795
|
// 把 scrollOffset 顶到插入行数(diff 常几百行),此后 contentWriteMd 见 offset>0 就只喂缓冲
|
|
@@ -804,7 +813,7 @@ function collapse(b, layout) {
|
|
|
804
813
|
// entries 可能多于已渲染行,按 entries.length 会多删并行批量子 agent 的行。
|
|
805
814
|
let lineCount = b.renderedCount;
|
|
806
815
|
for (const i of b.expandedEntries) {
|
|
807
|
-
lineCount += buildEntryDetailLines(b.entries[i], entryDetailIndent(b.
|
|
816
|
+
lineCount += buildEntryDetailLines(b.entries[i], entryDetailIndent(b.indent ?? '')).length;
|
|
808
817
|
}
|
|
809
818
|
// 组容器批折叠时:一并移除嵌套子批的摘要行(及其已展开详情),
|
|
810
819
|
// 否则父批再次展开后子批摘要仍残留在明细区,出现重复行。
|
|
@@ -824,7 +833,7 @@ function collapse(b, layout) {
|
|
|
824
833
|
// 否则删少了会留下孤儿明细行。
|
|
825
834
|
lineCount += child.renderedCount;
|
|
826
835
|
for (const j of child.expandedEntries) {
|
|
827
|
-
lineCount += buildEntryDetailLines(child.entries[j], entryDetailIndent(child.
|
|
836
|
+
lineCount += buildEntryDetailLines(child.entries[j], entryDetailIndent(child.indent ?? '')).length;
|
|
828
837
|
}
|
|
829
838
|
child.expandedEntries.clear();
|
|
830
839
|
expandedBatches.delete(child.id);
|
|
@@ -863,7 +872,7 @@ export function toggleEntry(batchId, entryIndex, layout) {
|
|
|
863
872
|
// 子批自己的摘要行(● 子 Agent 完成 ...)来控制。
|
|
864
873
|
if (b.groupParent) {
|
|
865
874
|
// 如果该 sub-agent entry 没有可展开的详情,fallback 到 toggle 子批工具列表。
|
|
866
|
-
const details = buildEntryDetailLines(b.entries[entryIndex], entryDetailIndent(b.
|
|
875
|
+
const details = buildEntryDetailLines(b.entries[entryIndex], entryDetailIndent(b.indent ?? ''));
|
|
867
876
|
if (details.length === 0) {
|
|
868
877
|
const child = [...batches.values()].find((x) => x.parentId === batchId && x.groupChildIndex === entryIndex);
|
|
869
878
|
if (child) {
|
|
@@ -879,7 +888,7 @@ export function toggleEntry(batchId, entryIndex, layout) {
|
|
|
879
888
|
}
|
|
880
889
|
if (headerIdx < 0)
|
|
881
890
|
return;
|
|
882
|
-
const details = buildEntryDetailLines(b.entries[entryIndex], entryDetailIndent(b.
|
|
891
|
+
const details = buildEntryDetailLines(b.entries[entryIndex], entryDetailIndent(b.indent ?? ''));
|
|
883
892
|
if (details.length === 0)
|
|
884
893
|
return;
|
|
885
894
|
const wasExpanded = b.expandedEntries.has(entryIndex);
|