@geravant/sinain 1.0.14 → 1.0.16

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.
Files changed (3) hide show
  1. package/SKILL.md +335 -0
  2. package/install.js +6 -1
  3. package/package.json +3 -2
package/SKILL.md ADDED
@@ -0,0 +1,335 @@
1
+ # SinainHUD Skill
2
+
3
+ ## What
4
+ Two-way communication with sinain-core on Geravant's Mac:
5
+ 1. **Receive escalations** — respond to context, errors, and questions from sinain-core
6
+ 2. **Delegate tasks** — spawn subagents for research and background work
7
+ 3. **Read transcripts** — access sinain session history for context
8
+
9
+ ---
10
+
11
+ ## Architecture
12
+
13
+ ```
14
+ sinain-core (Mac) OpenClaw Server
15
+ │ │
16
+ ├── Escalates ──────────────────────→ │ (message with inline context)
17
+ │ [digest, OCR, audio, errors] │
18
+ │ ├── Main agent processes
19
+ │ │
20
+ │ ←───────────────────────────────────┤ Response via escalation reply
21
+ │ (displayed on HUD overlay) │
22
+ │ │
23
+ └── Session transcripts ────────────→ sessions_history (queryable)
24
+ ```
25
+
26
+ **Key insight:** There is no separate relay server. sinain-core escalates directly to the OpenClaw server. Responses flow back through the escalation response mechanism and are displayed on the Mac's HUD overlay.
27
+
28
+ ---
29
+
30
+ ## Part 1: Handling Escalations
31
+
32
+ sinain-core monitors screen and audio on the Mac, then escalates to OpenClaw when it needs help or has context to share.
33
+
34
+ ### Message Format
35
+
36
+ Escalation messages carry **inline context**:
37
+ - **Digest** — summarized screen/audio activity
38
+ - **OCR** — text extracted from screen
39
+ - **Audio transcripts** — recent speech-to-text
40
+ - **Errors** — detected errors from IDEs, terminals, logs
41
+
42
+ **Example incoming escalation:**
43
+ ```
44
+ [sinain-hud live context — tick #42]
45
+
46
+ ## Digest
47
+ User is editing analyzer.ts in IntelliJ IDEA. TypeScript error visible on line 45.
48
+
49
+ ## OCR
50
+ TypeError: Cannot read property 'map' of undefined
51
+ at processItems (analyzer.ts:45:12)
52
+
53
+ ## Audio
54
+ "Why isn't this working... I already checked for null"
55
+ ```
56
+
57
+ ### Response Guidelines
58
+
59
+ - **Respond directly** — your reply goes back to the HUD overlay
60
+ - **Be detailed** — 5-10 sentences for escalation responses, drawing on the digest/OCR/audio context provided
61
+ - **Address errors first** — prioritize fixing what's broken
62
+ - **Reference the context** — use the digest/OCR/audio to be specific
63
+ - **Never NO_REPLY** — always respond to escalations
64
+
65
+ **Example response:**
66
+ "The error suggests `ctx.items` is undefined before the `.map()` call. Add a guard: `ctx.items?.map(...)` or check the data source that populates `ctx.items`."
67
+
68
+ ---
69
+
70
+ ## Part 2: Spawn-Task Requests
71
+
72
+ Messages with `[sinain-core:spawn-task]` request a background subagent for longer work.
73
+
74
+ ### How to Handle
75
+
76
+ 1. Extract the task description
77
+ 2. Call `sessions_spawn` with the task
78
+ 3. **Include spawn result in your response** (sinain-core tracks this)
79
+
80
+ **Example incoming:**
81
+ ```
82
+ [sinain-core:spawn-task] (label: "Team standup")
83
+
84
+ Please spawn a subagent to handle this task:
85
+
86
+ Clean up and summarize this recording transcript:
87
+
88
+ [00:00] Hey everyone, let's start the standup...
89
+ [00:15] I finished the authentication PR yesterday...
90
+ ```
91
+
92
+ **Your response (must include JSON for tracking):**
93
+ ```
94
+ Spawning subagent for 'Team standup'...
95
+ spawn_result: {"status":"accepted","childSessionKey":"agent:main:subagent:xxxxx","runId":"xxxxx"}
96
+ ```
97
+
98
+ ### sessions_spawn Usage
99
+
100
+ ```javascript
101
+ sessions_spawn({
102
+ task: "Clean up and summarize this recording transcript:\n\n[00:00] Hey everyone...",
103
+ label: "standup-summary", // optional, for tracking
104
+ cleanup: "delete" // auto-cleanup when done
105
+ })
106
+ ```
107
+
108
+ **Note:** Subagent results are delivered via Telegram (the main channel), not directly to the HUD. The user sees completion notifications in their normal message flow.
109
+
110
+ ---
111
+
112
+ ## Part 3: Reading Sinain Session History
113
+
114
+ Use `sessions_history` to read past sinain session transcripts and context.
115
+
116
+ ### When to Use
117
+ - Understanding what the user was working on earlier
118
+ - Finding context from past escalations
119
+ - Reviewing audio transcripts from earlier in the day
120
+ - Checking what errors were reported and whether they were resolved
121
+
122
+ ### Usage
123
+
124
+ ```javascript
125
+ // Get recent sinain session history
126
+ sessions_history({
127
+ sessionKey: "agent:main:sinain", // full session key (required)
128
+ limit: 20, // number of messages (optional, default varies)
129
+ includeTools: false // include tool calls in output (optional, default false)
130
+ })
131
+ ```
132
+
133
+ **Parameters:**
134
+ | Parameter | Type | Required | Description |
135
+ |-----------|------|----------|-------------|
136
+ | `sessionKey` | string | **yes** | The session to query. For sinain: `"agent:main:sinain"` |
137
+ | `limit` | number | no | Max messages to return |
138
+ | `includeTools` | boolean | no | Whether to include tool call messages |
139
+
140
+ **Important:** There is no `since` or `session` parameter. Always use the full `sessionKey`.
141
+
142
+ ### What You Get Back
143
+ - Timestamped messages with inline context (digest, OCR, audio, errors)
144
+ - Your previous responses to escalations
145
+ - Spawn-task requests and their outcomes
146
+
147
+ ---
148
+
149
+ ## Output Routing
150
+
151
+ | Content Type | Destination | Why |
152
+ |--------------|-------------|-----|
153
+ | Escalation responses | **HUD** (via escalation reply) | Immediate, contextual help |
154
+ | Subagent completions | **Telegram** | Persistent notification |
155
+ | Urgent alerts | **Telegram** | Needs acknowledgment |
156
+ | Proactive research results | **Telegram** | Non-blocking, async delivery |
157
+
158
+ **Rule:** Your direct response to an escalation goes to the HUD. Everything else flows through normal Telegram messaging.
159
+
160
+ ---
161
+
162
+ ## Part 4: Learning from Feedback Signals
163
+
164
+ sinain-core tracks what happens **after** each escalation and computes feedback signals. These are sent periodically as `[sinain-core:feedback-summary]` messages.
165
+
166
+ ### Feedback Signal Format
167
+
168
+ Each escalation gets scored on these signals:
169
+
170
+ | Signal | What It Measures | Good | Bad |
171
+ |--------|-----------------|------|-----|
172
+ | `errorCleared` | Error disappeared from screen after your response | `true` | `false` |
173
+ | `noReEscalation` | Same issue didn't re-escalate within 5 minutes | `true` | `false` |
174
+ | `dwellTimeMs` | Time user spent on app after response | > 60s | < 10s |
175
+ | `quickAppSwitch` | User switched apps within 10s of your response | `false` | `true` |
176
+ | `compositeScore` | Weighted combo of above signals | 0.5 to 1.0 | -1.0 to 0 |
177
+
178
+ ### Reading a Feedback Summary
179
+
180
+ ```
181
+ [sinain-core:feedback-summary]
182
+
183
+ Escalations: 12 | Avg score: 0.45 | Avg latency: 3200ms
184
+ Top tags: coding (8), error (5), app:intellij (7)
185
+
186
+ Recent (last 5):
187
+ ✓ 0.80 [coding, error] — error cleared, no re-escalation
188
+ ✓ 0.60 [coding] — no re-escalation, good dwell
189
+ ✗ -0.20 [error, app:intellij] — error persisted, re-escalated
190
+ ✓ 0.50 [coding] — no re-escalation
191
+ ✓ 0.30 [general] — quick app switch but no re-escalation
192
+ ```
193
+
194
+ ### How to Use Feedback
195
+
196
+ **Positive patterns (score > 0.3):**
197
+ - Your approach is working — keep it up
198
+ - Note what tags/contexts correlate with high scores
199
+
200
+ **Negative patterns (score < 0):**
201
+ - `errorCleared: false` → your fixes aren't working. Try different approaches:
202
+ - Ask for more context instead of guessing
203
+ - Suggest debugging steps rather than direct fixes
204
+ - Check if the error is a red herring (build artifact, stale cache)
205
+ - `quickAppSwitch: true` → user found your response unhelpful. Adjust:
206
+ - Be more concise — user may be scanning quickly
207
+ - Lead with the actionable fix, not the explanation
208
+ - Match the urgency — if they're debugging, don't philosophize
209
+ - High re-escalation rate → same issues keep coming back:
210
+ - Your fixes are superficial — address root cause
211
+ - The issue might be environmental (config, dependency)
212
+ - Consider suggesting a different tool or approach entirely
213
+
214
+ ### Anti-Patterns to Watch
215
+
216
+ 1. **Always suggesting restarts** — if `errorCleared` is often false after restart suggestions, stop suggesting restarts
217
+ 2. **Too verbose** — if `quickAppSwitch` is consistently true, shorten your responses dramatically
218
+ 3. **Missing the real error** — if the same error type keeps re-escalating, you're probably fixing symptoms not causes
219
+ 4. **Ignoring audio context** — if user mentions something in audio that your response doesn't address, the feedback will be negative
220
+
221
+ ### Inline Feedback in Escalations
222
+
223
+ Escalation messages may include a `## Recent Feedback` section at the bottom:
224
+
225
+ ```
226
+ ## Recent Feedback (last 5 escalations)
227
+ Score: 0.45 avg | Errors cleared: 3/5 | Re-escalated: 1/5
228
+ Recent: ✓ 0.8 (coding, error) | ✓ 0.6 (coding) | ✗ -0.2 (error, intellij) | ✓ 0.5 (coding) | ✓ 0.3 (general)
229
+ ```
230
+
231
+ Use this inline context to calibrate your response — if recent scores are low, try a different approach than what you've been doing.
232
+
233
+ ---
234
+
235
+ ## Part 5: Proactive Research from Escalations
236
+
237
+ When processing escalation ticks, watch for opportunities to **spawn research subagents** proactively. This turns passive observation into active assistance.
238
+
239
+ ### When to Spawn Research
240
+
241
+ | Signal in Escalation | Research to Spawn |
242
+ |---------------------|-------------------|
243
+ | User researching new tech/library | `sessions_spawn`: "Deep-dive on [tech]. Quickstart, gotchas, best practices, alternatives." |
244
+ | Environment-related error (config, deps, infra) | `sessions_spawn`: "Root cause analysis for [error]. Check known issues, changelogs, migration guides." |
245
+ | User asked a question in audio transcript | `sessions_spawn`: "Find answer to: [question]. Summarize with sources." |
246
+ | User reading docs/tutorials on a topic | `sessions_spawn`: "Compile key insights on [topic]. What matters most, common mistakes." |
247
+
248
+ ### Rules
249
+
250
+ 1. **Respond to the escalation first** — always send your HUD response before spawning
251
+ 2. **Max 1 spawn per escalation** — don't flood with subagents
252
+ 3. **Don't duplicate heartbeat research** — check recent chat history for overlapping spawns
253
+ 4. **Non-blocking** — `sessions_spawn` returns immediately; the subagent works in the background
254
+ 5. **Only spawn when the value is clear** — if the user's activity is routine (normal coding, switching apps), don't spawn
255
+
256
+ ### Example Flow
257
+
258
+ ```
259
+ Incoming escalation:
260
+ Digest: User browsing Bun documentation. Switched from Node.js project.
261
+ OCR: "Bun.serve() API reference — HTTP server"
262
+ Audio: "I wonder if Bun handles websockets differently..."
263
+
264
+ Your response (to HUD):
265
+ "Bun handles WebSockets natively via Bun.serve() with a `websocket` handler —
266
+ no separate ws package needed. The API is: server.upgrade(req) in the fetch handler,
267
+ then define open/message/close callbacks in the websocket config."
268
+
269
+ Then spawn (non-blocking):
270
+ sessions_spawn({
271
+ task: "Deep-dive: Bun WebSocket API vs Node.js ws package. Key differences, migration path, performance characteristics, gotchas. Include code examples.",
272
+ label: "bun-websocket-research",
273
+ cleanup: "delete"
274
+ })
275
+ ```
276
+
277
+ The subagent result will arrive via Telegram later, giving the user a thorough reference.
278
+
279
+ ---
280
+
281
+ ## Part 6: Self-Improving Heartbeat
282
+
283
+ The heartbeat (`HEARTBEAT.md`) runs every 15 minutes and implements a **self-improving feedback loop** — it doesn't just observe and act, it learns from accumulated experience.
284
+
285
+ ### Three-Phase Cycle
286
+
287
+ | Phase | Purpose | Key Action |
288
+ |-------|---------|------------|
289
+ | **1. Git Backup** | Persist learning | Commit `memory/` (playbook, archive, logs) and push |
290
+ | **2. Observe & Act** | Reactive | Scan recent history, spawn subagents or send suggestions |
291
+ | **3. Reflect & Curate** | Self-improving | Update playbook from feedback signals, log decisions, synthesize output |
292
+
293
+ ### Playbook — `memory/sinain-playbook.md`
294
+
295
+ The heartbeat maintains a curated playbook of what works and what doesn't, updated each tick:
296
+ - **Successful patterns** — approaches with high `compositeScore` (>0.3) from feedback signals
297
+ - **Failed patterns** — approaches that didn't work, with reasons
298
+ - **User preferences** — recurring topics, preferred tools, work rhythms
299
+ - Capped at 50 lines; stale entries are pruned, repeated patterns promoted from "observed" to "established"
300
+
301
+ ### Decision Logs — `memory/playbook-logs/YYYY-MM-DD.jsonl`
302
+
303
+ Every heartbeat tick appends a structured JSON line capturing: what was observed, what actions were considered (and why some were skipped), playbook changes, and the output produced. This enables offline evaluation of the self-improvement process.
304
+
305
+ ### Playbook Archive — `memory/playbook-archive/`
306
+
307
+ Before each mutation, the current playbook is archived with a timestamp. The archive forms a versioned dataset showing how the agent's strategy evolves over time.
308
+
309
+ ### Output Format
310
+
311
+ Each heartbeat produces a Telegram message with two components:
312
+ - **Suggestion** — practical, actionable recommendation grounded in playbook patterns
313
+ - **Insight** — surprising, non-obvious connection from accumulated observations
314
+
315
+ Both must reference concrete data. Generic advice and repeated outputs are prohibited.
316
+
317
+ ### Setup Requirements
318
+
319
+ The `openclaw-config-patch.json` documents the required server configuration:
320
+ - `agents.defaults.heartbeat.every: "15m"` — 15-minute heartbeat cadence
321
+ - `agents.defaults.sandbox.sessionToolsVisibility: "all"` — cross-session history access
322
+
323
+ ---
324
+
325
+ ## Quick Reference
326
+
327
+ | Task | Method |
328
+ |------|--------|
329
+ | Respond to live context | Reply directly (goes to HUD) |
330
+ | Spawn background work | `sessions_spawn({task: "...", cleanup: "delete"})` |
331
+ | Read past context (light) | `sessions_history({sessionKey: "agent:main:sinain", limit: 50, includeTools: false})` |
332
+ | Read past context (detailed) | `sessions_history({sessionKey: "agent:main:sinain", limit: 10, includeTools: true})` — only when signals found |
333
+ | Proactive research | Respond first, then `sessions_spawn` with research task (max 1 per escalation) |
334
+ | Process feedback | Read `[sinain-core:feedback-summary]`, adjust strategy |
335
+ | Self-improving loop | Heartbeat curates `memory/sinain-playbook.md` every 15m (see HEARTBEAT.md) |
package/install.js CHANGED
@@ -14,6 +14,7 @@ const WORKSPACE = path.join(HOME, ".openclaw/workspace");
14
14
  const PKG_DIR = path.dirname(new URL(import.meta.url).pathname);
