@ahyi/restart-continuity 0.4.0 → 0.5.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/README.md CHANGED
@@ -1,80 +1,35 @@
1
1
  # Restart Continuity Plugin
2
2
 
3
- OpenClaw plugin for **gateway restart continuity**:
4
-
5
- - runs resumable startup checks when the plugin service starts
6
- - can health-check and replay selected cron jobs
7
- - writes a structured continuity state file
8
- - writes a human-readable daily memory log
9
- - can hand off a one-shot startup receipt during agent bootstrap
10
- - works out of the box after `openclaw plugins install ...` + `enable`, with built-in default resumers for this mh instance
3
+ OpenClaw plugin for **gateway restart continuity** with **zero-config behavior on this mh instance**.
11
4
 
12
5
  ## Install
13
6
 
14
- ### npm registry
15
-
16
7
  ```bash
17
- openclaw --profile <profile> plugins install @ahyi/restart-continuity@0.4.0
8
+ openclaw --profile <profile> plugins install @ahyi/restart-continuity@0.5.0
18
9
  openclaw --profile <profile> plugins enable restart-continuity
19
10
  ```
20
11
 
21
12
  Then restart the gateway.
22
13
 
23
- ## What it does
24
-
25
- This plugin replaces scattered hook-based restart continuity setups with one installable extension.
26
-
27
- On plugin service start it can:
14
+ ## Zero-config behavior
28
15
 
29
- 1. initialize runtime marker/state files
30
- 2. run configured startup resumers
31
- 3. fall back to built-in default resumers when none are configured
32
- 4. write `memory/restart-continuity-state.json`
33
- 5. append a summary to `memory/YYYY-MM-DD.md`
34
- 6. stage a one-time startup receipt for bootstrap delivery
16
+ After install + enable, the plugin will work **without any extra config** on this mh instance.
35
17
 
36
- ## Default behavior
18
+ It automatically:
37
19
 
38
- If you do **not** provide `plugins.entries.restart-continuity.config.resumers`, the plugin will automatically use built-in defaults for this mh instance:
39
-
40
- - `mh-nightly-learnings-check`
41
- - `mh-weekly-self-improve`
42
-
43
- That means install + enable is enough to make restart continuity work on this machine.
20
+ - detects the mh workspace directory
21
+ - assumes profile `mh` unless overridden
22
+ - uses built-in default resumers for:
23
+ - `mh-nightly-learnings-check`
24
+ - `mh-weekly-self-improve`
25
+ - writes `memory/restart-continuity-state.json`
26
+ - writes `memory/restart-continuity-installed.json`
27
+ - appends a summary to the daily memory log
28
+ - stages a one-shot bootstrap receipt
44
29
 
45
30
  ## Optional explicit config
46
31
 
47
- ```json
48
- {
49
- "plugins": {
50
- "entries": {
51
- "restart-continuity": {
52
- "enabled": true,
53
- "config": {
54
- "profile": "mh",
55
- "workspaceDir": "/root/.openclaw/workspace-mh",
56
- "logToDailyMemory": true,
57
- "notifyOnBootstrap": true,
58
- "resumers": [
59
- {
60
- "id": "nightly-learnings",
61
- "kind": "cron-healthcheck",
62
- "name": "mh-nightly-learnings-check",
63
- "jobId": "38a8b8cb-c25a-4bc2-a8a1-d252f9d933ec"
64
- },
65
- {
66
- "id": "weekly-self-improve",
67
- "kind": "cron-healthcheck",
68
- "name": "mh-weekly-self-improve",
69
- "jobId": "6e912522-0591-4307-a155-a6ece496be9c"
70
- }
71
- ]
72
- }
73
- }
74
- }
75
- }
76
- }
77
- ```
32
+ You can still override behavior with `plugins.entries.restart-continuity.config`, but it is not required for this instance.
78
33
 
79
34
  ## Uninstall
80
35
 
package/index.ts CHANGED
@@ -5,6 +5,7 @@ import { promisify } from "node:util";
5
5
 
6
6
  const execFileAsync = promisify(execFile);
7
7
  const OPENCLAW_BIN = process.env.OPENCLAW_BIN || "openclaw";
8
+ let bootStarted = false;
8
9
 
