nexus-agents 2.77.13 → 2.79.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 (132) hide show
  1. package/dist/{child-mcp-config-MJMUF7TL.js → child-mcp-config-CTO2MBRM.js} +3 -4
  2. package/dist/{child-mcp-config-MJMUF7TL.js.map → child-mcp-config-CTO2MBRM.js.map} +1 -1
  3. package/dist/{chunk-YJ2IGAD2.js → chunk-2UYTFLMO.js} +2 -2
  4. package/dist/{chunk-6AY5DK4E.js → chunk-2YPG6PDG.js} +3 -3
  5. package/dist/{chunk-3VWMM6UF.js → chunk-3NIPH6UP.js} +2 -2
  6. package/dist/{chunk-GFKGL2GQ.js → chunk-3ULMVOIF.js} +171 -83
  7. package/dist/chunk-3ULMVOIF.js.map +1 -0
  8. package/dist/{chunk-JN6UWGHH.js → chunk-5O6XLBPP.js} +2 -2
  9. package/dist/{chunk-ERWXGXV2.js → chunk-6TFTVW77.js} +3 -3
  10. package/dist/{chunk-GOT7OAL5.js → chunk-7BMOZJYS.js} +29 -5
  11. package/dist/chunk-7BMOZJYS.js.map +1 -0
  12. package/dist/{chunk-C2LLQ6TW.js → chunk-7XCUZI4G.js} +4 -4
  13. package/dist/chunk-7XCUZI4G.js.map +1 -0
  14. package/dist/{chunk-TDV5ALHY.js → chunk-D6TM2VHX.js} +3 -3
  15. package/dist/{chunk-PWTJGGKB.js → chunk-DLXT23AC.js} +2 -2
  16. package/dist/chunk-DNO2INX5.js +276 -0
  17. package/dist/chunk-DNO2INX5.js.map +1 -0
  18. package/dist/{chunk-G2CSKBY5.js → chunk-FJWWSVWB.js} +29 -6
  19. package/dist/chunk-FJWWSVWB.js.map +1 -0
  20. package/dist/{chunk-DSQ5XM4O.js → chunk-FVPYP5DD.js} +4 -4
  21. package/dist/{chunk-MGLWPN2I.js → chunk-GONMG4NM.js} +2 -2
  22. package/dist/{chunk-YQMQSJQK.js → chunk-HYU4GZY6.js} +2 -2
  23. package/dist/{chunk-3DH5SLFH.js → chunk-K2QILJG4.js} +6 -6
  24. package/dist/{chunk-5WHWKY32.js → chunk-KT5FIBWS.js} +2 -2
  25. package/dist/{chunk-DIB6V67T.js → chunk-L6SCKLGO.js} +3 -3
  26. package/dist/{chunk-IPWCD22D.js → chunk-PLX6FCFC.js} +2 -2
  27. package/dist/chunk-PQHVC4BD.js +639 -0
  28. package/dist/chunk-PQHVC4BD.js.map +1 -0
  29. package/dist/chunk-Q5CFPIJ5.js +5581 -0
  30. package/dist/chunk-Q5CFPIJ5.js.map +1 -0
  31. package/dist/{chunk-G6ZPVADX.js → chunk-SD76JZBG.js} +2 -2
  32. package/dist/{chunk-Y2CP4Z5B.js → chunk-SWFJU3W2.js} +220 -4580
  33. package/dist/chunk-SWFJU3W2.js.map +1 -0
  34. package/dist/{chunk-3MRM53T4.js → chunk-WDYCIJWN.js} +640 -470
  35. package/dist/chunk-WDYCIJWN.js.map +1 -0
  36. package/dist/{chunk-RBZ4CDMY.js → chunk-YMMYYAZT.js} +5 -5
  37. package/dist/{chunk-CM3TORGV.js → chunk-YXWGEIQR.js} +2 -2
  38. package/dist/{chunk-JX6OI4FS.js → chunk-ZI6G7U7Y.js} +125 -33
  39. package/dist/chunk-ZI6G7U7Y.js.map +1 -0
  40. package/dist/{chunk-7NK7BTWP.js → chunk-ZVCED4Z4.js} +2 -2
  41. package/dist/cli-circuit-breaker-I74ZQ44Q.js +13 -0
  42. package/dist/cli.js +109 -58
  43. package/dist/cli.js.map +1 -1
  44. package/dist/{composite-router-S6E26BCI.js → composite-router-V3OC57IE.js} +3 -4
  45. package/dist/consensus-vote-ESFPGEJE.js +30 -0
  46. package/dist/context-retriever-MB3D7KS6.js +18 -0
  47. package/dist/dist-NIXVXYIH.js +42 -0
  48. package/dist/doctor-deep-KQ765XZA.js +12 -0
  49. package/dist/expert-bridge-JKLC57IC.js +10 -0
  50. package/dist/factory-BUUXNGIB.js +14 -0
  51. package/dist/{factory-X3VKIGKP.js → factory-LHHYDVZX.js} +5 -6
  52. package/dist/index.d.ts +72 -8
  53. package/dist/index.js +208 -316
  54. package/dist/index.js.map +1 -1
  55. package/dist/{init-opencode-CFE7M6XA.js → init-opencode-GXZN2W5S.js} +6 -7
  56. package/dist/{init-opencode-CFE7M6XA.js.map → init-opencode-GXZN2W5S.js.map} +1 -1
  57. package/dist/issue-triage-RMXPDZ2K.js +15 -0
  58. package/dist/{learning-persistence-N6ILD2HX.js → learning-persistence-Q3HTOGTU.js} +2 -3
  59. package/dist/outcome-store-adapter-QRFJJIKB.js +57 -0
  60. package/dist/outcome-store-adapter-QRFJJIKB.js.map +1 -0
  61. package/dist/{registry-command-RPPC7N2K.js → registry-command-6E4YKAMT.js} +3 -4
  62. package/dist/{registry-command-RPPC7N2K.js.map → registry-command-6E4YKAMT.js.map} +1 -1
  63. package/dist/{repo-security-plan-7ZCDVH5O.js → repo-security-plan-AGRU72DL.js} +4 -5
  64. package/dist/research-helpers-synthesize-K2UCJQQG.js +13 -0
  65. package/dist/{routing-memory-5VTX7LQX.js → routing-memory-3B6DDZ76.js} +3 -4
  66. package/dist/{session-memory-7XBV6BMY.js → session-memory-L7EQIY2O.js} +4 -5
  67. package/dist/{setup-command-W6UKPODL.js → setup-command-R4BOEMLZ.js} +11 -12
  68. package/dist/setup-config-EQT24DD4.js +10 -0
  69. package/dist/{setup-custom-api-WM5W5AY5.js → setup-custom-api-IBDV654K.js} +5 -6
  70. package/dist/{setup-custom-api-WM5W5AY5.js.map → setup-custom-api-IBDV654K.js.map} +1 -1
  71. package/dist/tool-memory-6HCHQLAN.js +19 -0
  72. package/dist/{weather-report-YJMVKJGA.js → weather-report-ER3WUZ7S.js} +3 -4
  73. package/package.json +3 -2
  74. package/dist/adaptive-memory-EI564K4C.js +0 -16
  75. package/dist/chunk-3MRM53T4.js.map +0 -1
  76. package/dist/chunk-BJ2OMC7P.js +0 -944
  77. package/dist/chunk-BJ2OMC7P.js.map +0 -1
  78. package/dist/chunk-C2LLQ6TW.js.map +0 -1
  79. package/dist/chunk-G2CSKBY5.js.map +0 -1
  80. package/dist/chunk-GFKGL2GQ.js.map +0 -1
  81. package/dist/chunk-GOT7OAL5.js.map +0 -1
  82. package/dist/chunk-I7ORMAO7.js +0 -32
  83. package/dist/chunk-I7ORMAO7.js.map +0 -1
  84. package/dist/chunk-JX6OI4FS.js.map +0 -1
  85. package/dist/chunk-Y2CP4Z5B.js.map +0 -1
  86. package/dist/cli-circuit-breaker-YX4BWZD5.js +0 -14
  87. package/dist/consensus-vote-MUQ4HPIF.js +0 -30
  88. package/dist/doctor-deep-BRU5ZUJI.js +0 -13
  89. package/dist/expert-bridge-ZPNVLJVN.js +0 -11
  90. package/dist/factory-A7DTCCUY.js +0 -15
  91. package/dist/issue-triage-6XD6CVPB.js +0 -16
  92. package/dist/mobimem-CG2MNS7V.js +0 -14
  93. package/dist/nexus-data-dir-77UO7N6J.js +0 -12
  94. package/dist/research-helpers-synthesize-36TUTUUA.js +0 -14
  95. package/dist/setup-config-EI5KROA3.js +0 -11
  96. /package/dist/{chunk-YJ2IGAD2.js.map → chunk-2UYTFLMO.js.map} +0 -0
  97. /package/dist/{chunk-6AY5DK4E.js.map → chunk-2YPG6PDG.js.map} +0 -0
  98. /package/dist/{chunk-3VWMM6UF.js.map → chunk-3NIPH6UP.js.map} +0 -0
  99. /package/dist/{chunk-JN6UWGHH.js.map → chunk-5O6XLBPP.js.map} +0 -0
  100. /package/dist/{chunk-ERWXGXV2.js.map → chunk-6TFTVW77.js.map} +0 -0
  101. /package/dist/{chunk-TDV5ALHY.js.map → chunk-D6TM2VHX.js.map} +0 -0
  102. /package/dist/{chunk-PWTJGGKB.js.map → chunk-DLXT23AC.js.map} +0 -0
  103. /package/dist/{chunk-DSQ5XM4O.js.map → chunk-FVPYP5DD.js.map} +0 -0
  104. /package/dist/{chunk-MGLWPN2I.js.map → chunk-GONMG4NM.js.map} +0 -0
  105. /package/dist/{chunk-YQMQSJQK.js.map → chunk-HYU4GZY6.js.map} +0 -0
  106. /package/dist/{chunk-3DH5SLFH.js.map → chunk-K2QILJG4.js.map} +0 -0
  107. /package/dist/{chunk-5WHWKY32.js.map → chunk-KT5FIBWS.js.map} +0 -0
  108. /package/dist/{chunk-DIB6V67T.js.map → chunk-L6SCKLGO.js.map} +0 -0
  109. /package/dist/{chunk-IPWCD22D.js.map → chunk-PLX6FCFC.js.map} +0 -0
  110. /package/dist/{chunk-G6ZPVADX.js.map → chunk-SD76JZBG.js.map} +0 -0
  111. /package/dist/{chunk-RBZ4CDMY.js.map → chunk-YMMYYAZT.js.map} +0 -0
  112. /package/dist/{chunk-CM3TORGV.js.map → chunk-YXWGEIQR.js.map} +0 -0
  113. /package/dist/{chunk-7NK7BTWP.js.map → chunk-ZVCED4Z4.js.map} +0 -0
  114. /package/dist/{adaptive-memory-EI564K4C.js.map → cli-circuit-breaker-I74ZQ44Q.js.map} +0 -0
  115. /package/dist/{cli-circuit-breaker-YX4BWZD5.js.map → composite-router-V3OC57IE.js.map} +0 -0
  116. /package/dist/{composite-router-S6E26BCI.js.map → consensus-vote-ESFPGEJE.js.map} +0 -0
  117. /package/dist/{consensus-vote-MUQ4HPIF.js.map → context-retriever-MB3D7KS6.js.map} +0 -0
  118. /package/dist/{doctor-deep-BRU5ZUJI.js.map → dist-NIXVXYIH.js.map} +0 -0
  119. /package/dist/{expert-bridge-ZPNVLJVN.js.map → doctor-deep-KQ765XZA.js.map} +0 -0
  120. /package/dist/{factory-A7DTCCUY.js.map → expert-bridge-JKLC57IC.js.map} +0 -0
  121. /package/dist/{factory-X3VKIGKP.js.map → factory-BUUXNGIB.js.map} +0 -0
  122. /package/dist/{issue-triage-6XD6CVPB.js.map → factory-LHHYDVZX.js.map} +0 -0
  123. /package/dist/{learning-persistence-N6ILD2HX.js.map → issue-triage-RMXPDZ2K.js.map} +0 -0
  124. /package/dist/{mobimem-CG2MNS7V.js.map → learning-persistence-Q3HTOGTU.js.map} +0 -0
  125. /package/dist/{nexus-data-dir-77UO7N6J.js.map → repo-security-plan-AGRU72DL.js.map} +0 -0
  126. /package/dist/{repo-security-plan-7ZCDVH5O.js.map → research-helpers-synthesize-K2UCJQQG.js.map} +0 -0
  127. /package/dist/{research-helpers-synthesize-36TUTUUA.js.map → routing-memory-3B6DDZ76.js.map} +0 -0
  128. /package/dist/{routing-memory-5VTX7LQX.js.map → session-memory-L7EQIY2O.js.map} +0 -0
  129. /package/dist/{session-memory-7XBV6BMY.js.map → setup-command-R4BOEMLZ.js.map} +0 -0
  130. /package/dist/{setup-command-W6UKPODL.js.map → setup-config-EQT24DD4.js.map} +0 -0
  131. /package/dist/{setup-config-EI5KROA3.js.map → tool-memory-6HCHQLAN.js.map} +0 -0
  132. /package/dist/{weather-report-YJMVKJGA.js.map → weather-report-ER3WUZ7S.js.map} +0 -0
