@visorcraft/idlehands 1.2.8 → 1.3.2
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.js +100 -38
- package/dist/agent.js.map +1 -1
- package/dist/anton/controller.js +117 -37
- package/dist/anton/controller.js.map +1 -1
- package/dist/anton/parser.js +12 -13
- package/dist/anton/parser.js.map +1 -1
- package/dist/anton/prompt.js +116 -49
- package/dist/anton/prompt.js.map +1 -1
- package/dist/anton/reporter.js +29 -2
- package/dist/anton/reporter.js.map +1 -1
- package/dist/anton/session.js +25 -0
- package/dist/anton/session.js.map +1 -1
- package/dist/anton/verifier.js +3 -3
- package/dist/anton/verifier.js.map +1 -1
- package/dist/bot/commands.js +65 -2
- package/dist/bot/commands.js.map +1 -1
- package/dist/bot/discord.js +63 -6
- package/dist/bot/discord.js.map +1 -1
- package/dist/bot/telegram.js +22 -7
- package/dist/bot/telegram.js.map +1 -1
- package/dist/cli/commands/anton.js +15 -3
- package/dist/cli/commands/anton.js.map +1 -1
- package/dist/cli/commands/project.js +9 -0
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/config.js +6 -1
- package/dist/config.js.map +1 -1
- package/dist/runtime/executor.js +8 -3
- package/dist/runtime/executor.js.map +1 -1
- package/dist/sys/snapshot.sh +0 -0
- package/dist/tools.js +12 -2
- package/dist/tools.js.map +1 -1
- package/dist/utils.js +16 -8
- package/dist/utils.js.map +1 -1
- package/dist/vault.js +29 -31
- package/dist/vault.js.map +1 -1
- package/dist/vim.js +21 -12
- package/dist/vim.js.map +1 -1
- package/dist/watchdog.js +11 -2
- package/dist/watchdog.js.map +1 -1
- package/package.json +1 -1
- package/src/sys/snapshot.sh +0 -0
package/dist/agent.js
CHANGED
|
@@ -157,41 +157,41 @@ class AgentLoopBreak extends Error {
|
|
|
157
157
|
this.name = 'AgentLoopBreak';
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
const SYSTEM_PROMPT = `You are a coding agent with filesystem and shell access. Execute the user's request using the provided tools.
|
|
161
|
-
|
|
162
|
-
Rules:
|
|
163
|
-
- Work in the current directory. Use relative paths for all file operations.
|
|
164
|
-
- Do the work directly. Do NOT use spawn_task to delegate the user's primary request — only use it for genuinely independent subtasks that benefit from parallel execution.
|
|
165
|
-
- Never use spawn_task to bypass confirmation/safety restrictions (for example blocked package installs). If a command is blocked, adapt the plan or ask the user for approval mode changes.
|
|
166
|
-
- Read the target file before editing. You need the exact text for search/replace.
|
|
167
|
-
- Use read_file with search=... to jump to relevant code; avoid reading whole files.
|
|
168
|
-
- Never call read_file/read_files/list_dir twice in a row with identical arguments (same path/options). Reuse the previous result instead.
|
|
169
|
-
- Prefer apply_patch or edit_range for code edits (token-efficient). Use edit_file only when exact old_text replacement is necessary.
|
|
170
|
-
- Tool-call arguments MUST be strict JSON (double-quoted keys/strings, no comments, no trailing commas).
|
|
171
|
-
- edit_range example: {"path":"src/foo.ts","start_line":10,"end_line":14,"replacement":"line A\nline B"}
|
|
172
|
-
- apply_patch example: {"patch":"--- a/src/foo.ts\n+++ b/src/foo.ts\n@@ -10,2 +10,2 @@\n-old\n+new","files":["src/foo.ts"]}
|
|
173
|
-
- write_file is for new files or explicit full rewrites only. Existing non-empty files require overwrite=true/force=true.
|
|
174
|
-
- Use insert_file for insertions (prepend/append/line).
|
|
175
|
-
- Use exec to run commands, tests, builds; check results before reporting success.
|
|
176
|
-
- When running commands in a subdirectory, use exec's cwd parameter — NOT "cd /path && cmd". Each exec call is a fresh shell; cd does not persist.
|
|
177
|
-
- Batch work: read all files you need, then apply all edits, then verify.
|
|
178
|
-
- Be concise. Report what you changed and why.
|
|
179
|
-
- Do NOT read every file in a directory. Use search_files or exec with grep to locate relevant code first, then read only the files that match.
|
|
180
|
-
- If search_files returns 0 matches, try a broader pattern or use: exec grep -rn "keyword" path/
|
|
181
|
-
- Anton (the autonomous task runner) is ONLY activated when the user explicitly invokes /anton. Never self-activate as Anton or start processing task files on your own.
|
|
182
|
-
|
|
183
|
-
Tool call format:
|
|
184
|
-
- Use tool_calls. Do not write JSON tool invocations in your message text.
|
|
160
|
+
const SYSTEM_PROMPT = `You are a coding agent with filesystem and shell access. Execute the user's request using the provided tools.
|
|
161
|
+
|
|
162
|
+
Rules:
|
|
163
|
+
- Work in the current directory. Use relative paths for all file operations.
|
|
164
|
+
- Do the work directly. Do NOT use spawn_task to delegate the user's primary request — only use it for genuinely independent subtasks that benefit from parallel execution.
|
|
165
|
+
- Never use spawn_task to bypass confirmation/safety restrictions (for example blocked package installs). If a command is blocked, adapt the plan or ask the user for approval mode changes.
|
|
166
|
+
- Read the target file before editing. You need the exact text for search/replace.
|
|
167
|
+
- Use read_file with search=... to jump to relevant code; avoid reading whole files.
|
|
168
|
+
- Never call read_file/read_files/list_dir twice in a row with identical arguments (same path/options). Reuse the previous result instead.
|
|
169
|
+
- Prefer apply_patch or edit_range for code edits (token-efficient). Use edit_file only when exact old_text replacement is necessary.
|
|
170
|
+
- Tool-call arguments MUST be strict JSON (double-quoted keys/strings, no comments, no trailing commas).
|
|
171
|
+
- edit_range example: {"path":"src/foo.ts","start_line":10,"end_line":14,"replacement":"line A\nline B"}
|
|
172
|
+
- apply_patch example: {"patch":"--- a/src/foo.ts\n+++ b/src/foo.ts\n@@ -10,2 +10,2 @@\n-old\n+new","files":["src/foo.ts"]}
|
|
173
|
+
- write_file is for new files or explicit full rewrites only. Existing non-empty files require overwrite=true/force=true.
|
|
174
|
+
- Use insert_file for insertions (prepend/append/line).
|
|
175
|
+
- Use exec to run commands, tests, builds; check results before reporting success.
|
|
176
|
+
- When running commands in a subdirectory, use exec's cwd parameter — NOT "cd /path && cmd". Each exec call is a fresh shell; cd does not persist.
|
|
177
|
+
- Batch work: read all files you need, then apply all edits, then verify.
|
|
178
|
+
- Be concise. Report what you changed and why.
|
|
179
|
+
- Do NOT read every file in a directory. Use search_files or exec with grep to locate relevant code first, then read only the files that match.
|
|
180
|
+
- If search_files returns 0 matches, try a broader pattern or use: exec grep -rn "keyword" path/
|
|
181
|
+
- Anton (the autonomous task runner) is ONLY activated when the user explicitly invokes /anton. Never self-activate as Anton or start processing task files on your own.
|
|
182
|
+
|
|
183
|
+
Tool call format:
|
|
184
|
+
- Use tool_calls. Do not write JSON tool invocations in your message text.
|
|
185
185
|
`;
|
|
186
186
|
const MCP_TOOLS_REQUEST_TOKEN = '[[MCP_TOOLS_REQUEST]]';
|
|
187
|
-
const DEFAULT_SUB_AGENT_SYSTEM_PROMPT = `You are a focused coding sub-agent. Execute only the delegated task.
|
|
188
|
-
- Work in the current directory. Use relative paths for all file operations.
|
|
189
|
-
- Read the target file before editing. You need the exact text for search/replace.
|
|
190
|
-
- Keep tool usage tight and efficient.
|
|
191
|
-
- Prefer surgical edits over rewrites.
|
|
192
|
-
- Do NOT create files outside the working directory unless explicitly requested.
|
|
193
|
-
- When running commands in a subdirectory, use exec's cwd parameter — NOT "cd /path && cmd".
|
|
194
|
-
- Run verification commands when relevant.
|
|
187
|
+
const DEFAULT_SUB_AGENT_SYSTEM_PROMPT = `You are a focused coding sub-agent. Execute only the delegated task.
|
|
188
|
+
- Work in the current directory. Use relative paths for all file operations.
|
|
189
|
+
- Read the target file before editing. You need the exact text for search/replace.
|
|
190
|
+
- Keep tool usage tight and efficient.
|
|
191
|
+
- Prefer surgical edits over rewrites.
|
|
192
|
+
- Do NOT create files outside the working directory unless explicitly requested.
|
|
193
|
+
- When running commands in a subdirectory, use exec's cwd parameter — NOT "cd /path && cmd".
|
|
194
|
+
- Run verification commands when relevant.
|
|
195
195
|
- Return a concise outcome summary.`;
|
|
196
196
|
const DEFAULT_SUB_AGENT_RESULT_TOKEN_CAP = 4000;
|
|
197
197
|
const APPROVAL_MODE_SET = new Set(['plan', 'reject', 'default', 'auto-edit', 'yolo']);
|
|
@@ -1136,6 +1136,7 @@ export async function createSession(opts) {
|
|
|
1136
1136
|
dirPinned: cfg.dir_pinned,
|
|
1137
1137
|
repoCandidates: cfg.repo_candidates,
|
|
1138
1138
|
confirm: overrides?.confirmBridge ?? defaultConfirmBridge,
|
|
1139
|
+
maxReadLines: cfg.max_read_lines,
|
|
1139
1140
|
replay,
|
|
1140
1141
|
vault,
|
|
1141
1142
|
lens,
|
|
@@ -1267,6 +1268,34 @@ export async function createSession(opts) {
|
|
|
1267
1268
|
const guidance = compactionVaultGuidance();
|
|
1268
1269
|
return guidance ? `${prefix} ${guidance}` : prefix;
|
|
1269
1270
|
};
|
|
1271
|
+
const buildCompactionSummaryPrompt = (dropped) => {
|
|
1272
|
+
const parts = [];
|
|
1273
|
+
for (const m of dropped) {
|
|
1274
|
+
if (m.role === 'assistant') {
|
|
1275
|
+
const text = typeof m.content === 'string' ? m.content : '';
|
|
1276
|
+
const toolCalls = m.tool_calls;
|
|
1277
|
+
if (toolCalls?.length) {
|
|
1278
|
+
for (const tc of toolCalls) {
|
|
1279
|
+
const args = typeof tc.function?.arguments === 'string'
|
|
1280
|
+
? tc.function.arguments.slice(0, 200)
|
|
1281
|
+
: '';
|
|
1282
|
+
parts.push(`[tool_call: ${tc.function?.name}(${args})]`);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
if (text.trim())
|
|
1286
|
+
parts.push(`[assistant]: ${text.slice(0, 500)}`);
|
|
1287
|
+
}
|
|
1288
|
+
else if (m.role === 'tool') {
|
|
1289
|
+
const content = typeof m.content === 'string' ? m.content : '';
|
|
1290
|
+
parts.push(`[tool_result]: ${content.slice(0, 300)}`);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
let combined = parts.join('\n');
|
|
1294
|
+
if (combined.length > 4000) {
|
|
1295
|
+
combined = combined.slice(0, 4000) + '\n[...truncated]';
|
|
1296
|
+
}
|
|
1297
|
+
return combined;
|
|
1298
|
+
};
|
|
1270
1299
|
let lastAskInstructionText = '';
|
|
1271
1300
|
let lastCompactionReminderObjective = '';
|
|
1272
1301
|
const injectCompactionReminder = (reason) => {
|
|
@@ -2128,7 +2157,7 @@ export async function createSession(opts) {
|
|
|
2128
2157
|
messages: beforeMsgs,
|
|
2129
2158
|
contextWindow,
|
|
2130
2159
|
maxTokens: maxTokens,
|
|
2131
|
-
minTailMessages: 12,
|
|
2160
|
+
minTailMessages: cfg.compact_min_tail ?? 12,
|
|
2132
2161
|
compactAt: cfg.compact_at ?? 0.8,
|
|
2133
2162
|
toolSchemaTokens: estimateToolSchemaTokens(getToolsSchema()),
|
|
2134
2163
|
});
|
|
@@ -2164,7 +2193,39 @@ export async function createSession(opts) {
|
|
|
2164
2193
|
}
|
|
2165
2194
|
messages = compacted;
|
|
2166
2195
|
if (dropped.length) {
|
|
2167
|
-
|
|
2196
|
+
const droppedTokens = estimateTokensFromMessages(dropped);
|
|
2197
|
+
if (cfg.compact_summary !== false && droppedTokens > 200) {
|
|
2198
|
+
try {
|
|
2199
|
+
const summaryContent = buildCompactionSummaryPrompt(dropped);
|
|
2200
|
+
const summaryMaxTokens = cfg.compact_summary_max_tokens ?? 300;
|
|
2201
|
+
const resp = await client.chat({
|
|
2202
|
+
model,
|
|
2203
|
+
messages: [
|
|
2204
|
+
{ role: 'system', content: 'Summarize this agent session progress concisely. List: files read, key findings, decisions made, current approach. Be terse.' },
|
|
2205
|
+
{ role: 'user', content: summaryContent },
|
|
2206
|
+
],
|
|
2207
|
+
max_tokens: summaryMaxTokens,
|
|
2208
|
+
temperature: 0,
|
|
2209
|
+
responseTimeoutMs: 5_000,
|
|
2210
|
+
});
|
|
2211
|
+
const summary = resp.choices?.[0]?.message?.content ?? '';
|
|
2212
|
+
if (summary.trim()) {
|
|
2213
|
+
messages.push({
|
|
2214
|
+
role: 'system',
|
|
2215
|
+
content: `[Compacted ${dropped.length} messages (~${droppedTokens} tokens). Progress summary:]\n${summary.trim()}\n[Continue from where you left off. Do not repeat completed work.]`,
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
else {
|
|
2219
|
+
messages.push({ role: 'system', content: buildCompactionSystemNote('auto', dropped.length) });
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
catch {
|
|
2223
|
+
messages.push({ role: 'system', content: buildCompactionSystemNote('auto', dropped.length) });
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
else {
|
|
2227
|
+
messages.push({ role: 'system', content: buildCompactionSystemNote('auto', dropped.length) });
|
|
2228
|
+
}
|
|
2168
2229
|
}
|
|
2169
2230
|
// Update token count AFTER injections so downstream reads are accurate
|
|
2170
2231
|
currentContextTokens = estimateTokensFromMessages(messages);
|
|
@@ -2202,8 +2263,8 @@ export async function createSession(opts) {
|
|
|
2202
2263
|
let resp;
|
|
2203
2264
|
try {
|
|
2204
2265
|
try {
|
|
2205
|
-
const toolsForTurn = forceToollessRecoveryTurn ? [] : getToolsSchema();
|
|
2206
|
-
const toolChoiceForTurn = forceToollessRecoveryTurn ? 'none' : 'auto';
|
|
2266
|
+
const toolsForTurn = (cfg.no_tools || forceToollessRecoveryTurn) ? [] : getToolsSchema();
|
|
2267
|
+
const toolChoiceForTurn = (cfg.no_tools || forceToollessRecoveryTurn) ? 'none' : 'auto';
|
|
2207
2268
|
resp = await client.chatStream({
|
|
2208
2269
|
model,
|
|
2209
2270
|
messages,
|
|
@@ -3256,7 +3317,8 @@ export async function createSession(opts) {
|
|
|
3256
3317
|
const assistantText = visible || content || '';
|
|
3257
3318
|
// Recovery fuse: if the model keeps narrating/planning without tool use,
|
|
3258
3319
|
// nudge it once with the original task. Never resend more than once per ask().
|
|
3259
|
-
|
|
3320
|
+
// Skip this check entirely when no_tools is set — text IS the final answer.
|
|
3321
|
+
if (!cfg.no_tools && looksLikePlanningNarration(assistantText, finishReason)) {
|
|
3260
3322
|
noToolTurns += 1;
|
|
3261
3323
|
messages.push({ role: 'assistant', content: assistantText });
|
|
3262
3324
|
if (noToolTurns >= NO_TOOL_REPROMPT_THRESHOLD) {
|