9
10
  const BUILTIN_DEFAULT_RESUMERS = [
10
11
  {
@@ -29,14 +30,17 @@ function normalizeString(value, fallback = "") {
29
30
  return typeof value === "string" && value.trim() ? value.trim() : fallback;
30
31
  }
31
32
 
32
- function getWorkspaceDir(api) {
33
+ function detectWorkspaceDir(api) {
33
34
  const pluginConfig = api.pluginConfig || {};
34
35
  const explicit = normalizeString(pluginConfig.workspaceDir, "");
35
36
  if (explicit) return explicit;
36
- return normalizeString(api.config?.workspace?.dir, process.cwd());
37
+ const cfgWorkspace = normalizeString(api.config?.workspace?.dir, "");
38
+ if (cfgWorkspace) return cfgWorkspace;
39
+ const mhWorkspace = "/root/.openclaw/workspace-mh";
40
+ return mhWorkspace;
37
41
  }
38
42
 
39
- function getProfile(api) {
43
+ function detectProfile(api) {
40
44
  const pluginConfig = api.pluginConfig || {};
41
45
  return normalizeString(pluginConfig.profile, "mh");
42
46
  }
@@ -165,9 +169,7 @@ async function runCronHealthcheck(profile, resumer) {
165
169
  return { status: "resumed", detail: `${resumer.name || resumer.id} => ${normalized}`, latestStatus };
166
170
  }
167
171
 
168
- async function ensureConfigInitialized(api) {
169
- const workspaceDir = getWorkspaceDir(api);
170
- const pluginConfig = api.pluginConfig || {};
172
+ async function ensureConfigInitialized(api, workspaceDir, pluginConfig) {
171
173
  const stateFile = resolvePath(workspaceDir, pluginConfig.stateFile, "memory/restart-continuity-state.json");
172
174
  const markerFile = resolvePath(workspaceDir, pluginConfig.markerFile, "memory/restart-continuity-installed.json");
173
175
 
@@ -193,10 +195,8 @@ async function ensureConfigInitialized(api) {
193
195
  api.logger.info?.("[restart-continuity] initialized");
194
196
  }
195
197
 
196
- async function runStartupCheck(api) {
197
- const pluginConfig = api.pluginConfig || {};
198
- const profile = getProfile(api);
199
- const workspaceDir = getWorkspaceDir(api);
198
+ async function runStartupCheck(api, workspaceDir, pluginConfig) {
199
+ const profile = detectProfile(api);
200
200
  const stateFile = resolvePath(workspaceDir, pluginConfig.stateFile, "memory/restart-continuity-state.json");
201
201
  const receiptFile = resolvePath(workspaceDir, pluginConfig.receiptFile, "memory/restart-continuity-receipt.json");
202
202
  const logToDailyMemory = pluginConfig.logToDailyMemory !== false;
@@ -261,6 +261,20 @@ async function runStartupCheck(api) {
261
261
  api.logger.info?.(`[restart-continuity] ${summary.receipt}`);
262
262
  }
263
263
 
264
+ async function boot(api) {
265
+ if (bootStarted) return;
266
+ bootStarted = true;
267
+ const pluginConfig = api.pluginConfig || {};
268
+ const workspaceDir = detectWorkspaceDir(api);
269
+
270
+ try {
271
+ await ensureConfigInitialized(api, workspaceDir, pluginConfig);
272
+ await runStartupCheck(api, workspaceDir, pluginConfig);
273
+ } catch (err) {
274
+ api.logger.warn?.(`[restart-continuity] boot failed: ${err instanceof Error ? err.message : String(err)}`);
275
+ }
276
+ }
277
+
264
278
  const plugin = {
265
279
  id: "restart-continuity",
266
280
  name: "Restart Continuity",
@@ -274,7 +288,6 @@ const plugin = {
274
288
  workspaceDir: { label: "Workspace Directory" },
275
289
  stateFile: { label: "State File" },
276
290
  receiptFile: { label: "Receipt File" },
277
- defaultsFile: { label: "Defaults File" },
278
291
  markerFile: { label: "Install Marker File" },
279
292
  logToDailyMemory: { label: "Append summary to daily memory" },
280
293
  notifyOnBootstrap: { label: "Inject startup receipt into next bootstrap reply" },
@@ -282,18 +295,7 @@ const plugin = {
282
295
  },
283
296
  },
284
297
  register(api) {
285
- api.registerService({
286
- id: "restart-continuity-service",
287
- start: async () => {
288
- try {
289
- await ensureConfigInitialized(api);
290
- await runStartupCheck(api);
291
- } catch (err) {
292
- api.logger.warn?.(`[restart-continuity] service start failed: ${err instanceof Error ? err.message : String(err)}`);
293
- }
294
- },
295
- stop: async () => {},
296
- });
298
+ void boot(api);
297
299
 
298
300
  api.registerHook(
299
301
  "agent:bootstrap",
@@ -304,7 +306,7 @@ const plugin = {
304
306
  const bootstrapFiles = Array.isArray(ctx.bootstrapFiles) ? ctx.bootstrapFiles : null;
305
307
  if (!bootstrapFiles) return;
306
308
 
307
- const workspaceDir = getWorkspaceDir(api);
309
+ const workspaceDir = detectWorkspaceDir(api);
308
310
  const receiptFile = resolvePath(workspaceDir, pluginConfig.receiptFile, "memory/restart-continuity-receipt.json");
309
311
  const pending = await readJsonSafe(receiptFile, null);
310
312
  if (!pending || !pending.receipt) return;
@@ -2,7 +2,7 @@
2
2
  "id": "restart-continuity",
3
3
  "name": "Restart Continuity",
4
4
  "description": "Gateway restart continuity plugin with resumable startup checks and receipt handoff.",
5
- "version": "0.4.0",
5
+ "version": "0.5.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
@@ -11,7 +11,6 @@
11
11
  "workspaceDir": { "type": "string", "default": "" },
12
12
  "stateFile": { "type": "string", "default": "memory/restart-continuity-state.json" },
13
13
  "receiptFile": { "type": "string", "default": "memory/restart-continuity-receipt.json" },
14
- "defaultsFile": { "type": "string", "default": "plugins/restart-continuity.defaults.json" },
15
14
  "markerFile": { "type": "string", "default": "memory/restart-continuity-installed.json" },
16
15
  "logToDailyMemory": { "type": "boolean", "default": true },
17
16
  "notifyOnBootstrap": { "type": "boolean", "default": true },
@@ -45,7 +44,6 @@
45
44
  "workspaceDir": { "label": "Workspace Directory" },
46
45
  "stateFile": { "label": "State File" },
47
46
  "receiptFile": { "label": "Receipt File" },
48
- "defaultsFile": { "label": "Defaults File" },
49
47
  "markerFile": { "label": "Install Marker File" },
50
48
  "logToDailyMemory": { "label": "Append summary to daily memory" },
51
49
  "notifyOnBootstrap": { "label": "Inject startup receipt into next bootstrap reply" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahyi/restart-continuity",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "OpenClaw restart continuity plugin with resumable startup checks and receipt handoff",
5
5
  "type": "module",
6
6
  "license": "MIT",