mocode-ai 0.6.5 → 0.6.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/agent/core.js +54 -31
- package/dist/context/age-aware.js +136 -0
- package/dist/context/budget.js +56 -86
- package/dist/context/encoders/code.js +186 -60
- package/dist/context/encoders/command.js +201 -0
- package/dist/context/encoders/graph.js +69 -19
- package/dist/context/encoders/index.js +2 -2
- package/dist/context/encoders/log.js +2 -52
- package/dist/context/encoders/search.js +116 -50
- package/dist/context/index.js +1 -1
- package/dist/context/pipeline.js +5 -1
- package/dist/context/relevance.js +166 -121
- package/dist/context/token-calibration.js +104 -0
- package/dist/llm/index.js +42 -99
- package/dist/llm/think-filter.js +90 -0
- package/dist/repl/index.js +0 -2
- package/dist/session/compact.js +20 -23
- package/dist/session/index.js +3 -3
- package/dist/session/scheduler.js +18 -38
- package/dist/tools/builtins/run-command.js +29 -9
- package/dist/tools/constants.js +0 -17
- package/package.json +1 -1
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import { spawn, spawnSync } from 'node:child_process';
|
|
2
2
|
import { MAX_OUTPUT } from '../constants.js';
|
|
3
3
|
import { getSandboxRoot, filterEnv, isCommandDenied } from '../../sandbox/index.js';
|
|
4
|
+
const OUTPUT_HEAD_LIMIT = Math.floor(MAX_OUTPUT * 0.4);
|
|
5
|
+
const OUTPUT_TAIL_LIMIT = MAX_OUTPUT - OUTPUT_HEAD_LIMIT;
|
|
6
|
+
/** 有界采集:短输出逐字保留;超限后保留 head+tail,避免构建/测试错误只出现在尾部时被丢弃。 */
|
|
7
|
+
class BoundedCommandOutput {
|
|
8
|
+
head = '';
|
|
9
|
+
tail = '';
|
|
10
|
+
total = 0;
|
|
11
|
+
append(text) {
|
|
12
|
+
this.total += text.length;
|
|
13
|
+
const headRoom = OUTPUT_HEAD_LIMIT - this.head.length;
|
|
14
|
+
const headPart = headRoom > 0 ? text.slice(0, headRoom) : '';
|
|
15
|
+
this.head += headPart;
|
|
16
|
+
const rest = text.slice(headPart.length);
|
|
17
|
+
if (rest)
|
|
18
|
+
this.tail = (this.tail + rest).slice(-OUTPUT_TAIL_LIMIT);
|
|
19
|
+
}
|
|
20
|
+
render() {
|
|
21
|
+
if (this.total <= MAX_OUTPUT)
|
|
22
|
+
return this.head + this.tail;
|
|
23
|
+
const removed = this.total - MAX_OUTPUT;
|
|
24
|
+
return `${this.head}\n...(输出已截断 ${removed} 字符,保留开头与结尾)...\n${this.tail}`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
4
27
|
// ---------- run_command ----------
|
|
5
28
|
export const runCommandTool = {
|
|
6
29
|
name: 'run_command',
|
|
@@ -25,7 +48,7 @@ export const runCommandTool = {
|
|
|
25
48
|
const isWin = process.platform === 'win32';
|
|
26
49
|
// 沙箱 best-effort:cwd 钉死 sandbox root(相对路径写落在牢内)+ env 脱敏(剥 *KEY/*TOKEN 等,防 LLM_API_KEY 泄子进程)
|
|
27
50
|
const child = spawn(isWin ? 'cmd.exe' : 'bash', isWin ? ['/c', command] : ['-c', command], { cwd: getSandboxRoot() ?? process.cwd(), env: filterEnv(process.env) });
|
|
28
|
-
|
|
51
|
+
const output = new BoundedCommandOutput();
|
|
29
52
|
let finished = false;
|
|
30
53
|
let timer;
|
|
31
54
|
// 杀整棵进程树。child.kill() 在 Windows 只杀 cmd.exe、npm 等子进程会孤儿继续跑(占锁、污染下一步),
|
|
@@ -50,7 +73,7 @@ export const runCommandTool = {
|
|
|
50
73
|
// abort(用户 Ctrl+C,经 executeTool ctx.signal 透传)→ 杀子进程树 + 返[已中断]
|
|
51
74
|
const onAbort = () => {
|
|
52
75
|
killTree();
|
|
53
|
-
finish(`[已中断]\n${
|
|
76
|
+
finish(`[已中断]\n${output.render().trim()}`);
|
|
54
77
|
};
|
|
55
78
|
const finish = (s) => {
|
|
56
79
|
if (finished)
|
|
@@ -61,21 +84,18 @@ export const runCommandTool = {
|
|
|
61
84
|
done(s);
|
|
62
85
|
};
|
|
63
86
|
const onChunk = (chunk) => {
|
|
64
|
-
|
|
65
|
-
out += chunk.toString('utf8');
|
|
87
|
+
output.append(chunk.toString('utf8'));
|
|
66
88
|
};
|
|
67
89
|
child.stdout.on('data', onChunk);
|
|
68
90
|
child.stderr.on('data', onChunk);
|
|
69
91
|
child.on('error', (e) => finish(`执行失败: ${e.message}`));
|
|
70
92
|
child.on('close', (code) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
r += '\n...(输出已截断)';
|
|
74
|
-
finish(`[退出码 ${code}]\n${r || '(无输出)'}`);
|
|
93
|
+
const result = output.render().trim();
|
|
94
|
+
finish(`[退出码 ${code}]\n${result || '(无输出)'}`);
|
|
75
95
|
});
|
|
76
96
|
timer = setTimeout(() => {
|
|
77
97
|
killTree();
|
|
78
|
-
finish(`[超时,已终止]\n${
|
|
98
|
+
finish(`[超时,已终止]\n${output.render().trim()}`);
|
|
79
99
|
}, timeout);
|
|
80
100
|
// 外部 abort signal:已 aborted 即时杀(防御;agent 循环顶检查通常会先拦),否则挂监听
|
|
81
101
|
if (ctx?.signal) {
|
package/dist/tools/constants.js
CHANGED
|
@@ -23,23 +23,6 @@ export const GC_DAYS = 90;
|
|
|
23
23
|
/** memory_search 结果(召回的记忆正文)的放宽上限:指令性内容,中截破坏语义,对齐 use_skill。 */
|
|
24
24
|
export const MAX_MEMORY_RESULT = 64000;
|
|
25
25
|
export const IGNORE = ['**/node_modules/**', '**/.git/**'];
|
|
26
|
-
// ── Context Budget Scheduler(五区分账)────────────────────────────────────
|
|
27
|
-
/** Hot/Cold 划分:当前 step 起往前 N 个 user turn 之内的工具结果视为 Hot(绝对不压),
|
|
28
|
-
* 之外的视为 Cold(可调度器压)。默认 4 = 跨过 4 个用户问题仍生效。 */
|
|
29
|
-
export const HOT_TURN_WINDOW = 4;
|
|
30
|
-
/** Cold 区内可被就地 stub 的 tool 消息最低 age(经过的消费者 push 数)。默认 2,
|
|
31
|
-
* 与 lifecycle.ts DEFAULT_AGE_THRESHOLD 对齐。 */
|
|
32
|
-
export const TOOL_OLD_AGE = 2;
|
|
33
|
-
/** 五区预算占比(总和 0.95,留 5% 给 Reserve)。对齐 user 修正版:
|
|
34
|
-
* System 15 / History 20 / Hot Tool 25 / Cold Tool 25 / Summary 10。 */
|
|
35
|
-
export const BUDGET_RATIO = {
|
|
36
|
-
system: 0.15,
|
|
37
|
-
history: 0.20,
|
|
38
|
-
toolRecent: 0.25,
|
|
39
|
-
toolOld: 0.25,
|
|
40
|
-
summary: 0.10,
|
|
41
|
-
reserve: 0.05,
|
|
42
|
-
};
|
|
43
26
|
// ── plan 模式(只读规划,不执行)──────────────────────────────────────────────
|
|
44
27
|
/**
|
|
45
28
|
* plan 模式下从工具 schema 里剔除的工具(模型根本看不到 → 调不到):
|