@gamaze/hicortex 0.19.2 → 0.19.4
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 +17 -5
- package/dist/backup.d.ts +50 -0
- package/dist/backup.js +118 -2
- package/dist/capture.d.ts +27 -2
- package/dist/capture.js +103 -6
- package/dist/embedder.d.ts +23 -0
- package/dist/embedder.js +29 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +286 -5
- package/dist/mcp-server.d.ts +25 -4
- package/dist/mcp-server.js +101 -38
- package/dist/nightly.d.ts +25 -0
- package/dist/nightly.js +125 -20
- package/dist/prompts.d.ts +15 -0
- package/dist/prompts.js +21 -3
- package/dist/recall-index.d.ts +105 -4
- package/dist/recall-index.js +217 -2
- package/dist/retrieval.d.ts +37 -0
- package/dist/retrieval.js +17 -2
- package/dist/storage.d.ts +30 -0
- package/dist/storage.js +46 -1
- package/dist/type-classify.js +3 -1
- package/dist/types.d.ts +17 -0
- package/dist/uninstall.d.ts +33 -0
- package/dist/uninstall.js +78 -26
- package/dist/viz.d.ts +1 -1
- package/dist/viz.js +28 -1
- package/openclaw.plugin.json +10 -1
- package/package.json +1 -1
package/dist/uninstall.js
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* Preserves the database (user data).
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.SESSION_START_HOOK_COMMAND_RE = void 0;
|
|
7
|
+
exports.RECALL_HOOK_COMMAND_RE = exports.SESSION_START_HOOK_COMMAND_RE = void 0;
|
|
8
8
|
exports.isHicortexSessionStartHook = isHicortexSessionStartHook;
|
|
9
|
+
exports.isHicortexRecallHook = isHicortexRecallHook;
|
|
10
|
+
exports.removeHicortexCcHooks = removeHicortexCcHooks;
|
|
9
11
|
exports.runUninstall = runUninstall;
|
|
10
12
|
const paths_js_1 = require("./paths.js");
|
|
11
13
|
const node_fs_1 = require("node:fs");
|
|
@@ -33,6 +35,69 @@ exports.SESSION_START_HOOK_COMMAND_RE = /(^|\s)(?:learnings-identity|lessons-con
|
|
|
33
35
|
function isHicortexSessionStartHook(command) {
|
|
34
36
|
return typeof command === "string" && exports.SESSION_START_HOOK_COMMAND_RE.test(command);
|
|
35
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Matches a CC hook `command` that runs the Hicortex recall hook — the
|
|
40
|
+
* `recall-hook` subcommand (#192). Same word-boundary discipline as the
|
|
41
|
+
* learnings matcher: an unrelated command that merely CONTAINS the substring
|
|
42
|
+
* ("my-recall-hook", "recall-hooks-old") is never swept up. Used for BOTH
|
|
43
|
+
* event arrays the installer writes (UserPromptSubmit + SessionStart).
|
|
44
|
+
*/
|
|
45
|
+
exports.RECALL_HOOK_COMMAND_RE = /(^|\s)recall-hook(\s|$)/;
|
|
46
|
+
/** True when a CC hook `command` string runs the Hicortex recall hook. */
|
|
47
|
+
function isHicortexRecallHook(command) {
|
|
48
|
+
return typeof command === "string" && exports.RECALL_HOOK_COMMAND_RE.test(command);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Remove every Hicortex hook entry from a PARSED ~/.claude/settings.json
|
|
52
|
+
* (#327): the SessionStart learnings hook (canonical + legacy alias) AND the
|
|
53
|
+
* recall-hook pair (UserPromptSubmit + SessionStart, installed together by
|
|
54
|
+
* installRecallHooks — leaving either behind is a silent npx spawn per prompt
|
|
55
|
+
* forever). Mutates `settings` in place; returns what was removed (empty when
|
|
56
|
+
* nothing matched — a clean no-op). Exact-match discipline throughout: only
|
|
57
|
+
* entries whose `hooks[].command` matches a Hicortex subcommand are removed;
|
|
58
|
+
* foreign hooks (and prefix-colliding names) stay untouched.
|
|
59
|
+
*
|
|
60
|
+
* Pure on the parsed object so the uninstall behavior is unit-testable
|
|
61
|
+
* without spinning up CC; runUninstall owns the file I/O.
|
|
62
|
+
*/
|
|
63
|
+
function removeHicortexCcHooks(settings) {
|
|
64
|
+
const hooks = settings.hooks;
|
|
65
|
+
if (!hooks || typeof hooks !== "object")
|
|
66
|
+
return [];
|
|
67
|
+
const groups = [
|
|
68
|
+
{ event: "SessionStart", kind: "learnings", match: isHicortexSessionStartHook },
|
|
69
|
+
{ event: "SessionStart", kind: "recall", match: isHicortexRecallHook },
|
|
70
|
+
{ event: "UserPromptSubmit", kind: "recall", match: isHicortexRecallHook },
|
|
71
|
+
];
|
|
72
|
+
const removed = [];
|
|
73
|
+
for (const g of groups) {
|
|
74
|
+
const arr = hooks[g.event];
|
|
75
|
+
if (!Array.isArray(arr))
|
|
76
|
+
continue;
|
|
77
|
+
const filtered = arr.filter((entry) => {
|
|
78
|
+
if (typeof entry !== "object" || entry === null)
|
|
79
|
+
return true;
|
|
80
|
+
const e = entry;
|
|
81
|
+
if (Array.isArray(e.hooks)) {
|
|
82
|
+
return !e.hooks.some((h) => typeof h === "object" &&
|
|
83
|
+
h !== null &&
|
|
84
|
+
typeof h.command === "string" &&
|
|
85
|
+
g.match(h.command));
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
});
|
|
89
|
+
if (filtered.length < arr.length) {
|
|
90
|
+
// Drop the event key entirely when the filter emptied it — no
|
|
91
|
+
// `"UserPromptSubmit": []` husk left in the settings file.
|
|
92
|
+
if (filtered.length > 0)
|
|
93
|
+
hooks[g.event] = filtered;
|
|
94
|
+
else
|
|
95
|
+
delete hooks[g.event];
|
|
96
|
+
removed.push({ event: g.event, kind: g.kind, count: arr.length - filtered.length });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return removed;
|
|
100
|
+
}
|
|
36
101
|
async function ask(question) {
|
|
37
102
|
const rl = (0, node_readline_1.createInterface)({ input: process.stdin, output: process.stdout });
|
|
38
103
|
return new Promise((resolve) => {
|
|
@@ -146,34 +211,21 @@ async function runUninstall() {
|
|
|
146
211
|
}
|
|
147
212
|
if (removedCmds > 0)
|
|
148
213
|
console.log(` ✓ Removed ${removedCmds} legacy CC command${removedCmds > 1 ? "s" : ""} (/learn, /hicortex-activate)`);
|
|
149
|
-
// 4. Remove
|
|
150
|
-
//
|
|
151
|
-
//
|
|
214
|
+
// 4. Remove ALL Hicortex CC hooks (#327): the SessionStart learnings hook
|
|
215
|
+
// (canonical `learnings-identity` OR the legacy `lessons-context` alias,
|
|
216
|
+
// #264 backcompat) AND BOTH `recall-hook` entries (UserPromptSubmit +
|
|
217
|
+
// SessionStart — installed as a pair by installRecallHooks; leaving
|
|
218
|
+
// either behind keeps a silent npx spawn per prompt forever).
|
|
219
|
+
// Fail-soft when absent; word-boundary matchers never touch foreign hooks.
|
|
152
220
|
try {
|
|
153
221
|
const raw = (0, node_fs_1.readFileSync)(CC_SETTINGS, "utf-8");
|
|
154
222
|
const settings = JSON.parse(raw);
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return true;
|
|
162
|
-
const e = entry;
|
|
163
|
-
if (Array.isArray(e.hooks)) {
|
|
164
|
-
return !e.hooks.some((h) => {
|
|
165
|
-
if (typeof h !== "object" || h === null)
|
|
166
|
-
return false;
|
|
167
|
-
const hook = h;
|
|
168
|
-
return typeof hook.command === "string" && isHicortexSessionStartHook(hook.command);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
return true;
|
|
172
|
-
});
|
|
173
|
-
if (filtered.length < before) {
|
|
174
|
-
hooks.SessionStart = filtered;
|
|
175
|
-
(0, node_fs_1.writeFileSync)(CC_SETTINGS, JSON.stringify(settings, null, 2));
|
|
176
|
-
console.log(" ✓ Removed SessionStart learnings-identity hook");
|
|
223
|
+
const removed = removeHicortexCcHooks(settings);
|
|
224
|
+
if (removed.length > 0) {
|
|
225
|
+
(0, node_fs_1.writeFileSync)(CC_SETTINGS, JSON.stringify(settings, null, 2));
|
|
226
|
+
for (const r of removed) {
|
|
227
|
+
const name = r.kind === "learnings" ? "learnings-identity" : "recall-hook";
|
|
228
|
+
console.log(` ✓ Removed ${r.event} ${name} hook${r.count > 1 ? "s" : ""}`);
|
|
177
229
|
}
|
|
178
230
|
}
|
|
179
231
|
}
|
package/dist/viz.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare const VIZ_VENDOR_FILES: ReadonlySet<string>;
|
|
|
54
54
|
* this — a hosted tenant dir is fail-closed by default. mcp-server.ts captures
|
|
55
55
|
* the marker state once at boot and passes it in (no per-request stat).
|
|
56
56
|
*/
|
|
57
|
-
export declare function createAuthMiddleware(authToken: string | undefined, authTokenPrevious?: string, allowLocalhostBypass?: boolean): express.RequestHandler;
|
|
57
|
+
export declare function createAuthMiddleware(authToken: string | undefined, authTokenPrevious?: string, allowLocalhostBypass?: boolean, bodyLimitBytes?: number): express.RequestHandler;
|
|
58
58
|
/**
|
|
59
59
|
* Resolve the on-disk path of the viz page. Throws (fail explicitly) when the
|
|
60
60
|
* asset is missing — a broken install should surface, not degrade silently.
|
package/dist/viz.js
CHANGED
|
@@ -101,10 +101,37 @@ function safeBearerMatch(headerValue, expectedToken) {
|
|
|
101
101
|
* this — a hosted tenant dir is fail-closed by default. mcp-server.ts captures
|
|
102
102
|
* the marker state once at boot and passes it in (no per-request stat).
|
|
103
103
|
*/
|
|
104
|
-
function createAuthMiddleware(authToken, authTokenPrevious, allowLocalhostBypass) {
|
|
104
|
+
function createAuthMiddleware(authToken, authTokenPrevious, allowLocalhostBypass, bodyLimitBytes) {
|
|
105
105
|
const previous = authTokenPrevious && authTokenPrevious.length > 0 ? authTokenPrevious : undefined;
|
|
106
106
|
const bypassEnabled = allowLocalhostBypass === true;
|
|
107
|
+
const contentLengthCap = Number.isFinite(bodyLimitBytes) && bodyLimitBytes > 0
|
|
108
|
+
? bodyLimitBytes
|
|
109
|
+
: null;
|
|
107
110
|
return (req, res, next) => {
|
|
111
|
+
// #328 item 4 (package-server half) — BELT. The PRIMARY gate is
|
|
112
|
+
// makeContentLengthGate (mcp-server.ts), registered BEFORE express.json:
|
|
113
|
+
// this middleware sits AFTER the parser, so by the time it runs the body
|
|
114
|
+
// has already been buffered (up to the parser's limit) — its Content-Length
|
|
115
|
+
// check can only catch what a caller wires WITHOUT the front gate. Kept
|
|
116
|
+
// for standalone/reuse callers of createAuthMiddleware and as
|
|
117
|
+
// defense-in-depth; 413 mirrors express.json's own oversize status.
|
|
118
|
+
//
|
|
119
|
+
// RESIDUAL RISK (unchanged by either check): chunked transfer-encoding
|
|
120
|
+
// sends no Content-Length, so neither gate sees it — those requests still
|
|
121
|
+
// buffer up to the parser limit inside express.json before the 413
|
|
122
|
+
// (bounded per request, no pre-auth rejection), and there is no
|
|
123
|
+
// concurrency cap here. Full pre-auth bounding lives in the hosted
|
|
124
|
+
// router's webhook path (stripe.ts, #328 item 4) — the tenant data plane
|
|
125
|
+
// trusts its bearer (self-hosted threat model) or sits behind the
|
|
126
|
+
// provider's edge (hosted).
|
|
127
|
+
if (contentLengthCap !== null) {
|
|
128
|
+
const declared = req.headers["content-length"];
|
|
129
|
+
const declaredNum = typeof declared === "string" ? Number(declared) : NaN;
|
|
130
|
+
if (Number.isFinite(declaredNum) && declaredNum > contentLengthCap) {
|
|
131
|
+
res.status(413).json({ error: "request body too large" });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
108
135
|
if (req.path === "/health")
|
|
109
136
|
return next();
|
|
110
137
|
// The /viz page SHELL is public like /health — it contains no data and no
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "hicortex",
|
|
3
3
|
"name": "Hicortex — Long-term Memory That Learns",
|
|
4
4
|
"description": "Your agents remember past decisions, avoid repeated mistakes, and get smarter every day. Nightly reflection generates actionable lessons that automatically update agent behavior.",
|
|
5
|
-
"version": "0.19.
|
|
5
|
+
"version": "0.19.4",
|
|
6
6
|
"kind": "lifecycle",
|
|
7
7
|
"skills": ["./skills/hicortex-memory"],
|
|
8
8
|
"configSchema": {
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
"type": "number",
|
|
26
26
|
"default": 8,
|
|
27
27
|
"description": "Max memories per recall on the pre-0.14 /search fallback (default 8). The pushed recall index is sized by SERVER config (recallMaxItems) — the server accepts no client limit."
|
|
28
|
+
},
|
|
29
|
+
"scaffoldDeadMan": {
|
|
30
|
+
"type": "boolean",
|
|
31
|
+
"default": true,
|
|
32
|
+
"description": "Auto-scaffold the dead-man identity-guard line into the agent workspace bootstrap (BOOTSTRAP.md) at startup — the secondary defense under the identity-unavailable banner the plugin injects when the identity fetch fails. Idempotent: the .bak backup is written once and never touched again. Set false to keep the plugin from writing any bootstrap file."
|
|
28
33
|
}
|
|
29
34
|
},
|
|
30
35
|
"required": []
|
|
@@ -46,6 +51,10 @@
|
|
|
46
51
|
"recallLimit": {
|
|
47
52
|
"label": "Recall Limit",
|
|
48
53
|
"placeholder": "8"
|
|
54
|
+
},
|
|
55
|
+
"scaffoldDeadMan": {
|
|
56
|
+
"label": "Scaffold Dead-Man Guard",
|
|
57
|
+
"placeholder": "true"
|
|
49
58
|
}
|
|
50
59
|
}
|
|
51
60
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gamaze/hicortex",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.4",
|
|
4
4
|
"description": "Persistent agent identity for AI agents \u2014 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": {
|