micro-models-agent 0.24.3 → 0.24.5
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/main.js +169 -21
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2125,9 +2125,9 @@ var init_defaults = __esm(() => {
|
|
|
2125
2125
|
offloadKvCacheToGpu: true
|
|
2126
2126
|
},
|
|
2127
2127
|
retry: {
|
|
2128
|
-
maxRetries:
|
|
2129
|
-
baseDelay:
|
|
2130
|
-
maxDelay:
|
|
2128
|
+
maxRetries: 5,
|
|
2129
|
+
baseDelay: 5000,
|
|
2130
|
+
maxDelay: 120000
|
|
2131
2131
|
},
|
|
2132
2132
|
maxToolIterations: 1000,
|
|
2133
2133
|
stuckThreshold: 8,
|
|
@@ -4435,12 +4435,12 @@ class OpenAICompatProvider {
|
|
|
4435
4435
|
};
|
|
4436
4436
|
this.rateLimiter = createRateLimiter(config.rateLimits);
|
|
4437
4437
|
}
|
|
4438
|
-
async* chat(messages, tools) {
|
|
4438
|
+
async* chat(messages, tools, signal) {
|
|
4439
4439
|
if (!this.rateLimiter.canMakeRequest()) {
|
|
4440
4440
|
throw new Error(`Rate limit exceeded: ${this.rateLimiter.getConfig().maxRequestsPerMinute} requests per minute`);
|
|
4441
4441
|
}
|
|
4442
4442
|
this.rateLimiter.recordRequest();
|
|
4443
|
-
const streamResult = this.doStream(messages, tools);
|
|
4443
|
+
const streamResult = this.doStream(messages, tools, signal);
|
|
4444
4444
|
let hasToolCall = false;
|
|
4445
4445
|
let hasText = false;
|
|
4446
4446
|
let reasoningAcc = "";
|
|
@@ -4455,13 +4455,13 @@ class OpenAICompatProvider {
|
|
|
4455
4455
|
yield chunk;
|
|
4456
4456
|
}
|
|
4457
4457
|
if (!hasToolCall && !hasText) {
|
|
4458
|
-
const fallback = await this.doNonStreaming(messages, tools);
|
|
4458
|
+
const fallback = await this.doNonStreaming(messages, tools, signal);
|
|
4459
4459
|
for (const chunk of fallback) {
|
|
4460
4460
|
yield chunk;
|
|
4461
4461
|
}
|
|
4462
4462
|
}
|
|
4463
4463
|
}
|
|
4464
|
-
async* doStream(messages, tools) {
|
|
4464
|
+
async* doStream(messages, tools, externalSignal) {
|
|
4465
4465
|
const body = {
|
|
4466
4466
|
model: this.model,
|
|
4467
4467
|
messages,
|
|
@@ -4488,6 +4488,15 @@ class OpenAICompatProvider {
|
|
|
4488
4488
|
const controller = new AbortController;
|
|
4489
4489
|
const totalTimeoutMs = 120000;
|
|
4490
4490
|
const timeoutId = setTimeout(() => controller.abort(), totalTimeoutMs);
|
|
4491
|
+
if (externalSignal) {
|
|
4492
|
+
if (externalSignal.aborted) {
|
|
4493
|
+
controller.abort();
|
|
4494
|
+
} else {
|
|
4495
|
+
externalSignal.addEventListener("abort", () => controller.abort(), {
|
|
4496
|
+
once: true
|
|
4497
|
+
});
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4491
4500
|
const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
|
|
4492
4501
|
method: "POST",
|
|
4493
4502
|
headers,
|
|
@@ -4591,7 +4600,7 @@ class OpenAICompatProvider {
|
|
|
4591
4600
|
reader.releaseLock();
|
|
4592
4601
|
}
|
|
4593
4602
|
}
|
|
4594
|
-
async doNonStreaming(messages, tools) {
|
|
4603
|
+
async doNonStreaming(messages, tools, externalSignal) {
|
|
4595
4604
|
const body = {
|
|
4596
4605
|
model: this.model,
|
|
4597
4606
|
messages,
|
|
@@ -4616,11 +4625,15 @@ class OpenAICompatProvider {
|
|
|
4616
4625
|
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
4617
4626
|
}
|
|
4618
4627
|
try {
|
|
4619
|
-
const
|
|
4628
|
+
const fetchInit = {
|
|
4620
4629
|
method: "POST",
|
|
4621
4630
|
headers,
|
|
4622
4631
|
body: JSON.stringify(body)
|
|
4623
|
-
}
|
|
4632
|
+
};
|
|
4633
|
+
if (externalSignal) {
|
|
4634
|
+
fetchInit.signal = externalSignal;
|
|
4635
|
+
}
|
|
4636
|
+
const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, fetchInit);
|
|
4624
4637
|
if (!response.ok) {
|
|
4625
4638
|
const errorText = await response.text();
|
|
4626
4639
|
throw new Error(t("error.llm_api", {
|
|
@@ -4884,7 +4897,8 @@ function runCommand(command, options = {}) {
|
|
|
4884
4897
|
cwd,
|
|
4885
4898
|
callId,
|
|
4886
4899
|
timeoutMs = 120000,
|
|
4887
|
-
maxBuffer = 10 * 1024 * 1024
|
|
4900
|
+
maxBuffer = 10 * 1024 * 1024,
|
|
4901
|
+
onOutput
|
|
4888
4902
|
} = options;
|
|
4889
4903
|
return new Promise((resolve) => {
|
|
4890
4904
|
let timedOut = false;
|
|
@@ -4903,6 +4917,7 @@ function runCommand(command, options = {}) {
|
|
|
4903
4917
|
const decodeChunk = (chunk) => decoder ? decoder.decode(chunk, { stream: true }) : chunk.toString("utf-8");
|
|
4904
4918
|
child.stdout?.on("data", (chunk) => {
|
|
4905
4919
|
const text = decodeChunk(chunk);
|
|
4920
|
+
onOutput?.(text);
|
|
4906
4921
|
const next = stdoutRef.value.length + text.length;
|
|
4907
4922
|
if (next > maxBuffer) {
|
|
4908
4923
|
stdoutRef.value = stdoutRef.value.slice(stdoutRef.value.length + text.length - maxBuffer) + text;
|
|
@@ -4912,6 +4927,7 @@ function runCommand(command, options = {}) {
|
|
|
4912
4927
|
});
|
|
4913
4928
|
child.stderr?.on("data", (chunk) => {
|
|
4914
4929
|
const text = decodeChunk(chunk);
|
|
4930
|
+
onOutput?.(text);
|
|
4915
4931
|
const next = stderrRef.value.length + text.length;
|
|
4916
4932
|
if (next > maxBuffer) {
|
|
4917
4933
|
stderrRef.value = stderrRef.value.slice(stderrRef.value.length + text.length - maxBuffer) + text;
|
|
@@ -4945,7 +4961,13 @@ function runCommand(command, options = {}) {
|
|
|
4945
4961
|
clearTimeout(timer);
|
|
4946
4962
|
if (callId)
|
|
4947
4963
|
activeChildren.delete(callId);
|
|
4948
|
-
resolve({
|
|
4964
|
+
resolve({
|
|
4965
|
+
stdout: stdoutRef.value,
|
|
4966
|
+
stderr: stderrRef.value,
|
|
4967
|
+
code,
|
|
4968
|
+
signal,
|
|
4969
|
+
timedOut
|
|
4970
|
+
});
|
|
4949
4971
|
});
|
|
4950
4972
|
});
|
|
4951
4973
|
}
|
|
@@ -4954,11 +4976,61 @@ var init_runner = __esm(() => {
|
|
|
4954
4976
|
activeChildren = new Map;
|
|
4955
4977
|
});
|
|
4956
4978
|
|
|
4979
|
+
// src/tools/cache.ts
|
|
4980
|
+
class ToolResultCache {
|
|
4981
|
+
cache = new Map;
|
|
4982
|
+
maxEntries;
|
|
4983
|
+
defaultTtlMs;
|
|
4984
|
+
constructor(maxEntries = 50, defaultTtlMs = 60000) {
|
|
4985
|
+
this.maxEntries = maxEntries;
|
|
4986
|
+
this.defaultTtlMs = defaultTtlMs;
|
|
4987
|
+
}
|
|
4988
|
+
get(key) {
|
|
4989
|
+
const entry = this.cache.get(key);
|
|
4990
|
+
if (!entry)
|
|
4991
|
+
return;
|
|
4992
|
+
if (Date.now() > entry.expiresAt) {
|
|
4993
|
+
this.cache.delete(key);
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
this.cache.delete(key);
|
|
4997
|
+
this.cache.set(key, entry);
|
|
4998
|
+
return entry.value;
|
|
4999
|
+
}
|
|
5000
|
+
set(key, value, ttlMs) {
|
|
5001
|
+
if (this.cache.size >= this.maxEntries) {
|
|
5002
|
+
const firstKey = this.cache.keys().next().value;
|
|
5003
|
+
if (firstKey !== undefined) {
|
|
5004
|
+
this.cache.delete(firstKey);
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
this.cache.set(key, {
|
|
5008
|
+
value,
|
|
5009
|
+
expiresAt: Date.now() + (ttlMs ?? this.defaultTtlMs)
|
|
5010
|
+
});
|
|
5011
|
+
}
|
|
5012
|
+
has(key) {
|
|
5013
|
+
return this.get(key) !== undefined;
|
|
5014
|
+
}
|
|
5015
|
+
clear() {
|
|
5016
|
+
this.cache.clear();
|
|
5017
|
+
}
|
|
5018
|
+
get size() {
|
|
5019
|
+
return this.cache.size;
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
5022
|
+
function hashKey(toolName, args) {
|
|
5023
|
+
const payload = toolName + JSON.stringify(args);
|
|
5024
|
+
const hash = Bun.hash(payload).toString(16).slice(0, 16);
|
|
5025
|
+
return hash;
|
|
5026
|
+
}
|
|
5027
|
+
|
|
4957
5028
|
// src/tools/executor.ts
|
|
4958
5029
|
class ToolExecutor {
|
|
4959
5030
|
registry;
|
|
4960
5031
|
ctx;
|
|
4961
5032
|
pluginManager;
|
|
5033
|
+
cache = new ToolResultCache(50, CACHE_TTL_MS);
|
|
4962
5034
|
constructor(registry, ctx, pluginManager) {
|
|
4963
5035
|
this.registry = registry;
|
|
4964
5036
|
this.ctx = ctx;
|
|
@@ -4973,6 +5045,18 @@ class ToolExecutor {
|
|
|
4973
5045
|
toolCallId: call.id
|
|
4974
5046
|
};
|
|
4975
5047
|
}
|
|
5048
|
+
if (CACHEABLE_TOOLS.has(call.name)) {
|
|
5049
|
+
const key = hashKey(call.name, call.arguments);
|
|
5050
|
+
const cached = this.cache.get(key);
|
|
5051
|
+
if (cached !== undefined) {
|
|
5052
|
+
this.ctx.logger.debug(`Tool ${call.name}: CACHE HIT`);
|
|
5053
|
+
return {
|
|
5054
|
+
success: true,
|
|
5055
|
+
output: cached,
|
|
5056
|
+
toolCallId: call.id
|
|
5057
|
+
};
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
4976
5060
|
for (const plugin of this.pluginManager.getAllPlugins()) {
|
|
4977
5061
|
if (plugin.onBeforeTool) {
|
|
4978
5062
|
try {
|
|
@@ -5043,6 +5127,11 @@ class ToolExecutor {
|
|
|
5043
5127
|
}
|
|
5044
5128
|
}
|
|
5045
5129
|
}
|
|
5130
|
+
if (result.success && CACHEABLE_TOOLS.has(call.name)) {
|
|
5131
|
+
const key = hashKey(call.name, call.arguments);
|
|
5132
|
+
this.cache.set(key, result.output);
|
|
5133
|
+
this.ctx.logger.debug(`Tool ${call.name}: CACHED`);
|
|
5134
|
+
}
|
|
5046
5135
|
this.ctx.logger.debug(`Tool ${call.name}: ${result.success ? "OK" : "FAIL"}`);
|
|
5047
5136
|
return result;
|
|
5048
5137
|
}
|
|
@@ -5052,6 +5141,9 @@ class ToolExecutor {
|
|
|
5052
5141
|
getRegistry() {
|
|
5053
5142
|
return this.registry;
|
|
5054
5143
|
}
|
|
5144
|
+
getContext() {
|
|
5145
|
+
return this.ctx;
|
|
5146
|
+
}
|
|
5055
5147
|
setScope(scope) {
|
|
5056
5148
|
this.ctx.scope = scope;
|
|
5057
5149
|
}
|
|
@@ -5059,10 +5151,11 @@ class ToolExecutor {
|
|
|
5059
5151
|
this.ctx.llmProvider = provider;
|
|
5060
5152
|
}
|
|
5061
5153
|
}
|
|
5062
|
-
var TOOL_EXECUTION_TIMEOUT_MS = 60000;
|
|
5154
|
+
var TOOL_EXECUTION_TIMEOUT_MS = 60000, CACHEABLE_TOOLS, CACHE_TTL_MS = 60000;
|
|
5063
5155
|
var init_executor = __esm(() => {
|
|
5064
5156
|
init_runner();
|
|
5065
5157
|
init_i18n();
|
|
5158
|
+
CACHEABLE_TOOLS = new Set(["web_fetch"]);
|
|
5066
5159
|
});
|
|
5067
5160
|
|
|
5068
5161
|
// src/modules/security/path-validator.ts
|
|
@@ -5593,7 +5686,7 @@ function safeResolvePath(baseDir, userPath) {
|
|
|
5593
5686
|
var init_path_utils = () => {};
|
|
5594
5687
|
|
|
5595
5688
|
// src/tools/preview.ts
|
|
5596
|
-
var MAX_PREVIEW_LINES =
|
|
5689
|
+
var MAX_PREVIEW_LINES = 100;
|
|
5597
5690
|
|
|
5598
5691
|
// src/tools/read-file.ts
|
|
5599
5692
|
import { readFileSync as readFileSync5, existsSync as existsSync9 } from "fs";
|
|
@@ -6957,8 +7050,14 @@ var init_bash = __esm(() => {
|
|
|
6957
7050
|
type: "object",
|
|
6958
7051
|
properties: {
|
|
6959
7052
|
command: { type: "string", description: "Shell command to execute" },
|
|
6960
|
-
workdir: {
|
|
6961
|
-
|
|
7053
|
+
workdir: {
|
|
7054
|
+
type: "string",
|
|
7055
|
+
description: "Working directory (default: baseDir)"
|
|
7056
|
+
},
|
|
7057
|
+
background: {
|
|
7058
|
+
type: "boolean",
|
|
7059
|
+
description: "Start the command in the background and return immediately with a process id (default: auto-detect long-running commands)"
|
|
7060
|
+
}
|
|
6962
7061
|
},
|
|
6963
7062
|
required: ["command"]
|
|
6964
7063
|
},
|
|
@@ -7005,7 +7104,8 @@ ${t("proc.manage_hint", {
|
|
|
7005
7104
|
const res = await runCommand(command, {
|
|
7006
7105
|
cwd: workdir,
|
|
7007
7106
|
callId: ctx.activeCallId,
|
|
7008
|
-
timeoutMs: BASH_TIMEOUT_MS
|
|
7107
|
+
timeoutMs: BASH_TIMEOUT_MS,
|
|
7108
|
+
onOutput: ctx.onMeta
|
|
7009
7109
|
});
|
|
7010
7110
|
const parts = [res.stdout.trimEnd(), res.stderr.trimEnd()].filter(Boolean);
|
|
7011
7111
|
let output = parts.join(`
|
|
@@ -9065,6 +9165,16 @@ var init_store = __esm(() => {
|
|
|
9065
9165
|
|
|
9066
9166
|
// src/core/agent.ts
|
|
9067
9167
|
import { join as join10 } from "path";
|
|
9168
|
+
function canRunInParallel(calls) {
|
|
9169
|
+
if (calls.length <= 1)
|
|
9170
|
+
return false;
|
|
9171
|
+
for (const call of calls) {
|
|
9172
|
+
if (SIDE_EFFECT_TOOLS.has(call.name) || WRITE_TOOLS.has(call.name)) {
|
|
9173
|
+
return false;
|
|
9174
|
+
}
|
|
9175
|
+
}
|
|
9176
|
+
return true;
|
|
9177
|
+
}
|
|
9068
9178
|
|
|
9069
9179
|
class Agent {
|
|
9070
9180
|
deps;
|
|
@@ -9232,7 +9342,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
9232
9342
|
const textChunks = [];
|
|
9233
9343
|
this.emitPhase(iteration, "thinking", onPhase);
|
|
9234
9344
|
try {
|
|
9235
|
-
for await (const chunk of llmProvider.chat(history, allTools)) {
|
|
9345
|
+
for await (const chunk of llmProvider.chat(history, allTools, this.abortController?.signal)) {
|
|
9236
9346
|
if (this.shutdownRequested)
|
|
9237
9347
|
break;
|
|
9238
9348
|
if (chunk.type === "text" && chunk.content) {
|
|
@@ -9327,7 +9437,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
9327
9437
|
});
|
|
9328
9438
|
const summaries = [];
|
|
9329
9439
|
let anyToolFailed = false;
|
|
9330
|
-
|
|
9440
|
+
const executeToolCall = async (call) => {
|
|
9331
9441
|
this.setScope();
|
|
9332
9442
|
const startTime = Date.now();
|
|
9333
9443
|
pluginManager.runOnToolCall({
|
|
@@ -9338,11 +9448,28 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
9338
9448
|
onTool?.({ type: "start", tool: call.name, args: call.arguments });
|
|
9339
9449
|
slog.logToolCall(call, iteration);
|
|
9340
9450
|
const tokensBeforeTool = contextManager.getEstimatedTokens();
|
|
9451
|
+
const toolCtx = this.deps.toolExecutor?.getContext?.();
|
|
9452
|
+
const prevOnMeta = toolCtx?.onMeta;
|
|
9453
|
+
if (toolCtx) {
|
|
9454
|
+
toolCtx.onMeta = onMeta;
|
|
9455
|
+
}
|
|
9341
9456
|
const result = await toolExecutor.execute(call, this.abortController?.signal);
|
|
9457
|
+
if (toolCtx) {
|
|
9458
|
+
toolCtx.onMeta = prevOnMeta;
|
|
9459
|
+
}
|
|
9342
9460
|
const duration = Date.now() - startTime;
|
|
9461
|
+
pluginManager.runOnToolEnd({ iteration, logger }, { id: call.id, name: call.name, arguments: call.arguments }, result, duration);
|
|
9462
|
+
return { call, result, duration, tokensBefore: tokensBeforeTool };
|
|
9463
|
+
};
|
|
9464
|
+
const processToolResult = (entry) => {
|
|
9465
|
+
const {
|
|
9466
|
+
call,
|
|
9467
|
+
result,
|
|
9468
|
+
duration,
|
|
9469
|
+
tokensBefore: tokensBeforeTool
|
|
9470
|
+
} = entry;
|
|
9343
9471
|
if (!result.success)
|
|
9344
9472
|
anyToolFailed = true;
|
|
9345
|
-
pluginManager.runOnToolEnd({ iteration, logger }, { id: call.id, name: call.name, arguments: call.arguments }, result, duration);
|
|
9346
9473
|
if (result.display) {
|
|
9347
9474
|
onMeta?.(`
|
|
9348
9475
|
` + result.display + `
|
|
@@ -9386,6 +9513,17 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
9386
9513
|
contextManager.compact();
|
|
9387
9514
|
logger.debug("Context compacted after tool result");
|
|
9388
9515
|
}
|
|
9516
|
+
};
|
|
9517
|
+
if (canRunInParallel(toolCalls)) {
|
|
9518
|
+
const entries = await Promise.all(toolCalls.map(executeToolCall));
|
|
9519
|
+
for (const entry of entries) {
|
|
9520
|
+
processToolResult(entry);
|
|
9521
|
+
}
|
|
9522
|
+
} else {
|
|
9523
|
+
for (const call of toolCalls) {
|
|
9524
|
+
const entry = await executeToolCall(call);
|
|
9525
|
+
processToolResult(entry);
|
|
9526
|
+
}
|
|
9389
9527
|
}
|
|
9390
9528
|
if (anyToolFailed) {
|
|
9391
9529
|
consecutiveToolFailures++;
|
|
@@ -9596,7 +9734,7 @@ ${taskReminder}</system-summary>`
|
|
|
9596
9734
|
});
|
|
9597
9735
|
}
|
|
9598
9736
|
}
|
|
9599
|
-
var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000;
|
|
9737
|
+
var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000, WRITE_TOOLS, SIDE_EFFECT_TOOLS;
|
|
9600
9738
|
var init_agent = __esm(() => {
|
|
9601
9739
|
init_i18n();
|
|
9602
9740
|
init_colors();
|
|
@@ -9604,6 +9742,14 @@ var init_agent = __esm(() => {
|
|
|
9604
9742
|
init_processes();
|
|
9605
9743
|
init_agent_moe();
|
|
9606
9744
|
init_store();
|
|
9745
|
+
WRITE_TOOLS = new Set([
|
|
9746
|
+
"write_file",
|
|
9747
|
+
"edit_file",
|
|
9748
|
+
"delete_file",
|
|
9749
|
+
"move_file",
|
|
9750
|
+
"create_dir"
|
|
9751
|
+
]);
|
|
9752
|
+
SIDE_EFFECT_TOOLS = new Set(["bash", "subagent", "pipeline_run"]);
|
|
9607
9753
|
});
|
|
9608
9754
|
|
|
9609
9755
|
// src/modules/context/manager.ts
|
|
@@ -15309,6 +15455,7 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
15309
15455
|
lines.push(``, `Windows environment — use Windows-compatible commands:`, `- Use "dir" instead of "ls". Use "dir /b" for bare listing.`, `- Use "type" or "Get-Content" instead of "cat".`, `- Use "cd" instead of "pwd". Use "echo %cd%" to print working directory.`, `- Use "copy" instead of "cp", "move" instead of "mv", "del" instead of "rm".`, `- Do not use "mkdir -p" — Windows mkdir creates intermediate dirs by default. Use the create_dir tool instead.`, `- Use forward slashes (/) or escaped backslashes (\\\\) in file paths.`, `- Your working directory is: ${baseDir}`);
|
|
15310
15456
|
}
|
|
15311
15457
|
lines.push(``, `Bash tool rules:`, `- Use the "workdir" parameter to run commands in a specific directory. Prefer workdir over "cd dir && cmd" chaining.`, `- Run one command per tool call. Split multi-step shell operations into separate bash calls.`, `- Background processes (dev servers, watchers, long-running npm install): use the "background: true" parameter or the tool will auto-detect and background them. Check output with process_log.`);
|
|
15458
|
+
lines.push(``, `Parallel tool calls:`, `- When you need to read multiple files, call read_file for ALL of them in a SINGLE response (one tool_calls array with multiple read_file calls). They will execute in parallel — much faster than reading one at a time.`, `- Example: to read 3 files, return one assistant message with 3 read_file tool_calls. Do NOT read them one by one in separate iterations.`, `- This works for: read_file, glob, grep, file_info, list_dir — any read-only operations.`, `- Do NOT parallelize write operations (write_file, edit_file, delete_file, bash) — these run sequentially.`);
|
|
15312
15459
|
lines.push(``, `=== DEVELOPMENT RULES — follow these strictly ===`, ``, `1. DEPENDENCIES FIRST: Before writing any source code, ALWAYS install project dependencies (e.g., "npm install", "pip install -r requirements.txt", "cargo build", "go mod tidy"). Verify the package manager's lock file or dependency directory exists. Never write code that imports/uses packages that aren't installed yet.`, `2. TOOLKIT/FWK FIRST: If the task specifies a framework or UI library, initialize and configure it BEFORE writing application code. Run its project init command first, then add components/modules. Never write your own version of what the framework already provides.`, `3. ONE STEP AT A TIME: Follow the plan sequentially. Complete step N before starting step N+1. When a step is done: verify the deliverables exist and have real content (not empty), then call "plan update step=N status=done". Do not redo completed work.`, `4. VERIFY YOUR WORK: After creating/modifying files, verify they exist on disk. After installing dependencies, verify the package manager completed successfully. After any command, check its output for errors. Don't assume operations succeeded.`, `5. NO PREMATURE WORK: Do not create files for future steps. Do not add imports/references to packages or modules that haven't been installed yet. Do not reference files or components that don't exist yet. Build incrementally — one layer at a time.`, `6. WHEN STUCK: If a command fails 2+ times, STOP and try a different approach. Write files directly instead of using commands. Ask the user for help. Never repeat the same failing command more than twice.`, ``, `=== PLAN QUALITY RULES — your plan MUST follow these ===`, ``, `- Each step must describe CONCRETE deliverables: exact filenames with paths, exact packages to install, exact CLI commands to run. Avoid vague steps — be specific.`, `- A step like "Настройка проекта" or "Setup the project" is too vague — describe what exactly needs to be configured or set up.`, `- A step like "Создать src/components/Header.tsx с навигацией и логотипом, добавить в src/App.tsx импорт <Header />" is GOOD.`, `- Include file extensions (.tsx, .css, .json) and directory paths. Every step must mention at least one file or command.`, `- The plan must cover EVERYTHING needed: init → deps → framework setup → code → verification.`, `- Number of steps: 5-8 for a typical task. Too few means you're being vague. Too many means you're over-splitting.`);
|
|
15313
15460
|
if (config.autoPlan) {
|
|
15314
15461
|
lines.push(``, `Plan rule (MANDATORY): For ANY task that requires creating files, installing packages, or multiple actions — you MUST create a plan using the "plan" tool BEFORE starting work. Each step must describe a concrete deliverable (specific files to create, packages to install, commands to run). Do not combine unrelated work into one step.`);
|
|
@@ -26122,6 +26269,7 @@ class Repl {
|
|
|
26122
26269
|
${t("repl.interrupt")}
|
|
26123
26270
|
`));
|
|
26124
26271
|
this.agent.shutdown();
|
|
26272
|
+
setTimeout(() => process.exit(1), 3000);
|
|
26125
26273
|
}
|
|
26126
26274
|
this.lastEscTime = 0;
|
|
26127
26275
|
return;
|