EXTENSION for TreeOS
heartbeat
The tree knows it's alive. Pure in-memory presence detection. No database writes. No metadata. No LLM. Two hooks record when humans interact. enrichContext injects one field: landHeartbeat. Values: alive (someone is here), quiet (recent but gone), dormant (nobody for a while). The AI at a quiet tree says welcome back. The AI at a busy tree knows others are here. The AI at a dormant tree understands the weight of a return after silence.
v1.0.1 by TreeOS Site 0 downloads 2 files 91 lines 2.4 KB published 38d ago
treeos ext install heartbeat
View changelog

Manifest

Requires

  • services: hooks
SHA256: 32fe2491b1e8ac30013a56b0996bb438bdeb11f738d7e5fc29eb405009dac5f9

Dependents

1 package depend on this

PackageTypeRelationship
treeos v1.0.1osstandalone

Hooks

Listens To

  • afterLLMCall
  • afterNavigate
  • enrichContext

Source Code

1/**
2 * Heartbeat
3 *
4 * The tree knows it's alive.
5 */
6
7import log from "../../seed/log.js";
8
9// In-memory only. Resets on restart. That's the point.
10let lastInteraction = 0;
11const activeSessions = new Set();
12
13const ALIVE_THRESHOLD = 5 * 60 * 1000;    // 5 min
14const QUIET_THRESHOLD = 30 * 60 * 1000;   // 30 min
15
16export async function init(core) {
17  core.hooks.register("afterLLMCall", async ({ userId, rootId }) => {
18    if (!userId || userId === "SYSTEM") return;
19    lastInteraction = Date.now();
20    if (rootId) activeSessions.add(rootId);
21  }, "heartbeat");
22
23  core.hooks.register("afterNavigate", async ({ userId, rootId }) => {
24    if (!userId) return;
25    lastInteraction = Date.now();
26    if (rootId) activeSessions.add(rootId);
27  }, "heartbeat");
28
29  // Prune stale sessions every 5 min
30  const pruneTimer = setInterval(() => {
31    if (Date.now() - lastInteraction > QUIET_THRESHOLD) {
32      activeSessions.clear();
33    }
34  }, ALIVE_THRESHOLD);
35  if (pruneTimer.unref) pruneTimer.unref();
36
37  core.hooks.register("enrichContext", async ({ context }) => {
38    if (lastInteraction === 0) return; // never had a heartbeat
39
40    const age = Date.now() - lastInteraction;
41
42    if (age < ALIVE_THRESHOLD) {
43      context.landHeartbeat = "alive";
44    } else if (age < QUIET_THRESHOLD) {
45      context.landHeartbeat = "quiet";
46    } else {
47      context.landHeartbeat = "dormant";
48    }
49  }, "heartbeat");
50
51  log.verbose("Heartbeat", "Heartbeat loaded");
52
53  return {
54    stop: () => clearInterval(pruneTimer),
55  };
56}
57
1export default {
2  name: "heartbeat",
3  version: "1.0.1",
4  builtFor: "TreeOS",
5  description:
6    "The tree knows it's alive. Pure in-memory presence detection. No database writes. " +
7    "No metadata. No LLM. Two hooks record when humans interact. enrichContext injects " +
8    "one field: landHeartbeat. Values: alive (someone is here), quiet (recent but gone), " +
9    "dormant (nobody for a while). The AI at a quiet tree says welcome back. The AI at " +
10    "a busy tree knows others are here. The AI at a dormant tree understands the weight " +
11    "of a return after silence.",
12
13  needs: {
14    services: ["hooks"],
15  },
16
17  optional: {},
18
19  provides: {
20    models: {},
21    routes: false,
22    tools: false,
23    jobs: false,
24    orchestrator: false,
25    energyActions: {},
26    sessionTypes: {},
27    hooks: {
28      fires: [],
29      listens: ["afterLLMCall", "afterNavigate", "enrichContext"],
30    },
31    cli: [],
32  },
33};
34

Versions

Version Published Downloads
1.0.1 38d ago 0
1.0.0 48d ago 0
0 stars
0 flags
React from the CLI: treeos ext star heartbeat

Comments

Loading comments...

Post comments from the CLI: treeos ext comment heartbeat "your comment"
Max 3 comments per extension. One star and one flag per user.