opencode-auto-resume 1.0.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2025 Mte90
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+
19
+ The full text of the GNU General Public License v3 can be found at:
20
+ https://www.gnu.org/licenses/gpl-3.0.txt
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # opencode-auto-resume
2
+
3
+ **Plugin for [OpenCode](https://github.com/opencode-ai/opencode) that automatically detects and recovers from LLM session failures — stalls, broken tool calls, hallucination loops, and stuck subagent parents. Fully silent, zero UI pollution.**
4
+
5
+ ## What it does
6
+
7
+ LLM sessions fail in predictable ways. This plugin monitors all sessions and automatically recovers without user intervention.
8
+
9
+ **Stall recovery** — the stream goes silent but the session stays "busy". The UI shows a blinking cursor with no progress. If no events arrive for 48 seconds, the plugin sends `"continue"` with exponential backoff. After 3 failed attempts it gives up.
10
+ _( [#55](https://github.com/opencode-ai/opencode/issues/55), [#199](https://github.com/opencode-ai/opencode/issues/199), [#283](https://github.com/opencode-ai/opencode/issues/283) )_
11
+
12
+ **Tool calls as raw text** — the model prints tool invocations as raw XML (`<function=edit>...`) instead of executing them. The session goes idle normally but the tool was never run. On idle, the plugin fetches the last messages and scans for XML tool-call patterns (including truncated and alternative formats). If found, it sends a specific recovery prompt.
13
+ _( [#150](https://github.com/opencode-ai/opencode/issues/150), [#313](https://github.com/opencode-ai/opencode/issues/313), [#353](https://github.com/opencode-ai/opencode/issues/353) )_
14
+
15
+ **Hallucination loop** — the model generates the same broken output repeatedly. Each continue just picks up the broken generation. If a session needs 3+ continues within 10 minutes, the plugin aborts the request and sends `"continue"` fresh, forcing a clean restart.
16
+ _( [#283](https://github.com/opencode-ai/opencode/issues/283), [#353](https://github.com/opencode-ai/opencode/issues/353) )_
17
+
18
+ **Orphan parent** — a subagent finishes but the parent session stays stuck as "busy" forever. The plugin detects when busyCount drops from >1 to 1, waits 15 seconds, then aborts and resumes the parent.
19
+ _( [#122](https://github.com/opencode-ai/opencode/issues/122), [#199](https://github.com/opencode-ai/opencode/issues/199), [#246](https://github.com/opencode-ai/opencode/issues/246) )_
20
+
21
+ **False positives during subagent work** — long tool execution or active subagents can look like a stall. Only the session emitting events gets its timer reset (not all sessions). When multiple sessions are busy, stall detection is paused entirely.
22
+ _( [#55](https://github.com/opencode-ai/opencode/issues/55), [#221](https://github.com/opencode-ai/opencode/issues/221) )_
23
+
24
+ **ESC cancel** — user presses ESC to cancel a request. The plugin detects `MessageAbortedError` and marks all busy sessions as cancelled, never resuming them.
25
+
26
+ **Spurious error messages** — after normal completion, OpenCode sometimes fires a `session.error`. All logging goes through `ctx.client.app.log()` (zero `console.log`), and errors on already-idle sessions are silently ignored.
27
+ _( [#128](https://github.com/opencode-ai/opencode/pulls/128), [#22](https://github.com/opencode-ai/opencode/pulls/22) )_
28
+
29
+ **Session discovery** — periodically calls `session.list()` to pick up sessions that were missed by event tracking. Idle sessions are cleaned up after 10 minutes to prevent memory leaks.
30
+
31
+ ## Architecture
32
+
33
+ ```
34
+ Any SSE Event
35
+ ├─ has sessionID? → touchSession(sid) — reset only that session's timer
36
+ └─ no sessionID → ignore
37
+
38
+ session.status events:
39
+ ├─ busy → reset timer, clear retry counters
40
+ └─ idle → schedule tool-text check (1.5s delay)
41
+ └─ fetch messages → scan for XML patterns
42
+ ├─ found → send recovery prompt (with backoff)
43
+ └─ not found → do nothing
44
+ └─ orphan check: busyCount dropped from >1 to 1?
45
+ └─ 15s watch → abort + continue
46
+
47
+ Timer loop (every 5s):
48
+ for each busy session:
49
+ ├─ orphan watch active? → wait or abort+continue
50
+ ├─ busyCount > 1? → skip (subagent running)
51
+ └─ idle > 48s? → hallucination loop? abort : continue with backoff
52
+
53
+ Periodic (every 60s): session.list() to discover missed sessions
54
+ Periodic: cleanup idle sessions older than 10min or >50 entries
55
+ ```
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ mkdir -p ~/.config/opencode/plugin/opencode-auto-resume
61
+ cd ~/.config/opencode/plugin/opencode-auto-resume
62
+ # Copy package.json, tsconfig.json, src/ here
63
+ bun install
64
+ bun run build
65
+ ```
66
+
67
+ Register in `opencode.json`:
68
+
69
+ ```json
70
+ {
71
+ "$schema": "https://opencode.ai/config.json",
72
+ "plugin": [
73
+ "file:///home/YOURUSER/.config/opencode/plugins/opencode-auto-resume/dist/index.js"
74
+ ]
75
+ }
76
+ ```
77
+
78
+ ## Configuration
79
+
80
+ ```json
81
+ {
82
+ "plugin": [
83
+ [
84
+ "file:///home/YOURUSER/.config/opencode/plugins/opencode-auto-resume/dist/index.js",
85
+ { "chunkTimeoutMs": 45000, "maxRetries": 3 }
86
+ ]
87
+ ]
88
+ }
89
+ ```
90
+
91
+ | Option | Default | Description |
92
+ |---|---|---|
93
+ | `chunkTimeoutMs` | `45000` | Inactivity timeout before considering stream stalled |
94
+ | `gracePeriodMs` | `3000` | Extra wait before acting (lets ESC/status events arrive) |
95
+ | `checkIntervalMs` | `5000` | Timer poll interval |
96
+ | `maxRetries` | `3` | Max auto-resume attempts before giving up |
97
+ | `baseBackoffMs` | `1000` | First retry delay (doubles each attempt) |
98
+ | `maxBackoffMs` | `8000` | Backoff cap |
99
+ | `subagentWaitMs` | `15000` | Wait before treating orphan parent as stuck |
100
+ | `loopMaxContinues` | `3` | Continues in window before triggering abort |
101
+ | `loopWindowMs` | `600000` | Hallucination loop detection window (10 min) |
102
+
103
+ ## Manual resume
104
+
105
+ The plugin exposes a `resume` tool:
106
+
107
+ ```
108
+ Please use the resume tool to unstick this session
109
+ Please use the resume tool with prompt "try the edit on src/main.js again"
110
+ ```
111
+
112
+ ## Troubleshooting
113
+
114
+ | Problem | Solution |
115
+ |---|---|
116
+ | Resumes after ESC | Increase `gracePeriodMs` to `5000` |
117
+ | Too aggressive | Increase `chunkTimeoutMs` to `60000` |
118
+ | Too slow to react | Decrease `checkIntervalMs` to `2000` |
119
+ | Orphan parent not detected | Increase `subagentWaitMs` to `20000` |
120
+ | Hallucination loop not caught | Decrease `loopMaxContinues` to `2` |
121
+ | Tool-text not detected | Check server logs — requires SDK message fetching |