@geravant/sinain 1.0.9 → 1.0.11
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/HEARTBEAT.md +62 -0
- package/install.js +22 -22
- package/package.json +4 -2
package/HEARTBEAT.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# HEARTBEAT.md
|
|
2
|
+
|
|
3
|
+
> **Execution contract:**
|
|
4
|
+
> 1. Setup → call `sinain_heartbeat_tick` → act on result → HEARTBEAT_OK
|
|
5
|
+
> 2. You MUST call the tool. Do NOT skip it. Do NOT reply HEARTBEAT_OK without calling it first.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
1. `sessions_history({ sessionKey: "agent:main:sinain", limit: 20, includeTools: false })`
|
|
12
|
+
2. Determine **IDLE** status: no user activity in the last 30 minutes
|
|
13
|
+
3. Compose **SESSION_SUMMARY**: 2–3 sentences describing the current state (what the user is doing, key topics, errors seen)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Execute Tick
|
|
18
|
+
|
|
19
|
+
Call the `sinain_heartbeat_tick` tool:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
sinain_heartbeat_tick({ sessionSummary: "...", idle: true|false })
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The tool runs all scripts (git backup, signal analysis, insight synthesis) and writes the log entry automatically.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Act on Result
|
|
30
|
+
|
|
31
|
+
- If `recommendedAction.action === "sessions_spawn"` → spawn a subagent with `.task`
|
|
32
|
+
- If `recommendedAction.action === "telegram_tip"` → send `.task` to Telegram (chat_id: 59835117)
|
|
33
|
+
- If `output` is not null → send to Telegram (chat_id: 59835117): `Suggestion: {suggestion}\n\nInsight: {insight}`
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Finish
|
|
38
|
+
|
|
39
|
+
Reply **HEARTBEAT_OK**
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Rules
|
|
44
|
+
|
|
45
|
+
- **Proactivity quota:** on active days, at least 2 ticks MUST produce output
|
|
46
|
+
- Max 2 subagents. NEVER repeat a recent action. Prefer depth over breadth.
|
|
47
|
+
- Memory mining, feedback, and curation run via plugin timer — do NOT invoke manually.
|
|
48
|
+
- Module management is on-demand, not per-tick — see SKILL.md for module commands.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## NemoClaw Provisioning
|
|
53
|
+
|
|
54
|
+
New Brev instance setup (run in Code-Server terminal):
|
|
55
|
+
```
|
|
56
|
+
SINAIN_BACKUP_REPO=<git-url> npx sinain
|
|
57
|
+
```
|
|
58
|
+
- Copies plugin files, patches `openclaw.json`, installs Python deps, restores memory from backup repo, reloads gateway
|
|
59
|
+
- Token printed at end (or visible in Brev dashboard → Gateway Token)
|
|
60
|
+
- Mac side: `./setup-nemoclaw.sh` → 5 prompts → overlay starts
|
|
61
|
+
|
|
62
|
+
Memory is git-backed via `git_backup.sh` on every heartbeat tick. New instances restore instantly via `SINAIN_BACKUP_REPO`.
|
package/install.js
CHANGED
|
@@ -33,29 +33,28 @@ console.log(" ✓ sinain-memory copied");
|
|
|
33
33
|
fs.copyFileSync(HEARTBEAT, path.join(SOURCES_DIR, "HEARTBEAT.md"));
|
|
34
34
|
console.log(" ✓ HEARTBEAT.md copied");
|
|
35
35
|
|
|
36
|
-
// 4. Install Python deps (for local bare-metal path; harmless to run here)
|
|
37
|
-
const reqFile = path.join(memoryDst, "requirements.txt");
|
|
38
|
-
if (fs.existsSync(reqFile)) {
|
|
39
|
-
console.log(" Installing Python dependencies...");
|
|
40
|
-
try {
|
|
41
|
-
execSync(`pip3 install -r "${reqFile}" --quiet --break-system-packages`, { stdio: "inherit" });
|
|
42
|
-
console.log(" ✓ Python dependencies installed");
|
|
43
|
-
} catch {
|
|
44
|
-
try {
|
|
45
|
-
execSync(`pip3 install -r "${reqFile}" --quiet`, { stdio: "inherit" });
|
|
46
|
-
console.log(" ✓ Python dependencies installed");
|
|
47
|
-
} catch {
|
|
48
|
-
console.warn(" ⚠ pip3 unavailable — Python eval features disabled");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
36
|
// ── Detect environment and branch ───────────────────────────────────────────
|
|
54
37
|
|
|
55
38
|
const nemoClaw = detectNemoClaw();
|
|
56
39
|
if (nemoClaw) {
|
|
57
40
|
await installNemoClaw(nemoClaw);
|
|
58
41
|
} else {
|
|
42
|
+
// 4. Install Python deps (local/bare-metal only — sandbox manages its own)
|
|
43
|
+
const reqFile = path.join(memoryDst, "requirements.txt");
|
|
44
|
+
if (fs.existsSync(reqFile)) {
|
|
45
|
+
console.log(" Installing Python dependencies...");
|
|
46
|
+
try {
|
|
47
|
+
execSync(`pip3 install -r "${reqFile}" --quiet --break-system-packages`, { stdio: "inherit" });
|
|
48
|
+
console.log(" ✓ Python dependencies installed");
|
|
49
|
+
} catch {
|
|
50
|
+
try {
|
|
51
|
+
execSync(`pip3 install -r "${reqFile}" --quiet`, { stdio: "inherit" });
|
|
52
|
+
console.log(" ✓ Python dependencies installed");
|
|
53
|
+
} catch {
|
|
54
|
+
console.warn(" ⚠ pip3 unavailable — Python eval features disabled");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
59
58
|
await installLocal();
|
|
60
59
|
}
|
|
61
60
|
|
|
@@ -94,8 +93,9 @@ async function installNemoClaw({ sandboxName }) {
|
|
|
94
93
|
console.log(" ✓ sinain-sources uploaded to sandbox");
|
|
95
94
|
|
|
96
95
|
// Download sandbox openclaw.json, patch, re-upload
|
|
97
|
-
const
|
|
98
|
-
run(`openshell sandbox download ${sandboxName} /sandbox/.openclaw/openclaw.json "${
|
|
96
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sinain-oc-"));
|
|
97
|
+
run(`openshell sandbox download ${sandboxName} /sandbox/.openclaw/openclaw.json "${tmpDir}"`);
|
|
98
|
+
const tmpJson = path.join(tmpDir, "openclaw.json");
|
|
99
99
|
|
|
100
100
|
let cfg = {};
|
|
101
101
|
try { cfg = JSON.parse(fs.readFileSync(tmpJson, "utf8")); } catch {}
|
|
@@ -123,7 +123,7 @@ async function installNemoClaw({ sandboxName }) {
|
|
|
123
123
|
|
|
124
124
|
fs.writeFileSync(tmpJson, JSON.stringify(cfg, null, 2));
|
|
125
125
|
run(`openshell sandbox upload ${sandboxName} "${tmpJson}" /sandbox/.openclaw/openclaw.json`);
|
|
126
|
-
fs.rmSync(
|
|
126
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
127
127
|
console.log(" ✓ openclaw.json patched in sandbox");
|
|
128
128
|
|
|
129
129
|
// Memory restore from backup repo (workspace lives inside sandbox)
|
|
@@ -251,11 +251,11 @@ function detectNemoClaw() {
|
|
|
251
251
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
252
252
|
|
|
253
253
|
function run(cmd) {
|
|
254
|
-
execSync(cmd, { stdio: "inherit" });
|
|
254
|
+
execSync(cmd, { stdio: "inherit", cwd: HOME });
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
function run_capture(cmd) {
|
|
258
|
-
return execSync(cmd, { encoding: "utf-8", stdio: ["pipe","pipe","pipe"] }).trim();
|
|
258
|
+
return execSync(cmd, { encoding: "utf-8", stdio: ["pipe","pipe","pipe"], cwd: HOME }).trim();
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
function copyDir(src, dst) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geravant/sinain",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "sinain OpenClaw plugin — AI overlay for macOS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"sinain-memory",
|
|
17
17
|
"HEARTBEAT.md"
|
|
18
18
|
],
|
|
19
|
-
"engines": {
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
20
22
|
"license": "MIT"
|
|
21
23
|
}
|