@jshookmcp/jshook 0.2.7 → 0.2.9

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 (157) hide show
  1. package/README.md +36 -5
  2. package/README.zh.md +36 -5
  3. package/dist/{AntiCheatDetector-S8VRj-dD.mjs → AntiCheatDetector-BNk-EoBt.mjs} +3 -3
  4. package/dist/{CodeInjector-4Z3ngPoX.mjs → CodeInjector-Cq8q01kp.mjs} +5 -5
  5. package/dist/ConsoleMonitor-CPVQW1Y-.mjs +2201 -0
  6. package/dist/{DarwinAPI-B8hg_yhz.mjs → DarwinAPI-BNPxu0RH.mjs} +1 -1
  7. package/dist/DetailedDataManager-BQQcxh64.mjs +217 -0
  8. package/dist/EventBus-DgPmwpeu.mjs +141 -0
  9. package/dist/EvidenceGraphBridge-SFesNera.mjs +153 -0
  10. package/dist/{ExtensionManager-CZ6IveoV.mjs → ExtensionManager-CWYgw0YW.mjs} +13 -6
  11. package/dist/{FingerprintManager-BVxFJL2-.mjs → FingerprintManager-gzWtkKuf.mjs} +1 -1
  12. package/dist/{HardwareBreakpoint-DK1yjWkV.mjs → HardwareBreakpoint-B9gZCdFP.mjs} +3 -3
  13. package/dist/{HeapAnalyzer-CEbo10xU.mjs → HeapAnalyzer-BLDH0dCv.mjs} +4 -4
  14. package/dist/HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs +639 -0
  15. package/dist/InstrumentationSession-CvPC7Jwy.mjs +244 -0
  16. package/dist/{MemoryController-DdtnBdD4.mjs → MemoryController-CbVdCIJF.mjs} +3 -3
  17. package/dist/{MemoryScanSession-RMixN3bX.mjs → MemoryScanSession-BsDZbLYm.mjs} +81 -78
  18. package/dist/{MemoryScanner-QjK4ld0B.mjs → MemoryScanner-Bcpml6II.mjs} +44 -18
  19. package/dist/{NativeMemoryManager.impl-CB6gJ0NM.mjs → NativeMemoryManager.impl-dZtA1ZGn.mjs} +14 -53
  20. package/dist/{NativeMemoryManager.utils-BML4q1ry.mjs → NativeMemoryManager.utils-B-FjA2mJ.mjs} +1 -1
  21. package/dist/{PEAnalyzer-CK0xe0Fs.mjs → PEAnalyzer-D1lzJ_VG.mjs} +2 -2
  22. package/dist/PageController-Bqm2kZ_X.mjs +417 -0
  23. package/dist/{PointerChainEngine-Cd73qu5b.mjs → PointerChainEngine-BOhyVsjx.mjs} +4 -4
  24. package/dist/PrerequisiteError-Dl33Svkz.mjs +20 -0
  25. package/dist/ResponseBuilder-D3iFYx2N.mjs +143 -0
  26. package/dist/ReverseEvidenceGraph-Dlsk94LC.mjs +269 -0
  27. package/dist/ScriptManager-aHHq0X7U.mjs +3000 -0
  28. package/dist/{Speedhack-CeF0XmEz.mjs → Speedhack-CqdIFlQl.mjs} +2 -2
  29. package/dist/{StructureAnalyzer-D4GkMduU.mjs → StructureAnalyzer-DhFaPvRO.mjs} +3 -3
  30. package/dist/ToolCatalog-C0JGZoOm.mjs +582 -0
  31. package/dist/ToolError-jh9whhMd.mjs +15 -0
  32. package/dist/ToolProbe-oC7aPrkv.mjs +45 -0
  33. package/dist/ToolRegistry-BjaF4oNz.mjs +131 -0
  34. package/dist/ToolRouter.policy-BWV67ZK-.mjs +304 -0
  35. package/dist/TraceRecorder-DgxyVbdQ.mjs +519 -0
  36. package/dist/{Win32API-Bc0QnQsN.mjs → Win32API-CePkipZY.mjs} +1 -1
  37. package/dist/{Win32Debug-DUHt9XUn.mjs → Win32Debug-BvKs-gxc.mjs} +2 -2
  38. package/dist/WorkflowEngine-CuvkZtWu.mjs +598 -0
  39. package/dist/analysis-CL9uACt9.mjs +463 -0
  40. package/dist/antidebug-CqDTB_uk.mjs +1081 -0
  41. package/dist/artifactRetention-CFEprwPw.mjs +591 -0
  42. package/dist/artifacts-Bk2-_uPq.mjs +59 -0
  43. package/dist/betterSqlite3-0pqusHHH.mjs +74 -0
  44. package/dist/binary-instrument-CXfpx6fT.mjs +979 -0
  45. package/dist/bind-helpers-xFfRF-qm.mjs +22 -0
  46. package/dist/boringssl-inspector-BH2D3VKc.mjs +180 -0
  47. package/dist/browser-BpOr5PEx.mjs +4082 -0
  48. package/dist/concurrency-Bt0yv1kJ.mjs +41 -0
  49. package/dist/{constants-CCvsN80K.mjs → constants-B0OANIBL.mjs} +88 -46
  50. package/dist/coordination-qUbyF8KU.mjs +259 -0
  51. package/dist/debugger-gnKxRSN0.mjs +1271 -0
  52. package/dist/definitions-6M-eejaT.mjs +53 -0
  53. package/dist/definitions-B18eyf0B.mjs +18 -0
  54. package/dist/definitions-B3QdlrHv.mjs +34 -0
  55. package/dist/definitions-B4rAvHNZ.mjs +63 -0
  56. package/dist/definitions-BB_4jnmy.mjs +37 -0
  57. package/dist/definitions-BMfYXoNC.mjs +43 -0
  58. package/dist/definitions-Beid2EB3.mjs +27 -0
  59. package/dist/definitions-C1UvM5Iy.mjs +126 -0
  60. package/dist/definitions-CXEI7QC72.mjs +216 -0
  61. package/dist/definitions-C_4r7Fo-2.mjs +14 -0
  62. package/dist/definitions-CkFDALoa.mjs +26 -0
  63. package/dist/definitions-Cke7zEb8.mjs +94 -0
  64. package/dist/definitions-ClJLzsJQ.mjs +25 -0
  65. package/dist/definitions-Cq-zroAU.mjs +28 -0
  66. package/dist/definitions-Cy3Sl6gV.mjs +34 -0
  67. package/dist/definitions-D3VsGcvz.mjs +47 -0
  68. package/dist/definitions-DVGfrn7y.mjs +96 -0
  69. package/dist/definitions-LKpC3-nL.mjs +9 -0
  70. package/dist/definitions-bAhHQJq9.mjs +359 -0
  71. package/dist/encoding-Bvz5jLRv.mjs +1065 -0
  72. package/dist/evidence-graph-bridge-C_fv9PuC.mjs +135 -0
  73. package/dist/{factory-CibqTNC8.mjs → factory-DxlGh9Xf.mjs} +37 -52
  74. package/dist/graphql-DYWzJ29s.mjs +1026 -0
  75. package/dist/handlers-9sAbfIg-.mjs +2552 -0
  76. package/dist/handlers-Bl8zkwz1.mjs +2716 -0
  77. package/dist/handlers-C67ktuRN.mjs +710 -0
  78. package/dist/handlers-C87g8oCe.mjs +276 -0
  79. package/dist/handlers-CTsDAO6p.mjs +681 -0
  80. package/dist/handlers-Cgyg6c0U.mjs +645 -0
  81. package/dist/handlers-D6j6yka7.mjs +2124 -0
  82. package/dist/handlers-DdFzXLvF.mjs +446 -0
  83. package/dist/handlers-DeLOCd5m.mjs +799 -0
  84. package/dist/handlers-DlCJN4Td.mjs +757 -0
  85. package/dist/handlers-DxGIq15_2.mjs +917 -0
  86. package/dist/handlers-U6L4xhuF.mjs +585 -0
  87. package/dist/handlers-tB9Mp9ZK.mjs +84 -0
  88. package/dist/handlers-tiy7EIBp.mjs +572 -0
  89. package/dist/handlers.impl-DS0d9fUw.mjs +761 -0
  90. package/dist/hooks-CzCWByww.mjs +898 -0
  91. package/dist/index.mjs +384 -155
  92. package/dist/{logger-BmWzC2lM.mjs → logger-Dh_xb7_2.mjs} +14 -6
  93. package/dist/maintenance-P7ePRXQC.mjs +830 -0
  94. package/dist/manifest-2ToTpjv8.mjs +106 -0
  95. package/dist/manifest-3g71z6Bg.mjs +79 -0
  96. package/dist/manifest-82baTv4U.mjs +45 -0
  97. package/dist/manifest-B3QVVeBS.mjs +82 -0
  98. package/dist/manifest-BB2J8IMJ.mjs +149 -0
  99. package/dist/manifest-BKbgbSiY.mjs +60 -0
  100. package/dist/manifest-Bcf-TJzH.mjs +848 -0
  101. package/dist/manifest-BmtZzQiQ2.mjs +45 -0
  102. package/dist/manifest-Bnd7kqEY.mjs +55 -0
  103. package/dist/manifest-BqQX6OQC2.mjs +65 -0
  104. package/dist/manifest-BqrQ4Tpj.mjs +81 -0
  105. package/dist/manifest-Br4RPFt5.mjs +370 -0
  106. package/dist/manifest-C5qDjysN.mjs +107 -0
  107. package/dist/manifest-C9RT5nk32.mjs +34 -0
  108. package/dist/manifest-CAhOuvSl.mjs +204 -0
  109. package/dist/manifest-CBYWCUBJ.mjs +51 -0
  110. package/dist/manifest-CFADCRa1.mjs +37 -0
  111. package/dist/manifest-CQVhavRF.mjs +114 -0
  112. package/dist/manifest-CT7zZBV1.mjs +48 -0
  113. package/dist/manifest-CV12bcrF.mjs +121 -0
  114. package/dist/manifest-CXsRWjjI.mjs +224 -0
  115. package/dist/manifest-CZLUCfG02.mjs +95 -0
  116. package/dist/manifest-D6phHKFd.mjs +131 -0
  117. package/dist/manifest-DCyjf4n2.mjs +294 -0
  118. package/dist/manifest-DHsnKgP6.mjs +60 -0
  119. package/dist/manifest-Df_dliIe.mjs +55 -0
  120. package/dist/manifest-Dh8WBmEW.mjs +129 -0
  121. package/dist/manifest-DhKRAT8_.mjs +92 -0
  122. package/dist/manifest-DlpTj4ic2.mjs +193 -0
  123. package/dist/manifest-DrbmZcFl2.mjs +253 -0
  124. package/dist/manifest-DuwHjUa5.mjs +70 -0
  125. package/dist/manifest-DzwvxPJX.mjs +38 -0
  126. package/dist/manifest-NXctwWQq.mjs +68 -0
  127. package/dist/manifest-Sc_0JQ13.mjs +418 -0
  128. package/dist/manifest-gZ4s_UtG.mjs +96 -0
  129. package/dist/manifest-qSleDqdO.mjs +1023 -0
  130. package/dist/modules-C184v-S9.mjs +11365 -0
  131. package/dist/mojo-ipc-B_H61Afw.mjs +525 -0
  132. package/dist/network-671Cw6hV.mjs +3346 -0
  133. package/dist/{artifacts-BbdOMET5.mjs → outputPaths-B1uGmrWZ.mjs} +219 -212
  134. package/dist/parse-args-BlRjqlkL.mjs +39 -0
  135. package/dist/platform-WmNn8Sxb.mjs +2070 -0
  136. package/dist/process-QcbIy5Zq.mjs +1401 -0
  137. package/dist/proxy-DqNs0bAd.mjs +170 -0
  138. package/dist/registry-D-6e18lB.mjs +34 -0
  139. package/dist/response-BQVP-xUn.mjs +28 -0
  140. package/dist/server/plugin-api.mjs +2 -2
  141. package/dist/shared-state-board-DV-dpHFJ.mjs +586 -0
  142. package/dist/sourcemap-Dq8ez8vS.mjs +650 -0
  143. package/dist/ssrf-policy-ZaUfvhq7.mjs +166 -0
  144. package/dist/streaming-BUQ0VJsg.mjs +725 -0
  145. package/dist/tool-builder-DCbIC5Eo.mjs +186 -0
  146. package/dist/transform-CiYJfNX0.mjs +1007 -0
  147. package/dist/types-Bx92KJfT.mjs +4 -0
  148. package/dist/wasm-DQTnHDs4.mjs +531 -0
  149. package/dist/workflow-f3xJOcjx.mjs +725 -0
  150. package/package.json +48 -78
  151. package/dist/ExtensionManager-DqUSOamB.mjs +0 -2
  152. package/dist/ToolCatalog-CnwmMIw3.mjs +0 -61483
  153. package/dist/{CacheAdapters-CzFNpD9a.mjs → CacheAdapters-CDe5WPSV.mjs} +0 -0
  154. package/dist/{StealthVerifier-BzBCFiwx.mjs → StealthVerifier-Bo4T3bz8.mjs} +0 -0
  155. package/dist/{VersionDetector-CNXcvD46.mjs → VersionDetector-CwVLVdDM.mjs} +0 -0
  156. package/dist/{formatAddress-ChCSIRWT.mjs → formatAddress-DVkj9kpI.mjs} +0 -0
  157. package/dist/{types-BBjOqye-.mjs → types-CPhOReNX.mjs} +1 -1
