crbro-memory 2.10.0 → 2.11.0

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 (205) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +256 -465
  3. package/SECURITY.md +114 -12
  4. package/bin/crbro.mjs +539 -300
  5. package/dist/build-id.json +10 -0
  6. package/dist/cli/common.js +211 -0
  7. package/dist/cli/export.js +522 -0
  8. package/dist/cli/import.js +683 -0
  9. package/dist/cli/markdown.js +313 -0
  10. package/dist/cli/mcpclient.js +107 -0
  11. package/dist/cli/serve.js +453 -0
  12. package/dist/cli/view.js +358 -0
  13. package/dist/cli/viewer-page.js +378 -0
  14. package/dist/daemon/daemon.js +119 -11
  15. package/dist/daemon/endpoint.js +222 -21
  16. package/dist/daemon/lines.js +102 -13
  17. package/dist/daemon/proxy.js +480 -125
  18. package/dist/daemon/surface.js +116 -0
  19. package/dist/daemon/trace.js +73 -0
  20. package/dist/engine/atrest.js +132 -0
  21. package/dist/engine/backup.js +139 -19
  22. package/dist/engine/brain.js +22 -6
  23. package/dist/engine/codexconfig.js +476 -0
  24. package/dist/engine/cortex.js +667 -232
  25. package/dist/engine/doctor.js +312 -14
  26. package/dist/engine/heat.js +81 -37
  27. package/dist/engine/hippocampus.js +18 -7
  28. package/dist/engine/hookrefresh.js +296 -0
  29. package/dist/engine/hookverify.js +15 -3
  30. package/dist/engine/installer.js +1022 -0
  31. package/dist/engine/installio.js +279 -0
  32. package/dist/engine/keychain.js +721 -162
  33. package/dist/engine/maintenance.js +355 -87
  34. package/dist/engine/modinstall.js +98 -45
  35. package/dist/engine/prefrontal.js +29 -6
  36. package/dist/engine/quarantine.js +204 -0
  37. package/dist/engine/secrets.js +41 -5
  38. package/dist/engine/shelf.js +25 -3
  39. package/dist/engine/synapses.js +183 -80
  40. package/dist/engine/triggers.js +141 -11
  41. package/dist/index.js +37 -3
  42. package/dist/mcp-surface.json +1 -0
  43. package/dist/miner/extractor.js +64 -17
  44. package/dist/miner/scheduler.js +144 -68
  45. package/dist/search/index.js +797 -176
  46. package/dist/search/semantic.js +208 -18
  47. package/dist/search/tokenize.js +44 -0
  48. package/dist/server.js +583 -373
  49. package/dist/sync/git.js +203 -72
  50. package/dist/sync/space.js +100 -25
  51. package/dist/sync/validate.js +204 -0
  52. package/dist/utils/budget.js +15 -2
  53. package/dist/utils/fs.js +40 -6
  54. package/dist/utils/ids.js +128 -14
  55. package/dist/utils/lock.js +94 -7
  56. package/hooks/crbro-codex.mjs +284 -0
  57. package/hooks/crbro-guard.mjs +281 -173
  58. package/hooks/crbro-hooks.shipped.json +20 -0
  59. package/hooks/crbro-lifecycle.mjs +16 -4
  60. package/hooks/crbro-subagent.mjs +180 -180
  61. package/package.json +9 -5
  62. package/dist/daemon/daemon.d.ts +0 -25
  63. package/dist/daemon/daemon.d.ts.map +0 -1
  64. package/dist/daemon/daemon.js.map +0 -1
  65. package/dist/daemon/endpoint.d.ts +0 -66
  66. package/dist/daemon/endpoint.d.ts.map +0 -1
  67. package/dist/daemon/endpoint.js.map +0 -1
  68. package/dist/daemon/lines.d.ts +0 -55
  69. package/dist/daemon/lines.d.ts.map +0 -1
  70. package/dist/daemon/lines.js.map +0 -1
  71. package/dist/daemon/proxy.d.ts +0 -55
  72. package/dist/daemon/proxy.d.ts.map +0 -1
  73. package/dist/daemon/proxy.js.map +0 -1
  74. package/dist/engine/backup.d.ts +0 -68
  75. package/dist/engine/backup.d.ts.map +0 -1
  76. package/dist/engine/backup.js.map +0 -1
  77. package/dist/engine/brain.d.ts +0 -79
  78. package/dist/engine/brain.d.ts.map +0 -1
  79. package/dist/engine/brain.js.map +0 -1
  80. package/dist/engine/cortex.d.ts +0 -682
  81. package/dist/engine/cortex.d.ts.map +0 -1
  82. package/dist/engine/cortex.js.map +0 -1
  83. package/dist/engine/dates.d.ts +0 -28
  84. package/dist/engine/dates.d.ts.map +0 -1
  85. package/dist/engine/dates.js.map +0 -1
  86. package/dist/engine/doctor.d.ts +0 -93
  87. package/dist/engine/doctor.d.ts.map +0 -1
  88. package/dist/engine/doctor.js.map +0 -1
  89. package/dist/engine/evidence.d.ts +0 -26
  90. package/dist/engine/evidence.d.ts.map +0 -1
  91. package/dist/engine/evidence.js.map +0 -1
  92. package/dist/engine/heat.d.ts +0 -28
  93. package/dist/engine/heat.d.ts.map +0 -1
  94. package/dist/engine/heat.js.map +0 -1
  95. package/dist/engine/hippocampus.d.ts +0 -60
  96. package/dist/engine/hippocampus.d.ts.map +0 -1
  97. package/dist/engine/hippocampus.js.map +0 -1
  98. package/dist/engine/hookverify.d.ts +0 -42
  99. package/dist/engine/hookverify.d.ts.map +0 -1
  100. package/dist/engine/hookverify.js.map +0 -1
  101. package/dist/engine/keychain.d.ts +0 -32
  102. package/dist/engine/keychain.d.ts.map +0 -1
  103. package/dist/engine/keychain.js.map +0 -1
  104. package/dist/engine/maintenance.d.ts +0 -218
  105. package/dist/engine/maintenance.d.ts.map +0 -1
  106. package/dist/engine/maintenance.js.map +0 -1
  107. package/dist/engine/modinstall.d.ts +0 -215
  108. package/dist/engine/modinstall.d.ts.map +0 -1
  109. package/dist/engine/modinstall.js.map +0 -1
  110. package/dist/engine/postmortem.d.ts +0 -81
  111. package/dist/engine/postmortem.d.ts.map +0 -1
  112. package/dist/engine/postmortem.js.map +0 -1
  113. package/dist/engine/prefrontal.d.ts +0 -64
  114. package/dist/engine/prefrontal.d.ts.map +0 -1
  115. package/dist/engine/prefrontal.js.map +0 -1
  116. package/dist/engine/projects.d.ts +0 -20
  117. package/dist/engine/projects.d.ts.map +0 -1
  118. package/dist/engine/projects.js.map +0 -1
  119. package/dist/engine/secrets.d.ts +0 -30
  120. package/dist/engine/secrets.d.ts.map +0 -1
  121. package/dist/engine/secrets.js.map +0 -1
  122. package/dist/engine/shelf.d.ts +0 -155
  123. package/dist/engine/shelf.d.ts.map +0 -1
  124. package/dist/engine/shelf.js.map +0 -1
  125. package/dist/engine/source.d.ts +0 -6
  126. package/dist/engine/source.d.ts.map +0 -1
  127. package/dist/engine/source.js.map +0 -1
  128. package/dist/engine/synapses.d.ts +0 -82
  129. package/dist/engine/synapses.d.ts.map +0 -1
  130. package/dist/engine/synapses.js.map +0 -1
  131. package/dist/engine/triggers.d.ts +0 -53
  132. package/dist/engine/triggers.d.ts.map +0 -1
  133. package/dist/engine/triggers.js.map +0 -1
  134. package/dist/engine/usage.d.ts +0 -61
  135. package/dist/engine/usage.d.ts.map +0 -1
  136. package/dist/engine/usage.js.map +0 -1
  137. package/dist/index.d.ts +0 -2
  138. package/dist/index.d.ts.map +0 -1
  139. package/dist/index.js.map +0 -1
  140. package/dist/miner/extractor.d.ts +0 -12
  141. package/dist/miner/extractor.d.ts.map +0 -1
  142. package/dist/miner/extractor.js.map +0 -1
  143. package/dist/miner/index.d.ts +0 -61
  144. package/dist/miner/index.d.ts.map +0 -1
  145. package/dist/miner/index.js.map +0 -1
  146. package/dist/miner/scheduler.d.ts +0 -30
  147. package/dist/miner/scheduler.d.ts.map +0 -1
  148. package/dist/miner/scheduler.js.map +0 -1
  149. package/dist/miner/types.d.ts +0 -11
  150. package/dist/miner/types.d.ts.map +0 -1
  151. package/dist/miner/types.js.map +0 -1
  152. package/dist/search/index.d.ts +0 -328
  153. package/dist/search/index.d.ts.map +0 -1
  154. package/dist/search/index.js.map +0 -1
  155. package/dist/search/quality.d.ts +0 -18
  156. package/dist/search/quality.d.ts.map +0 -1
  157. package/dist/search/quality.js.map +0 -1
  158. package/dist/search/semantic.d.ts +0 -80
  159. package/dist/search/semantic.d.ts.map +0 -1
  160. package/dist/search/semantic.js.map +0 -1
  161. package/dist/search/synonyms.d.ts +0 -2
  162. package/dist/search/synonyms.d.ts.map +0 -1
  163. package/dist/search/synonyms.js.map +0 -1
  164. package/dist/search/tokenize.d.ts +0 -39
  165. package/dist/search/tokenize.d.ts.map +0 -1
  166. package/dist/search/tokenize.js.map +0 -1
  167. package/dist/server.d.ts +0 -41
  168. package/dist/server.d.ts.map +0 -1
  169. package/dist/server.js.map +0 -1
  170. package/dist/sync/git.d.ts +0 -36
  171. package/dist/sync/git.d.ts.map +0 -1
  172. package/dist/sync/git.js.map +0 -1
  173. package/dist/sync/materialize.d.ts +0 -36
  174. package/dist/sync/materialize.d.ts.map +0 -1
  175. package/dist/sync/materialize.js.map +0 -1
  176. package/dist/sync/ops.d.ts +0 -147
  177. package/dist/sync/ops.d.ts.map +0 -1
  178. package/dist/sync/ops.js.map +0 -1
  179. package/dist/sync/space.d.ts +0 -118
  180. package/dist/sync/space.d.ts.map +0 -1
  181. package/dist/sync/space.js.map +0 -1
  182. package/dist/types/index.d.ts +0 -369
  183. package/dist/types/index.d.ts.map +0 -1
  184. package/dist/types/index.js.map +0 -1
  185. package/dist/utils/budget.d.ts +0 -44
  186. package/dist/utils/budget.d.ts.map +0 -1
  187. package/dist/utils/budget.js.map +0 -1
  188. package/dist/utils/fs.d.ts +0 -59
  189. package/dist/utils/fs.d.ts.map +0 -1
  190. package/dist/utils/fs.js.map +0 -1
  191. package/dist/utils/hash.d.ts +0 -20
  192. package/dist/utils/hash.d.ts.map +0 -1
  193. package/dist/utils/hash.js.map +0 -1
  194. package/dist/utils/ids.d.ts +0 -47
  195. package/dist/utils/ids.d.ts.map +0 -1
  196. package/dist/utils/ids.js.map +0 -1
  197. package/dist/utils/lock.d.ts +0 -13
  198. package/dist/utils/lock.d.ts.map +0 -1
  199. package/dist/utils/lock.js.map +0 -1
  200. package/dist/utils/transcripts.d.ts +0 -63
  201. package/dist/utils/transcripts.d.ts.map +0 -1
  202. package/dist/utils/transcripts.js.map +0 -1
  203. package/dist/version.d.ts +0 -26
  204. package/dist/version.d.ts.map +0 -1
  205. package/dist/version.js.map +0 -1
