@vainplex/openclaw-leuko 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0] — 2026-02-27
4
+
5
+ ### Added
6
+ - **L1 Daemon** — Portable Node.js health monitor, zero external dependencies
7
+ - 7 heuristic checks: file freshness, gateway alive, plugin loading, disk usage, service health (HTTP + TCP)
8
+ - Auto-discovers workspace (`AGENTS.md` / `.openclaw/` detection)
9
+ - CLI: `npx @vainplex/openclaw-leuko daemon [--watch] [--config <path>]`
10
+ - Binary: `leuko-daemon` (via `bin` field in package.json)
11
+ - Watch mode with configurable interval (1–1440 min), graceful shutdown (SIGTERM/SIGINT)
12
+ - TCP probes via `net.createConnection` (no shell, no bash dependency)
13
+ - HTTP probes via `execFileSync("curl", [...])` (no shell interpolation)
14
+ - `src/daemon/types.ts` — Shared type definitions for daemon checks, config, and status
15
+ - 43 new tests (34 daemon + 9 security) — 160 total
16
+
17
+ ### Security
18
+ - No `execSync` anywhere — all subprocess calls use `execFileSync` (no shell)
19
+ - Host regex validation (`/^[\w.\-]+$/`) before any network probe
20
+ - `Number.isInteger()` validation on port and timeout before template interpolation
21
+ - `main()` guard prevents auto-execution on import (testable module)
22
+ - Gateway alive check filters own PID + PPID to prevent self-match false positives
23
+ - Config type-checking: `typeof` guards on all loaded values
24
+
25
+ ### Changed
26
+ - Architecture diagram updated to show L1 ↔ L2 data flow
27
+
3
28
  ## [0.1.0] — 2026-02-23
4
29
 
5
30
  ### Added
