@gamaze/hicortex 0.16.0 → 0.16.2
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/README.md +9 -0
- package/dist/capture.d.ts +18 -1
- package/dist/capture.js +3 -2
- package/dist/classify-domains.d.ts +1 -1
- package/dist/classify-domains.js +5 -7
- package/dist/cli.js +10 -2
- package/dist/cluster.d.ts +5 -4
- package/dist/cluster.js +2 -3
- package/dist/consolidate.js +6 -5
- package/dist/db.js +23 -0
- package/dist/dedup.js +1 -1
- package/dist/distiller.js +19 -12
- package/dist/domain-classify.d.ts +1 -1
- package/dist/domain-classify.js +1 -5
- package/dist/eval/relevance-eval.d.ts +64 -0
- package/dist/eval/relevance-eval.js +1954 -0
- package/dist/eval/run-eval.js +0 -1
- package/dist/index.js +3 -3
- package/dist/init.d.ts +165 -0
- package/dist/init.js +283 -57
- package/dist/lessons-context.js +3 -2
- package/dist/mcp-server.js +72 -25
- package/dist/nightly.js +35 -3
- package/dist/nofit.d.ts +1 -1
- package/dist/nofit.js +1 -2
- package/dist/prompts.js +22 -13
- package/dist/recall-index.d.ts +56 -21
- package/dist/recall-index.js +51 -29
- package/dist/retrieval.d.ts +7 -7
- package/dist/retrieval.js +20 -24
- package/dist/schema-prototypes.d.ts +8 -13
- package/dist/schema-prototypes.js +13 -22
- package/dist/seed-lesson.d.ts +1 -1
- package/dist/seed-lesson.js +1 -2
- package/dist/storage.d.ts +9 -12
- package/dist/storage.js +19 -21
- package/dist/types.d.ts +47 -23
- package/domains.example.json +2 -3
- package/hermes-plugin/hicortex/README.md +3 -1
- package/hermes-plugin/hicortex/config.py +33 -2
- package/hermes-plugin/hicortex/plugin.yaml +1 -1
- package/hermes-plugin/hicortex/provider.py +5 -0
- package/package.json +2 -1
package/dist/types.d.ts
CHANGED
|
@@ -13,9 +13,23 @@ export interface Memory {
|
|
|
13
13
|
ingested_at: string;
|
|
14
14
|
source_agent: string;
|
|
15
15
|
source_session: string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Stable attribution id of the capturing client (a per-install UUID from
|
|
18
|
+
* config.json `agentId`). Survives agent/machine renames — unlike
|
|
19
|
+
* `source_agent` (a readable name). Attribution only; nothing filters on it.
|
|
20
|
+
* NULL on memories captured before this column existed. (0.16.x)
|
|
21
|
+
*/
|
|
22
|
+
source_agent_id: string | null;
|
|
16
23
|
project: string | null;
|
|
17
24
|
domain: string | null;
|
|
18
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Provenance only (0.16.x): the client-declared topic/domain of the
|
|
27
|
+
* capturing agent (config.json `sourceDomain`). NOT used for recall filtering
|
|
28
|
+
* or scoring, and NOT the content-classified primary (that is `domain`
|
|
29
|
+
* above). NULL when the client declares none. Echoed back on /memory GET.
|
|
30
|
+
*/
|
|
31
|
+
source_domain: string | null;
|
|
32
|
+
privacy: ("PUBLIC" | "WORK" | "PERSONAL" | "SENSITIVE") | null;
|
|
19
33
|
memory_type: "episode" | "lesson" | "fact" | "decision";
|
|
20
34
|
updated_at: string | null;
|
|
21
35
|
}
|
|
@@ -157,6 +171,15 @@ export interface HicortexConfig {
|
|
|
157
171
|
serverUrl?: string;
|
|
158
172
|
/** Bearer token for the Hicortex server. Localhost bypasses auth by default. */
|
|
159
173
|
authToken?: string;
|
|
174
|
+
/**
|
|
175
|
+
* Stable per-install UUID generated by `init` (see ensureAgentId in init.ts;
|
|
176
|
+
* never rotated). Attribution identity of the capturing client — stored on
|
|
177
|
+
* each captured memory as `source_agent_id` (see Memory.source_agent_id) and
|
|
178
|
+
* sent on every /distill segment. Survives agent/machine renames, unlike the
|
|
179
|
+
* readable `source_agent` name. Pure attribution; nothing filters or scopes
|
|
180
|
+
* on it. (0.16.x)
|
|
181
|
+
*/
|
|
182
|
+
agentId?: string;
|
|
160
183
|
/** @deprecated Use the Hicortex server for distillation and consolidation. */
|
|
161
184
|
llmBaseUrl?: string;
|
|
162
185
|
/** @deprecated Use the Hicortex server for distillation and consolidation. */
|
|
@@ -194,6 +217,21 @@ export interface HicortexConfig {
|
|
|
194
217
|
consolidateHour?: number;
|
|
195
218
|
/** @deprecated The OC plugin no longer opens its own database. */
|
|
196
219
|
dbPath?: string;
|
|
220
|
+
/**
|
|
221
|
+
* Client-declared topic/domain of THIS capturing agent (provenance only,
|
|
222
|
+
* 0.16.x). Sent on captured memories as `source_domain` (see
|
|
223
|
+
* Memory.source_domain) — NOT used for recall filtering or scoring, and NOT
|
|
224
|
+
* the content-classified primary (which is the server-derived `domain`
|
|
225
|
+
* column on each memory, classified against `domains` below).
|
|
226
|
+
*
|
|
227
|
+
* DISTINCT from `domains` (plural) directly below: `domains` is the
|
|
228
|
+
* config-owned VOCABULARY — the server's life-sphere list that memories are
|
|
229
|
+
* content-classified against; this singular `sourceDomain` is the client
|
|
230
|
+
* declaring "I am an agent that works on topic X", recorded as provenance on
|
|
231
|
+
* what it captures. Do not conflate the two. (Renamed from `domain` in
|
|
232
|
+
* 0.16.x — one char from `domains`, meant something unrelated.)
|
|
233
|
+
*/
|
|
234
|
+
sourceDomain?: string;
|
|
197
235
|
/**
|
|
198
236
|
* Optional config-owned domain list — the user's top-level memory spheres
|
|
199
237
|
* (life areas OR project/topic areas). When present, the nightly multi-tag
|
|
@@ -205,7 +243,7 @@ export interface HicortexConfig {
|
|
|
205
243
|
* Server-mode `init` scaffolds a generic 5-domain default (Work, Personal,
|
|
206
244
|
* People, Health, Finance — see GENERIC_DEFAULT_DOMAINS in init.ts) when
|
|
207
245
|
* this key is absent, and NEVER touches an existing list. A power-user
|
|
208
|
-
* example (
|
|
246
|
+
* example (custom weakPrimaryFloor) ships as
|
|
209
247
|
* domains.example.json in the package root.
|
|
210
248
|
*
|
|
211
249
|
* NO fallback bucket is needed or special-cased (owner amendment 07.07):
|
|
@@ -227,13 +265,6 @@ export interface HicortexConfig {
|
|
|
227
265
|
export interface DomainDef {
|
|
228
266
|
name: string;
|
|
229
267
|
description: string;
|
|
230
|
-
/**
|
|
231
|
-
* Deliberate compartmentalization (graded-schema spec, 07.07.2026): when
|
|
232
|
-
* true, this domain becomes the PRIMARY (memories.domain) whenever it is
|
|
233
|
-
* tagged, overriding the argmax-weight rule. The owner's config flags only
|
|
234
|
-
* Work — a work/life firewall. Optional; absent = false.
|
|
235
|
-
*/
|
|
236
|
-
compartment?: boolean;
|
|
237
268
|
}
|
|
238
269
|
/** Response from license validation API. */
|
|
239
270
|
export interface LicenseInfo {
|
|
@@ -286,8 +317,14 @@ export interface ModuleIndex {
|
|
|
286
317
|
export interface InsertMemoryOptions {
|
|
287
318
|
sourceAgent?: string;
|
|
288
319
|
sourceSession?: string | null;
|
|
320
|
+
/** Stable client UUID (config.json `agentId`). Attribution only. */
|
|
321
|
+
sourceAgentId?: string | null;
|
|
322
|
+
/** Client-declared topic/domain of the capturing agent. Provenance only. */
|
|
323
|
+
sourceDomain?: string | null;
|
|
289
324
|
project?: string | null;
|
|
290
|
-
|
|
325
|
+
/** 0.16.x: vestigial — stored but never filtered. null (or absent) when the
|
|
326
|
+
* caller doesn't declare one; an explicit value is honored as-is. */
|
|
327
|
+
privacy?: string | null;
|
|
291
328
|
memoryType?: string;
|
|
292
329
|
baseStrength?: number;
|
|
293
330
|
createdAt?: string;
|
|
@@ -297,16 +334,3 @@ export interface VectorSearchOptions {
|
|
|
297
334
|
limit?: number;
|
|
298
335
|
excludeIds?: string[];
|
|
299
336
|
}
|
|
300
|
-
/** Options for FTS search. */
|
|
301
|
-
export interface FtsSearchOptions {
|
|
302
|
-
limit?: number;
|
|
303
|
-
privacy?: string[];
|
|
304
|
-
sourceAgent?: string;
|
|
305
|
-
}
|
|
306
|
-
/** Options for retrieval. */
|
|
307
|
-
export interface RetrievalOptions {
|
|
308
|
-
limit?: number;
|
|
309
|
-
project?: string | null;
|
|
310
|
-
privacy?: string[];
|
|
311
|
-
sourceAgent?: string;
|
|
312
|
-
}
|
package/domains.example.json
CHANGED
|
@@ -33,14 +33,13 @@
|
|
|
33
33
|
"_powerUserExample": {
|
|
34
34
|
"_readme": [
|
|
35
35
|
"A narrower life-sphere set for users who want tighter buckets.",
|
|
36
|
-
"
|
|
36
|
+
"The PRIMARY domain is derived by argmax association weight (LLM tag order breaks ties) — no manual override flag.",
|
|
37
37
|
"`weakPrimaryFloor` (default 0.45) is the minimum embedding similarity for a no-fit memory to earn a weak primary; tune it from your corpus."
|
|
38
38
|
],
|
|
39
39
|
"domains": [
|
|
40
40
|
{
|
|
41
41
|
"name": "Work",
|
|
42
|
-
"description": "Employer, day job, client projects, workstreams"
|
|
43
|
-
"compartment": true
|
|
42
|
+
"description": "Employer, day job, client projects, workstreams"
|
|
44
43
|
},
|
|
45
44
|
{
|
|
46
45
|
"name": "Personal",
|
|
@@ -22,7 +22,7 @@ That's the whole surface. No `sync_turn`, no compaction/session-end capture —
|
|
|
22
22
|
|
|
23
23
|
### Pushed recall index (0.7.0, server ≥ 0.14)
|
|
24
24
|
|
|
25
|
-
Instead of injecting full memory content every turn, `prefetch` sends the user's message to the server's `POST /recall-index` and injects the returned **index block** verbatim — one line per memory (id, title, date), capped and relevance-gated server-side. The agent fetches full content with `hicortex_get(id)` only when a line is actually relevant; that fetch is what strengthens the memory (exposure ≠ use). All tuning knobs (`recallMaxItems`, `recallMinSimilarity`, `recallReshowTurns`, `recallMinPromptChars`, …) live in the **server** config — the plugin carries none. Dedup is turn-based and server-side per session; the plugin resets it at `initialize` (the Hermes `MemoryProvider` interface exposes no compaction signal, so a mid-session context rebuild cannot trigger a reset — the server's turn-based re-show window covers that gap). Against a pre-0.14 server (404) the plugin falls back to the 0.6.x `GET /search` full-content prefetch, fail-soft, re-probing the endpoint every 10 minutes so a later server upgrade is picked up without a gateway restart. The recall calls carry the profile's configured `
|
|
25
|
+
Instead of injecting full memory content every turn, `prefetch` sends the user's message to the server's `POST /recall-index` and injects the returned **index block** verbatim — one line per memory (id, title, date), capped and relevance-gated server-side. The agent fetches full content with `hicortex_get(id)` only when a line is actually relevant; that fetch is what strengthens the memory (exposure ≠ use). All tuning knobs (`recallMaxItems`, `recallMinSimilarity`, `recallReshowTurns`, `recallMinPromptChars`, …) live in the **server** config — the plugin carries none. Dedup is turn-based and server-side per session; the plugin resets it at `initialize` (the Hermes `MemoryProvider` interface exposes no compaction signal, so a mid-session context rebuild cannot trigger a reset — the server's turn-based re-show window covers that gap). Against a pre-0.14 server (404) the plugin falls back to the 0.6.x `GET /search` full-content prefetch, fail-soft, re-probing the endpoint every 10 minutes so a later server upgrade is picked up without a gateway restart. The recall calls carry the profile's configured `default_project` (and `mission_domains`) and use a short dedicated timeout (1.5 s) so a slow server can never stall a turn. (`privacy_filter` is deprecated since 0.7.2 — the server ignores privacy; see [Configuration](#configuration).)
|
|
26
26
|
|
|
27
27
|
### Per-agent standing context (0.13)
|
|
28
28
|
|
|
@@ -84,6 +84,8 @@ export HICORTEX_AUTH_TOKEN=hctx-default-token # or your custom token
|
|
|
84
84
|
|
|
85
85
|
Env overrides: `HICORTEX_URL`, `HICORTEX_AUTH_TOKEN`.
|
|
86
86
|
|
|
87
|
+
> **`privacy_filter` is DEPRECATED** (plugin 0.7.2 / server 0.16.2). The server no longer filters on privacy — the `privacy` column is vestigial (stored, never filtered). The setting is still accepted for backward compatibility but is now a harmless no-op; setting it emits a one-time-per-process warning in the gateway log. For work/personal isolation, run a **separate Hicortex server** per scope rather than relying on in-server privacy filtering.
|
|
88
|
+
|
|
87
89
|
## Topology
|
|
88
90
|
|
|
89
91
|
- **Server host:** runs Hicortex. Set `hicortex_url: http://localhost:8787` (localhost bypasses auth).
|
|
@@ -8,9 +8,15 @@ plugin also works with env-only setup.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
|
+
import logging
|
|
11
12
|
import os
|
|
12
13
|
from typing import Any, Dict, Optional
|
|
13
14
|
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
# One-time-per-process guard for the privacy_filter deprecation warning.
|
|
18
|
+
_privacy_filter_deprecation_warned = False
|
|
19
|
+
|
|
14
20
|
# Declarative config schema — drives `hermes memory setup` (see MemoryProvider
|
|
15
21
|
# .get_config_schema). Field shape per the Hermes MemoryProvider contract:
|
|
16
22
|
# key, label, description, default, required, secret, env_var, choices, url.
|
|
@@ -56,8 +62,15 @@ CONFIG_SCHEMA: list[dict[str, Any]] = [
|
|
|
56
62
|
},
|
|
57
63
|
{
|
|
58
64
|
"key": "privacy_filter",
|
|
59
|
-
"label": "Privacy filter",
|
|
60
|
-
"description":
|
|
65
|
+
"label": "Privacy filter (DEPRECATED)",
|
|
66
|
+
"description": (
|
|
67
|
+
"DEPRECATED since plugin 0.7.2 / server 0.16.2. The server no "
|
|
68
|
+
"longer filters on privacy — the column is vestigial. This setting "
|
|
69
|
+
"is now a harmless no-op: it is still accepted for backward "
|
|
70
|
+
"compat but ignored. For work/personal isolation, run a separate "
|
|
71
|
+
"Hicortex server per scope. (Historically: comma-separated privacy "
|
|
72
|
+
"levels to include, e.g. WORK,PERSONAL.)"
|
|
73
|
+
),
|
|
61
74
|
"default": "WORK,PERSONAL",
|
|
62
75
|
"required": False,
|
|
63
76
|
},
|
|
@@ -94,14 +107,19 @@ def _config_path(hermes_home: Optional[str] = None) -> str:
|
|
|
94
107
|
|
|
95
108
|
def load_config() -> Dict[str, Any]:
|
|
96
109
|
"""Load merged config: file <- env overrides <- defaults."""
|
|
110
|
+
global _privacy_filter_deprecation_warned
|
|
97
111
|
path = _config_path()
|
|
98
112
|
cfg: Dict[str, Any] = {}
|
|
113
|
+
file_set_privacy_filter = False
|
|
99
114
|
if os.path.exists(path):
|
|
100
115
|
try:
|
|
101
116
|
with open(path, encoding="utf-8") as f:
|
|
102
117
|
cfg = json.load(f) or {}
|
|
103
118
|
except Exception:
|
|
104
119
|
cfg = {}
|
|
120
|
+
# Detect an EXPLICIT user setting (the default is applied via setdefault
|
|
121
|
+
# below); only warn when the profile actually configured it.
|
|
122
|
+
file_set_privacy_filter = "privacy_filter" in cfg
|
|
105
123
|
|
|
106
124
|
# Env overrides
|
|
107
125
|
if os.environ.get("HICORTEX_URL"):
|
|
@@ -113,6 +131,19 @@ def load_config() -> Dict[str, Any]:
|
|
|
113
131
|
cfg.setdefault("hicortex_url", "http://localhost:8787")
|
|
114
132
|
cfg.setdefault("recall_limit", 5)
|
|
115
133
|
cfg.setdefault("privacy_filter", "WORK,PERSONAL")
|
|
134
|
+
|
|
135
|
+
# 0.16.2 deprecation: privacy_filter is a no-op now (server ignores privacy
|
|
136
|
+
# entirely). Warn once per process if the profile explicitly sets it.
|
|
137
|
+
if file_set_privacy_filter and not _privacy_filter_deprecation_warned:
|
|
138
|
+
_privacy_filter_deprecation_warned = True
|
|
139
|
+
logger.warning(
|
|
140
|
+
"hicortex: config.json sets 'privacy_filter', which is deprecated "
|
|
141
|
+
"since plugin 0.7.2 / server 0.16.2 — the server no longer filters "
|
|
142
|
+
"on privacy (the column is vestigial). It is a harmless no-op now. "
|
|
143
|
+
"For work/personal isolation, run a separate Hicortex server per "
|
|
144
|
+
"scope. (This warning fires once per process.)"
|
|
145
|
+
)
|
|
146
|
+
|
|
116
147
|
return cfg
|
|
117
148
|
|
|
118
149
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: hicortex
|
|
2
|
-
version: 0.7.
|
|
2
|
+
version: 0.7.2
|
|
3
3
|
description: "Self-learning memory for Hermes agents — every session is distilled into lessons overnight, and your agent wakes up wiser. Pushes a compact per-turn recall index (lazy-loaded with hicortex_get), injects fresh lessons plus a per-agent standing context block, and exposes the full 9-tool memory surface (search, get, recent, ingest, lessons, index, graph, update, delete) via a shared Hicortex server. Stdlib-only."
|
|
4
4
|
pip_dependencies: []
|
|
5
5
|
hooks: []
|
|
@@ -446,6 +446,11 @@ class HicortexProvider(MemoryProvider):
|
|
|
446
446
|
lines.append("Lessons:")
|
|
447
447
|
for l in lessons:
|
|
448
448
|
c = (l.get("content") or "").strip().replace("\n", " ")
|
|
449
|
+
# Legacy lessons were stored with a "## Lesson:" prefix; new ones are
|
|
450
|
+
# topic-first (selected by memory_type, not the prefix). Strip it so
|
|
451
|
+
# Hermes renders the same topic-first line as the CC/OC lessons blocks.
|
|
452
|
+
if c.startswith("## Lesson: "):
|
|
453
|
+
c = c[len("## Lesson: "):]
|
|
449
454
|
lines.append(f"- {c[:200]}")
|
|
450
455
|
if idx.get("total"):
|
|
451
456
|
lines.append(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gamaze/hicortex",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"description": "Self-learning memory for AI agents — experience captured automatically, distilled into lessons overnight, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, and Pi.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"test:watch": "vitest",
|
|
40
40
|
"eval": "node dist/eval/run-eval.js",
|
|
41
41
|
"eval:recall-sweep": "node dist/eval/recall-sweep.js",
|
|
42
|
+
"eval:relevance": "node dist/eval/relevance-eval.js",
|
|
42
43
|
"prepack": "npm run build && rm -rf ./hermes-plugin && mkdir -p ./hermes-plugin && cp -r ../../hermes-plugin/hicortex ./hermes-plugin/ && find ./hermes-plugin -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true",
|
|
43
44
|
"prepublishOnly": "npm run build && rm -rf ./hermes-plugin && mkdir -p ./hermes-plugin && cp -r ../../hermes-plugin/hicortex ./hermes-plugin/ && find ./hermes-plugin -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true"
|
|
44
45
|
},
|