@elvatis_com/openclaw-self-healing-elvatis 0.2.7 → 0.2.9
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/.ai/handoff/CONVENTIONS.md +67 -0
- package/.ai/handoff/DASHBOARD.md +38 -13
- package/.ai/handoff/LOG.md +61 -3
- package/.ai/handoff/NEXT_ACTIONS.md +25 -34
- package/.ai/handoff/STATUS.md +37 -20
- package/.clawhubignore +8 -0
- package/README.md +22 -15
- package/index.ts +17 -5
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# CONVENTIONS.md — openclaw-self-healing-elvatis
|
|
2
|
+
|
|
3
|
+
## Language & Runtime
|
|
4
|
+
- TypeScript strict mode, ESM (`"type": "module"`)
|
|
5
|
+
- Node 16 module resolution (`"moduleResolution": "Node16"`)
|
|
6
|
+
- Target: ES2022
|
|
7
|
+
|
|
8
|
+
## Package
|
|
9
|
+
- Scope: `@elvatis_com/openclaw-self-healing-elvatis`
|
|
10
|
+
- Plugin ID: `openclaw-self-healing-elvatis`
|
|
11
|
+
- Test runner: vitest
|
|
12
|
+
|
|
13
|
+
## File Layout
|
|
14
|
+
```
|
|
15
|
+
.ai/handoff/ ← AAHP protocol files (this folder)
|
|
16
|
+
src/ ← (future) extracted helpers
|
|
17
|
+
index.ts ← plugin entry point + all business logic
|
|
18
|
+
test/ ← vitest test suites
|
|
19
|
+
openclaw.plugin.json ← manifest
|
|
20
|
+
package.json / tsconfig.json / tsconfig.check.json
|
|
21
|
+
scripts/ ← one-off utilities (roadmap issue creation, etc.)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Code Style
|
|
25
|
+
- Named exports for all pure helpers (testable without plugin API)
|
|
26
|
+
- `saveState()` must be called BEFORE any destructive system call (e.g. `openclaw gateway restart`)
|
|
27
|
+
→ Reason: systemd-managed gateway restarts kill the process mid-execution; state written after the call is never persisted
|
|
28
|
+
- No secrets in logs — redact with `[REDACTED]`
|
|
29
|
+
- `runCmd` always uses `bash -lc` for login shell compatibility
|
|
30
|
+
- All `autoFix.*` flags default to the safest value (`false` unless stated otherwise)
|
|
31
|
+
- `whatsappRestartEnabled` is the one exception — defaults to `true` (most useful default)
|
|
32
|
+
|
|
33
|
+
## Release Checklist (mandatory for every publish)
|
|
34
|
+
|
|
35
|
+
### Before release
|
|
36
|
+
1. `npm run typecheck` — must pass
|
|
37
|
+
2. `npm test` — all tests must pass
|
|
38
|
+
3. Bump version in `package.json` AND `openclaw.plugin.json`
|
|
39
|
+
|
|
40
|
+
### Publish (all three platforms, no exceptions)
|
|
41
|
+
4. `git tag vX.Y.Z && git push origin main && git push origin vX.Y.Z`
|
|
42
|
+
5. `gh release create vX.Y.Z --title "..." --notes "..."`
|
|
43
|
+
6. `npm publish --access public`
|
|
44
|
+
7. ClawHub (use rsync workaround — `.clawhubignore` is NOT respected by `clawhub publish`):
|
|
45
|
+
```bash
|
|
46
|
+
TMP=$(mktemp -d)
|
|
47
|
+
rsync -a --exclude='node_modules' --exclude='.git' --exclude='dist' \
|
|
48
|
+
--exclude='package-lock.json' ./ "$TMP/"
|
|
49
|
+
clawhub publish "$TMP" --slug openclaw-self-healing-elvatis \
|
|
50
|
+
--name "OpenClaw Self Healing" --version X.Y.Z --changelog "..." --no-input
|
|
51
|
+
rm -rf "$TMP"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### After release
|
|
55
|
+
8. Update ALL docs in this repo: STATUS.md, DASHBOARD.md, LOG.md, NEXT_ACTIONS.md, README.md, SKILL.md
|
|
56
|
+
9. Update MEMORY.md on server if architecture decisions changed
|
|
57
|
+
|
|
58
|
+
## Documentation Rule (MANDATORY)
|
|
59
|
+
**Every release MUST update the following files before committing:**
|
|
60
|
+
- `.ai/handoff/STATUS.md` — current version, state, open risks
|
|
61
|
+
- `.ai/handoff/DASHBOARD.md` — task table
|
|
62
|
+
- `.ai/handoff/LOG.md` — append entry for this session
|
|
63
|
+
- `.ai/handoff/NEXT_ACTIONS.md` — move done tasks, add new ones
|
|
64
|
+
- `README.md` — version number + any changed behavior
|
|
65
|
+
- `SKILL.md` — if commands or config changed
|
|
66
|
+
|
|
67
|
+
Skipping documentation = incomplete release. No exceptions.
|
package/.ai/handoff/DASHBOARD.md
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
|
-
# DASHBOARD
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
|
8
|
-
|
|
9
|
-
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
|
1
|
+
# DASHBOARD.md — openclaw-self-healing-elvatis
|
|
2
|
+
|
|
3
|
+
_Last updated: 2026-03-07_
|
|
4
|
+
|
|
5
|
+
## 🏗️ Plugin Status
|
|
6
|
+
|
|
7
|
+
| Component | Version | Build | Tests | Status |
|
|
8
|
+
|-----------|---------|-------|-------|--------|
|
|
9
|
+
| openclaw-self-healing-elvatis | 0.2.8 | ✅ | 181/181 ✅ | ✅ Stable |
|
|
10
|
+
|
|
11
|
+
## 🚀 Release State
|
|
12
|
+
|
|
13
|
+
| Platform | Version | Status |
|
|
14
|
+
|----------|---------|--------|
|
|
15
|
+
| GitHub | v0.2.8 | ✅ Tagged + Release |
|
|
16
|
+
| npm | 0.2.8 | ✅ Published |
|
|
17
|
+
| ClawHub | 0.2.8 | ✅ Published |
|
|
18
|
+
|
|
19
|
+
## 📋 Open Tasks
|
|
20
|
+
|
|
21
|
+
| ID | Task | Priority | Status |
|
|
22
|
+
|----|------|----------|--------|
|
|
23
|
+
| T-014 | Export heal metrics to `~/.aahp/metrics.jsonl` | 🟡 MEDIUM | Ready |
|
|
24
|
+
|
|
25
|
+
## ✅ Completed Tasks
|
|
26
|
+
|
|
27
|
+
| Task | Title | Version |
|
|
28
|
+
|------|-------|---------|
|
|
29
|
+
| T-015 | Fix infinite gateway restart loop (lastRestartAt before restart) | 0.2.8 |
|
|
30
|
+
| T-005 | Plugin health monitoring via JSON API + auto-disable | 0.2.7 |
|
|
31
|
+
| T-013 | Status snapshot file on each monitor tick | 0.2.6 |
|
|
32
|
+
| T-012 | Startup config validation (fail-fast) | 0.2.6 |
|
|
33
|
+
| T-011 | Integration tests for monitor tick flows | 0.2.6 |
|
|
34
|
+
| T-004 | TypeScript build pipeline + typecheck | 0.2.5 |
|
|
35
|
+
| T-010 | Observability events + status endpoint | 0.2.4 |
|
|
36
|
+
| T-009 | Dry-run mode | 0.2.3 |
|
|
37
|
+
| T-008 | Active recovery probing | 0.2.3 |
|
|
38
|
+
| T-007 | Config hot-reload | 0.2.3 |
|
package/.ai/handoff/LOG.md
CHANGED
|
@@ -1,4 +1,62 @@
|
|
|
1
|
-
# LOG
|
|
1
|
+
# LOG.md — openclaw-self-healing-elvatis
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
## 2026-03-07 — Session (Akido / claude-sonnet-4-6)
|
|
4
|
+
|
|
5
|
+
**Bug: Infinite gateway restart loop (fixed in v0.2.8)**
|
|
6
|
+
|
|
7
|
+
Root cause: `openclaw gateway restart` kills the process via systemd. `lastRestartAt = nowSec()`,
|
|
8
|
+
`disconnectStreak = 0`, and `saveState()` were placed AFTER `runCmd("openclaw gateway restart")`.
|
|
9
|
+
These lines never executed when the process was killed. On next boot, `lastRestartAt = 0`,
|
|
10
|
+
`since = huge`, bypassing the 5-minute rate-limit guard. WhatsApp takes 60–120s to reconnect
|
|
11
|
+
after any restart → self-healing saw 2 disconnect ticks → hit threshold → restarted again.
|
|
12
|
+
Infinite loop.
|
|
13
|
+
|
|
14
|
+
Fix: moved `lastRestartAt = nowSec()`, `disconnectStreak = 0`, and `saveState()` to BEFORE
|
|
15
|
+
the `runCmd("openclaw gateway restart")` call.
|
|
16
|
+
|
|
17
|
+
**Release pipeline:**
|
|
18
|
+
- v0.2.8 committed, tagged, pushed to GitHub
|
|
19
|
+
- GitHub release created: https://github.com/elvatis/openclaw-self-healing-elvatis/releases/tag/v0.2.8
|
|
20
|
+
- npm published: `@elvatis_com/openclaw-self-healing-elvatis@0.2.8`
|
|
21
|
+
- ClawHub published: `openclaw-self-healing-elvatis@0.2.8` (rsync workaround — .clawhubignore not respected by clawhub publish)
|
|
22
|
+
- Added `.clawhubignore` and documented rsync workaround in CONVENTIONS.md
|
|
23
|
+
|
|
24
|
+
All 181 tests passed before release.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2026-03-02 — Session (Akido)
|
|
29
|
+
|
|
30
|
+
- T-013: Status snapshot file written on each monitor tick
|
|
31
|
+
- T-012: Startup config validation with fail-fast
|
|
32
|
+
- T-011: Integration tests for monitor service tick flows
|
|
33
|
+
- T-005: Plugin health monitoring implemented via `openclaw plugins list --json`
|
|
34
|
+
- Atomic state writes (tmp + rename)
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2026-03-01 — Session (Akido)
|
|
39
|
+
|
|
40
|
+
- T-004: TypeScript build pipeline + typecheck
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2026-02-28 — Session (Akido)
|
|
45
|
+
|
|
46
|
+
- T-010: Self-heal status endpoint / observability events
|
|
47
|
+
- T-009: Dry-run mode
|
|
48
|
+
- T-008: Active recovery probing
|
|
49
|
+
- T-007: Config hot-reload
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2026-02-27 — Session (Akido)
|
|
54
|
+
|
|
55
|
+
- Defined v0.3 roadmap with 8 items. Created ROADMAP.md + scripts/create-roadmap-issues.sh.
|
|
56
|
+
- GitHub issue creation deferred (gh CLI not authenticated at the time).
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 2026-02-24 — Session (Akido)
|
|
61
|
+
|
|
62
|
+
- Initialized AAHP handoff structure.
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
# NEXT_ACTIONS
|
|
1
|
+
# NEXT_ACTIONS.md — openclaw-self-healing-elvatis
|
|
2
|
+
|
|
3
|
+
_Last updated: 2026-03-07_
|
|
2
4
|
|
|
3
5
|
## Status Summary
|
|
4
6
|
|
|
5
|
-
| Status
|
|
6
|
-
|
|
7
|
-
| Done
|
|
8
|
-
| Ready
|
|
9
|
-
| Blocked |
|
|
7
|
+
| Status | Count |
|
|
8
|
+
|--------|-------|
|
|
9
|
+
| Done | 15 |
|
|
10
|
+
| Ready | 1 |
|
|
11
|
+
| Blocked | 0 |
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
13
|
-
## Ready
|
|
15
|
+
## Ready — Work These Next
|
|
14
16
|
|
|
15
|
-
### T-014: [medium]
|
|
16
|
-
- **Goal:** Append one JSONL line per heal event
|
|
17
|
-
- **Context:** Heal events are
|
|
17
|
+
### T-014: [medium] — Export heal metrics to `~/.aahp/metrics.jsonl`
|
|
18
|
+
- **Goal:** Append one JSONL line per heal event for analysis and alerting.
|
|
19
|
+
- **Context:** Heal events are only visible in logs and via `api.emit()`. No persistent record for analysis.
|
|
18
20
|
- **What to do:**
|
|
19
21
|
- Export `appendMetric(line, metricsFile)` helper
|
|
20
|
-
- Write entries for: model-cooldown
|
|
22
|
+
- Write entries for: `model-cooldown`, `session-patched`, `whatsapp-restart`, `cron-disabled`, `model-recovered`
|
|
21
23
|
- Default metrics file: `~/.aahp/metrics.jsonl` (configurable via `metricsFile`)
|
|
22
24
|
- Skip or mark dry-run events
|
|
23
25
|
- Create parent directory if missing
|
|
@@ -27,28 +29,17 @@
|
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
30
|
-
## Blocked
|
|
31
|
-
|
|
32
|
-
### T-005: [high] - Implement structured plugin health monitoring and auto-disable (issue #3)
|
|
33
|
-
- **Blocked by:** Waiting for `openclaw plugins list --json` API from openclaw core
|
|
34
|
-
- **Goal:** Monitor plugin health and auto-disable failing plugins using structured JSON output.
|
|
35
|
-
- **Context:** Current code has a stub that parses plain text output from `openclaw plugins list`. No robust parsing is possible without the `--json` flag.
|
|
36
|
-
- **What to do (when unblocked):**
|
|
37
|
-
- Parse `openclaw plugins list --json` output for plugin status
|
|
38
|
-
- Auto-disable plugins with `status=error` (respecting `pluginDisableCooldownSec`)
|
|
39
|
-
- Create GitHub issues for disabled plugins
|
|
40
|
-
- **Files:** `index.ts`, `test/index.test.ts`
|
|
41
|
-
- **Definition of done:** Failing plugins are detected via JSON API and auto-disabled; tests cover detection and disable logic.
|
|
42
|
-
- **GitHub Issue:** #3
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
32
|
## Recently Completed
|
|
47
33
|
|
|
48
|
-
| Task
|
|
49
|
-
|
|
50
|
-
| T-
|
|
51
|
-
| T-
|
|
52
|
-
| T-
|
|
53
|
-
| T-
|
|
54
|
-
| T-
|
|
34
|
+
| Task | Title | Date |
|
|
35
|
+
|------|-------|------|
|
|
36
|
+
| T-015 | Fix infinite gateway restart loop | 2026-03-07 |
|
|
37
|
+
| T-005 | Plugin health monitoring via JSON API | 2026-03-07 |
|
|
38
|
+
| T-013 | Status snapshot file on each monitor tick | 2026-03-02 |
|
|
39
|
+
| T-012 | Startup config validation (fail-fast) | 2026-03-02 |
|
|
40
|
+
| T-011 | Integration tests for monitor tick flows | 2026-03-02 |
|
|
41
|
+
| T-004 | TypeScript build pipeline + typecheck | 2026-03-01 |
|
|
42
|
+
| T-010 | Observability events + status endpoint | 2026-02-28 |
|
|
43
|
+
| T-009 | Dry-run mode | 2026-02-28 |
|
|
44
|
+
| T-008 | Active recovery probing | 2026-02-28 |
|
|
45
|
+
| T-007 | Config hot-reload | 2026-02-28 |
|
package/.ai/handoff/STATUS.md
CHANGED
|
@@ -1,20 +1,37 @@
|
|
|
1
|
-
# STATUS
|
|
2
|
-
|
|
3
|
-
(
|
|
4
|
-
|
|
5
|
-
## Current
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
1
|
+
# STATUS.md — openclaw-self-healing-elvatis
|
|
2
|
+
|
|
3
|
+
_Last updated: 2026-03-07 by Akido (claude-sonnet-4-6)_
|
|
4
|
+
|
|
5
|
+
## Current Version: 0.2.8 — STABLE
|
|
6
|
+
|
|
7
|
+
## What is done
|
|
8
|
+
|
|
9
|
+
- ✅ Repo: `https://github.com/elvatis/openclaw-self-healing-elvatis`
|
|
10
|
+
- ✅ npm: `@elvatis_com/openclaw-self-healing-elvatis@0.2.8`
|
|
11
|
+
- ✅ ClawHub: `openclaw-self-healing-elvatis@0.2.8`
|
|
12
|
+
- ✅ Model failover: rate-limit + auth-scope cooldown, configurable fallback order
|
|
13
|
+
- ✅ WhatsApp reconnect: disconnect streak detection + gateway restart
|
|
14
|
+
- ✅ Cron failure: consecutive fail threshold → disable + GitHub issue
|
|
15
|
+
- ✅ Plugin health monitoring: `openclaw plugins list --json` → auto-disable on crash/error
|
|
16
|
+
- ✅ Config guardrails: never modify/restart if `openclaw.json` is invalid JSON
|
|
17
|
+
- ✅ Startup config validation (fail-fast)
|
|
18
|
+
- ✅ Status snapshot: written to file on every tick for external monitoring
|
|
19
|
+
- ✅ Active recovery probing: polls limited models to detect early recovery
|
|
20
|
+
- ✅ Dry-run mode: full behavior simulation without side effects
|
|
21
|
+
- ✅ Config hot-reload: reads `api.pluginConfig` on each tick
|
|
22
|
+
- ✅ Atomic state writes: tmp file + rename to avoid partial writes
|
|
23
|
+
- ✅ 181 tests across 2 suites (unit + integration)
|
|
24
|
+
- ✅ TypeScript build + typecheck pipeline
|
|
25
|
+
- ✅ `.clawhubignore` + rsync-based ClawHub publish documented in CONVENTIONS.md
|
|
26
|
+
|
|
27
|
+
## Critical Bug Fixed (v0.2.8)
|
|
28
|
+
|
|
29
|
+
**Infinite gateway restart loop** — `lastRestartAt` was being saved AFTER
|
|
30
|
+
`openclaw gateway restart`, which kills the process via systemd. On the next
|
|
31
|
+
boot, `lastRestartAt = 0`, bypassing the `whatsappMinRestartIntervalSec`
|
|
32
|
+
rate-limit guard. Fixed by saving state BEFORE the restart call.
|
|
33
|
+
|
|
34
|
+
## Open Risks
|
|
35
|
+
|
|
36
|
+
- `T-014`: Heal metrics export to JSONL not yet implemented (low priority, no blocker)
|
|
37
|
+
- ClawHub publish via `clawhub publish <dir>` ignores `.clawhubignore` — use rsync workaround (see CONVENTIONS.md)
|
package/.clawhubignore
ADDED
package/README.md
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
# openclaw-self-healing-elvatis
|
|
2
2
|
|
|
3
|
+
**Current version: `0.2.8`**
|
|
4
|
+
|
|
3
5
|
OpenClaw plugin that improves resilience by automatically fixing reversible failures.
|
|
4
6
|
|
|
5
|
-
## What it
|
|
7
|
+
## What it heals
|
|
8
|
+
|
|
9
|
+
- **Model outage** — Detect rate limit / quota / auth-scope failures, put model into cooldown, patch pinned session to a safe fallback
|
|
10
|
+
- **WhatsApp disconnect** — If WhatsApp appears disconnected repeatedly: restart the gateway (streak threshold + minimum restart interval guard)
|
|
11
|
+
- **Cron failures** — If a cron job fails repeatedly: disable it + create a GitHub issue
|
|
12
|
+
- **Plugin crashes** — If a plugin reports `status=error` or `status=crash`: auto-disable + GitHub issue
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
## Changelog
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
### v0.2.8 — 2026-03-07
|
|
17
|
+
**Fix: Infinite gateway restart loop**
|
|
18
|
+
`lastRestartAt` and `disconnectStreak` are now saved to disk **before** calling
|
|
19
|
+
`openclaw gateway restart`. Previously they were saved after, but systemd kills
|
|
20
|
+
the process during restart — state was never persisted, the rate-limit guard was
|
|
21
|
+
bypassed on every boot, causing an infinite restart loop when used alongside
|
|
22
|
+
any plugin that triggers a config-driven gateway restart (e.g. `openclaw-cli-bridge-elvatis`).
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- Guardrails: streak threshold + minimum restart interval
|
|
24
|
+
### v0.2.7 — 2026-03-07
|
|
25
|
+
Fix `runCommandWithTimeout` call signature + field name.
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- Create a GitHub issue with last error context (rate limited)
|
|
27
|
+
### v0.2.6 — 2026-03-02
|
|
28
|
+
Status snapshot file, startup config validation, integration tests.
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- Waiting for `openclaw plugins list --json` or an equivalent stable API
|
|
30
|
+
### v0.2.5 and earlier
|
|
31
|
+
Model failover, WhatsApp reconnect, cron failure, dry-run mode, active recovery probing, config hot-reload.
|
|
25
32
|
|
|
26
33
|
## Install
|
|
27
34
|
|
package/index.ts
CHANGED
|
@@ -618,7 +618,11 @@ export default function register(api: any) {
|
|
|
618
618
|
if (config.whatsappRestartEnabled) {
|
|
619
619
|
const st = await runCmd(api, "openclaw channels status --json", 15000);
|
|
620
620
|
if (st.ok) {
|
|
621
|
-
|
|
621
|
+
// openclaw CLI prints plugin startup lines (e.g. "[plugins] [self-heal] enabled...")
|
|
622
|
+
// to stdout before the JSON payload. Extract the first JSON object to avoid
|
|
623
|
+
// safeJsonParse returning undefined and falsely treating WA as disconnected.
|
|
624
|
+
const jsonMatch = st.stdout.match(/\{[\s\S]*\}/);
|
|
625
|
+
const parsed = jsonMatch ? safeJsonParse<any>(jsonMatch[0]) : undefined;
|
|
622
626
|
const wa = parsed?.channels?.whatsapp;
|
|
623
627
|
const connected = wa?.status === "connected" || wa?.connected === true;
|
|
624
628
|
|
|
@@ -651,12 +655,18 @@ export default function register(api: any) {
|
|
|
651
655
|
if (!v.ok) {
|
|
652
656
|
api.logger?.error?.(`[self-heal] NOT restarting gateway: openclaw.json invalid: ${v.error}`);
|
|
653
657
|
} else {
|
|
658
|
+
// CRITICAL: persist lastRestartAt + reset streak BEFORE calling gateway restart.
|
|
659
|
+
// openclaw gateway restart kills this process via systemd. Any state updates
|
|
660
|
+
// placed AFTER runCmd will never execute, leaving lastRestartAt=0 and
|
|
661
|
+
// bypassing the whatsappMinRestartIntervalSec rate-limit guard on the next boot.
|
|
662
|
+
// This was the root cause of the infinite restart loop.
|
|
663
|
+
state.whatsapp!.lastRestartAt = nowSec();
|
|
664
|
+
state.whatsapp!.disconnectStreak = 0;
|
|
665
|
+
saveState(config.stateFile, state);
|
|
654
666
|
backupConfig("pre-gateway-restart");
|
|
655
667
|
await runCmd(api, "openclaw gateway restart", 60000);
|
|
656
668
|
// If we are still alive after restart, attempt cleanup.
|
|
657
669
|
await cleanupPendingBackups("post-gateway-restart");
|
|
658
|
-
state.whatsapp!.lastRestartAt = nowSec();
|
|
659
|
-
state.whatsapp!.disconnectStreak = 0;
|
|
660
670
|
}
|
|
661
671
|
}
|
|
662
672
|
api.emit?.("self-heal:whatsapp-restart", {
|
|
@@ -672,7 +682,8 @@ export default function register(api: any) {
|
|
|
672
682
|
if (config.disableFailingCrons) {
|
|
673
683
|
const res = await runCmd(api, "openclaw cron list --json", 15000);
|
|
674
684
|
if (res.ok) {
|
|
675
|
-
const
|
|
685
|
+
const cronJsonMatch = res.stdout.match(/\{[\s\S]*\}/);
|
|
686
|
+
const parsed = cronJsonMatch ? safeJsonParse<any>(cronJsonMatch[0]) : undefined;
|
|
676
687
|
const jobs: any[] = parsed?.jobs ?? [];
|
|
677
688
|
for (const job of jobs) {
|
|
678
689
|
const id = job.id;
|
|
@@ -761,7 +772,8 @@ export default function register(api: any) {
|
|
|
761
772
|
const res = await runCmd(api, "openclaw plugins list --json", 15000);
|
|
762
773
|
if (res.ok) {
|
|
763
774
|
type PluginEntry = { id: string; name?: string; enabled?: boolean; status?: string; version?: string; error?: string };
|
|
764
|
-
const
|
|
775
|
+
const pluginJsonMatch = res.stdout.match(/\{[\s\S]*\}/);
|
|
776
|
+
const parsed = pluginJsonMatch ? safeJsonParse<{ plugins: PluginEntry[] }>(pluginJsonMatch[0]) : undefined;
|
|
765
777
|
const plugins: PluginEntry[] = parsed?.plugins ?? [];
|
|
766
778
|
const selfId = "openclaw-self-healing-elvatis";
|
|
767
779
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "openclaw-self-healing-elvatis",
|
|
3
3
|
"name": "OpenClaw Self Healing",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.9",
|
|
5
5
|
"description": "Self-healing health checks + guardrails + auto-fix for reversible failures (rate limits, auth errors, stuck session pins).",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"$schema": "http://json-schema.org/draft-07/schema#",
|