package/README.md CHANGED
@@ -8,21 +8,91 @@ Part of the [Vainplex OpenClaw Plugin Suite](https://github.com/alberthild/vainp
8
8
 
9
9
  Leuko operates as a **two-tier hybrid system**:
10
10
 
11
- - **Level 1 (Python daemon):** Heuristic checks — file freshness, JSON validity, service connectivity, cron health. Runs every 15min, zero API cost.
12
- - **Level 2 (This plugin):** Cognitive checks — semantic analysis via LLM + deterministic correlation. Runs every 2h or on-demand.
11
+ - **Level 1 (L1 Daemon):** Heuristic checks — file freshness, gateway alive, plugin loading, disk usage, service health. Runs every 15min, zero API cost. **Included in this package** since v0.2.0.
12
+ - **Level 2 (L2 Plugin):** Cognitive checks — semantic analysis via LLM + deterministic correlation. Runs every 2h or on-demand.
13
13
 
14
14
  ```
15
- Plugin (L2) Agents
16
- │ │
17
- ┌─ Read daemon_checks[] from leuko-status.json
18
- ├─ Run CK-01..CK-06 (4 LLM + 2 deterministic)
19
- ├─ Write cognitive_checks[] to leuko-status.json
20
-
21
- ├── leuko_status tool ────────────────────────────┤
22
- ├── before_agent_start hook ──────────────────────┤
23
- └── /leuko command ──────────────────────────────→│
15
+ L1 Daemon (Node.js) Plugin (L2) Agents
16
+
17
+ ┌─ 7 heuristic checks
18
+ ├─ Write daemon_checks[]
19
+ to leuko-status.json
20
+ ┌──────────┘
21
+ │ ├─ Read daemon_checks[] │
22
+ │ ├─ Run CK-01..CK-06 (4 LLM + 2 det.) │
23
+ │ ├─ Write cognitive_checks[] │
24
+ │ │ │
25
+ │ ├── leuko_status tool ─────────────────┤
26
+ │ ├── before_agent_start hook ───────────┤
27
+ │ └── /leuko command ───────────────────→│
28
+ │ │
29
+ └── npx leuko-daemon [--watch] (standalone) │
24
30
  ```
25
31
 
32
+ ## L1 Daemon
33
+
34
+ The L1 daemon is a portable Node.js process that produces `leuko-status.json` — no Python, no NATS, no external dependencies required.
35
+
36
+ ### Usage
37
+
38
+ ```bash
39
+ # Run once
40
+ npx @vainplex/openclaw-leuko daemon
41
+
42
+ # Watch mode (re-check every 15min)
43
+ npx @vainplex/openclaw-leuko daemon --watch
44
+
45
+ # Custom config
46
+ npx @vainplex/openclaw-leuko daemon --config /path/to/daemon-config.json
47
+ ```
48
+
49
+ Or via the `leuko-daemon` binary after global install:
50
+
51
+ ```bash
52
+ npm install -g @vainplex/openclaw-leuko
53
+ leuko-daemon --watch
54
+ ```
55
+
56
+ ### L1 Checks
57
+
58
+ | Check | What it does |
59
+ |-------|-------------|
60
+ | File Freshness | Monitors key files (BOOTSTRAP.md, threads.json, etc.) for staleness |
61
+ | Gateway Alive | Verifies OpenClaw gateway process is running |
62
+ | Plugin Loading | Reads `openclaw.json` and counts enabled plugins |
63
+ | Disk Usage | Warns at configurable thresholds (default: 85% warn, 95% crit) |
64
+ | Service Health | HTTP/TCP probes for configured endpoints |
65
+
66
+ Auto-discovers workspace by looking for `.openclaw/` or `AGENTS.md`.
67
+
68
+ ### Daemon Config
69
+
70
+ Optional JSON config file:
71
+
72
+ ```json
73
+ {
74
+ "statusPath": "~/.openclaw/leuko-status.json",
75
+ "workspace": "~/clawd",
76
+ "watchIntervalMin": 15,
77
+ "checks": {
78
+ "file_freshness": {
79
+ "targets": [
80
+ { "name": "boot-context", "path": "~/clawd/BOOTSTRAP.md", "warnHours": 4, "critHours": 8 }
81
+ ]
82
+ },
83
+ "service_health": {
84
+ "endpoints": [
85
+ { "name": "nats", "type": "tcp", "host": "localhost", "port": 4222, "timeoutMs": 3000 },
86
+ { "name": "ollama", "type": "http", "url": "http://localhost:11434/api/tags", "timeoutMs": 3000 }
87
+ ]
88
+ },
89
+ "disk_usage": { "warnPercent": 85, "critPercent": 95 }
90
+ }
91
+ }
92
+ ```
93
+
94
+ If no config is provided, freshness targets are auto-discovered from the workspace.
95
+
26
96
  ## Quick Start
27
97
 
28
98
  ```bash
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Leuko L1 Daemon — Lightweight health monitor
4
+ *
5
+ * Produces leuko-status.json consumed by the L2 OpenClaw Plugin.
6
+ * Portable: runs on any OpenClaw installation (no Python, no NATS required).
7
+ *
8
+ * Usage:
9
+ * npx @vainplex/openclaw-leuko daemon # Run once
10
+ * npx @vainplex/openclaw-leuko daemon --watch # Run every 15min
11
+ * npx @vainplex/openclaw-leuko daemon --config /path/to/config.json
12
+ */
13
+ import type { DaemonCheck, StatusFile, DaemonConfig, FreshnessTarget, ServiceEndpoint } from "./types.js";
14
+ export type { DaemonCheck, StatusFile, DaemonConfig, FreshnessTarget, ServiceEndpoint };
15
+ declare function defaultConfig(): DaemonConfig;
16
+ declare function check(name: string, severity: "ok" | "warn" | "critical", detail: string): DaemonCheck;
17
+ declare function hoursAgo(mtime: Date): number;
18
+ declare function computeSeverity(checks: DaemonCheck[]): "ok" | "warn" | "critical";
19
+ declare function checkFileFreshness(targets: FreshnessTarget[]): DaemonCheck[];
20
+ declare function checkGatewayAlive(): DaemonCheck;
21
+ declare function checkPluginLoading(): DaemonCheck;
22
+ declare function checkDiskUsage(warnPct: number, critPct: number): DaemonCheck;
23
+ /** TCP probe using Node.js net — no shell, no subprocess. */
24
+ declare function tcpProbe(host: string, port: number, timeoutMs: number): Promise<boolean>;
25
+ /** Sync TCP probe — spins event loop briefly via execFileSync. */
26
+ declare function tcpProbeSync(host: string, port: number, timeoutMs: number): boolean;
27
+ /** HTTP probe using execFileSync with curl (no shell interpolation). */
28
+ declare function httpProbe(url: string, timeoutMs: number): boolean;
29
+ declare function checkServiceHealth(endpoints: ServiceEndpoint[]): DaemonCheck[];
30
+ declare function autoDiscoverFreshnessTargets(workspace: string): FreshnessTarget[];
31
+ declare function runDaemon(cfg: DaemonConfig): StatusFile;
32
+ declare function loadDaemonConfig(configPath?: string): DaemonConfig;
33
+ declare function writeStatus(status: StatusFile, path: string): void;
34
+ export { runDaemon, loadDaemonConfig, writeStatus, defaultConfig, checkFileFreshness, checkGatewayAlive, checkPluginLoading, checkDiskUsage, checkServiceHealth, autoDiscoverFreshnessTargets, httpProbe, tcpProbe, tcpProbeSync, check, hoursAgo, computeSeverity, };
35
+ export declare function main(argv?: string[]): void;
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/daemon/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1G,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;AAQxF,iBAAS,aAAa,IAAI,YAAY,CAwBrC;AAUD,iBAAS,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,MAAM,GAAG,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAE9F;AAED,iBAAS,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAErC;AAED,iBAAS,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,CAK1E;AAMD,iBAAS,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,WAAW,EAAE,CAkBrE;AAED,iBAAS,iBAAiB,IAAI,WAAW,CAgBxC;AAED,iBAAS,kBAAkB,IAAI,WAAW,CAezC;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAgBrE;AAED,6DAA6D;AAC7D,iBAAS,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUjF;AAED,kEAAkE;AAClE,iBAAS,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAoB5E;AAED,wEAAwE;AACxE,iBAAS,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAS1D;AAED,iBAAS,kBAAkB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,WAAW,EAAE,CAmBvE;AAED,iBAAS,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAU1E;AAMD,iBAAS,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,UAAU,CAsBhD;AAED,iBAAS,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAkB3D;AAED,iBAAS,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI3D;AAMD,OAAO,EACL,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EACvD,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EACzD,cAAc,EAAE,kBAAkB,EAAE,4BAA4B,EAChE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,GACpE,CAAC;AAMF,wBAAgB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,IAAI,CA8BjE"}
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Leuko L1 Daemon — Lightweight health monitor
4
+ *
5
+ * Produces leuko-status.json consumed by the L2 OpenClaw Plugin.
6
+ * Portable: runs on any OpenClaw installation (no Python, no NATS required).
7
+ *
8
+ * Usage:
9
+ * npx @vainplex/openclaw-leuko daemon # Run once
10
+ * npx @vainplex/openclaw-leuko daemon --watch # Run every 15min
11
+ * npx @vainplex/openclaw-leuko daemon --config /path/to/config.json
12
+ */
13
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync } from "node:fs";
14
+ import { join, dirname } from "node:path";
15
+ import { execFileSync } from "node:child_process";
16
+ import { createConnection } from "node:net";
17
+ // ============================================================
18
+ // Defaults
19
+ // ============================================================
20
+ const HOME = process.env["HOME"] ?? "/tmp";
21
+ function defaultConfig() {
22
+ const candidates = [
23
+ process.env["OPENCLAW_WORKSPACE"],
24
+ join(HOME, "clawd"),
25
+ join(HOME, "workspace"),
26
+ HOME,
27
+ ].filter(Boolean);
28
+ const workspace = candidates.find(d => existsSync(join(d, ".openclaw")) || existsSync(join(d, "AGENTS.md"))) ?? HOME;
29
+ return {
30
+ statusPath: join(HOME, ".openclaw", "leuko-status.json"),
31
+ workspace,
32
+ watchIntervalMin: 15,
33
+ checks: {
34
+ file_freshness: { enabled: true, targets: [] },
35
+ service_health: { enabled: true, endpoints: [] },
36
+ disk_usage: { enabled: true, warnPercent: 85, critPercent: 95 },
37
+ gateway_alive: { enabled: true },
38
+ plugin_loading: { enabled: true },
39
+ },
40
+ };
41
+ }
42
+ // ============================================================
43
+ // Helpers
44
+ // ============================================================
45
+ function now() {
46
+ return new Date().toISOString();
47
+ }
48
+ function check(name, severity, detail) {
49
+ return { check_name: name, severity, detail, auto_healed: false, timestamp: now(), heal_action: null, heal_key: null };
50
+ }
51
+ function hoursAgo(mtime) {
52
+ return (Date.now() - mtime.getTime()) / (1000 * 60 * 60);
53
+ }
54
+ function computeSeverity(checks) {
55
+ for (const c of checks) {
56
+ if (c.severity === "critical")
57
+ return "critical";
58
+ }
59
+ return checks.some(c => c.severity === "warn") ? "warn" : "ok";
60
+ }
61
+ // ============================================================
62
+ // Check Implementations
63
+ // ============================================================
64
+ function checkFileFreshness(targets) {
65
+ const results = [];
66
+ for (const t of targets) {
67
+ const resolved = t.path.replace(/^~/, HOME);
68
+ if (!existsSync(resolved)) {
69
+ results.push(check(`freshness:${t.name}`, "warn", `${t.name} not found at ${resolved}`));
70
+ continue;
71
+ }
72
+ const age = hoursAgo(statSync(resolved).mtime);
73
+ if (age > t.critHours) {
74
+ results.push(check(`freshness:${t.name}`, "critical", `${t.name} modified ${age.toFixed(1)}h ago (crit: ${t.critHours}h)`));
75
+ }
76
+ else if (age > t.warnHours) {
77
+ results.push(check(`freshness:${t.name}`, "warn", `${t.name} modified ${age.toFixed(1)}h ago (warn: ${t.warnHours}h)`));
78
+ }
79
+ else {
80
+ results.push(check(`freshness:${t.name}`, "ok", `${t.name} modified ${age.toFixed(1)}h ago`));
81
+ }
82
+ }
83
+ return results;
84
+ }
85
+ function checkGatewayAlive() {
86
+ const myPid = String(process.pid);
87
+ const myPpid = String(process.ppid);
88
+ for (const pattern of ["openclaw-gateway", "openclaw"]) {
89
+ try {
90
+ const output = execFileSync("pgrep", ["-f", pattern], {
91
+ timeout: 5000, encoding: "utf-8",
92
+ }).trim();
93
+ // Filter out own PID and parent PID to avoid self-match
94
+ const pids = output.split("\n").filter(p => p !== myPid && p !== myPpid);
95
+ if (pids.length > 0) {
96
+ return check("gateway_alive", "ok", `Gateway process found (PID: ${pids[0]})`);
97
+ }
98
+ }
99
+ catch { /* pgrep exits non-zero when no match */ }
100
+ }
101
+ return check("gateway_alive", "critical", "No OpenClaw gateway process found");
102
+ }
103
+ function checkPluginLoading() {
104
+ try {
105
+ const configPath = join(HOME, ".openclaw", "openclaw.json");
106
+ if (!existsSync(configPath)) {
107
+ return check("plugin_loading", "warn", "No openclaw.json found");
108
+ }
109
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
110
+ const plugins = config?.plugins?.entries ?? {};
111
+ const enabled = Object.entries(plugins).filter(([, v]) => v?.enabled !== false);
112
+ return check("plugin_loading", "ok", `${enabled.length} plugins configured`);
113
+ }
114
+ catch (e) {
115
+ return check("plugin_loading", "warn", `Failed to read config: ${e instanceof Error ? e.message : String(e)}`);
116
+ }
117
+ }
118
+ function checkDiskUsage(warnPct, critPct) {
119
+ try {
120
+ const output = execFileSync("df", ["-h", "/"], { timeout: 5000, encoding: "utf-8" }).trim();
121
+ const lines = output.split("\n");
122
+ const lastLine = lines[lines.length - 1] ?? "";
123
+ const match = lastLine.match(/(\d+)%/);
124
+ if (match) {
125
+ const pct = parseInt(match[1], 10);
126
+ if (pct >= critPct)
127
+ return check("disk_usage", "critical", `Disk ${pct}% full`);
128
+ if (pct >= warnPct)
129
+ return check("disk_usage", "warn", `Disk ${pct}% full`);
130
+ return check("disk_usage", "ok", `Disk ${pct}% used`);
131
+ }
132
+ return check("disk_usage", "ok", "Could not parse disk usage");
133
+ }
134
+ catch {
135
+ return check("disk_usage", "warn", "Failed to check disk");
136
+ }
137
+ }
138
+ /** TCP probe using Node.js net — no shell, no subprocess. */
139
+ function tcpProbe(host, port, timeoutMs) {
140
+ return new Promise((resolve) => {
141
+ const sock = createConnection({ host, port }, () => {
142
+ sock.destroy();
143
+ resolve(true);
144
+ });
145
+ sock.setTimeout(timeoutMs);
146
+ sock.on("timeout", () => { sock.destroy(); resolve(false); });
147
+ sock.on("error", () => { sock.destroy(); resolve(false); });
148
+ });
149
+ }
150
+ /** Sync TCP probe — spins event loop briefly via execFileSync. */
151
+ function tcpProbeSync(host, port, timeoutMs) {
152
+ // Validate inputs to prevent injection — host already regex-checked by caller
153
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
154
+ return false;
155
+ if (!Number.isInteger(timeoutMs) || timeoutMs < 0)
156
+ return false;
157
+ try {
158
+ execFileSync(process.execPath, [
159
+ "--input-type=module",
160
+ "-e",
161
+ // Static template — all values pre-validated above
162
+ `import{createConnection}from"net";`
163
+ + `const s=createConnection({host:${JSON.stringify(host)},port:${port}},`
164
+ + `()=>{s.destroy();process.exit(0)});`
165
+ + `s.setTimeout(${timeoutMs});`
166
+ + `s.on("timeout",()=>{s.destroy();process.exit(1)});`
167
+ + `s.on("error",()=>{s.destroy();process.exit(1)});`,
168
+ ], { timeout: timeoutMs + 2000, stdio: "ignore" });
169
+ return true;
170
+ }
171
+ catch {
172
+ return false;
173
+ }
174
+ }
175
+ /** HTTP probe using execFileSync with curl (no shell interpolation). */
176
+ function httpProbe(url, timeoutMs) {
177
+ try {
178
+ execFileSync("curl", ["-sf", "--max-time", String(Math.ceil(timeoutMs / 1000)), url], {
179
+ timeout: timeoutMs + 2000, stdio: "ignore",
180
+ });
181
+ return true;
182
+ }
183
+ catch {
184
+ return false;
185
+ }
186
+ }
187
+ function checkServiceHealth(endpoints) {
188
+ const results = [];
189
+ for (const ep of endpoints) {
190
+ if (ep.type === "http" && ep.url) {
191
+ const ok = httpProbe(ep.url, ep.timeoutMs);
192
+ results.push(check(`service:${ep.name}`, ok ? "ok" : "warn", ok ? `${ep.name} reachable` : `${ep.name} unreachable at ${ep.url}`));
193
+ }
194
+ else if (ep.type === "tcp" && ep.host && ep.port) {
195
+ if (!/^[\w.\-]+$/.test(ep.host) || !Number.isInteger(ep.port) || ep.port < 1 || ep.port > 65535) {
196
+ results.push(check(`service:${ep.name}`, "warn", `Invalid host/port: ${ep.host}:${ep.port}`));
197
+ continue;
198
+ }
199
+ const timeout = Number.isInteger(ep.timeoutMs) ? ep.timeoutMs : 3000;
200
+ const ok = tcpProbeSync(ep.host, ep.port, timeout);
201
+ results.push(check(`service:${ep.name}`, ok ? "ok" : "warn", ok ? `${ep.name} reachable at ${ep.host}:${ep.port}` : `${ep.name} unreachable at ${ep.host}:${ep.port}`));
202
+ }
203
+ }
204
+ return results;
205
+ }
206
+ function autoDiscoverFreshnessTargets(workspace) {
207
+ const candidates = [
208
+ { rel: "BOOTSTRAP.md", name: "boot-context", warnHours: 4, critHours: 8 },
209
+ { rel: "memory/reboot/threads.json", name: "threads", warnHours: 24, critHours: 48 },
210
+ { rel: "memory/reboot/decisions.json", name: "decisions", warnHours: 24, critHours: 48 },
211
+ { rel: "memory/reboot/goals.json", name: "goals", warnHours: 48, critHours: 96 },
212
+ ];
213
+ return candidates
214
+ .filter(c => existsSync(join(workspace, c.rel)))
215
+ .map(c => ({ ...c, path: join(workspace, c.rel) }));
216
+ }
217
+ // ============================================================
218
+ // Core
219
+ // ============================================================
220
+ function runDaemon(cfg) {
221
+ const checks = [];
222
+ const ft = cfg.checks.file_freshness;
223
+ const targets = ft.targets.length > 0 ? ft.targets : autoDiscoverFreshnessTargets(cfg.workspace);
224
+ if (ft.enabled && targets.length > 0)
225
+ checks.push(...checkFileFreshness(targets));
226
+ if (cfg.checks.gateway_alive.enabled)
227
+ checks.push(checkGatewayAlive());
228
+ if (cfg.checks.plugin_loading.enabled)
229
+ checks.push(checkPluginLoading());
230
+ if (cfg.checks.disk_usage.enabled) {
231
+ checks.push(checkDiskUsage(cfg.checks.disk_usage.warnPercent, cfg.checks.disk_usage.critPercent));
232
+ }
233
+ if (cfg.checks.service_health.enabled && cfg.checks.service_health.endpoints.length > 0) {
234
+ checks.push(...checkServiceHealth(cfg.checks.service_health.endpoints));
235
+ }
236
+ return {
237
+ last_check: now(),
238
+ overall_severity: computeSeverity(checks),
239
+ daemon_checks: checks,
240
+ cognitive_checks: [],
241
+ auto_heal_history: [],
242
+ };
243
+ }
244
+ function loadDaemonConfig(configPath) {
245
+ const cfg = defaultConfig();
246
+ if (!configPath || !existsSync(configPath))
247
+ return cfg;
248
+ try {
249
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
250
+ if (typeof raw.statusPath === "string")
251
+ cfg.statusPath = raw.statusPath;
252
+ if (typeof raw.workspace === "string")
253
+ cfg.workspace = raw.workspace;
254
+ if (typeof raw.watchIntervalMin === "number")
255
+ cfg.watchIntervalMin = raw.watchIntervalMin;
256
+ if (Array.isArray(raw.checks?.file_freshness?.targets)) {
257
+ cfg.checks.file_freshness.targets = raw.checks.file_freshness.targets;
258
+ }
259
+ if (Array.isArray(raw.checks?.service_health?.endpoints)) {
260
+ cfg.checks.service_health.endpoints = raw.checks.service_health.endpoints;
261
+ }
262
+ }
263
+ catch {
264
+ console.error(`[leuko-daemon] Failed to parse config at ${configPath}`);
265
+ }
266
+ return cfg;
267
+ }
268
+ function writeStatus(status, path) {
269
+ const dir = dirname(path);
270
+ if (!existsSync(dir))
271
+ mkdirSync(dir, { recursive: true });
272
+ writeFileSync(path, JSON.stringify(status, null, 2) + "\n");
273
+ }
274
+ // ============================================================
275
+ // Exports (for testing)
276
+ // ============================================================
277
+ export { runDaemon, loadDaemonConfig, writeStatus, defaultConfig, checkFileFreshness, checkGatewayAlive, checkPluginLoading, checkDiskUsage, checkServiceHealth, autoDiscoverFreshnessTargets, httpProbe, tcpProbe, tcpProbeSync, check, hoursAgo, computeSeverity, };
278
+ // ============================================================
279
+ // CLI
280
+ // ============================================================
281
+ export function main(argv = process.argv.slice(2)) {
282
+ const watchMode = argv.includes("--watch");
283
+ const configIdx = argv.indexOf("--config");
284
+ const configPath = configIdx >= 0 ? argv[configIdx + 1] : undefined;
285
+ const cfg = loadDaemonConfig(configPath);
286
+ cfg.watchIntervalMin = Math.max(1, Math.min(1440, cfg.watchIntervalMin));
287
+ console.log(`[leuko-daemon] Workspace: ${cfg.workspace}`);
288
+ console.log(`[leuko-daemon] Status output: ${cfg.statusPath}`);
289
+ function tick() {
290
+ const t0 = Date.now();
291
+ const status = runDaemon(cfg);
292
+ writeStatus(status, cfg.statusPath);
293
+ const ms = Date.now() - t0;
294
+ const w = status.daemon_checks.filter(c => c.severity === "warn").length;
295
+ const cr = status.daemon_checks.filter(c => c.severity === "critical").length;
296
+ console.log(`[leuko-daemon] ${status.overall_severity.toUpperCase()} — ${status.daemon_checks.length} checks (${w} warn, ${cr} crit) in ${ms}ms`);
297
+ }
298
+ tick();
299
+ if (watchMode) {
300
+ console.log(`[leuko-daemon] Watch mode: running every ${cfg.watchIntervalMin} minutes`);
301
+ const timer = setInterval(tick, cfg.watchIntervalMin * 60 * 1000);
302
+ timer.unref();
303
+ process.on("SIGTERM", () => { clearInterval(timer); process.exit(0); });
304
+ process.on("SIGINT", () => { clearInterval(timer); process.exit(0); });
305
+ }
306
+ }
307
+ // Only run CLI when executed directly (not imported for tests)
308
+ if (process.argv[1] && /(?:daemon\/index\.[jt]s|leuko-daemon)$/.test(process.argv[1])) {
309
+ main();
310
+ }
311
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/daemon/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /** Leuko L1 Daemon — Shared types */
2
+ export interface DaemonCheck {
3
+ check_name: string;
4
+ severity: "ok" | "warn" | "critical";
5
+ detail: string;
6
+ auto_healed: boolean;
7
+ timestamp: string;
8
+ heal_action: string | null;
9
+ heal_key: string | null;
10
+ }
11
+ export interface StatusFile {
12
+ last_check: string;
13
+ overall_severity: "ok" | "warn" | "critical";
14
+ daemon_checks: DaemonCheck[];
15
+ cognitive_checks: never[];
16
+ auto_heal_history: never[];
17
+ }
18
+ export interface DaemonConfig {
19
+ statusPath: string;
20
+ workspace: string;
21
+ watchIntervalMin: number;
22
+ checks: {
23
+ file_freshness: {
24
+ enabled: boolean;
25
+ targets: FreshnessTarget[];
26
+ };
27
+ service_health: {
28
+ enabled: boolean;
29
+ endpoints: ServiceEndpoint[];
30
+ };
31
+ disk_usage: {
32
+ enabled: boolean;
33
+ warnPercent: number;
34
+ critPercent: number;
35
+ };
36
+ gateway_alive: {
37
+ enabled: boolean;
38
+ };
39
+ plugin_loading: {
40
+ enabled: boolean;
41
+ };
42
+ };
43
+ }
44
+ export interface FreshnessTarget {
45
+ name: string;
46
+ path: string;
47
+ warnHours: number;
48
+ critHours: number;
49
+ }
50
+ export interface ServiceEndpoint {
51
+ name: string;
52
+ type: "http" | "tcp";
53
+ url?: string;
54
+ host?: string;
55
+ port?: number;
56
+ timeoutMs: number;
57
+ }
58
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/daemon/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;IAC7C,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,gBAAgB,EAAE,KAAK,EAAE,CAAC;IAC1B,iBAAiB,EAAE,KAAK,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE;QACN,cAAc,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,OAAO,EAAE,eAAe,EAAE,CAAA;SAAE,CAAC;QACjE,cAAc,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,SAAS,EAAE,eAAe,EAAE,CAAA;SAAE,CAAC;QACnE,UAAU,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3E,aAAa,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,CAAC;QACpC,cAAc,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,CAAC;KACtC,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,3 @@
1
+ /** Leuko L1 Daemon — Shared types */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/daemon/types.ts"],"names":[],"mappings":"AAAA,qCAAqC"}
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@vainplex/openclaw-leuko",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Cognitive immune system — L2 semantic health checks with LLM analysis, tool exposure for agent queries, and Sitrep replacement",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
7
7
  "types": "dist/src/index.d.ts",
8
+ "bin": {
9
+ "leuko-daemon": "./dist/src/daemon/index.js"
10
+ },
8
11
  "files": [
9
12
  "dist",
10
13
  "openclaw.plugin.json",