@gamaze/hicortex 0.7.1 → 0.10.1

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 (49) hide show
  1. package/README.md +72 -39
  2. package/dist/claude-md.d.ts +9 -21
  3. package/dist/claude-md.js +9 -241
  4. package/dist/cli.d.ts +3 -2
  5. package/dist/cli.js +29 -11
  6. package/dist/consolidate.js +0 -7
  7. package/dist/db.js +24 -0
  8. package/dist/embedder.d.ts +11 -0
  9. package/dist/embedder.js +27 -0
  10. package/dist/extensions.d.ts +41 -88
  11. package/dist/extensions.js +36 -61
  12. package/dist/features.d.ts +21 -25
  13. package/dist/features.js +47 -83
  14. package/dist/hermes-transcript-reader.d.ts +27 -0
  15. package/dist/hermes-transcript-reader.js +134 -0
  16. package/dist/index.d.ts +16 -4
  17. package/dist/index.js +252 -344
  18. package/dist/init.d.ts +41 -1
  19. package/dist/init.js +545 -190
  20. package/dist/lesson-selection.d.ts +62 -0
  21. package/dist/lesson-selection.js +159 -0
  22. package/dist/lessons-context.d.ts +17 -0
  23. package/dist/lessons-context.js +96 -0
  24. package/dist/llm.d.ts +42 -29
  25. package/dist/llm.js +89 -270
  26. package/dist/mcp-server.d.ts +0 -1
  27. package/dist/mcp-server.js +404 -86
  28. package/dist/nightly.d.ts +9 -6
  29. package/dist/nightly.js +197 -357
  30. package/dist/oc-transcript-reader.d.ts +20 -0
  31. package/dist/oc-transcript-reader.js +61 -0
  32. package/dist/pi-transcript-reader.d.ts +1 -0
  33. package/dist/status.js +22 -2
  34. package/dist/storage.d.ts +7 -1
  35. package/dist/storage.js +28 -7
  36. package/dist/transcript-reader.d.ts +19 -0
  37. package/dist/transcript-reader.js +17 -3
  38. package/dist/types.d.ts +10 -0
  39. package/dist/uninstall.js +31 -1
  40. package/hermes-plugin/hicortex/README.md +77 -0
  41. package/hermes-plugin/hicortex/__init__.py +17 -0
  42. package/hermes-plugin/hicortex/client.py +162 -0
  43. package/hermes-plugin/hicortex/config.py +105 -0
  44. package/hermes-plugin/hicortex/plugin.yaml +12 -0
  45. package/hermes-plugin/hicortex/provider.py +432 -0
  46. package/openclaw.plugin.json +17 -44
  47. package/package.json +7 -5
  48. package/dist/pro-loader.d.ts +0 -33
  49. package/dist/pro-loader.js +0 -187
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Hermes transcript reader — the nightly capture path for Nous Research Hermes.
3
+ *
4
+ * Hermes stores conversation in a SQLite state DB, one per profile:
5
+ * ~/.hermes/profiles/<profile>/state.db (per-profile agents: lenny, raider, nano)
6
+ * ~/.hermes/state.db (global, non-profile setups)
7
+ *
8
+ * Schema (relevant columns):
9
+ * sessions(id TEXT PK, started_at REAL, ended_at REAL, ...)
10
+ * messages(session_id TEXT, role TEXT, content TEXT, tool_name TEXT, timestamp REAL, active INT, ...)
11
+ *
12
+ * Compaction is NON-DESTRUCTIVE (compacted-out turns kept with active=0) and
13
+ * sessions are retained ~90 days — so the full history of any ended session is
14
+ * readable here nightly. No runtime plugin capture is needed; the Hermes plugin
15
+ * is recall-only.
16
+ *
17
+ * We process only ENDED sessions (ended_at set) that ended since the last run.
18
+ * A live session is distilled after it ends — this avoids partial-session
19
+ * distillation and keeps per-session dedup clean (chunks are stored as
20
+ * `<sessionId>#<chunkIndex>`; see nightly.ts).
21
+ */
22
+ import type { TranscriptBatch } from "./transcript-reader.js";
23
+ /**
24
+ * Read Hermes sessions that ended since `since`, across all profiles.
25
+ * Returns one batch per session, parallel to readCcTranscripts().
26
+ */
27
+ export declare function readHermesSessions(since: Date, hermesHome?: string): TranscriptBatch[];
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ /**
3
+ * Hermes transcript reader — the nightly capture path for Nous Research Hermes.
4
+ *
5
+ * Hermes stores conversation in a SQLite state DB, one per profile:
6
+ * ~/.hermes/profiles/<profile>/state.db (per-profile agents: lenny, raider, nano)
7
+ * ~/.hermes/state.db (global, non-profile setups)
8
+ *
9
+ * Schema (relevant columns):
10
+ * sessions(id TEXT PK, started_at REAL, ended_at REAL, ...)
11
+ * messages(session_id TEXT, role TEXT, content TEXT, tool_name TEXT, timestamp REAL, active INT, ...)
12
+ *
13
+ * Compaction is NON-DESTRUCTIVE (compacted-out turns kept with active=0) and
14
+ * sessions are retained ~90 days — so the full history of any ended session is
15
+ * readable here nightly. No runtime plugin capture is needed; the Hermes plugin
16
+ * is recall-only.
17
+ *
18
+ * We process only ENDED sessions (ended_at set) that ended since the last run.
19
+ * A live session is distilled after it ends — this avoids partial-session
20
+ * distillation and keeps per-session dedup clean (chunks are stored as
21
+ * `<sessionId>#<chunkIndex>`; see nightly.ts).
22
+ */
23
+ var __importDefault = (this && this.__importDefault) || function (mod) {
24
+ return (mod && mod.__esModule) ? mod : { "default": mod };
25
+ };
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.readHermesSessions = readHermesSessions;
28
+ const node_fs_1 = require("node:fs");
29
+ const node_path_1 = require("node:path");
30
+ const node_os_1 = require("node:os");
31
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
32
+ const HERMES_HOME = process.env.HERMES_HOME || (0, node_path_1.join)((0, node_os_1.homedir)(), ".hermes");
33
+ /**
34
+ * Session `source` values that are NOT primary conversations and must not be
35
+ * captured — capturing them would pollute long-term memory with automated,
36
+ * non-conversational runs. `cron` is Hermes' scheduled-task source (garmin
37
+ * syncs, daily scans, self-reflection loops). This mirrors the MemoryProvider
38
+ * contract's own guidance to skip non-primary `agent_context` (e.g. "cron").
39
+ * Everything else (cli, discord, telegram, slack, …) is a real conversation.
40
+ */
41
+ const NON_PRIMARY_SOURCES = new Set(["cron"]);
42
+ /**
43
+ * Message roles that are metadata/noise, not conversation — mapped so the
44
+ * distiller's extractConversationText drops them (it skips "tool_result").
45
+ */
46
+ const NOISE_ROLES = new Set(["tool", "session_meta"]);
47
+ /**
48
+ * Read Hermes sessions that ended since `since`, across all profiles.
49
+ * Returns one batch per session, parallel to readCcTranscripts().
50
+ */
51
+ function readHermesSessions(since, hermesHome = HERMES_HOME) {
52
+ const batches = [];
53
+ const sinceEpoch = since.getTime() / 1000; // Hermes timestamps are unix seconds (REAL)
54
+ for (const { profile, dbPath } of discoverProfileDbs(hermesHome)) {
55
+ let db;
56
+ try {
57
+ db = new better_sqlite3_1.default(dbPath, { readonly: true, fileMustExist: true });
58
+ }
59
+ catch {
60
+ continue; // locked / unreadable / wrong owner — skip, retry next run
61
+ }
62
+ try {
63
+ const sessions = db
64
+ .prepare("SELECT id, ended_at, source FROM sessions WHERE ended_at IS NOT NULL AND ended_at > ? ORDER BY ended_at")
65
+ .all(sinceEpoch);
66
+ const msgStmt = db.prepare("SELECT role, content, tool_name, timestamp FROM messages WHERE session_id = ? ORDER BY timestamp, id");
67
+ for (const s of sessions) {
68
+ // Skip automated (non-primary) sessions — cron runs are not
69
+ // conversations and would pollute memory. Checked before pulling
70
+ // messages so we don't even read them.
71
+ if (NON_PRIMARY_SOURCES.has(s.source))
72
+ continue;
73
+ const rows = msgStmt.all(s.id);
74
+ // Skip only genuinely empty sessions. Do NOT gate on message count —
75
+ // a short 2-message exchange can carry a real decision. Meaningful-
76
+ // content is gated downstream by the post-denoise 200-char check in
77
+ // nightly.ts, so short-but-dense sessions aren't dropped here.
78
+ if (rows.length === 0)
79
+ continue;
80
+ // Map Hermes rows to the shape extractConversationText() understands
81
+ // (it reads m.role + m.content). Metadata/noise roles (tool results,
82
+ // session_meta) are relabelled "tool_result" so the distiller drops them.
83
+ const entries = rows.map((r) => ({
84
+ role: NOISE_ROLES.has(r.role) ? "tool_result" : r.role,
85
+ content: r.content ?? "",
86
+ }));
87
+ const endTs = s.ended_at ?? rows[rows.length - 1].timestamp;
88
+ batches.push({
89
+ sessionId: s.id,
90
+ projectName: profile,
91
+ sourceAgent: `hermes/${profile}`,
92
+ date: new Date(endTs * 1000).toISOString().slice(0, 10),
93
+ entries,
94
+ });
95
+ }
96
+ }
97
+ catch {
98
+ // Query failed (schema drift on a Hermes upgrade) — skip this DB, don't crash the run.
99
+ }
100
+ finally {
101
+ db.close();
102
+ }
103
+ }
104
+ return batches;
105
+ }
106
+ /**
107
+ * Find every Hermes state DB: one per profile, plus the global DB for
108
+ * non-profile installs. The profile name becomes the provenance label.
109
+ */
110
+ function discoverProfileDbs(hermesHome) {
111
+ const out = [];
112
+ const profilesDir = (0, node_path_1.join)(hermesHome, "profiles");
113
+ try {
114
+ for (const entry of (0, node_fs_1.readdirSync)(profilesDir)) {
115
+ if (entry.startsWith(".") || entry.startsWith("_"))
116
+ continue;
117
+ const dbPath = (0, node_path_1.join)(profilesDir, entry, "state.db");
118
+ try {
119
+ if ((0, node_fs_1.statSync)(dbPath).isFile())
120
+ out.push({ profile: entry, dbPath });
121
+ }
122
+ catch {
123
+ // no state.db for this profile
124
+ }
125
+ }
126
+ }
127
+ catch {
128
+ // no profiles dir
129
+ }
130
+ const globalDb = (0, node_path_1.join)(hermesHome, "state.db");
131
+ if ((0, node_fs_1.existsSync)(globalDb))
132
+ out.push({ profile: "default", dbPath: globalDb });
133
+ return out;
134
+ }
package/dist/index.d.ts CHANGED
@@ -1,9 +1,21 @@
1
1
  /**
2
- * Hicortex OpenClaw Plugin — Long-term Memory That Learns.
2
+ * Hicortex OpenClaw Plugin — Long-term Memory That Learns. (0.10.0)
3
3
  *
4
- * Pure in-process plugin: no sidecar, no HTTP. Uses better-sqlite3 + sqlite-vec
5
- * for storage, @huggingface/transformers for embeddings, and multi-provider LLM
6
- * for distillation and consolidation.
4
+ * Thin-client model: the plugin requires a Hicortex server (co-located at
5
+ * http://127.0.0.1:8787 by default, or a remote URL via `serverUrl` config).
6
+ * No local database, no local LLM, no embedder, no consolidation scheduler.
7
+ *
8
+ * Install once: `openclaw plugins install @gamaze/hicortex`
9
+ * Run server: `npx @gamaze/hicortex init`
10
+ *
11
+ * Responsibilities (recall-only adapter, like the Hermes plugin):
12
+ * - before_agent_start → GET /lessons (fail-soft, 3s timeout) → inject context
13
+ * - Tools → HTTP proxies to /search, /context, /ingest, /lessons
14
+ *
15
+ * CAPTURE IS NOT THIS PLUGIN'S JOB. OpenClaw persists sessions at
16
+ * ~/.openclaw/agents/<agentId>/sessions/*.jsonl in the Pi v3 format; the
17
+ * machine's Hicortex nightly reads them via oc-transcript-reader.ts —
18
+ * canonical nightly-from-logs, same as CC JSONL and Hermes state.db.
7
19
  */
8
20
  declare const _default: {
9
21
  id: string;