micro-models-agent 0.41.2 → 0.43.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/bin/mma.mjs +41 -41
- package/dist/cli/commands.js +19 -9
- package/dist/cli/completer.js +37 -36
- package/dist/cli/index.js +2 -2
- package/dist/cli/main.js +23 -48
- package/dist/cli/repl-commands.js +12 -40
- package/dist/cli/repl.js +87 -217
- package/dist/cli/security-commands.js +7 -5
- package/dist/cli/setup.js +26 -8
- package/dist/config/config.js +5 -52
- package/dist/config/defaults.js +5 -29
- package/dist/config/experts.js +1 -1
- package/dist/config/index.js +3 -3
- package/dist/config/security.js +10 -3
- package/dist/core/agent-moe.js +10 -2
- package/dist/core/agent.js +82 -273
- package/dist/core/bootstrap.js +13 -80
- package/dist/core/index.js +2 -2
- package/dist/core/prompt-builder.js +2 -23
- package/dist/core/session-logger.js +4 -46
- package/dist/i18n/en.json +2 -75
- package/dist/i18n/ru.json +1 -74
- package/dist/index.js +1 -1
- package/dist/llm/image-utils.js +5 -4
- package/dist/llm/index.js +4 -4
- package/dist/llm/model-loader.js +6 -6
- package/dist/llm/openai-compat.js +34 -40
- package/dist/llm/orchestrator.js +29 -33
- package/dist/llm/response.js +9 -9
- package/dist/logger/app-logger.js +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/main.js +648 -183
- package/dist/migration/backup.js +13 -13
- package/dist/migration/detect.js +11 -11
- package/dist/migration/index.js +2 -2
- package/dist/modules/browser/actions.js +4 -34
- package/dist/modules/browser/bridge-server.mjs +202 -202
- package/dist/modules/browser/cookie-store.js +6 -6
- package/dist/modules/browser/index.js +5 -7
- package/dist/modules/browser/module.js +7 -8
- package/dist/modules/browser/session.js +84 -87
- package/dist/modules/browser/snapshot.js +58 -92
- package/dist/modules/browser/types.js +1 -4
- package/dist/modules/certification/cli.js +4 -2
- package/dist/modules/certification/fact-checker.js +3 -1
- package/dist/modules/certification/loader.js +9 -3
- package/dist/modules/certification/runner.js +4 -1
- package/dist/modules/context/index.js +1 -1
- package/dist/modules/context/manager.js +86 -160
- package/dist/modules/execution/auditor.js +25 -177
- package/dist/modules/execution/module.js +544 -201
- package/dist/modules/execution/moe-executor.js +0 -25
- package/dist/modules/execution/plan-store.js +3 -1
- package/dist/modules/execution/plan-validator.js +10 -10
- package/dist/modules/execution/planner.js +1 -6
- package/dist/modules/execution/stuck-detector.js +10 -173
- package/dist/modules/execution/verifier.js +42 -86
- package/dist/modules/hallucination/confidence.js +1 -8
- package/dist/modules/hallucination/detector.js +5 -2
- package/dist/modules/hallucination/factual.js +64 -3
- package/dist/modules/hallucination/index.js +1 -1
- package/dist/modules/hallucination/js-identifiers.js +0 -190
- package/dist/modules/hallucination/llm-judge.js +3 -1
- package/dist/modules/indexer/cache.js +7 -9
- package/dist/modules/indexer/index.js +3 -3
- package/dist/modules/indexer/module.js +42 -95
- package/dist/modules/indexer/walker.js +17 -17
- package/dist/modules/lsp/client.js +31 -74
- package/dist/modules/lsp/config.js +33 -87
- package/dist/modules/lsp/index.js +3 -3
- package/dist/modules/lsp/module.js +21 -185
- package/dist/modules/mcp/module.js +6 -2
- package/dist/modules/memory/index.js +1 -1
- package/dist/modules/memory/module.js +23 -71
- package/dist/modules/memory/search.js +9 -11
- package/dist/modules/memory/store.js +13 -13
- package/dist/modules/pipelines/engine.js +10 -10
- package/dist/modules/pipelines/index.js +3 -3
- package/dist/modules/pipelines/parser.js +14 -17
- package/dist/modules/pipelines/template.js +1 -1
- package/dist/modules/plugins/builtin/lint-on-write.js +16 -21
- package/dist/modules/plugins/builtin/notify.js +2 -3
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/loader.js +17 -59
- package/dist/modules/plugins/manager.js +17 -73
- package/dist/modules/processes/index.js +1 -1
- package/dist/modules/processes/registry.js +46 -135
- package/dist/modules/registry.js +2 -4
- package/dist/modules/security/audit-notifier.js +39 -39
- package/dist/modules/security/command-validator.js +8 -2
- package/dist/modules/security/data-sanitizer.js +9 -1
- package/dist/modules/security/encryption.js +56 -58
- package/dist/modules/security/network-validator.js +9 -1
- package/dist/modules/security/path-validator.js +3 -1
- package/dist/modules/security/security-policies.js +19 -3
- package/dist/modules/security/session-encryption.js +1 -1
- package/dist/modules/security/session-isolation.js +8 -8
- package/dist/modules/session/index.js +3 -3
- package/dist/modules/session/module.js +5 -5
- package/dist/modules/session/store.js +9 -3
- package/dist/modules/skills/module.js +2 -1
- package/dist/modules/updater/checker.js +6 -70
- package/dist/modules/updater/index.js +1 -2
- package/dist/modules/user-profile/compressor.js +2 -2
- package/dist/modules/user-profile/index.js +1 -1
- package/dist/modules/user-profile/profile.js +9 -9
- package/dist/tools/attach-image.js +1 -1
- package/dist/tools/bash.js +19 -178
- package/dist/tools/browser.js +29 -46
- package/dist/tools/executor.js +5 -4
- package/dist/tools/file-info.js +12 -13
- package/dist/tools/filter-tools.js +2 -9
- package/dist/tools/glob-tool.js +11 -11
- package/dist/tools/grep-tool.js +3 -1
- package/dist/tools/index.js +2 -13
- package/dist/tools/list-dir.js +17 -18
- package/dist/tools/load-skill.js +3 -1
- package/dist/tools/path-utils.js +4 -4
- package/dist/tools/pipeline-run.js +25 -25
- package/dist/tools/process-kill.js +11 -11
- package/dist/tools/process-list.js +22 -20
- package/dist/tools/process-log.js +18 -22
- package/dist/tools/question.js +3 -1
- package/dist/tools/read-file.js +2 -10
- package/dist/tools/recall.js +37 -44
- package/dist/tools/registry.js +4 -15
- package/dist/tools/remember.js +29 -29
- package/dist/tools/scope-check.js +9 -9
- package/dist/tools/subagent.js +9 -54
- package/dist/tools/user-input.js +1 -1
- package/dist/tools/web-browse.js +3 -3
- package/dist/tools/web-fetch.js +3 -3
- package/dist/tools/web-search.js +3 -3
- package/dist/tools/write-file.js +3 -1
- package/dist/ui/box.js +5 -1
- package/dist/ui/index.js +6 -6
- package/dist/ui/md-formatter.js +33 -33
- package/dist/ui/output.js +5 -5
- package/dist/ui/renderer.js +10 -15
- package/dist/ui/table.js +1 -1
- package/package.json +48 -48
- package/dist/cli/plugin-commands.js +0 -36
- package/dist/cli/run-result.js +0 -22
- package/dist/core/version.js +0 -24
- package/dist/modules/artifacts/store.js +0 -61
- package/dist/modules/browser/bridge-client.js +0 -199
- package/dist/modules/browser/bridge-path.js +0 -10
- package/dist/modules/browser/driver.js +0 -136
- package/dist/modules/context/chunk-query.js +0 -100
- package/dist/modules/context/fact-extractor.js +0 -162
- package/dist/modules/context/history.js +0 -15
- package/dist/modules/execution/audit-runners.js +0 -152
- package/dist/modules/execution/execution-plugin.js +0 -272
- package/dist/modules/execution/plan-tool.js +0 -508
- package/dist/modules/execution/windows-commands.js +0 -41
- package/dist/modules/indexer/project-profile.js +0 -183
- package/dist/modules/lsp/check-tool.js +0 -58
- package/dist/modules/lsp/command.js +0 -60
- package/dist/modules/lsp/probe.js +0 -76
- package/dist/modules/lsp/project-root.js +0 -32
- package/dist/modules/lsp/startup-check.js +0 -141
- package/dist/modules/processes/detect.js +0 -34
- package/dist/modules/skills/matcher.js +0 -27
- package/dist/modules/updater/module.js +0 -116
- package/dist/tools/chunk-query.js +0 -99
- package/dist/tools/download-file.js +0 -116
- package/dist/tools/enable-tools.js +0 -58
- package/dist/tools/hidden-tools-block.js +0 -37
- package/dist/ui/line-editor.js +0 -703
- package/dist/ui/line-math.js +0 -69
- package/dist/ui/plan-view.js +0 -103
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import { t } from "../../i18n/index";
|
|
2
|
-
import { detectTestResults } from "../../tools/bash";
|
|
3
|
-
import { forbiddenWindowsCommand } from "./windows-commands";
|
|
4
|
-
import { platform } from "os";
|
|
5
|
-
/**
|
|
6
|
-
* Cooldown (in iterations) between stuck-recovery injections. Exported so the
|
|
7
|
-
* ExecutionModule can seed its state's lastRecoveryIteration with the same
|
|
8
|
-
* offset the plugin compares against.
|
|
9
|
-
*/
|
|
10
|
-
export const STUCK_RECOVERY_COOLDOWN = 5;
|
|
11
|
-
const MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3;
|
|
12
|
-
const FORCE_SKIP_THRESHOLD = 10;
|
|
13
|
-
/**
|
|
14
|
-
* The execution plugin hooks, extracted verbatim from ExecutionModule.getPlugin().
|
|
15
|
-
* All shared mutable state (pendingMessages, forbiddenBashFailures, state,
|
|
16
|
-
* tracker) is owned by the module and mutated by reference through `deps`.
|
|
17
|
-
*/
|
|
18
|
-
export function createExecutionPlugin(deps) {
|
|
19
|
-
return {
|
|
20
|
-
name: "execution",
|
|
21
|
-
onBeforeThink: (ctx) => {
|
|
22
|
-
// Flush deferred <system-summary> messages first so they are visible
|
|
23
|
-
// to the next model call but never interleave tool messages.
|
|
24
|
-
if (ctx.contextManager && deps.pendingMessages.length > 0) {
|
|
25
|
-
for (const m of deps.pendingMessages.splice(0)) {
|
|
26
|
-
ctx.contextManager.addMessage(m);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (deps.trackerRef.current?.isComplete()) {
|
|
30
|
-
// All steps done/skipped — stop counting "no progress" against
|
|
31
|
-
// the last step and silence step-stuck warnings for a finished
|
|
32
|
-
// plan, BUT keep the tool-call history so a read-without-write
|
|
33
|
-
// loop is still caught (observed: plan complete + false-positive
|
|
34
|
-
// audit → the model re-read files for 50+ iterations with zero
|
|
35
|
-
// writes and no recovery hint).
|
|
36
|
-
deps.stuckDetector.resetStepProgress();
|
|
37
|
-
deps.state.consecutivePlanWarnings = 0;
|
|
38
|
-
deps.state.lastStepId = -1;
|
|
39
|
-
deps.state.stuckNotified = false;
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
const step = deps.trackerRef.current?.getCurrentStep();
|
|
43
|
-
if (deps.trackerRef.current && step) {
|
|
44
|
-
if (step.id !== deps.state.lastStepId) {
|
|
45
|
-
deps.state.consecutivePlanWarnings = 0;
|
|
46
|
-
deps.state.lastStepId = step.id;
|
|
47
|
-
deps.state.stuckNotified = false;
|
|
48
|
-
}
|
|
49
|
-
deps.stuckDetector.setCurrentStep(step.id, step.description);
|
|
50
|
-
deps.stuckDetector.recordIteration(step.id);
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
deps.stuckDetector.reset();
|
|
54
|
-
deps.state.consecutivePlanWarnings = 0;
|
|
55
|
-
deps.state.lastStepId = -1;
|
|
56
|
-
deps.state.stuckNotified = false;
|
|
57
|
-
const iter = typeof ctx.iteration === "number" ? ctx.iteration : 0;
|
|
58
|
-
if (iter === 3 && !deps.trackerRef.current && ctx.contextManager) {
|
|
59
|
-
ctx.contextManager.addMessage({
|
|
60
|
-
role: "user",
|
|
61
|
-
content: `<system-summary>You have made 3 tool calls without creating a plan. For any task that involves creating files, installing packages, or multiple steps — you MUST use plan create BEFORE continuing. Use the plan tool now with concrete steps (exact filenames, commands, deliverables). Do NOT make any more write/edit/bash calls until you have a plan.</system-summary>`,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
if (iter >= 6 && !deps.trackerRef.current && ctx.contextManager) {
|
|
65
|
-
ctx.contextManager.addMessage({
|
|
66
|
-
role: "user",
|
|
67
|
-
content: `<system-summary>STOP. ${iter} iterations without a plan. You MUST call plan create RIGHT NOW. No more tool calls until you create a plan.</system-summary>`,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const stuckReason = deps.stuckDetector.getStuckReason();
|
|
73
|
-
if (stuckReason) {
|
|
74
|
-
// Log once per stuck episode instead of spamming every iteration.
|
|
75
|
-
const logIt = deps.stuckDetector.isStuck() ? !deps.state.stuckNotified : true;
|
|
76
|
-
if (logIt) {
|
|
77
|
-
ctx.logger?.warn(stuckReason);
|
|
78
|
-
ctx.sessionLog?.plan("stuck-warning", stuckReason, typeof ctx.iteration === "number" ? ctx.iteration : undefined);
|
|
79
|
-
if (deps.stuckDetector.isStuck())
|
|
80
|
-
deps.state.stuckNotified = true;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (deps.stuckDetector.isStuck() ||
|
|
84
|
-
deps.stuckDetector.hasRepetitiveToolCalls() ||
|
|
85
|
-
deps.stuckDetector.hasReadOnlyLoop()) {
|
|
86
|
-
const currentIter = typeof ctx.iteration === "number" ? ctx.iteration : 0;
|
|
87
|
-
if (currentIter - deps.state.lastRecoveryIteration >= STUCK_RECOVERY_COOLDOWN) {
|
|
88
|
-
const recovery = deps.stuckDetector.getRecoveryMessage();
|
|
89
|
-
if (recovery && ctx.contextManager) {
|
|
90
|
-
const lastError = deps.stuckDetector.getLastErrorOutput();
|
|
91
|
-
const skillHint = lastError
|
|
92
|
-
? "\nIf you have relevant skills available, consider loading one with load_skill for expert guidance."
|
|
93
|
-
: "";
|
|
94
|
-
// Actionable hints based on actual error output
|
|
95
|
-
const actionableHints = deps.stuckDetector.getActionableHints();
|
|
96
|
-
const actionableHintStr = actionableHints.length > 0
|
|
97
|
-
? `\n${t("exec.hints", { hints: actionableHints.map((h) => `- ${h}`).join("\n") })}`
|
|
98
|
-
: "";
|
|
99
|
-
// Tool alternative suggestion
|
|
100
|
-
const alternative = deps.stuckDetector.getToolAlternative();
|
|
101
|
-
const altHint = alternative
|
|
102
|
-
? `\nTool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}" instead.`
|
|
103
|
-
: "";
|
|
104
|
-
ctx.contextManager.addMessage({
|
|
105
|
-
role: "user",
|
|
106
|
-
content: `<system-summary>${recovery}${skillHint}${actionableHintStr}${altHint}</system-summary>`,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
const hints = deps.stuckDetector.getHints();
|
|
110
|
-
if (hints.length > 0 && ctx.contextManager) {
|
|
111
|
-
const hintMsg = t("exec.hints", {
|
|
112
|
-
hints: hints.map((h) => `- ${h}`).join("\n"),
|
|
113
|
-
});
|
|
114
|
-
ctx.contextManager.addMessage({
|
|
115
|
-
role: "user",
|
|
116
|
-
content: `<system-summary>${hintMsg}</system-summary>`,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
deps.stuckDetector.recordEscalation();
|
|
120
|
-
deps.state.lastRecoveryIteration = currentIter;
|
|
121
|
-
if (deps.stuckDetector.shouldEscalate() && ctx.onMeta) {
|
|
122
|
-
const escalation = t("exec.escalation", {
|
|
123
|
-
stepId: String(deps.trackerRef.current?.getCurrentStep()?.id ?? "?"),
|
|
124
|
-
description: deps.trackerRef.current?.getCurrentStep()?.description ?? "",
|
|
125
|
-
});
|
|
126
|
-
ctx.onMeta(escalation);
|
|
127
|
-
}
|
|
128
|
-
// Force skip after too many iterations on the same step
|
|
129
|
-
if (deps.stuckDetector.getIterationsOnCurrentStep() >= FORCE_SKIP_THRESHOLD &&
|
|
130
|
-
ctx.contextManager) {
|
|
131
|
-
const step = deps.trackerRef.current?.getCurrentStep();
|
|
132
|
-
ctx.contextManager.addMessage({
|
|
133
|
-
role: "user",
|
|
134
|
-
content: `<system-summary>STOP. Step ${step?.id ?? "?"} ("${step?.description ?? ""}") took ${deps.stuckDetector.getIterationsOnCurrentStep()} iterations with no progress. DO NOT continue this step. Immediately call: plan update step=${step?.id ?? "?"} status=done (if code works despite warnings) OR plan update step=${step?.id ?? "?"} status=skipped note="reason". Do NOT make any other tool calls before updating the plan.</system-summary>`,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
onBeforeTool: (_ctx, call) => {
|
|
141
|
-
const warning = deps.checkPlanAlignment(call);
|
|
142
|
-
if (warning) {
|
|
143
|
-
deps.pendingMessages.push({
|
|
144
|
-
role: "user",
|
|
145
|
-
content: `<system-summary>${warning}</system-summary>`,
|
|
146
|
-
});
|
|
147
|
-
deps.state.consecutivePlanWarnings++;
|
|
148
|
-
if (deps.state.consecutivePlanWarnings >= MAX_PLAN_WARNINGS_BEFORE_BLOCK) {
|
|
149
|
-
deps.pendingMessages.push({
|
|
150
|
-
role: "user",
|
|
151
|
-
content: `<system-summary>${t("exec.plan_blocked", { step: String(deps.trackerRef.current?.getCurrentStep()?.id ?? "?"), max: MAX_PLAN_WARNINGS_BEFORE_BLOCK })}</system-summary>`,
|
|
152
|
-
});
|
|
153
|
-
// Block with an explicit reason so the model sees WHY the call
|
|
154
|
-
// was blocked (executor shows it via tool.blocked_reason).
|
|
155
|
-
return t("exec.plan_blocked", {
|
|
156
|
-
step: String(deps.trackerRef.current?.getCurrentStep()?.id ?? "?"),
|
|
157
|
-
max: MAX_PLAN_WARNINGS_BEFORE_BLOCK,
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
deps.state.consecutivePlanWarnings = 0;
|
|
163
|
-
}
|
|
164
|
-
return true;
|
|
165
|
-
},
|
|
166
|
-
onToolCall: (ctx) => {
|
|
167
|
-
const toolName = ctx?.toolName;
|
|
168
|
-
const args = ctx?.args;
|
|
169
|
-
if (toolName && args) {
|
|
170
|
-
deps.stuckDetector.recordToolCall(toolName, args);
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
|
-
onAfterTool: (ctx, call, result) => {
|
|
174
|
-
// Remember every bash invocation (successful or not) so stuck
|
|
175
|
-
// detection can reason about e.g. repeated runs with empty output.
|
|
176
|
-
if (call.name === "bash") {
|
|
177
|
-
deps.stuckDetector.recordBashOutput(String(call.arguments?.command ?? ""), String(result.output ?? ""));
|
|
178
|
-
}
|
|
179
|
-
// A write/edit/bash that reports success but still carries a
|
|
180
|
-
// type/syntax error in its output is NOT a success — the model must
|
|
181
|
-
// fix the actual error, not keep rewriting the file blindly. Feed it
|
|
182
|
-
// to the stuck detector so the rewrite-loop hint fires.
|
|
183
|
-
const toolText = String(result.output ?? "");
|
|
184
|
-
if (/error TS\d+|\[Project typecheck failed\]|\[Syntax check failed\]/.test(toolText)) {
|
|
185
|
-
deps.stuckDetector.recordToolError(call.name, toolText.slice(0, 300));
|
|
186
|
-
}
|
|
187
|
-
if (!result.success) {
|
|
188
|
-
// Hard stop for forbidden Windows commands: after the second
|
|
189
|
-
// failure of the same forbidden command (grep/sed/ls/find/…),
|
|
190
|
-
// inject a STOP message so the session stops burning bash calls
|
|
191
|
-
// on commands cmd.exe does not have. Mirrors the bash tool's own
|
|
192
|
-
// win32-gated hard-stop (src/tools/bash.ts) — on macOS/Linux
|
|
193
|
-
// these commands exist and fail for legit reasons.
|
|
194
|
-
if (call.name === "bash" && platform() === "win32") {
|
|
195
|
-
const cmd = String(call.arguments?.command ?? "");
|
|
196
|
-
const forbidden = forbiddenWindowsCommand(cmd);
|
|
197
|
-
if (forbidden) {
|
|
198
|
-
const n = (deps.forbiddenBashFailures.get(forbidden) || 0) + 1;
|
|
199
|
-
deps.forbiddenBashFailures.set(forbidden, n);
|
|
200
|
-
if (n === 2) {
|
|
201
|
-
deps.pendingMessages.push({
|
|
202
|
-
role: "user",
|
|
203
|
-
content: `<system-summary>${t("exec.forbidden_cmd", { cmd: forbidden })}</system-summary>`,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
deps.stuckDetector.recordToolError(call.name, result.output);
|
|
209
|
-
// Immediately queue an actionable hint on failure (don't wait for
|
|
210
|
-
// the stuck threshold). Flushed in onBeforeThink so it does not
|
|
211
|
-
// land between tool messages.
|
|
212
|
-
const actionableHints = deps.stuckDetector.getActionableHints();
|
|
213
|
-
const alternative = deps.stuckDetector.getToolAlternative();
|
|
214
|
-
if (actionableHints.length > 0 || alternative) {
|
|
215
|
-
const parts = [...actionableHints];
|
|
216
|
-
if (alternative) {
|
|
217
|
-
parts.push(`Tool "${call.name}" crashed. Try "${alternative}" instead.`);
|
|
218
|
-
}
|
|
219
|
-
deps.pendingMessages.push({
|
|
220
|
-
role: "user",
|
|
221
|
-
content: `<system-summary>${t("exec.hints", { hints: parts.map((h) => `- ${h}`).join("\n") })}</system-summary>`,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
deps.stuckDetector.recordToolSuccess();
|
|
227
|
-
// When a bash command runs code successfully, suggest marking the
|
|
228
|
-
// step done — unless the output shows failing tests, which must
|
|
229
|
-
// never be reported as a clean success.
|
|
230
|
-
if (call.name === "bash" && result.success) {
|
|
231
|
-
const cmd = String(call.arguments?.command ?? "");
|
|
232
|
-
const testRun = detectTestResults(String(result.output ?? ""));
|
|
233
|
-
if (testRun && testRun.failed > 0) {
|
|
234
|
-
deps.pendingMessages.push({
|
|
235
|
-
role: "user",
|
|
236
|
-
content: `<system-summary>${testRun.framework} reported ${testRun.failed} FAILING test(s) (${testRun.passed} passing). Do NOT mark the current step as done — fix the failing tests (read the failure output, correct the code) and re-run them until all pass.</system-summary>`,
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
else if (testRun && testRun.failed === 0 && testRun.passed > 0) {
|
|
240
|
-
deps.pendingMessages.push({
|
|
241
|
-
role: "user",
|
|
242
|
-
content: `<system-summary>${testRun.framework}: all ${testRun.passed} test(s) passed for "${cmd}". You may mark the current step as done via plan update step=N status=done.</system-summary>`,
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
else if (/node|tsx|ts-node|python|npm\s+(start|test|run)/.test(cmd)) {
|
|
246
|
-
deps.pendingMessages.push({
|
|
247
|
-
role: "user",
|
|
248
|
-
content: `<system-summary>The command "${cmd}" completed successfully. If this was testing your code, mark the current step as done via plan update step=N status=done.</system-summary>`,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (result.success && (call.name === "write_file" || call.name === "edit_file")) {
|
|
254
|
-
const filePath = call.arguments?.path;
|
|
255
|
-
if (filePath) {
|
|
256
|
-
deps.stuckDetector.recordFileRewrite(filePath);
|
|
257
|
-
if (deps.stuckDetector.hasExcessiveRewrites()) {
|
|
258
|
-
const file = deps.stuckDetector.getExcessiveRewriteFile();
|
|
259
|
-
const count = deps.stuckDetector.getFileRewriteCount(file);
|
|
260
|
-
if (ctx.onMeta) {
|
|
261
|
-
ctx.onMeta(t("exec.file_rewrite_warning", {
|
|
262
|
-
file: file,
|
|
263
|
-
count: String(count),
|
|
264
|
-
}));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
deps.advancePlanIfStepComplete(ctx.contextManager, ctx.sessionLog);
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
};
|
|
272
|
-
}
|