@@ -0,0 +1,10 @@
1
+ {
2
+ "build": "2.11.0-facd12b9308f70d1",
3
+ "version": "2.11.0",
4
+ "hash": "facd12b9308f70d1d1a73893100f10af8aa28c0a8f26f486a3ac7a23afb8a9e3",
5
+ "files": 65,
6
+ "check": {
7
+ "file": "server.js",
8
+ "sha256": "c05fd945b738c1f2c91059251c12ba24f443a2b583b62068f5d4170d028d4d36"
9
+ }
10
+ }
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ // ─── Shared pieces of the export / import / view / serve commands ──
3
+ //
4
+ // Small on purpose: argument parsing, path containment, tokens and the two
5
+ // checks every local HTTP listener of this package makes (Host header and
6
+ // bearer token). Nothing here reads or writes the brain.
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.BASE_SECURITY_HEADERS = void 0;
12
+ exports.parseArgs = parseArgs;
13
+ exports.realpathNearest = realpathNearest;
14
+ exports.isInside = isInside;
15
+ exports.safeFileName = safeFileName;
16
+ exports.randomToken = randomToken;
17
+ exports.tokenMatches = tokenMatches;
18
+ exports.bearerOf = bearerOf;
19
+ exports.isLoopbackHost = isLoopbackHost;
20
+ exports.loopbackHosts = loopbackHosts;
21
+ exports.hostAllowed = hostAllowed;
22
+ exports.waitForStop = waitForStop;
23
+ exports.openBrowser = openBrowser;
24
+ const node_path_1 = __importDefault(require("node:path"));
25
+ const node_fs_1 = require("node:fs");
26
+ const node_crypto_1 = require("node:crypto");
27
+ const node_child_process_1 = require("node:child_process");
28
+ /**
29
+ * `--name value`, `--name=value` and bare `--flag`. Unknown flags are an
30
+ * error, never ignored: a typo in `--include-retired` must not export less
31
+ * than the user asked for and say nothing.
32
+ */
33
+ function parseArgs(argv, spec) {
34
+ const flags = {};
35
+ const positionals = [];
36
+ const errors = [];
37
+ for (let i = 0; i < argv.length; i++) {
38
+ const a = argv[i];
39
+ if (a === '-h') {
40
+ flags['help'] = true;
41
+ continue;
42
+ }
43
+ if (!a.startsWith('--')) {
44
+ positionals.push(a);
45
+ continue;
46
+ }
47
+ const eq = a.indexOf('=');
48
+ const name = eq === -1 ? a.slice(2) : a.slice(2, eq);
49
+ const kind = spec[name] ?? (name === 'help' ? 'boolean' : undefined);
50
+ if (!kind) {
51
+ errors.push(`unknown option --${name}`);
52
+ continue;
53
+ }
54
+ if (kind === 'boolean') {
55
+ if (eq !== -1)
56
+ errors.push(`--${name} takes no value`);
57
+ flags[name] = true;
58
+ continue;
59
+ }
60
+ let value = eq === -1 ? argv[i + 1] : a.slice(eq + 1);
61
+ if (eq === -1) {
62
+ if (value === undefined || value.startsWith('--')) {
63
+ errors.push(`--${name} needs a value`);
64
+ continue;
65
+ }
66
+ i++;
67
+ }
68
+ if (kind === 'number') {
69
+ const n = Number(value);
70
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(n)) {
71
+ errors.push(`--${name} must be a whole number`);
72
+ continue;
73
+ }
74
+ flags[name] = n;
75
+ }
76
+ else if (kind === 'list') {
77
+ const list = flags[name] ?? [];
78
+ list.push(value);
79
+ flags[name] = list;
80
+ }
81
+ else {
82
+ flags[name] = value;
83
+ }
84
+ }
85
+ return { flags, positionals, errors };
86
+ }
87
+ // ─── Paths ───────────────────────────────────────────────────────
88
+ /** The real path of `p`, or of its nearest existing ancestor plus the rest. Follows links and junctions. */
89
+ async function realpathNearest(p) {
90
+ let current = node_path_1.default.resolve(p);
91
+ const rest = [];
92
+ for (;;) {
93
+ try {
94
+ const real = await node_fs_1.promises.realpath(current);
95
+ return rest.length ? node_path_1.default.join(real, ...rest.reverse()) : real;
96
+ }
97
+ catch {
98
+ const parent = node_path_1.default.dirname(current);
99
+ if (parent === current)
100
+ return node_path_1.default.resolve(p);
101
+ rest.push(node_path_1.default.basename(current));
102
+ current = parent;
103
+ }
104
+ }
105
+ }
106
+ /** Is `child` the same folder as `parent`, or inside it? Case-insensitive where the file system is. */
107
+ function isInside(child, parent) {
108
+ const norm = (s) => (process.platform === 'win32' || process.platform === 'darwin' ? s.toLowerCase() : s);
109
+ const rel = node_path_1.default.relative(norm(node_path_1.default.resolve(parent)), norm(node_path_1.default.resolve(child)));
110
+ return rel === '' || (!rel.startsWith('..') && !node_path_1.default.isAbsolute(rel));
111
+ }
112
+ /**
113
+ * A file name from free text (a domain, a neuron id): letters, digits, dot,
114
+ * dash and underscore only, never `.`/`..`, never empty, at most 120 chars.
115
+ * Everything a note is called goes through here, so no part of the brain can
116
+ * steer a write outside the export folder.
117
+ */
118
+ function safeFileName(raw, fallback = 'untitled') {
119
+ let s = String(raw ?? '').normalize('NFKD').replace(/[̀-ͯ]/g, '')
120
+ .replace(/[^A-Za-z0-9._-]+/g, '_').replace(/_+/g, '_').replace(/^[._]+/, '').slice(0, 120);
121
+ s = s.replace(/[. ]+$/, '');
122
+ if (!s || s === '.' || s === '..')
123
+ s = fallback;
124
+ // Windows reserved device names are not valid file names on any drive.
125
+ if (/^(con|prn|aux|nul|com\d|lpt\d)(\..*)?$/i.test(s))
126
+ s = `_${s}`;
127
+ return s;
128
+ }
129
+ // ─── Tokens and HTTP guards ──────────────────────────────────────
130
+ /** 32 random bytes, hex: no character a shell, a URL or a header has to escape. */
131
+ function randomToken() {
132
+ return (0, node_crypto_1.randomBytes)(32).toString('hex');
133
+ }
134
+ /**
135
+ * Constant-time comparison of a presented secret with the expected one.
136
+ * Both sides are hashed first so the lengths always match and the time does
137
+ * not depend on how many leading characters were right.
138
+ */
139
+ function tokenMatches(presented, expected) {
140
+ if (typeof presented !== 'string' || presented.length === 0 || presented.length > 4096)
141
+ return false;
142
+ const a = (0, node_crypto_1.createHash)('sha256').update(presented, 'utf8').digest();
143
+ const b = (0, node_crypto_1.createHash)('sha256').update(expected, 'utf8').digest();
144
+ return (0, node_crypto_1.timingSafeEqual)(a, b);
145
+ }
146
+ /** The bearer value of an Authorization header, or null. */
147
+ function bearerOf(header) {
148
+ if (typeof header !== 'string')
149
+ return null;
150
+ const m = /^Bearer[ ]+([^\s]+)\s*$/i.exec(header);
151
+ return m ? m[1] : null;
152
+ }
153
+ function isLoopbackHost(host) {
154
+ const h = host.trim().toLowerCase().replace(/^\[|\]$/g, '');
155
+ return h === 'localhost' || h === '::1' || /^127(\.\d{1,3}){3}$/.test(h);
156
+ }
157
+ /** The Host header values a loopback listener on `port` accepts. Anything else is a DNS-rebinding attempt or a mistake. */
158
+ function loopbackHosts(port) {
159
+ return [`127.0.0.1:${port}`, `localhost:${port}`, `[::1]:${port}`];
160
+ }
161
+ function hostAllowed(hostHeader, allowed) {
162
+ if (typeof hostHeader !== 'string' || !hostHeader)
163
+ return false;
164
+ const h = hostHeader.trim().toLowerCase();
165
+ for (const a of allowed)
166
+ if (a.toLowerCase() === h)
167
+ return true;
168
+ return false;
169
+ }
170
+ /** Headers every response of ours carries: nothing cached, nothing sniffed, nothing framed, no referrer. */
171
+ exports.BASE_SECURITY_HEADERS = {
172
+ 'X-Content-Type-Options': 'nosniff',
173
+ 'Cache-Control': 'no-store',
174
+ 'Referrer-Policy': 'no-referrer',
175
+ 'X-Frame-Options': 'DENY',
176
+ 'Cross-Origin-Resource-Policy': 'same-origin',
177
+ };
178
+ // ─── Lifetime ────────────────────────────────────────────────────
179
+ /** Resolve on Ctrl+C, SIGTERM or the abort signal, then forget the handlers. */
180
+ function waitForStop(signal) {
181
+ return new Promise(resolve => {
182
+ const stop = () => {
183
+ process.off('SIGINT', stop);
184
+ process.off('SIGTERM', stop);
185
+ signal?.removeEventListener('abort', stop);
186
+ resolve();
187
+ };
188
+ process.on('SIGINT', stop);
189
+ process.on('SIGTERM', stop);
190
+ if (signal?.aborted)
191
+ stop();
192
+ else
193
+ signal?.addEventListener('abort', stop);
194
+ });
195
+ }
196
+ // ─── Browser ─────────────────────────────────────────────────────
197
+ /** Open a URL in the default browser. Best effort: the URL is printed anyway. */
198
+ function openBrowser(url) {
199
+ try {
200
+ const opts = { detached: true, stdio: 'ignore', windowsHide: true };
201
+ const child = process.platform === 'win32'
202
+ ? (0, node_child_process_1.spawn)('rundll32', ['url.dll,FileProtocolHandler', url], opts)
203
+ : process.platform === 'darwin'
204
+ ? (0, node_child_process_1.spawn)('open', [url], opts)
205
+ : (0, node_child_process_1.spawn)('xdg-open', [url], opts);
206
+ child.on('error', () => undefined);
207
+ child.unref();
208
+ }
209
+ catch { /* printed URL is the fallback */ }
210
+ }
211
+ //# sourceMappingURL=common.js.map