@gamaze/hicortex 0.18.1 → 0.18.3
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/assets/dashboard.html +8 -3
- package/assets/viz.html +9 -3
- package/dist/consolidate.js +7 -7
- package/dist/dashboard.js +3 -3
- package/dist/db.js +24 -1
- package/dist/distiller.d.ts +9 -7
- package/dist/distiller.js +37 -19
- package/dist/eval/recall-sweep.js +2 -2
- package/dist/eval/reflection-census.js +3 -3
- package/dist/hosted-boot.d.ts +61 -0
- package/dist/hosted-boot.js +72 -0
- package/dist/index.js +13 -13
- package/dist/init.d.ts +15 -0
- package/dist/init.js +99 -8
- package/dist/learnings-identity.js +4 -4
- package/dist/localhost-bypass.d.ts +27 -0
- package/dist/localhost-bypass.js +71 -0
- package/dist/mcp-server.js +115 -19
- package/dist/prompts.js +12 -12
- package/dist/recall-index.js +7 -2
- package/dist/retrieval.js +2 -1
- package/dist/seed-lesson.js +1 -1
- package/dist/status.d.ts +8 -0
- package/dist/status.js +15 -1
- package/dist/storage.js +4 -4
- package/dist/token-budget.d.ts +34 -0
- package/dist/token-budget.js +131 -0
- package/dist/type-classify.d.ts +29 -26
- package/dist/type-classify.js +52 -45
- package/dist/type-labels.d.ts +48 -17
- package/dist/type-labels.js +89 -18
- package/dist/types.d.ts +10 -1
- package/dist/viz.d.ts +9 -1
- package/dist/viz.js +11 -2
- package/hermes-plugin/hicortex/client.py +1 -1
- package/hermes-plugin/hicortex/provider.py +13 -13
- package/package.json +1 -1
package/dist/type-labels.d.ts
CHANGED
|
@@ -1,30 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Human-term labels for the
|
|
2
|
+
* Human-term labels + normalization for the `memory_type` enum (#264 final).
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* via
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* The DB column `memories.memory_type` stores the four CANONICAL human terms:
|
|
5
|
+
* knowledge / experience / decisions / learnings
|
|
6
|
+
* These replaced the older raw internal enum (fact/episode/decision/lesson)
|
|
7
|
+
* via migration v13. Every SQL query, the distiller's type tag mapping, the
|
|
8
|
+
* type-classify prompt, and the CREATE TABLE default all use the new terms.
|
|
9
|
+
*
|
|
10
|
+
* Backward-compat window: the OLD raw values are still accepted on the
|
|
11
|
+
* request/agent wire (REST `/ingest` + `/update`, MCP tools, OC + Hermes
|
|
12
|
+
* plugin schemas) and normalized to the new canonical value before any DB
|
|
13
|
+
* write via {@link normalizeMemoryType}. The label map also still carries
|
|
14
|
+
* the old keys so a briefly-stale reader (e.g. a snapshot taken mid-migrate)
|
|
15
|
+
* renders correctly.
|
|
11
16
|
*
|
|
12
17
|
* Mapping (decided 2026-08-11, research/2026-08-11-identity-reframe-brainstorm.md):
|
|
13
|
-
* fact →
|
|
14
|
-
* episode →
|
|
15
|
-
* decision →
|
|
16
|
-
* lesson →
|
|
18
|
+
* fact → knowledge
|
|
19
|
+
* episode → experience
|
|
20
|
+
* decision → decisions
|
|
21
|
+
* lesson → learnings
|
|
17
22
|
*
|
|
18
23
|
* Unknown / future types fall back to the raw value (never silently remapped).
|
|
19
24
|
*/
|
|
20
25
|
/**
|
|
21
|
-
* The four
|
|
22
|
-
*
|
|
26
|
+
* The four canonical memory types mapped to their human-term labels, PLUS the
|
|
27
|
+
* legacy raw keys kept during the backward-compat window (old values may appear
|
|
28
|
+
* briefly in snapshots taken before migration v13, or in-flight requests from
|
|
29
|
+
* older clients). Kept as a plain record so it can be iterated for coverage
|
|
30
|
+
* assertions.
|
|
23
31
|
*/
|
|
24
32
|
export declare const MEMORY_TYPE_LABELS: Record<string, string>;
|
|
25
33
|
/**
|
|
26
|
-
* Return the human-term label for a `memory_type`
|
|
27
|
-
* future types (including null/undefined) fall back to the raw
|
|
28
|
-
* types are visible rather than silently mislabeled.
|
|
34
|
+
* Return the human-term label for a `memory_type` value (canonical OR legacy).
|
|
35
|
+
* Unknown or future types (including null/undefined) fall back to the raw
|
|
36
|
+
* input so new types are visible rather than silently mislabeled.
|
|
29
37
|
*/
|
|
30
38
|
export declare function labelForType(t: string | null | undefined): string;
|
|
39
|
+
/**
|
|
40
|
+
* Normalize a `memory_type` input (from a request body, MCP tool arg, etc.)
|
|
41
|
+
* to the canonical value the DB stores (post-v13). Accepts the four legacy
|
|
42
|
+
* raw enum values (fact/episode/decision/lesson, mapped to the new terms) AND
|
|
43
|
+
* the four canonical human terms (passthrough). Unknown values pass through
|
|
44
|
+
* verbatim — the caller validates.
|
|
45
|
+
*/
|
|
46
|
+
export declare function normalizeMemoryType(input: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* The full accept-set for input validation: the four canonical values plus the
|
|
49
|
+
* four legacy raw values (kept for backward compat of older clients). Exposed
|
|
50
|
+
* so every validating surface (REST `/ingest`, `/update`, MCP zod enums, OC
|
|
51
|
+
* JSON-schema enums, the Hermes plugin) lists the SAME accepted values — no
|
|
52
|
+
* drift. Compare membership case-insensitively (caller normalizes via
|
|
53
|
+
* {@link normalizeMemoryType} before the DB write).
|
|
54
|
+
*/
|
|
55
|
+
export declare const ACCEPTED_MEMORY_TYPES: readonly string[];
|
|
56
|
+
/**
|
|
57
|
+
* True if `input` is one of the accepted memory_type values (canonical OR
|
|
58
|
+
* legacy raw, any casing). Use this as the validation gate; follow with
|
|
59
|
+
* {@link normalizeMemoryType} to map the accepted value to the canonical term.
|
|
60
|
+
*/
|
|
61
|
+
export declare function isAcceptedMemoryType(input: string): boolean;
|
package/dist/type-labels.js
CHANGED
|
@@ -1,43 +1,114 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Human-term labels for the
|
|
3
|
+
* Human-term labels + normalization for the `memory_type` enum (#264 final).
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* via
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* The DB column `memories.memory_type` stores the four CANONICAL human terms:
|
|
6
|
+
* knowledge / experience / decisions / learnings
|
|
7
|
+
* These replaced the older raw internal enum (fact/episode/decision/lesson)
|
|
8
|
+
* via migration v13. Every SQL query, the distiller's type tag mapping, the
|
|
9
|
+
* type-classify prompt, and the CREATE TABLE default all use the new terms.
|
|
10
|
+
*
|
|
11
|
+
* Backward-compat window: the OLD raw values are still accepted on the
|
|
12
|
+
* request/agent wire (REST `/ingest` + `/update`, MCP tools, OC + Hermes
|
|
13
|
+
* plugin schemas) and normalized to the new canonical value before any DB
|
|
14
|
+
* write via {@link normalizeMemoryType}. The label map also still carries
|
|
15
|
+
* the old keys so a briefly-stale reader (e.g. a snapshot taken mid-migrate)
|
|
16
|
+
* renders correctly.
|
|
12
17
|
*
|
|
13
18
|
* Mapping (decided 2026-08-11, research/2026-08-11-identity-reframe-brainstorm.md):
|
|
14
|
-
* fact →
|
|
15
|
-
* episode →
|
|
16
|
-
* decision →
|
|
17
|
-
* lesson →
|
|
19
|
+
* fact → knowledge
|
|
20
|
+
* episode → experience
|
|
21
|
+
* decision → decisions
|
|
22
|
+
* lesson → learnings
|
|
18
23
|
*
|
|
19
24
|
* Unknown / future types fall back to the raw value (never silently remapped).
|
|
20
25
|
*/
|
|
21
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.MEMORY_TYPE_LABELS = void 0;
|
|
27
|
+
exports.ACCEPTED_MEMORY_TYPES = exports.MEMORY_TYPE_LABELS = void 0;
|
|
23
28
|
exports.labelForType = labelForType;
|
|
29
|
+
exports.normalizeMemoryType = normalizeMemoryType;
|
|
30
|
+
exports.isAcceptedMemoryType = isAcceptedMemoryType;
|
|
24
31
|
/**
|
|
25
|
-
* The four
|
|
26
|
-
*
|
|
32
|
+
* The four canonical memory types mapped to their human-term labels, PLUS the
|
|
33
|
+
* legacy raw keys kept during the backward-compat window (old values may appear
|
|
34
|
+
* briefly in snapshots taken before migration v13, or in-flight requests from
|
|
35
|
+
* older clients). Kept as a plain record so it can be iterated for coverage
|
|
36
|
+
* assertions.
|
|
27
37
|
*/
|
|
28
38
|
exports.MEMORY_TYPE_LABELS = {
|
|
39
|
+
// Canonical (post-v13) values.
|
|
40
|
+
knowledge: "Knowledge",
|
|
41
|
+
experience: "Experience",
|
|
42
|
+
decisions: "Decisions",
|
|
43
|
+
learnings: "Learnings",
|
|
44
|
+
// Legacy raw enum (kept so stale readers render correctly during the
|
|
45
|
+
// migration window). Same labels — these are the SAME types, renamed.
|
|
29
46
|
fact: "Knowledge",
|
|
30
47
|
episode: "Experience",
|
|
31
48
|
decision: "Decisions",
|
|
32
49
|
lesson: "Learnings",
|
|
33
50
|
};
|
|
34
51
|
/**
|
|
35
|
-
* Return the human-term label for a `memory_type`
|
|
36
|
-
* future types (including null/undefined) fall back to the raw
|
|
37
|
-
* types are visible rather than silently mislabeled.
|
|
52
|
+
* Return the human-term label for a `memory_type` value (canonical OR legacy).
|
|
53
|
+
* Unknown or future types (including null/undefined) fall back to the raw
|
|
54
|
+
* input so new types are visible rather than silently mislabeled.
|
|
38
55
|
*/
|
|
39
56
|
function labelForType(t) {
|
|
40
57
|
if (!t)
|
|
41
58
|
return "—";
|
|
42
59
|
return exports.MEMORY_TYPE_LABELS[t] ?? t;
|
|
43
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Map BOTH legacy raw enum values AND canonical human terms TO the canonical
|
|
63
|
+
* value stored in the DB (post-v13). Used to normalize request input
|
|
64
|
+
* (`/ingest`, `/update`, MCP tools) so the wire/agent surface accepts the old
|
|
65
|
+
* vocabulary while the storage layer always sees the canonical term.
|
|
66
|
+
* Unknown inputs pass through untouched so the caller's own validation can
|
|
67
|
+
* reject them with a precise error (this helper never silently remaps).
|
|
68
|
+
*
|
|
69
|
+
* Lookup is case-insensitive on the input (the human terms are documented in
|
|
70
|
+
* Titlecase but agents/users send any casing); the four canonical values and
|
|
71
|
+
* the four legacy raw values are all lowercase in the DB.
|
|
72
|
+
*/
|
|
73
|
+
const TO_CANONICAL = {
|
|
74
|
+
// Legacy raw → canonical.
|
|
75
|
+
fact: "knowledge",
|
|
76
|
+
episode: "experience",
|
|
77
|
+
decision: "decisions",
|
|
78
|
+
lesson: "learnings",
|
|
79
|
+
// Canonical passthrough (also covered case-insensitively).
|
|
80
|
+
knowledge: "knowledge",
|
|
81
|
+
experience: "experience",
|
|
82
|
+
decisions: "decisions",
|
|
83
|
+
learnings: "learnings",
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Normalize a `memory_type` input (from a request body, MCP tool arg, etc.)
|
|
87
|
+
* to the canonical value the DB stores (post-v13). Accepts the four legacy
|
|
88
|
+
* raw enum values (fact/episode/decision/lesson, mapped to the new terms) AND
|
|
89
|
+
* the four canonical human terms (passthrough). Unknown values pass through
|
|
90
|
+
* verbatim — the caller validates.
|
|
91
|
+
*/
|
|
92
|
+
function normalizeMemoryType(input) {
|
|
93
|
+
return TO_CANONICAL[input.toLowerCase()] ?? input;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The full accept-set for input validation: the four canonical values plus the
|
|
97
|
+
* four legacy raw values (kept for backward compat of older clients). Exposed
|
|
98
|
+
* so every validating surface (REST `/ingest`, `/update`, MCP zod enums, OC
|
|
99
|
+
* JSON-schema enums, the Hermes plugin) lists the SAME accepted values — no
|
|
100
|
+
* drift. Compare membership case-insensitively (caller normalizes via
|
|
101
|
+
* {@link normalizeMemoryType} before the DB write).
|
|
102
|
+
*/
|
|
103
|
+
exports.ACCEPTED_MEMORY_TYPES = Object.freeze([
|
|
104
|
+
"knowledge", "experience", "decisions", "learnings",
|
|
105
|
+
"fact", "episode", "decision", "lesson",
|
|
106
|
+
]);
|
|
107
|
+
/**
|
|
108
|
+
* True if `input` is one of the accepted memory_type values (canonical OR
|
|
109
|
+
* legacy raw, any casing). Use this as the validation gate; follow with
|
|
110
|
+
* {@link normalizeMemoryType} to map the accepted value to the canonical term.
|
|
111
|
+
*/
|
|
112
|
+
function isAcceptedMemoryType(input) {
|
|
113
|
+
return exports.ACCEPTED_MEMORY_TYPES.includes(input.toLowerCase());
|
|
114
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface Memory {
|
|
|
30
30
|
*/
|
|
31
31
|
source_domain: string | null;
|
|
32
32
|
privacy: ("PUBLIC" | "WORK" | "PERSONAL" | "SENSITIVE") | null;
|
|
33
|
-
memory_type: "
|
|
33
|
+
memory_type: "experience" | "learnings" | "knowledge" | "decisions";
|
|
34
34
|
updated_at: string | null;
|
|
35
35
|
}
|
|
36
36
|
/** A link between two memories. */
|
|
@@ -412,6 +412,15 @@ export interface HicortexConfig {
|
|
|
412
412
|
* so these were not surfacing in the top-k anyway).
|
|
413
413
|
*/
|
|
414
414
|
memorySoftCap?: number;
|
|
415
|
+
/**
|
|
416
|
+
* Hosted-service mode (issue #110, #271 — spec 2026-07-27 §1-§2). When true,
|
|
417
|
+
* the server enforces hosted-tenant constraints at boot: it refuses to start
|
|
418
|
+
* if `HICORTEX_DB_PATH` is set (path-override attacks) or if the localhost
|
|
419
|
+
* auth-bypass marker file is present (hosted must be fail-closed — no bypass).
|
|
420
|
+
* Absent/false (the self-hosted default) → the assertions never fire and
|
|
421
|
+
* behaviour is unchanged. Read at server boot via readStrictBoolean.
|
|
422
|
+
*/
|
|
423
|
+
hostedMode?: boolean;
|
|
415
424
|
/**
|
|
416
425
|
* Monthly fair-use ceiling on consolidation LLM token consumption (#246).
|
|
417
426
|
* Default `0` = unlimited (the self-hosted default — no cap, never throttled).
|
package/dist/viz.d.ts
CHANGED
|
@@ -45,8 +45,16 @@ export declare const VIZ_VENDOR_FILES: ReadonlySet<string>;
|
|
|
45
45
|
* always evaluated (no short-circuit), so a caller cannot learn WHICH token
|
|
46
46
|
* matched from the response timing. Absent/empty `authTokenPrevious` behaves
|
|
47
47
|
* exactly as the single-token middleware always has.
|
|
48
|
+
*
|
|
49
|
+
* `allowLocalhostBypass` (0.18, #110 §2/#271): when false (or omitted), the
|
|
50
|
+
* localhost bypass is DISABLED — localhost connections need the bearer token
|
|
51
|
+
* like any other (fail-closed). When true, localhost loopback (127.0.0.1,
|
|
52
|
+
* ::1, ::ffff:127.0.0.1) bypasses auth as before. The marker file
|
|
53
|
+
* `~/.hicortex/.allow-localhost-bypass` (written by self-hosted init) gates
|
|
54
|
+
* this — a hosted tenant dir is fail-closed by default. mcp-server.ts captures
|
|
55
|
+
* the marker state once at boot and passes it in (no per-request stat).
|
|
48
56
|
*/
|
|
49
|
-
export declare function createAuthMiddleware(authToken: string | undefined, authTokenPrevious?: string): express.RequestHandler;
|
|
57
|
+
export declare function createAuthMiddleware(authToken: string | undefined, authTokenPrevious?: string, allowLocalhostBypass?: boolean): express.RequestHandler;
|
|
50
58
|
/**
|
|
51
59
|
* Resolve the on-disk path of the viz page. Throws (fail explicitly) when the
|
|
52
60
|
* asset is missing — a broken install should surface, not degrade silently.
|
package/dist/viz.js
CHANGED
|
@@ -92,9 +92,18 @@ function safeBearerMatch(headerValue, expectedToken) {
|
|
|
92
92
|
* always evaluated (no short-circuit), so a caller cannot learn WHICH token
|
|
93
93
|
* matched from the response timing. Absent/empty `authTokenPrevious` behaves
|
|
94
94
|
* exactly as the single-token middleware always has.
|
|
95
|
+
*
|
|
96
|
+
* `allowLocalhostBypass` (0.18, #110 §2/#271): when false (or omitted), the
|
|
97
|
+
* localhost bypass is DISABLED — localhost connections need the bearer token
|
|
98
|
+
* like any other (fail-closed). When true, localhost loopback (127.0.0.1,
|
|
99
|
+
* ::1, ::ffff:127.0.0.1) bypasses auth as before. The marker file
|
|
100
|
+
* `~/.hicortex/.allow-localhost-bypass` (written by self-hosted init) gates
|
|
101
|
+
* this — a hosted tenant dir is fail-closed by default. mcp-server.ts captures
|
|
102
|
+
* the marker state once at boot and passes it in (no per-request stat).
|
|
95
103
|
*/
|
|
96
|
-
function createAuthMiddleware(authToken, authTokenPrevious) {
|
|
104
|
+
function createAuthMiddleware(authToken, authTokenPrevious, allowLocalhostBypass) {
|
|
97
105
|
const previous = authTokenPrevious && authTokenPrevious.length > 0 ? authTokenPrevious : undefined;
|
|
106
|
+
const bypassEnabled = allowLocalhostBypass === true;
|
|
98
107
|
return (req, res, next) => {
|
|
99
108
|
if (req.path === "/health")
|
|
100
109
|
return next();
|
|
@@ -142,7 +151,7 @@ function createAuthMiddleware(authToken, authTokenPrevious) {
|
|
|
142
151
|
return next();
|
|
143
152
|
}
|
|
144
153
|
const ip = req.ip ?? req.socket.remoteAddress ?? "";
|
|
145
|
-
if (ip === "127.0.0.1" || ip === "::1" || ip === "::ffff:127.0.0.1")
|
|
154
|
+
if (bypassEnabled && (ip === "127.0.0.1" || ip === "::1" || ip === "::ffff:127.0.0.1"))
|
|
146
155
|
return next();
|
|
147
156
|
// Constant-time bearer check (#254). When authTokenPrevious is set, BOTH
|
|
148
157
|
// tokens are compared every request (no short-circuit) so timing cannot
|
|
@@ -169,7 +169,7 @@ class HicortexClient:
|
|
|
169
169
|
content: str,
|
|
170
170
|
source_agent: Optional[str] = None,
|
|
171
171
|
project: Optional[str] = None,
|
|
172
|
-
memory_type: str = "
|
|
172
|
+
memory_type: str = "experience",
|
|
173
173
|
privacy: str = "WORK",
|
|
174
174
|
) -> tuple[int, dict[str, Any]]:
|
|
175
175
|
return self._post(
|
|
@@ -132,7 +132,7 @@ def _order_section_names(names: Iterable[str]) -> List[str]:
|
|
|
132
132
|
|
|
133
133
|
|
|
134
134
|
def _render_context_block(sections: Dict[str, Any]) -> str:
|
|
135
|
-
"""Render the ``##
|
|
135
|
+
"""Render the ``## Identity`` block, or "" when every section is blank."""
|
|
136
136
|
body_parts: List[str] = []
|
|
137
137
|
for name in _order_section_names(sections.keys()):
|
|
138
138
|
body = sections.get(name)
|
|
@@ -141,7 +141,7 @@ def _render_context_block(sections: Dict[str, Any]) -> str:
|
|
|
141
141
|
body_parts.extend([f"### {_title_case_section(name)}", "", body.strip()])
|
|
142
142
|
if not body_parts:
|
|
143
143
|
return ""
|
|
144
|
-
return "\n".join(["##
|
|
144
|
+
return "\n".join(["## Identity", "", *body_parts])
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
class HicortexProvider(MemoryProvider):
|
|
@@ -397,7 +397,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
397
397
|
return "\n\n".join(b for b in blocks if b)
|
|
398
398
|
|
|
399
399
|
def _context_block(self, client: HicortexClient) -> str:
|
|
400
|
-
"""Fetch the standing context layer and render a ``##
|
|
400
|
+
"""Fetch the standing context layer and render a ``## Identity`` block,
|
|
401
401
|
or "" when nothing should be injected. Gates (ALL): "hermes" in the
|
|
402
402
|
server-resolved ``clients``; when an agent id was SENT, the response
|
|
403
403
|
echoes ``agent`` (old-server guard — a pre-0.13 server ignores ?agent=
|
|
@@ -444,7 +444,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
444
444
|
"the recall index), and `hicortex_recent` for recent memories by project.",
|
|
445
445
|
]
|
|
446
446
|
if lessons:
|
|
447
|
-
lines.append("
|
|
447
|
+
lines.append("Learnings:")
|
|
448
448
|
for l in lessons:
|
|
449
449
|
c = (l.get("content") or "").strip().replace("\n", " ")
|
|
450
450
|
# Legacy lessons were stored with a "## Lesson:" prefix; new ones are
|
|
@@ -455,7 +455,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
455
455
|
lines.append(f"- {c[:200]}")
|
|
456
456
|
if idx.get("total"):
|
|
457
457
|
lines.append(
|
|
458
|
-
f"({idx.get('total')} memories, {idx.get('lessonCount')}
|
|
458
|
+
f"({idx.get('total')} memories, {idx.get('lessonCount')} learnings "
|
|
459
459
|
f"across {idx.get('sourceCount')} agents)"
|
|
460
460
|
)
|
|
461
461
|
return "\n".join(lines)
|
|
@@ -523,7 +523,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
523
523
|
"name": "hicortex_ingest",
|
|
524
524
|
"description": (
|
|
525
525
|
"Store a new memory in long-term storage. "
|
|
526
|
-
"Use for
|
|
526
|
+
"Use for Knowledge, Decisions, or Learnings."
|
|
527
527
|
),
|
|
528
528
|
"parameters": {
|
|
529
529
|
"type": "object",
|
|
@@ -532,8 +532,8 @@ class HicortexProvider(MemoryProvider):
|
|
|
532
532
|
"project": {"type": "string", "description": "Project this memory belongs to"},
|
|
533
533
|
"memory_type": {
|
|
534
534
|
"type": "string",
|
|
535
|
-
"enum": ["
|
|
536
|
-
"description": "Type of memory (default:
|
|
535
|
+
"enum": ["knowledge", "experience", "decisions", "learnings", "fact", "episode", "decision", "lesson"],
|
|
536
|
+
"description": "Type of memory (default: experience). Accepted: Knowledge/Experience/Decisions/Learnings (legacy raw enum also accepted, normalized server-side).",
|
|
537
537
|
},
|
|
538
538
|
},
|
|
539
539
|
"required": ["content"],
|
|
@@ -542,7 +542,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
542
542
|
{
|
|
543
543
|
"name": "hicortex_lessons",
|
|
544
544
|
"description": (
|
|
545
|
-
"Get actionable
|
|
545
|
+
"Get actionable Learnings distilled from past sessions. "
|
|
546
546
|
"Auto-generated insights about mistakes to avoid."
|
|
547
547
|
),
|
|
548
548
|
"parameters": {
|
|
@@ -603,8 +603,8 @@ class HicortexProvider(MemoryProvider):
|
|
|
603
603
|
"project": {"type": "string", "description": "New project name"},
|
|
604
604
|
"memory_type": {
|
|
605
605
|
"type": "string",
|
|
606
|
-
"enum": ["
|
|
607
|
-
"description": "New memory type",
|
|
606
|
+
"enum": ["knowledge", "experience", "decisions", "learnings", "fact", "episode", "decision", "lesson"],
|
|
607
|
+
"description": "New memory type. Accepted: Knowledge/Experience/Decisions/Learnings (legacy raw enum also accepted, normalized server-side).",
|
|
608
608
|
},
|
|
609
609
|
},
|
|
610
610
|
"required": ["id"],
|
|
@@ -677,7 +677,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
677
677
|
content=content,
|
|
678
678
|
source_agent="hermes/manual",
|
|
679
679
|
project=args.get("project") or self._project,
|
|
680
|
-
memory_type=args.get("memory_type", "
|
|
680
|
+
memory_type=args.get("memory_type", "experience"),
|
|
681
681
|
)
|
|
682
682
|
if status not in (200, 201):
|
|
683
683
|
return json.dumps({"error": resp.get("error", f"HTTP {status}")})
|
|
@@ -688,7 +688,7 @@ class HicortexProvider(MemoryProvider):
|
|
|
688
688
|
data = client.lessons()
|
|
689
689
|
lessons = (data.get("lessons") or [])
|
|
690
690
|
if not lessons:
|
|
691
|
-
return json.dumps({"message": "No
|
|
691
|
+
return json.dumps({"message": "No Learnings found."})
|
|
692
692
|
return json.dumps([{"content": l.get("content", "")[:500]} for l in lessons])
|
|
693
693
|
|
|
694
694
|
elif tool_name == "hicortex_index":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gamaze/hicortex",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.3",
|
|
4
4
|
"description": "Persistent agent identity for AI agents — a hand-edited identity layer, nightly-distilled experience, and lessons injected every session, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, and Pi.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|