@@ -0,0 +1,586 @@
1
+ import { a as argString, i as argObject, r as argNumber, s as argStringRequired, t as argBool } from "./parse-args-BlRjqlkL.mjs";
2
+ import "./definitions-B3QdlrHv.mjs";
3
+ import { randomUUID } from "node:crypto";
4
+ //#region src/utils/escapeForRegex.ts
5
+ /**
6
+ * Utility: escape a user-provided string for safe use in a RegExp constructor.
7
+ * All regex metacharacters are escaped except `*`, which is preserved for
8
+ * wildcard matching (converted to `.*` by callers).
9
+ */
10
+ function escapeRegexStr(s) {
11
+ return s.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
12
+ }
13
+ //#endregion
14
+ //#region src/server/domains/shared-state-board/handlers/shared.ts
15
+ /**
16
+ * Shared types and state store for shared-state-board sub-handlers.
17
+ */
18
+ function matchesKeyPattern(key, keyPattern) {
19
+ if (!keyPattern) return true;
20
+ return new RegExp(`^${keyPattern.split("*").map((segment) => escapeRegexStr(segment)).join(".*")}$`).test(key);
21
+ }
22
+ var StateBoardStore = class {
23
+ state = /* @__PURE__ */ new Map();
24
+ history = /* @__PURE__ */ new Map();
25
+ watches = /* @__PURE__ */ new Map();
26
+ maxHistoryPerKey = 100;
27
+ mutationSeq = 0;
28
+ lastPersistedSeq = 0;
29
+ persistNotifier;
30
+ setPersistNotifier(notify) {
31
+ this.persistNotifier = notify;
32
+ }
33
+ markDirty() {
34
+ this.mutationSeq++;
35
+ this.persistNotifier?.();
36
+ }
37
+ recordChange(fullKey, record) {
38
+ this.markDirty();
39
+ let history = this.history.get(fullKey);
40
+ if (!history) {
41
+ history = [];
42
+ this.history.set(fullKey, history);
43
+ }
44
+ history.push(record);
45
+ if (history.length > this.maxHistoryPerKey) history.splice(0, history.length - this.maxHistoryPerKey);
46
+ }
47
+ deleteEntry(fullKey) {
48
+ const entry = this.state.get(fullKey);
49
+ if (!entry) return;
50
+ this.state.delete(fullKey);
51
+ this.recordChange(fullKey, {
52
+ id: randomUUID().slice(0, 8),
53
+ key: entry.key,
54
+ namespace: entry.namespace,
55
+ action: "delete",
56
+ oldValue: entry.value,
57
+ timestamp: Date.now()
58
+ });
59
+ }
60
+ isExpired(entry) {
61
+ return !!(entry.expiresAt && Date.now() > entry.expiresAt);
62
+ }
63
+ cleanupExpired() {
64
+ const now = Date.now();
65
+ let cleaned = 0;
66
+ for (const [fullKey, entry] of this.state.entries()) if (entry.expiresAt && now > entry.expiresAt) {
67
+ this.state.delete(fullKey);
68
+ this.recordChange(fullKey, {
69
+ id: randomUUID().slice(0, 8),
70
+ key: entry.key,
71
+ namespace: entry.namespace,
72
+ action: "expire",
73
+ oldValue: entry.value,
74
+ timestamp: now
75
+ });
76
+ cleaned++;
77
+ }
78
+ return cleaned;
79
+ }
80
+ getSnapshotSeq() {
81
+ return this.mutationSeq;
82
+ }
83
+ getLastPersistedSeq() {
84
+ return this.lastPersistedSeq;
85
+ }
86
+ markPersisted() {
87
+ this.lastPersistedSeq = this.mutationSeq;
88
+ }
89
+ isPersistDirty() {
90
+ return this.mutationSeq !== this.lastPersistedSeq;
91
+ }
92
+ exportSnapshot() {
93
+ return {
94
+ schemaVersion: 1,
95
+ savedAt: (/* @__PURE__ */ new Date()).toISOString(),
96
+ entries: [...this.state.entries()],
97
+ history: [...this.history.entries()]
98
+ };
99
+ }
100
+ restoreSnapshot(data) {
101
+ if (!data || typeof data !== "object") return;
102
+ const snapshot = data;
103
+ if (snapshot.schemaVersion !== 1) return;
104
+ const now = Date.now();
105
+ this.state.clear();
106
+ this.history.clear();
107
+ if (snapshot.entries) for (const [key, entry] of snapshot.entries) {
108
+ if (entry.expiresAt && now > entry.expiresAt) continue;
109
+ this.state.set(key, entry);
110
+ }
111
+ if (snapshot.history) for (const [key, records] of snapshot.history) this.history.set(key, records);
112
+ this.mutationSeq = this.state.size;
113
+ this.lastPersistedSeq = this.mutationSeq;
114
+ }
115
+ };
116
+ //#endregion
117
+ //#region src/server/domains/shared-state-board/handlers/store-handlers.ts
118
+ /**
119
+ * Store sub-handler — set, get, delete, list, clear, stats.
120
+ */
121
+ var StoreHandlers = class {
122
+ store;
123
+ constructor(store) {
124
+ this.store = store;
125
+ }
126
+ async handleSet(args) {
127
+ const key = argStringRequired(args, "key");
128
+ if (!key) throw new Error("key must be a non-empty string");
129
+ const value = args.value;
130
+ const namespace = argString(args, "namespace", "default");
131
+ const ttlSeconds = argNumber(args, "ttlSeconds");
132
+ const fullKey = `${namespace}:${key}`;
133
+ const now = Date.now();
134
+ const existing = this.store.state.get(fullKey);
135
+ const oldVersion = existing?.version ?? 0;
136
+ const oldValue = existing?.value;
137
+ const entry = {
138
+ key,
139
+ value,
140
+ namespace,
141
+ createdAt: existing?.createdAt ?? now,
142
+ updatedAt: now,
143
+ ttlSeconds,
144
+ expiresAt: ttlSeconds ? now + ttlSeconds * 1e3 : void 0,
145
+ version: oldVersion + 1
146
+ };
147
+ this.store.state.set(fullKey, entry);
148
+ this.store.recordChange(fullKey, {
149
+ id: randomUUID().slice(0, 8),
150
+ key,
151
+ namespace,
152
+ action: "set",
153
+ oldValue,
154
+ newValue: value,
155
+ timestamp: now
156
+ });
157
+ return {
158
+ success: true,
159
+ key,
160
+ namespace,
161
+ version: entry.version,
162
+ expiresAt: entry.expiresAt ? new Date(entry.expiresAt).toISOString() : void 0
163
+ };
164
+ }
165
+ async handleGet(args) {
166
+ const key = argStringRequired(args, "key");
167
+ if (!key) throw new Error("key must be a non-empty string");
168
+ const namespace = argString(args, "namespace", "default");
169
+ const fullKey = `${namespace}:${key}`;
170
+ const entry = this.store.state.get(fullKey);
171
+ if (!entry) return {
172
+ found: false,
173
+ key,
174
+ namespace
175
+ };
176
+ if (this.store.isExpired(entry)) {
177
+ this.store.deleteEntry(fullKey);
178
+ return {
179
+ found: false,
180
+ key,
181
+ namespace,
182
+ expired: true
183
+ };
184
+ }
185
+ return {
186
+ found: true,
187
+ key,
188
+ namespace,
189
+ value: entry.value,
190
+ version: entry.version,
191
+ createdAt: new Date(entry.createdAt).toISOString(),
192
+ updatedAt: new Date(entry.updatedAt).toISOString(),
193
+ ttlSeconds: entry.ttlSeconds,
194
+ expiresAt: entry.expiresAt ? new Date(entry.expiresAt).toISOString() : void 0
195
+ };
196
+ }
197
+ async handleDelete(args) {
198
+ const key = argStringRequired(args, "key");
199
+ if (!key) throw new Error("key must be a non-empty string");
200
+ const namespace = argString(args, "namespace", "default");
201
+ const fullKey = `${namespace}:${key}`;
202
+ if (!this.store.state.get(fullKey)) return {
203
+ deleted: false,
204
+ key,
205
+ namespace,
206
+ reason: "not_found"
207
+ };
208
+ this.store.deleteEntry(fullKey);
209
+ return {
210
+ deleted: true,
211
+ key,
212
+ namespace
213
+ };
214
+ }
215
+ async handleList(args) {
216
+ const namespace = argString(args, "namespace");
217
+ const includeValues = argBool(args, "includeValues", false);
218
+ const entries = [];
219
+ const toDelete = [];
220
+ for (const entry of this.store.state.values()) {
221
+ if (namespace && entry.namespace !== namespace) continue;
222
+ if (this.store.isExpired(entry)) {
223
+ toDelete.push(`${entry.namespace}:${entry.key}`);
224
+ continue;
225
+ }
226
+ entries.push({
227
+ key: entry.key,
228
+ namespace: entry.namespace,
229
+ version: entry.version,
230
+ updatedAt: new Date(entry.updatedAt).toISOString(),
231
+ ...includeValues ? { value: entry.value } : {}
232
+ });
233
+ }
234
+ for (const fullKey of toDelete) this.store.deleteEntry(fullKey);
235
+ entries.sort((a, b) => {
236
+ if (a.namespace !== b.namespace) return a.namespace.localeCompare(b.namespace);
237
+ return a.key.localeCompare(b.key);
238
+ });
239
+ return {
240
+ entries,
241
+ total: entries.length,
242
+ namespaces: [...new Set(entries.map((e) => e.namespace))]
243
+ };
244
+ }
245
+ async handleClear(args) {
246
+ const namespace = argString(args, "namespace");
247
+ const keyPattern = argString(args, "keyPattern");
248
+ const toDelete = [];
249
+ for (const [fullKey, entry] of this.store.state.entries()) {
250
+ if (namespace && entry.namespace !== namespace) continue;
251
+ if (!matchesKeyPattern(entry.key, keyPattern)) continue;
252
+ toDelete.push(fullKey);
253
+ }
254
+ for (const fullKey of toDelete) this.store.deleteEntry(fullKey);
255
+ return {
256
+ cleared: toDelete.length,
257
+ namespace: namespace ?? "all",
258
+ pattern: keyPattern
259
+ };
260
+ }
261
+ async handleStats() {
262
+ const now = Date.now();
263
+ const entriesByNamespace = {};
264
+ let expiredCount = 0;
265
+ for (const [, entry] of this.store.state.entries()) {
266
+ if (entry.expiresAt && now > entry.expiresAt) {
267
+ expiredCount++;
268
+ continue;
269
+ }
270
+ entriesByNamespace[entry.namespace] = (entriesByNamespace[entry.namespace] ?? 0) + 1;
271
+ }
272
+ let historySize = 0;
273
+ for (const records of this.store.history.values()) historySize += records.length;
274
+ return {
275
+ totalEntries: Object.values(entriesByNamespace).reduce((a, b) => a + b, 0),
276
+ entriesByNamespace,
277
+ expiredEntries: expiredCount,
278
+ totalWatches: this.store.watches.size,
279
+ historySize
280
+ };
281
+ }
282
+ };
283
+ //#endregion
284
+ //#region src/server/domains/shared-state-board/handlers/watch-handlers.ts
285
+ /**
286
+ * Watch sub-handler — watch, unwatch, poll.
287
+ */
288
+ var WatchHandlers = class {
289
+ store;
290
+ constructor(store) {
291
+ this.store = store;
292
+ }
293
+ async handleWatch(args) {
294
+ const key = argStringRequired(args, "key");
295
+ if (!key) throw new Error("key must be a non-empty string");
296
+ const namespace = argString(args, "namespace", "default");
297
+ const pollIntervalMs = argNumber(args, "pollIntervalMs", 1e3);
298
+ const watchId = `watch_${randomUUID().slice(0, 8)}`;
299
+ const isPattern = key.includes("*");
300
+ const watch = {
301
+ id: watchId,
302
+ key,
303
+ namespace,
304
+ pattern: isPattern,
305
+ pollIntervalMs,
306
+ lastChecked: Date.now(),
307
+ lastVersion: {},
308
+ createdAt: Date.now()
309
+ };
310
+ const prefix = `${namespace}:`;
311
+ for (const [fullKey, entry] of this.store.state.entries()) if (fullKey.startsWith(prefix)) {
312
+ if (isPattern) {
313
+ if (matchesKeyPattern(entry.key, key)) watch.lastVersion[entry.key] = entry.version;
314
+ } else if (entry.key === key) watch.lastVersion[entry.key] = entry.version;
315
+ }
316
+ this.store.watches.set(watchId, watch);
317
+ return {
318
+ watchId,
319
+ key,
320
+ namespace,
321
+ pattern: isPattern,
322
+ pollIntervalMs,
323
+ initialKeys: Object.keys(watch.lastVersion)
324
+ };
325
+ }
326
+ async handleUnwatch(args) {
327
+ const watchId = argStringRequired(args, "watchId");
328
+ const watch = this.store.watches.get(watchId);
329
+ if (!watch) return {
330
+ removed: false,
331
+ watchId,
332
+ reason: "not_found"
333
+ };
334
+ this.store.watches.delete(watchId);
335
+ return {
336
+ removed: true,
337
+ watchId,
338
+ wasWatching: watch.key
339
+ };
340
+ }
341
+ async handlePoll(args) {
342
+ const watchId = argStringRequired(args, "watchId");
343
+ const watch = this.store.watches.get(watchId);
344
+ if (!watch) throw new Error(`Watch "${watchId}" not found`);
345
+ const now = Date.now();
346
+ const changes = [];
347
+ const prefix = `${watch.namespace}:`;
348
+ if (watch.pattern) {
349
+ for (const [fullKey, entry] of this.store.state.entries()) if (fullKey.startsWith(prefix) && matchesKeyPattern(entry.key, watch.key)) {
350
+ const lastVer = watch.lastVersion[entry.key];
351
+ if (lastVer === void 0) changes.push({
352
+ key: entry.key,
353
+ namespace: entry.namespace,
354
+ action: "created"
355
+ });
356
+ else if (entry.version > lastVer) changes.push({
357
+ key: entry.key,
358
+ namespace: entry.namespace,
359
+ action: "changed"
360
+ });
361
+ watch.lastVersion[entry.key] = entry.version;
362
+ }
363
+ for (const watchedKey of Object.keys(watch.lastVersion)) if (!this.store.state.has(`${watch.namespace}:${watchedKey}`) && matchesKeyPattern(watchedKey, watch.key)) {
364
+ changes.push({
365
+ key: watchedKey,
366
+ namespace: watch.namespace,
367
+ action: "deleted"
368
+ });
369
+ delete watch.lastVersion[watchedKey];
370
+ }
371
+ } else {
372
+ const fullKey = `${watch.namespace}:${watch.key}`;
373
+ const entry = this.store.state.get(fullKey);
374
+ const lastVer = watch.lastVersion[watch.key];
375
+ if (!entry && lastVer !== void 0) {
376
+ changes.push({
377
+ key: watch.key,
378
+ namespace: watch.namespace,
379
+ action: "deleted"
380
+ });
381
+ delete watch.lastVersion[watch.key];
382
+ } else if (entry) {
383
+ if (lastVer === void 0) changes.push({
384
+ key: entry.key,
385
+ namespace: entry.namespace,
386
+ action: "created"
387
+ });
388
+ else if (entry.version > lastVer) changes.push({
389
+ key: entry.key,
390
+ namespace: entry.namespace,
391
+ action: "changed"
392
+ });
393
+ watch.lastVersion[watch.key] = entry.version;
394
+ }
395
+ }
396
+ watch.lastChecked = now;
397
+ return {
398
+ watchId,
399
+ changes,
400
+ hasChanges: changes.length > 0,
401
+ checkedAt: new Date(now).toISOString()
402
+ };
403
+ }
404
+ };
405
+ //#endregion
406
+ //#region src/server/domains/shared-state-board/handlers/io-handlers.ts
407
+ /**
408
+ * IO sub-handler — history, export, import.
409
+ */
410
+ var IOHandlers = class {
411
+ store;
412
+ constructor(store) {
413
+ this.store = store;
414
+ }
415
+ async handleHistory(args) {
416
+ const key = argStringRequired(args, "key");
417
+ const namespace = argString(args, "namespace", "default");
418
+ const limit = argNumber(args, "limit", 50);
419
+ const fullKey = `${namespace}:${key}`;
420
+ const records = this.store.history.get(fullKey) ?? [];
421
+ const limited = [...records].toSorted((a, b) => b.timestamp - a.timestamp).slice(0, limit);
422
+ return {
423
+ key,
424
+ namespace,
425
+ history: limited.map((r) => ({
426
+ ...r,
427
+ timestamp: new Date(r.timestamp).toISOString()
428
+ })),
429
+ total: records.length,
430
+ returned: limited.length
431
+ };
432
+ }
433
+ async handleExport(args) {
434
+ const namespace = argString(args, "namespace");
435
+ const keyPattern = argString(args, "keyPattern");
436
+ const now = Date.now();
437
+ const data = {};
438
+ for (const [_fullKey, entry] of this.store.state.entries()) {
439
+ if (namespace && entry.namespace !== namespace) continue;
440
+ if (!matchesKeyPattern(entry.key, keyPattern)) continue;
441
+ if (entry.expiresAt && now > entry.expiresAt) continue;
442
+ data[entry.key] = entry.value;
443
+ }
444
+ return {
445
+ data,
446
+ count: Object.keys(data).length,
447
+ namespace: namespace ?? "all",
448
+ exportedAt: new Date(now).toISOString()
449
+ };
450
+ }
451
+ async handleImport(args) {
452
+ const data = argObject(args, "data");
453
+ const namespace = argString(args, "namespace", "default");
454
+ const overwrite = argBool(args, "overwrite", false);
455
+ if (!data) throw new Error("data must be an object");
456
+ const imported = [];
457
+ const skipped = [];
458
+ const overwritten = [];
459
+ for (const [key, value] of Object.entries(data)) {
460
+ const fullKey = `${namespace}:${key}`;
461
+ const existing = this.store.state.get(fullKey);
462
+ if (existing && !overwrite) {
463
+ skipped.push(key);
464
+ continue;
465
+ }
466
+ if (existing && overwrite) overwritten.push(key);
467
+ const now = Date.now();
468
+ const entry = {
469
+ key,
470
+ value,
471
+ namespace,
472
+ createdAt: existing?.createdAt ?? now,
473
+ updatedAt: now,
474
+ version: (existing?.version ?? 0) + 1
475
+ };
476
+ this.store.state.set(fullKey, entry);
477
+ this.store.recordChange(fullKey, {
478
+ id: randomUUID().slice(0, 8),
479
+ key,
480
+ namespace,
481
+ action: "set",
482
+ oldValue: existing?.value,
483
+ newValue: value,
484
+ timestamp: now,
485
+ source: "import"
486
+ });
487
+ imported.push(key);
488
+ }
489
+ return {
490
+ imported: imported.length,
491
+ skipped: skipped.length,
492
+ overwritten: overwritten.length,
493
+ total: Object.keys(data).length,
494
+ keys: imported
495
+ };
496
+ }
497
+ };
498
+ //#endregion
499
+ //#region src/server/domains/shared-state-board/handlers.impl.core.ts
500
+ var SharedStateBoardHandlers = class {
501
+ store;
502
+ storeHandlers;
503
+ watchHandlers;
504
+ ioHandlers;
505
+ constructor() {
506
+ this.store = new StateBoardStore();
507
+ this.storeHandlers = new StoreHandlers(this.store);
508
+ this.watchHandlers = new WatchHandlers(this.store);
509
+ this.ioHandlers = new IOHandlers(this.store);
510
+ }
511
+ setPersistNotifier(notify) {
512
+ this.store.setPersistNotifier(notify);
513
+ }
514
+ handleSet(args) {
515
+ return this.storeHandlers.handleSet(args);
516
+ }
517
+ handleGet(args) {
518
+ return this.storeHandlers.handleGet(args);
519
+ }
520
+ handleDelete(args) {
521
+ return this.storeHandlers.handleDelete(args);
522
+ }
523
+ handleList(args) {
524
+ return this.storeHandlers.handleList(args);
525
+ }
526
+ handleWatchDispatch(args) {
527
+ const action = String(args["action"] ?? "");
528
+ if (action === "stop") return this.watchHandlers.handleUnwatch(args);
529
+ if (action === "poll") return this.watchHandlers.handlePoll(args);
530
+ return this.watchHandlers.handleWatch(args);
531
+ }
532
+ handleIODispatch(args) {
533
+ if (String(args["action"] ?? "") === "import") return this.ioHandlers.handleImport(args);
534
+ return this.ioHandlers.handleExport(args);
535
+ }
536
+ handleWatch(args) {
537
+ return this.watchHandlers.handleWatch(args);
538
+ }
539
+ handleUnwatch(args) {
540
+ return this.watchHandlers.handleUnwatch(args);
541
+ }
542
+ handlePoll(args) {
543
+ return this.watchHandlers.handlePoll(args);
544
+ }
545
+ handleHistory(args) {
546
+ return this.ioHandlers.handleHistory(args);
547
+ }
548
+ handleExport(args) {
549
+ return this.ioHandlers.handleExport(args);
550
+ }
551
+ handleImport(args) {
552
+ return this.ioHandlers.handleImport(args);
553
+ }
554
+ handleClear(args) {
555
+ return this.storeHandlers.handleClear(args);
556
+ }
557
+ handleDispatch(args) {
558
+ const action = String(args["action"] ?? "");
559
+ switch (action) {
560
+ case "set": return this.storeHandlers.handleSet(args);
561
+ case "get": return this.storeHandlers.handleGet(args);
562
+ case "delete": return this.storeHandlers.handleDelete(args);
563
+ case "list": return this.storeHandlers.handleList(args);
564
+ case "history": return this.ioHandlers.handleHistory(args);
565
+ case "clear": return this.storeHandlers.handleClear(args);
566
+ default: return Promise.resolve({
567
+ content: [{
568
+ type: "text",
569
+ text: `Invalid action: "${action}". Expected one of: set, get, delete, list, history, clear`
570
+ }],
571
+ isError: true
572
+ });
573
+ }
574
+ }
575
+ handleStats() {
576
+ return this.storeHandlers.handleStats();
577
+ }
578
+ cleanupExpired() {
579
+ return this.store.cleanupExpired();
580
+ }
581
+ getStore() {
582
+ return this.store;
583
+ }
584
+ };
585
+ //#endregion
586
+ export { SharedStateBoardHandlers };