@@ -0,0 +1,639 @@
1
+ // ../nexus-memory/dist/index.js
2
+ import Database from "better-sqlite3";
3
+ import Database2 from "better-sqlite3";
4
+ import { existsSync, mkdirSync, renameSync, writeFileSync } from "fs";
5
+ import { dirname, join } from "path";
6
+ var KEY_SUMMARY_LIMIT = 120;
7
+ var PAYLOAD_SUMMARY_LIMIT = 240;
8
+ var counters = /* @__PURE__ */ new Map();
9
+ var listeners = /* @__PURE__ */ new Set();
10
+ function isAuditMode() {
11
+ return process.env["NEXUS_MEMORY_AUDIT_MODE"] === "audit";
12
+ }
13
+ function counterKey(domain, op) {
14
+ return `${domain}::${op}`;
15
+ }
16
+ function truncate(value, limit) {
17
+ let s;
18
+ if (typeof value === "string") {
19
+ s = value;
20
+ } else if (value === void 0) {
21
+ s = "<undefined>";
22
+ } else if (value === null) {
23
+ s = "<null>";
24
+ } else {
25
+ try {
26
+ s = JSON.stringify(value);
27
+ } catch {
28
+ s = "<unserializable>";
29
+ }
30
+ }
31
+ return s.length > limit ? `${s.slice(0, limit - 1)}\u2026` : s;
32
+ }
33
+ function updateCounter(event) {
34
+ const ck = counterKey(event.domain, event.op);
35
+ const existing = counters.get(ck);
36
+ const hitDelta = event.hit === true ? 1 : 0;
37
+ counters.set(ck, {
38
+ domain: event.domain,
39
+ op: event.op,
40
+ count: (existing?.count ?? 0) + 1,
41
+ hitCount: (existing?.hitCount ?? 0) + hitDelta,
42
+ totalDurationMs: (existing?.totalDurationMs ?? 0) + event.durationMs,
43
+ maxDurationMs: Math.max(existing?.maxDurationMs ?? 0, event.durationMs)
44
+ });
45
+ }
46
+ function buildPublicEvent(event, audit) {
47
+ return {
48
+ domain: event.domain,
49
+ op: event.op,
50
+ durationMs: event.durationMs,
51
+ ...event.cli !== void 0 && { cli: event.cli },
52
+ ...event.hit !== void 0 && { hit: event.hit },
53
+ ...audit && event.key !== void 0 && {
54
+ keySummary: truncate(event.key, KEY_SUMMARY_LIMIT)
55
+ },
56
+ ...audit && event.payload !== void 0 && {
57
+ payloadSummary: truncate(event.payload, PAYLOAD_SUMMARY_LIMIT)
58
+ },
59
+ ...audit && event.result !== void 0 && {
60
+ resultSummary: truncate(event.result, PAYLOAD_SUMMARY_LIMIT)
61
+ }
62
+ };
63
+ }
64
+ function recordMemoryEvent(event) {
65
+ updateCounter(event);
66
+ const publicEvent = buildPublicEvent(event, isAuditMode());
67
+ for (const listener of listeners) {
68
+ try {
69
+ listener(publicEvent);
70
+ } catch {
71
+ }
72
+ }
73
+ }
74
+ function getMemoryEventCounters() {
75
+ return [...counters.values()];
76
+ }
77
+ function subscribeToMemoryEvents(listener) {
78
+ listeners.add(listener);
79
+ return () => {
80
+ listeners.delete(listener);
81
+ };
82
+ }
83
+ function resetMemoryTelemetry() {
84
+ counters.clear();
85
+ listeners.clear();
86
+ }
87
+ var MemoryValidationError = class extends Error {
88
+ constructor(domain, cause) {
89
+ super(`nexus-memory: write rejected for domain "${domain}": ${String(cause)}`);
90
+ this.name = "MemoryValidationError";
91
+ }
92
+ };
93
+ function buildInMemoryRow(value, meta) {
94
+ return {
95
+ value,
96
+ ...meta?.cli !== void 0 && { cli: meta.cli },
97
+ ...meta?.source !== void 0 && { source: meta.source },
98
+ timestamp: meta?.timestamp ?? Date.now(),
99
+ ...meta?.trustTier !== void 0 && { trustTier: meta.trustTier }
100
+ };
101
+ }
102
+ function applyInMemoryFilter(values, filter) {
103
+ let out = values;
104
+ if (filter?.where !== void 0) {
105
+ const where = filter.where;
106
+ out = out.filter((v) => {
107
+ for (const [k, expected] of Object.entries(where)) {
108
+ if (v[k] !== expected) return false;
109
+ }
110
+ return true;
111
+ });
112
+ }
113
+ if (filter?.orderBy !== void 0) {
114
+ const orderBy = filter.orderBy;
115
+ const dir = filter.orderDir === "desc" ? -1 : 1;
116
+ out = [...out].sort((a, b) => {
117
+ const av = a[orderBy];
118
+ const bv = b[orderBy];
119
+ if (av === bv) return 0;
120
+ if (av === void 0 || av === null) return 1;
121
+ if (bv === void 0 || bv === null) return -1;
122
+ return (av < bv ? -1 : 1) * dir;
123
+ });
124
+ }
125
+ if (filter?.limit !== void 0) {
126
+ out = out.slice(0, filter.limit);
127
+ }
128
+ return out;
129
+ }
130
+ var InMemoryBackend = class {
131
+ domain;
132
+ rows = /* @__PURE__ */ new Map();
133
+ schema;
134
+ closed = false;
135
+ constructor(options) {
136
+ this.domain = options.domain;
137
+ if (options.schema !== void 0) {
138
+ this.schema = options.schema;
139
+ }
140
+ }
141
+ async read(key) {
142
+ this.assertOpen();
143
+ const start = Date.now();
144
+ const row = this.rows.get(key);
145
+ recordMemoryEvent({
146
+ domain: this.domain,
147
+ op: "read",
148
+ hit: row !== void 0,
149
+ durationMs: Date.now() - start,
150
+ key,
151
+ result: row?.value
152
+ });
153
+ return Promise.resolve(row?.value);
154
+ }
155
+ validate(value) {
156
+ if (this.schema === void 0) return;
157
+ const result = this.schema.safeParse(value);
158
+ if (!result.success) {
159
+ throw new MemoryValidationError(this.domain, result.error);
160
+ }
161
+ }
162
+ async write(key, value, meta) {
163
+ this.assertOpen();
164
+ const start = Date.now();
165
+ this.validate(value);
166
+ this.rows.set(key, buildInMemoryRow(value, meta));
167
+ recordMemoryEvent({
168
+ domain: this.domain,
169
+ op: "write",
170
+ ...meta?.cli !== void 0 && { cli: meta.cli },
171
+ durationMs: Date.now() - start,
172
+ key,
173
+ payload: value
174
+ });
175
+ return Promise.resolve();
176
+ }
177
+ async query(filter) {
178
+ this.assertOpen();
179
+ const start = Date.now();
180
+ let rows = [...this.rows.values()];
181
+ if (filter?.cli !== void 0) {
182
+ rows = rows.filter((r) => r.cli === filter.cli);
183
+ }
184
+ const values = applyInMemoryFilter(
185
+ rows.map((r) => r.value),
186
+ filter
187
+ );
188
+ recordMemoryEvent({
189
+ domain: this.domain,
190
+ op: "query",
191
+ hit: values.length > 0,
192
+ ...filter?.cli !== void 0 && { cli: filter.cli },
193
+ durationMs: Date.now() - start,
194
+ key: filter,
195
+ result: { count: values.length }
196
+ });
197
+ return Promise.resolve(values);
198
+ }
199
+ async delete(key) {
200
+ this.assertOpen();
201
+ const start = Date.now();
202
+ const removed = this.rows.delete(key);
203
+ recordMemoryEvent({
204
+ domain: this.domain,
205
+ op: "delete",
206
+ hit: removed,
207
+ durationMs: Date.now() - start,
208
+ key
209
+ });
210
+ return Promise.resolve(removed);
211
+ }
212
+ async stats() {
213
+ this.assertOpen();
214
+ const start = Date.now();
215
+ const timestamps = [...this.rows.values()].map((r) => r.timestamp);
216
+ const result = {
217
+ domain: this.domain,
218
+ count: this.rows.size,
219
+ oldestTimestamp: timestamps.length > 0 ? Math.min(...timestamps) : null,
220
+ newestTimestamp: timestamps.length > 0 ? Math.max(...timestamps) : null
221
+ };
222
+ recordMemoryEvent({
223
+ domain: this.domain,
224
+ op: "stats",
225
+ durationMs: Date.now() - start,
226
+ result
227
+ });
228
+ return Promise.resolve(result);
229
+ }
230
+ async close() {
231
+ this.closed = true;
232
+ this.rows.clear();
233
+ return Promise.resolve();
234
+ }
235
+ assertOpen() {
236
+ if (this.closed) {
237
+ throw new Error(`nexus-memory: backend "${this.domain}" is closed`);
238
+ }
239
+ }
240
+ };
241
+ function buildWriteRow(key, value, meta) {
242
+ return {
243
+ key: keyToString(key),
244
+ value: JSON.stringify(value),
245
+ cli: meta?.cli ?? null,
246
+ source: meta?.source ?? null,
247
+ timestamp: meta?.timestamp ?? Date.now(),
248
+ trust_tier: meta?.trustTier ?? null
249
+ };
250
+ }
251
+ function keyToString(key) {
252
+ if (typeof key === "string") return key;
253
+ if (typeof key === "number" || typeof key === "boolean") return String(key);
254
+ return JSON.stringify(key);
255
+ }
256
+ function applyQueryFilter(values, filter) {
257
+ let out = values;
258
+ if (filter?.where !== void 0) {
259
+ const where = filter.where;
260
+ out = out.filter((v) => {
261
+ for (const [k, expected] of Object.entries(where)) {
262
+ if (v[k] !== expected) return false;
263
+ }
264
+ return true;
265
+ });
266
+ }
267
+ if (filter?.orderBy !== void 0) {
268
+ const orderBy = filter.orderBy;
269
+ const dir = filter.orderDir === "desc" ? -1 : 1;
270
+ out = [...out].sort((a, b) => {
271
+ const av = a[orderBy];
272
+ const bv = b[orderBy];
273
+ if (av === bv) return 0;
274
+ if (av === void 0 || av === null) return 1;
275
+ if (bv === void 0 || bv === null) return -1;
276
+ return (av < bv ? -1 : 1) * dir;
277
+ });
278
+ }
279
+ if (filter?.limit !== void 0) {
280
+ out = out.slice(0, filter.limit);
281
+ }
282
+ return out;
283
+ }
284
+ var SqliteBackend = class {
285
+ domain;
286
+ db;
287
+ ownsDb;
288
+ schema;
289
+ stmts;
290
+ closed = false;
291
+ constructor(options) {
292
+ this.domain = options.domain;
293
+ if (options.db !== void 0) {
294
+ this.db = options.db;
295
+ this.ownsDb = false;
296
+ } else {
297
+ const db = new Database(options.dbPath);
298
+ db.pragma("journal_mode = WAL");
299
+ this.db = db;
300
+ this.ownsDb = true;
301
+ }
302
+ if (options.schema !== void 0) {
303
+ this.schema = options.schema;
304
+ }
305
+ this.ensureTable();
306
+ this.stmts = this.prepareStatements();
307
+ }
308
+ ensureTable() {
309
+ if (!/^[a-z][a-z0-9_]{0,63}$/i.test(this.domain)) {
310
+ throw new Error(
311
+ `nexus-memory: invalid domain "${this.domain}" \u2014 must match [a-zA-Z][a-zA-Z0-9_]{0,63}`
312
+ );
313
+ }
314
+ this.db.exec(`
315
+ CREATE TABLE IF NOT EXISTS ${this.domain} (
316
+ key TEXT PRIMARY KEY,
317
+ value TEXT NOT NULL,
318
+ cli TEXT,
319
+ source TEXT,
320
+ timestamp INTEGER NOT NULL,
321
+ trust_tier INTEGER
322
+ );
323
+ CREATE INDEX IF NOT EXISTS ${this.domain}_cli ON ${this.domain}(cli);
324
+ CREATE INDEX IF NOT EXISTS ${this.domain}_timestamp ON ${this.domain}(timestamp);
325
+ `);
326
+ }
327
+ prepareStatements() {
328
+ return {
329
+ read: this.db.prepare(
330
+ `SELECT key, value, cli, source, timestamp, trust_tier FROM ${this.domain} WHERE key = ?`
331
+ ),
332
+ write: this.db.prepare(
333
+ `INSERT INTO ${this.domain} (key, value, cli, source, timestamp, trust_tier)
334
+ VALUES (@key, @value, @cli, @source, @timestamp, @trust_tier)
335
+ ON CONFLICT(key) DO UPDATE SET
336
+ value = excluded.value,
337
+ cli = excluded.cli,
338
+ source = excluded.source,
339
+ timestamp = excluded.timestamp,
340
+ trust_tier = excluded.trust_tier`
341
+ ),
342
+ delete: this.db.prepare(`DELETE FROM ${this.domain} WHERE key = ?`),
343
+ count: this.db.prepare(`SELECT COUNT(*) AS count FROM ${this.domain}`),
344
+ bounds: this.db.prepare(
345
+ `SELECT MIN(timestamp) AS oldest, MAX(timestamp) AS newest FROM ${this.domain}`
346
+ ),
347
+ queryAll: this.db.prepare(
348
+ `SELECT key, value, cli, source, timestamp, trust_tier FROM ${this.domain}`
349
+ )
350
+ };
351
+ }
352
+ async read(key) {
353
+ this.assertOpen();
354
+ const start = Date.now();
355
+ const row = this.stmts.read.get(keyToString(key));
356
+ const value = row !== void 0 ? JSON.parse(row.value) : void 0;
357
+ recordMemoryEvent({
358
+ domain: this.domain,
359
+ op: "read",
360
+ hit: value !== void 0,
361
+ ...row?.cli !== null && row?.cli !== void 0 && { cli: row.cli },
362
+ durationMs: Date.now() - start,
363
+ key,
364
+ result: value
365
+ });
366
+ return Promise.resolve(value);
367
+ }
368
+ validate(value) {
369
+ if (this.schema === void 0) return;
370
+ const result = this.schema.safeParse(value);
371
+ if (!result.success) {
372
+ throw new MemoryValidationError(this.domain, result.error);
373
+ }
374
+ }
375
+ async write(key, value, meta) {
376
+ this.assertOpen();
377
+ const start = Date.now();
378
+ this.validate(value);
379
+ this.stmts.write.run(buildWriteRow(key, value, meta));
380
+ recordMemoryEvent({
381
+ domain: this.domain,
382
+ op: "write",
383
+ ...meta?.cli !== void 0 && { cli: meta.cli },
384
+ durationMs: Date.now() - start,
385
+ key,
386
+ payload: value
387
+ });
388
+ return Promise.resolve();
389
+ }
390
+ async query(filter) {
391
+ this.assertOpen();
392
+ const start = Date.now();
393
+ let rows = this.stmts.queryAll.all();
394
+ if (filter?.cli !== void 0) {
395
+ rows = rows.filter((r) => r.cli === filter.cli);
396
+ }
397
+ let values = rows.map((r) => JSON.parse(r.value));
398
+ values = applyQueryFilter(values, filter);
399
+ recordMemoryEvent({
400
+ domain: this.domain,
401
+ op: "query",
402
+ hit: values.length > 0,
403
+ ...filter?.cli !== void 0 && { cli: filter.cli },
404
+ durationMs: Date.now() - start,
405
+ key: filter,
406
+ result: { count: values.length }
407
+ });
408
+ return Promise.resolve(values);
409
+ }
410
+ async delete(key) {
411
+ this.assertOpen();
412
+ const start = Date.now();
413
+ const result = this.stmts.delete.run(keyToString(key));
414
+ const removed = result.changes > 0;
415
+ recordMemoryEvent({
416
+ domain: this.domain,
417
+ op: "delete",
418
+ hit: removed,
419
+ durationMs: Date.now() - start,
420
+ key
421
+ });
422
+ return Promise.resolve(removed);
423
+ }
424
+ async stats() {
425
+ this.assertOpen();
426
+ const start = Date.now();
427
+ const countRow = this.stmts.count.get();
428
+ const boundsRow = this.stmts.bounds.get();
429
+ const result = {
430
+ domain: this.domain,
431
+ count: countRow.count,
432
+ oldestTimestamp: boundsRow.oldest,
433
+ newestTimestamp: boundsRow.newest
434
+ };
435
+ recordMemoryEvent({
436
+ domain: this.domain,
437
+ op: "stats",
438
+ durationMs: Date.now() - start,
439
+ result
440
+ });
441
+ return Promise.resolve(result);
442
+ }
443
+ async close() {
444
+ if (this.closed) return Promise.resolve();
445
+ this.closed = true;
446
+ if (this.ownsDb) this.db.close();
447
+ return Promise.resolve();
448
+ }
449
+ assertOpen() {
450
+ if (this.closed) {
451
+ throw new Error(`nexus-memory: backend "${this.domain}" is closed`);
452
+ }
453
+ }
454
+ };
455
+ var MemoryRegistry = class {
456
+ backends = /* @__PURE__ */ new Map();
457
+ db;
458
+ closed = false;
459
+ constructor(options = {}) {
460
+ if (options.dbPath !== void 0) {
461
+ const db = new Database2(options.dbPath);
462
+ db.pragma("journal_mode = WAL");
463
+ this.db = db;
464
+ }
465
+ }
466
+ /**
467
+ * Register a backend for `domain`. Throws on duplicate domain.
468
+ *
469
+ * When the registry has a `dbPath`, the new backend is SQLite-backed
470
+ * and shares the registry's connection. Otherwise, an `InMemoryBackend`
471
+ * is created (used for tests).
472
+ */
473
+ register(options) {
474
+ this.assertOpen();
475
+ if (this.backends.has(options.domain)) {
476
+ throw new Error(`nexus-memory: domain "${options.domain}" already registered`);
477
+ }
478
+ const backend = this.db !== void 0 ? new SqliteBackend({
479
+ domain: options.domain,
480
+ dbPath: "<shared>",
481
+ // unused when db is supplied
482
+ db: this.db,
483
+ ...options.schema !== void 0 && { schema: options.schema }
484
+ }) : new InMemoryBackend({
485
+ domain: options.domain,
486
+ ...options.schema !== void 0 && { schema: options.schema }
487
+ });
488
+ this.backends.set(options.domain, backend);
489
+ return backend;
490
+ }
491
+ /**
492
+ * Attach an externally-managed {@link IMemoryBackend}. Use this when the
493
+ * backend owns its own storage (e.g., a pre-existing SQLite file under
494
+ * `~/.nexus-agents/memory/agentic.db`) and you want it discoverable
495
+ * through the registry without changing its persistence.
496
+ *
497
+ * Phase 5–7 of the memory-unification epic use this to bring the
498
+ * tool-memory backends (`agentic`, `adaptive`, `typed`, `belief`),
499
+ * OutcomeStore, SICA, skills, etc. under a unified observability
500
+ * contract without rewriting their internals. Each attached backend
501
+ * still owns its own `.db` (or JSONL, etc.) until a follow-up migration
502
+ * folds the storage in fully.
503
+ */
504
+ attach(domain, backend) {
505
+ this.assertOpen();
506
+ if (this.backends.has(domain)) {
507
+ throw new Error(`nexus-memory: domain "${domain}" already registered`);
508
+ }
509
+ this.backends.set(domain, backend);
510
+ return backend;
511
+ }
512
+ /**
513
+ * Get a previously-registered backend. Returns `undefined` if the
514
+ * domain isn't registered — callers should treat that as "not yet
515
+ * migrated to the unified contract."
516
+ */
517
+ get(domain) {
518
+ this.assertOpen();
519
+ const backend = this.backends.get(domain);
520
+ return backend;
521
+ }
522
+ /** List all registered domains. Useful for `memory_stats`-style readers. */
523
+ domains() {
524
+ return [...this.backends.keys()];
525
+ }
526
+ /**
527
+ * Close every registered backend and the shared SQLite handle. After
528
+ * `close()` the registry rejects all further operations.
529
+ */
530
+ async close() {
531
+ if (this.closed) return;
532
+ this.closed = true;
533
+ for (const backend of this.backends.values()) {
534
+ await backend.close();
535
+ }
536
+ this.backends.clear();
537
+ if (this.db !== void 0) this.db.close();
538
+ }
539
+ assertOpen() {
540
+ if (this.closed) {
541
+ throw new Error("nexus-memory: registry is closed");
542
+ }
543
+ }
544
+ };
545
+ var sharedRegistry = null;
546
+ function getMemoryRegistry() {
547
+ if (sharedRegistry === null) {
548
+ const dbPath = resolveDefaultDbPath();
549
+ sharedRegistry = new MemoryRegistry({ dbPath });
550
+ }
551
+ return sharedRegistry;
552
+ }
553
+ function setMemoryRegistry(registry) {
554
+ sharedRegistry = registry;
555
+ }
556
+ async function closeMemoryRegistry() {
557
+ if (sharedRegistry !== null) {
558
+ await sharedRegistry.close();
559
+ sharedRegistry = null;
560
+ }
561
+ }
562
+ function resolveDefaultDbPath() {
563
+ const root = process.env["NEXUS_DATA_DIR"] ?? `${process.env["HOME"] ?? "/tmp"}/.nexus-agents`;
564
+ return `${root}/memory/memory.db`;
565
+ }
566
+ function createInMemoryMemoryRegistry() {
567
+ return new MemoryRegistry({
568
+ /* no dbPath → InMemoryBackend per domain */
569
+ });
570
+ }
571
+ function createSqliteMemoryRegistry(dbPath) {
572
+ return new MemoryRegistry({ dbPath });
573
+ }
574
+ var importers = /* @__PURE__ */ new Map();
575
+ function registerImporter(importer) {
576
+ if (importers.has(importer.id)) {
577
+ throw new Error(`nexus-memory: importer "${importer.id}" already registered`);
578
+ }
579
+ importers.set(importer.id, importer);
580
+ }
581
+ function resetImporters() {
582
+ importers.clear();
583
+ }
584
+ function listImporters() {
585
+ return [...importers.keys()];
586
+ }
587
+ async function runImporters(registry, options) {
588
+ mkdirSync(options.markerDir, { recursive: true });
589
+ const runs = [];
590
+ const errors = [];
591
+ for (const importer of importers.values()) {
592
+ const marker = join(options.markerDir, `.imported-${importer.id}`);
593
+ if (options.force !== true && existsSync(marker)) continue;
594
+ try {
595
+ const run = await importer.run(registry);
596
+ writeMarker(marker, run);
597
+ runs.push(run);
598
+ } catch (err) {
599
+ errors.push({ id: importer.id, error: err instanceof Error ? err : new Error(String(err)) });
600
+ }
601
+ }
602
+ return { runs, errors };
603
+ }
604
+ function writeMarker(path, run) {
605
+ mkdirSync(dirname(path), { recursive: true });
606
+ writeFileSync(
607
+ path,
608
+ JSON.stringify({ ...run, completedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
609
+ "utf-8"
610
+ );
611
+ }
612
+ function backupSourceFile(sourcePath) {
613
+ if (!existsSync(sourcePath)) return null;
614
+ const backup = `${sourcePath}.bak.${String(Date.now())}`;
615
+ renameSync(sourcePath, backup);
616
+ return backup;
617
+ }
618
+
619
+ export {
620
+ recordMemoryEvent,
621
+ getMemoryEventCounters,
622
+ subscribeToMemoryEvents,
623
+ resetMemoryTelemetry,
624
+ MemoryValidationError,
625
+ InMemoryBackend,
626
+ SqliteBackend,
627
+ MemoryRegistry,
628
+ getMemoryRegistry,
629
+ setMemoryRegistry,
630
+ closeMemoryRegistry,
631
+ createInMemoryMemoryRegistry,
632
+ createSqliteMemoryRegistry,
633
+ registerImporter,
634
+ resetImporters,
635
+ listImporters,
636
+ runImporters,
637
+ backupSourceFile
638
+ };
639
+ //# sourceMappingURL=chunk-PQHVC4BD.js.map