15
15
  const MEMORY_SRC = path.join(PKG_DIR, "sinain-memory");
16
16
  const HEARTBEAT = path.join(PKG_DIR, "HEARTBEAT.md");
17
+ const SKILL = path.join(PKG_DIR, "SKILL.md");
17
18
 
18
19
  console.log("\nInstalling sinain plugin...");
19
20
 
@@ -29,9 +30,11 @@ const memoryDst = path.join(SOURCES_DIR, "sinain-memory");
29
30
  copyDir(MEMORY_SRC, memoryDst);
30
31
  console.log(" ✓ sinain-memory copied");
31
32
 
32
- // 3. Stage HEARTBEAT.md
33
+ // 3. Stage HEARTBEAT.md and SKILL.md
33
34
  fs.copyFileSync(HEARTBEAT, path.join(SOURCES_DIR, "HEARTBEAT.md"));
34
35
  console.log(" ✓ HEARTBEAT.md copied");
36
+ fs.copyFileSync(SKILL, path.join(SOURCES_DIR, "SKILL.md"));
37
+ console.log(" ✓ SKILL.md copied");
35
38
 
36
39
  // ── Detect environment and branch ───────────────────────────────────────────
37
40
 
@@ -107,6 +110,7 @@ async function installNemoClaw({ sandboxName }) {
107
110
  enabled: true,
108
111
  config: {
109
112
  heartbeatPath: "/sandbox/.openclaw/sinain-sources/HEARTBEAT.md",
113
+ skillPath: "/sandbox/.openclaw/sinain-sources/SKILL.md",
110
114
  memoryPath: "/sandbox/.openclaw/sinain-sources/sinain-memory",
111
115
  sessionKey: "agent:main:sinain"
112
116
  }
@@ -191,6 +195,7 @@ async function installLocal() {
191
195
  enabled: true,
192
196
  config: {
193
197
  heartbeatPath: path.join(SOURCES_DIR, "HEARTBEAT.md"),
198
+ skillPath: path.join(SOURCES_DIR, "SKILL.md"),
194
199
  memoryPath: memoryDst,
195
200
  sessionKey: "agent:main:sinain"
196
201
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geravant/sinain",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "sinain OpenClaw plugin — AI overlay for macOS",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,8 @@
14
14
  "openclaw.plugin.json",
15
15
  "install.js",
16
16
  "sinain-memory",
17
- "HEARTBEAT.md"
17
+ "HEARTBEAT.md",
18
+ "SKILL.md"
18
19
  ],
19
20
  "engines": {
20
21
  "node": ">=18"