@visorcraft/idlehands 1.3.3 → 1.3.4
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/README.md +28 -1
- package/dist/agent.js +20 -0
- package/dist/agent.js.map +1 -1
- package/dist/anton/controller.js +20 -1
- package/dist/anton/controller.js.map +1 -1
- package/dist/bot/auto-continue.js +24 -0
- package/dist/bot/auto-continue.js.map +1 -0
- package/dist/bot/commands.js +26 -0
- package/dist/bot/commands.js.map +1 -1
- package/dist/bot/discord.js +46 -1
- package/dist/bot/discord.js.map +1 -1
- package/dist/bot/telegram.js +23 -2
- package/dist/bot/telegram.js.map +1 -1
- package/dist/bot/ux/events.js +142 -0
- package/dist/bot/ux/events.js.map +1 -0
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -1
- package/dist/tui/controller.js +24 -1
- package/dist/tui/controller.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,10 +25,12 @@ Idle Hands is built for people who want an agent that can actually ship work, no
|
|
|
25
25
|
|
|
26
26
|
Trifecta is the integrated core of Idle Hands:
|
|
27
27
|
|
|
28
|
-
- **Vault** → persistent memory + notes (`/vault`, `/note`, `/notes`)
|
|
28
|
+
- **Vault** → persistent memory + notes (`/vault`, `/note`, `/notes`) + automatic turn action summaries
|
|
29
29
|
- **Replay** → file checkpoints and rewind/diff (`/checkpoints`, `/rewind`, `/diff`, `/undo`)
|
|
30
30
|
- **Lens** → structural compression/indexing for better context usage
|
|
31
31
|
|
|
32
|
+
Every tool-using turn is automatically summarized and persisted to the Vault, so the model can recall what it did — even after context compaction drops earlier messages. This is especially useful for local models with limited context windows.
|
|
33
|
+
|
|
32
34
|
Runtime controls:
|
|
33
35
|
|
|
34
36
|
```bash
|
|
@@ -222,6 +224,31 @@ idlehands health --scan-ports 8000-8100
|
|
|
222
224
|
idlehands health --scan-ports 8080,8081,9000
|
|
223
225
|
```
|
|
224
226
|
|
|
227
|
+
## Tool loop auto-continue
|
|
228
|
+
|
|
229
|
+
When the agent hits a critical tool loop (repeated identical tool calls with no progress), Idle Hands now automatically retries instead of stopping and waiting for a manual "Continue" message.
|
|
230
|
+
|
|
231
|
+
- **All surfaces**: TUI, Telegram bot, Discord bot, and Anton all support auto-continue
|
|
232
|
+
- **User notification**: each retry sends a visible notice with error details and attempt count
|
|
233
|
+
- **Configurable**: up to 5 retries by default (max 10), fully disableable
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"tool_loop_auto_continue": {
|
|
238
|
+
"enabled": true,
|
|
239
|
+
"max_retries": 5
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
On each retry the user sees:
|
|
245
|
+
> ⚠️ Tool loop detected: {error details}
|
|
246
|
+
> 🔄 Automatically continuing the task. (retry 1 of 5)
|
|
247
|
+
|
|
248
|
+
After exhausting all retries, the error surfaces normally. Anton handles this internally without orchestrator involvement.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
225
252
|
## Documentation map
|
|
226
253
|
|
|
227
254
|
- [Getting Started](https://visorcraft.github.io/IdleHands/guide/getting-started)
|
package/dist/agent.js
CHANGED
|
@@ -1879,6 +1879,26 @@ export async function createSession(opts) {
|
|
|
1879
1879
|
};
|
|
1880
1880
|
const finalizeAsk = async (text) => {
|
|
1881
1881
|
const finalText = ensureInformativeAssistantText(text, { toolCalls, turns });
|
|
1882
|
+
// Auto-persist turn action summary to Vault so the model can recall what it did.
|
|
1883
|
+
if (vault && toolCalls > 0) {
|
|
1884
|
+
try {
|
|
1885
|
+
const actions = [];
|
|
1886
|
+
for (const [callId, name] of toolNameByCallId) {
|
|
1887
|
+
const args = toolArgsByCallId.get(callId) ?? {};
|
|
1888
|
+
actions.push(planModeSummary(name, args));
|
|
1889
|
+
}
|
|
1890
|
+
if (actions.length) {
|
|
1891
|
+
const userPromptSnippet = rawInstructionText.length > 120
|
|
1892
|
+
? rawInstructionText.slice(0, 120) + '…'
|
|
1893
|
+
: rawInstructionText;
|
|
1894
|
+
const summary = `User asked: ${userPromptSnippet}\nActions (${actions.length} tool calls, ${turns} turns):\n${actions.map(a => `- ${a}`).join('\n')}\nResult: ${finalText.length > 200 ? finalText.slice(0, 200) + '…' : finalText}`;
|
|
1895
|
+
await vault.upsertNote(`turn_summary_${askId}`, summary, 'system');
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
catch {
|
|
1899
|
+
// best-effort — never block ask completion for summary persistence
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1882
1902
|
await hookManager.emit('ask_end', { askId, text: finalText, turns, toolCalls });
|
|
1883
1903
|
return { text: finalText, turns, toolCalls };
|
|
1884
1904
|
};
|