holosphere 2.0.0-alpha8 → 2.0.0-alpha9

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 (321) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/FEATURES.md +431 -0
  3. package/LICENSE +29 -166
  4. package/LICENSE-AGPL.md +180 -0
  5. package/dist/cdn/holosphere.min.js +55 -0
  6. package/dist/cdn/holosphere.min.js.map +1 -0
  7. package/dist/cjs/holosphere.cjs +1 -1
  8. package/dist/esm/holosphere.js +1 -1
  9. package/dist/{index-CKffQDmQ.cjs → index-DDGt_V9o.cjs} +2 -2
  10. package/dist/{index-CKffQDmQ.cjs.map → index-DDGt_V9o.cjs.map} +1 -1
  11. package/dist/{index-4XHHKe6S.js → index-DJXftyvB.js} +1905 -337
  12. package/dist/index-DJXftyvB.js.map +1 -0
  13. package/dist/{index-Dz5kOZMI.cjs → index-DMbdcMtK.cjs} +17 -4
  14. package/dist/index-DMbdcMtK.cjs.map +1 -0
  15. package/dist/{index-BjP1TXGz.js → index-DeZ1xz_s.js} +2 -2
  16. package/dist/{index-BjP1TXGz.js.map → index-DeZ1xz_s.js.map} +1 -1
  17. package/dist/{indexeddb-storage-lExjjFlV.js → indexeddb-storage-BFt6hMeF.js} +48 -4
  18. package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
  19. package/dist/{indexeddb-storage-DD7EFBVc.cjs → indexeddb-storage-BK5tv4Sh.cjs} +2 -2
  20. package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
  21. package/dist/{memory-storage-C68adso2.js → memory-storage-C9HuoL2E.js} +44 -4
  22. package/dist/memory-storage-C9HuoL2E.js.map +1 -0
  23. package/dist/{memory-storage-DD_6yyXT.cjs → memory-storage-Dao7jfYG.cjs} +2 -2
  24. package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
  25. package/dist/{secp256k1-DYELiqgx.cjs → secp256k1-BbKzbLtD.cjs} +2 -2
  26. package/dist/{secp256k1-DYELiqgx.cjs.map → secp256k1-BbKzbLtD.cjs.map} +1 -1
  27. package/dist/{secp256k1-OM8siPyy.js → secp256k1-CreY7Pcl.js} +2 -2
  28. package/dist/{secp256k1-OM8siPyy.js.map → secp256k1-CreY7Pcl.js.map} +1 -1
  29. package/docs/api/ai_aggregation.js.html +333 -0
  30. package/docs/api/ai_breakdown.js.html +524 -0
  31. package/docs/api/ai_classifier.js.html +231 -0
  32. package/docs/api/ai_council.js.html +246 -0
  33. package/docs/api/ai_embeddings.js.html +304 -0
  34. package/docs/api/ai_federation-ai.js.html +338 -0
  35. package/docs/api/ai_h3-ai.js.html +970 -0
  36. package/docs/api/ai_index.js.html +124 -0
  37. package/docs/api/ai_json-ops.js.html +241 -0
  38. package/docs/api/ai_llm-service.js.html +239 -0
  39. package/docs/api/ai_nl-query.js.html +236 -0
  40. package/docs/api/ai_relationships.js.html +367 -0
  41. package/docs/api/ai_schema-extractor.js.html +235 -0
  42. package/docs/api/ai_spatial.js.html +307 -0
  43. package/docs/api/ai_tts.js.html +214 -0
  44. package/docs/api/content_social-protocols.js.html +180 -0
  45. package/docs/api/core_holosphere.js.html +757 -0
  46. package/docs/api/crypto_nostr-utils.js.html +306 -0
  47. package/docs/api/crypto_secp256k1.js.html +267 -0
  48. package/docs/api/data/search.json +1 -0
  49. package/docs/api/federation_discovery.js.html +337 -0
  50. package/docs/api/federation_handshake.js.html +478 -0
  51. package/docs/api/federation_hologram.js.html +1053 -0
  52. package/docs/api/federation_registry.js.html +389 -0
  53. package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
  54. package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
  55. package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
  56. package/docs/api/global.html +3 -0
  57. package/docs/api/hierarchical_upcast.js.html +128 -0
  58. package/docs/api/index.html +265 -0
  59. package/docs/api/index.js.html +1868 -0
  60. package/docs/api/lib_ai-methods.js.html +660 -0
  61. package/docs/api/lib_contract-methods.js.html +445 -0
  62. package/docs/api/lib_errors.js.html +56 -0
  63. package/docs/api/lib_federation-methods.js.html +348 -0
  64. package/docs/api/lib_index.js.html +33 -0
  65. package/docs/api/module-ai.html +5 -0
  66. package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
  67. package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
  68. package/docs/api/module-ai_aggregation.html +3 -0
  69. package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
  70. package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
  71. package/docs/api/module-ai_breakdown.html +3 -0
  72. package/docs/api/module-ai_classifier-Classifier.html +6 -0
  73. package/docs/api/module-ai_classifier.Classifier.html +3 -0
  74. package/docs/api/module-ai_classifier.html +3 -0
  75. package/docs/api/module-ai_council-Council.html +6 -0
  76. package/docs/api/module-ai_council.Council.html +3 -0
  77. package/docs/api/module-ai_council.html +3 -0
  78. package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
  79. package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
  80. package/docs/api/module-ai_embeddings.html +3 -0
  81. package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
  82. package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
  83. package/docs/api/module-ai_federation-ai.html +3 -0
  84. package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
  85. package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
  86. package/docs/api/module-ai_h3-ai.html +3 -0
  87. package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
  88. package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
  89. package/docs/api/module-ai_json-ops.html +3 -0
  90. package/docs/api/module-ai_llm-service-LLMService.html +5 -0
  91. package/docs/api/module-ai_llm-service.LLMService.html +3 -0
  92. package/docs/api/module-ai_llm-service.html +3 -0
  93. package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
  94. package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
  95. package/docs/api/module-ai_nl-query.html +3 -0
  96. package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
  97. package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
  98. package/docs/api/module-ai_relationships.html +3 -0
  99. package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
  100. package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
  101. package/docs/api/module-ai_schema-extractor.html +3 -0
  102. package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
  103. package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
  104. package/docs/api/module-ai_spatial.html +3 -0
  105. package/docs/api/module-ai_tts-TTS.html +5 -0
  106. package/docs/api/module-ai_tts.TTS.html +3 -0
  107. package/docs/api/module-ai_tts.html +3 -0
  108. package/docs/api/module-content_social-protocols.html +3 -0
  109. package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
  110. package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
  111. package/docs/api/module-core_holosphere.html +3 -0
  112. package/docs/api/module-crypto_nostr-utils.html +3 -0
  113. package/docs/api/module-crypto_secp256k1.html +3 -0
  114. package/docs/api/module-federation_hologram.html +3 -0
  115. package/docs/api/module-hierarchical_upcast.html +3 -0
  116. package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
  117. package/docs/api/module-holosphere.html +3 -0
  118. package/docs/api/module-lib_ai-methods.html +3 -0
  119. package/docs/api/module-lib_contract-methods.html +3 -0
  120. package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
  121. package/docs/api/module-lib_errors-ValidationError.html +3 -0
  122. package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
  123. package/docs/api/module-lib_errors.ValidationError.html +3 -0
  124. package/docs/api/module-lib_errors.html +3 -0
  125. package/docs/api/module-lib_federation-methods.html +3 -0
  126. package/docs/api/module-lib_index.html +3 -0
  127. package/docs/api/module-schema_validator-ValidationError.html +3 -0
  128. package/docs/api/module-schema_validator.ValidationError.html +3 -0
  129. package/docs/api/module-schema_validator.html +3 -0
  130. package/docs/api/module-spatial_h3-operations.html +4 -0
  131. package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
  132. package/docs/api/module-storage_backend-factory.html +3 -0
  133. package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
  134. package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
  135. package/docs/api/module-storage_backend-interface.html +3 -0
  136. package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
  137. package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
  138. package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
  139. package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
  140. package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
  141. package/docs/api/module-storage_backends_activitypub_server.html +3 -0
  142. package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
  143. package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
  144. package/docs/api/module-storage_backends_gundb-backend.html +3 -0
  145. package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
  146. package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
  147. package/docs/api/module-storage_backends_nostr-backend.html +3 -0
  148. package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
  149. package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
  150. package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
  151. package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
  152. package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
  153. package/docs/api/module-storage_filesystem-storage.html +3 -0
  154. package/docs/api/module-storage_global-tables.html +3 -0
  155. package/docs/api/module-storage_gun-async.html +3 -0
  156. package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
  157. package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
  158. package/docs/api/module-storage_gun-auth.html +3 -0
  159. package/docs/api/module-storage_gun-federation.html +3 -0
  160. package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
  161. package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
  162. package/docs/api/module-storage_gun-references.html +3 -0
  163. package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
  164. package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
  165. package/docs/api/module-storage_gun-schema.html +3 -0
  166. package/docs/api/module-storage_gun-wrapper.html +11 -0
  167. package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
  168. package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
  169. package/docs/api/module-storage_indexeddb-storage.html +3 -0
  170. package/docs/api/module-storage_key-storage-simple.html +3 -0
  171. package/docs/api/module-storage_key-storage.html +4 -0
  172. package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
  173. package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
  174. package/docs/api/module-storage_memory-storage.html +3 -0
  175. package/docs/api/module-storage_migration-MigrationTool.html +6 -0
  176. package/docs/api/module-storage_migration.MigrationTool.html +3 -0
  177. package/docs/api/module-storage_migration.html +3 -0
  178. package/docs/api/module-storage_nostr-async.html +18 -0
  179. package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
  180. package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
  181. package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
  182. package/docs/api/module-storage_nostr-client.html +6 -0
  183. package/docs/api/module-storage_nostr-wrapper.html +3 -0
  184. package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
  185. package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
  186. package/docs/api/module-storage_outbox-queue.html +3 -0
  187. package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
  188. package/docs/api/module-storage_persistent-storage.html +4 -0
  189. package/docs/api/module-storage_sync-service-SyncService.html +5 -0
  190. package/docs/api/module-storage_sync-service.SyncService.html +3 -0
  191. package/docs/api/module-storage_sync-service.html +3 -0
  192. package/docs/api/module-storage_unified-storage.html +3 -0
  193. package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
  194. package/docs/api/module-subscriptions_manager.html +3 -0
  195. package/docs/api/schema_validator.js.html +113 -0
  196. package/docs/api/scripts/core.js +726 -0
  197. package/docs/api/scripts/core.min.js +23 -0
  198. package/docs/api/scripts/resize.js +90 -0
  199. package/docs/api/scripts/search.js +265 -0
  200. package/docs/api/scripts/search.min.js +6 -0
  201. package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
  202. package/docs/api/scripts/third-party/fuse.js +9 -0
  203. package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
  204. package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
  205. package/docs/api/scripts/third-party/hljs-original.js +5171 -0
  206. package/docs/api/scripts/third-party/hljs.js +1 -0
  207. package/docs/api/scripts/third-party/popper.js +5 -0
  208. package/docs/api/scripts/third-party/tippy.js +1 -0
  209. package/docs/api/scripts/third-party/tocbot.js +672 -0
  210. package/docs/api/scripts/third-party/tocbot.min.js +1 -0
  211. package/docs/api/spatial_h3-operations.js.html +129 -0
  212. package/docs/api/storage_backend-factory.js.html +133 -0
  213. package/docs/api/storage_backend-interface.js.html +164 -0
  214. package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
  215. package/docs/api/storage_backends_activitypub_server.js.html +678 -0
  216. package/docs/api/storage_backends_gundb-backend.js.html +878 -0
  217. package/docs/api/storage_backends_nostr-backend.js.html +254 -0
  218. package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
  219. package/docs/api/storage_filesystem-storage.js.html +207 -0
  220. package/docs/api/storage_global-tables.js.html +116 -0
  221. package/docs/api/storage_gun-async.js.html +344 -0
  222. package/docs/api/storage_gun-auth.js.html +376 -0
  223. package/docs/api/storage_gun-federation.js.html +788 -0
  224. package/docs/api/storage_gun-references.js.html +212 -0
  225. package/docs/api/storage_gun-schema.js.html +309 -0
  226. package/docs/api/storage_gun-wrapper.js.html +645 -0
  227. package/docs/api/storage_indexeddb-storage.js.html +224 -0
  228. package/docs/api/storage_key-storage-simple.js.html +102 -0
  229. package/docs/api/storage_key-storage.js.html +171 -0
  230. package/docs/api/storage_memory-storage.js.html +128 -0
  231. package/docs/api/storage_migration.js.html +354 -0
  232. package/docs/api/storage_nostr-async.js.html +1076 -0
  233. package/docs/api/storage_nostr-client.js.html +1598 -0
  234. package/docs/api/storage_nostr-wrapper.js.html +218 -0
  235. package/docs/api/storage_outbox-queue.js.html +248 -0
  236. package/docs/api/storage_persistent-storage.js.html +160 -0
  237. package/docs/api/storage_sync-service.js.html +201 -0
  238. package/docs/api/storage_unified-storage.js.html +157 -0
  239. package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
  240. package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
  241. package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
  242. package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
  243. package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
  244. package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
  245. package/docs/api/subscriptions_manager.js.html +162 -0
  246. package/jsdoc.json +26 -0
  247. package/package.json +14 -3
  248. package/src/ai/aggregation.js +13 -2
  249. package/src/ai/breakdown.js +12 -2
  250. package/src/ai/classifier.js +14 -3
  251. package/src/ai/council.js +22 -7
  252. package/src/ai/embeddings.js +37 -15
  253. package/src/ai/federation-ai.js +13 -2
  254. package/src/ai/h3-ai.js +14 -2
  255. package/src/ai/index.js +16 -7
  256. package/src/ai/json-ops.js +18 -5
  257. package/src/ai/llm-service.js +62 -31
  258. package/src/ai/nl-query.js +12 -2
  259. package/src/ai/relationships.js +13 -2
  260. package/src/ai/schema-extractor.js +24 -10
  261. package/src/ai/spatial.js +13 -2
  262. package/src/ai/tts.js +25 -8
  263. package/src/content/social-protocols.js +34 -25
  264. package/src/contracts/chain-manager.js +68 -40
  265. package/src/contracts/deployer.js +70 -42
  266. package/src/contracts/event-listener.js +61 -29
  267. package/src/contracts/holon-contracts.js +46 -31
  268. package/src/contracts/index.js +5 -6
  269. package/src/contracts/networks.js +19 -14
  270. package/src/contracts/operations.js +58 -41
  271. package/src/contracts/queries.js +54 -20
  272. package/src/core/holosphere.js +35 -6
  273. package/src/crypto/nostr-utils.js +82 -76
  274. package/src/crypto/secp256k1.js +7 -2
  275. package/src/federation/handshake.js +7 -7
  276. package/src/federation/hologram.js +9 -1
  277. package/src/hierarchical/upcast.js +34 -20
  278. package/src/index.js +655 -5
  279. package/src/lib/ai-methods.js +352 -3
  280. package/src/lib/contract-methods.js +152 -3
  281. package/src/lib/errors.js +31 -1
  282. package/src/lib/federation-methods.js +110 -3
  283. package/src/lib/index.js +9 -5
  284. package/src/schema/validator.js +22 -3
  285. package/src/spatial/h3-operations.js +17 -1
  286. package/src/storage/backend-factory.js +7 -2
  287. package/src/storage/backend-interface.js +21 -2
  288. package/src/storage/backends/activitypub/server.js +25 -3
  289. package/src/storage/backends/activitypub-backend.js +25 -2
  290. package/src/storage/backends/gundb-backend.js +29 -2
  291. package/src/storage/backends/nostr-backend.js +116 -1
  292. package/src/storage/filesystem-storage-browser.js +42 -2
  293. package/src/storage/filesystem-storage.js +72 -5
  294. package/src/storage/global-tables.js +7 -2
  295. package/src/storage/gun-async.js +20 -11
  296. package/src/storage/gun-auth.js +15 -4
  297. package/src/storage/gun-federation.js +14 -5
  298. package/src/storage/gun-references.js +16 -5
  299. package/src/storage/gun-schema.js +25 -10
  300. package/src/storage/gun-wrapper.js +99 -36
  301. package/src/storage/indexeddb-storage.js +65 -4
  302. package/src/storage/key-storage-simple.js +32 -9
  303. package/src/storage/key-storage.js +45 -13
  304. package/src/storage/memory-storage.js +65 -4
  305. package/src/storage/migration.js +20 -7
  306. package/src/storage/nostr-async.js +157 -67
  307. package/src/storage/nostr-client.js +173 -49
  308. package/src/storage/nostr-wrapper.js +6 -2
  309. package/src/storage/outbox-queue.js +55 -18
  310. package/src/storage/persistent-storage.js +56 -13
  311. package/src/storage/sync-service.js +51 -17
  312. package/src/storage/unified-storage.js +7 -2
  313. package/src/subscriptions/manager.js +33 -16
  314. package/dist/index-4XHHKe6S.js.map +0 -1
  315. package/dist/index-Dz5kOZMI.cjs.map +0 -1
  316. package/dist/indexeddb-storage-DD7EFBVc.cjs.map +0 -1
  317. package/dist/indexeddb-storage-lExjjFlV.js.map +0 -1
  318. package/dist/memory-storage-C68adso2.js.map +0 -1
  319. package/dist/memory-storage-DD_6yyXT.cjs.map +0 -1
  320. /package/{cleanup-test-data.js → scripts/cleanup-test-data.js} +0 -0
  321. /package/{test-ai-real-api.js → scripts/test-ai-real-api.js} +0 -0
@@ -0,0 +1,1076 @@
1
+ <!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: storage/nostr-async.js</title><!--[if lt IE 9]>
2
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
3
+ <![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="dark"><div class="sidebar-container"><div class="sidebar" id="sidebar"><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai.html">ai</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation.html">ai/aggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.html">ai/breakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.html">ai/classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.html">ai/council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.html">ai/embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.html">ai/federation-ai</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.html">ai/h3-ai</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.html">ai/json-ops</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.html">ai/llm-service</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.html">ai/nl-query</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.html">ai/relationships</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.html">ai/schema-extractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.html">ai/spatial</a></div><div class="sidebar-section-children"><a href="module-ai_tts.html">ai/tts</a></div><div class="sidebar-section-children"><a href="module-content_social-protocols.html">content/social-protocols</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.html">core/holosphere</a></div><div class="sidebar-section-children"><a href="module-crypto_nostr-utils.html">crypto/nostr-utils</a></div><div class="sidebar-section-children"><a href="module-crypto_secp256k1.html">crypto/secp256k1</a></div><div class="sidebar-section-children"><a href="module-federation_hologram.html">federation/hologram</a></div><div class="sidebar-section-children"><a href="module-hierarchical_upcast.html">hierarchical/upcast</a></div><div class="sidebar-section-children"><a href="module-holosphere.html">holosphere</a></div><div class="sidebar-section-children"><a href="module-lib_ai-methods.html">lib/ai-methods</a></div><div class="sidebar-section-children"><a href="module-lib_contract-methods.html">lib/contract-methods</a></div><div class="sidebar-section-children"><a href="module-lib_errors.html">lib/errors</a></div><div class="sidebar-section-children"><a href="module-lib_federation-methods.html">lib/federation-methods</a></div><div class="sidebar-section-children"><a href="module-lib_index.html">lib/index</a></div><div class="sidebar-section-children"><a href="module-schema_validator.html">schema/validator</a></div><div class="sidebar-section-children"><a href="module-spatial_h3-operations.html">spatial/h3-operations</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.html">storage/backend-factory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.html">storage/backend-interface</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.html">storage/backends/activitypub-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.html">storage/backends/activitypub/server</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.html">storage/backends/gundb-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.html">storage/backends/nostr-backend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.html">storage/filesystem-storage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.html">storage/filesystem-storage-browser</a></div><div class="sidebar-section-children"><a href="module-storage_global-tables.html">storage/global-tables</a></div><div class="sidebar-section-children"><a href="module-storage_gun-async.html">storage/gun-async</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.html">storage/gun-auth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-federation.html">storage/gun-federation</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.html">storage/gun-references</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.html">storage/gun-schema</a></div><div class="sidebar-section-children"><a href="module-storage_gun-wrapper.html">storage/gun-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.html">storage/indexeddb-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage.html">storage/key-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage-simple.html">storage/key-storage-simple</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.html">storage/memory-storage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.html">storage/migration</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-async.html">storage/nostr-async</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.html">storage/nostr-client</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-wrapper.html">storage/nostr-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.html">storage/outbox-queue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage.html">storage/persistent-storage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.html">storage/sync-service</a></div><div class="sidebar-section-children"><a href="module-storage_unified-storage.html">storage/unified-storage</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.html">subscriptions/manager</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai_aggregation.SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation-SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown-TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_classifier-Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_council-Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings-Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai-FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai-H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops-JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service-LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query-NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships-RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor-SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_spatial-SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_tts.TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-ai_tts-TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-core_holosphere-HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-lib_errors.AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.BackendFactory.html">BackendFactory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface-StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend-ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server-ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend-GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend-NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth-GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references-GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema-GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage-IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage-MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_migration-MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-LRUCache.html">LRUCache</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue-OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage-PersistentStorage.html">PersistentStorage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service-SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.SubscriptionRegistry.html">SubscriptionRegistry</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#FederationRequestPayload">FederationRequestPayload</a></div><div class="sidebar-section-children"><a href="global.html#FederationResponsePayload">FederationResponsePayload</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#addFederatedPartner">addFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#cleanupExpiredCapabilities">cleanupExpiredCapabilities</a></div><div class="sidebar-section-children"><a href="global.html#createFederationRequest">createFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#createFederationResponse">createFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#declineFederationRequest">declineFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#getCapabilityForAuthor">getCapabilityForAuthor</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthors">getFederatedAuthors</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthorsForScope">getFederatedAuthorsForScope</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedPartner">getFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#getFederationRegistry">getFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#getPendingFederationRequests">getPendingFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#initiateFederationHandshake">initiateFederationHandshake</a></div><div class="sidebar-section-children"><a href="global.html#isFederationRequest">isFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#isFederationResponse">isFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#rejectFederationRequest">rejectFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#removeFederatedPartner">removeFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#revokeOutboundCapability">revokeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#saveFederationRegistry">saveFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationResponse">sendFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#storeInboundCapability">storeInboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#storeOutboundCapability">storeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationAcceptances">subscribeFederationAcceptances</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationDeclines">subscribeFederationDeclines</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationRequests">subscribeFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#subscribeToFederationDMs">subscribeToFederationDMs</a></div><div class="sidebar-section-children"><a href="global.html#updateDiscoverySettings">updateDiscoverySettings</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">storage_nostr-async.js</h1></header><article><pre class="prettyprint source lang-js"><code>/**
4
+ * @fileoverview Nostr Async Utilities.
5
+ *
6
+ * Provides Promise-based wrappers and async patterns for Nostr operations.
7
+ * Includes local-first data access, query deduplication, subscription management,
8
+ * and background refresh capabilities for optimal performance.
9
+ *
10
+ * @module storage/nostr-async
11
+ */
12
+
13
+ /**
14
+ * Global subscription manager to prevent duplicate subscriptions.
15
+ * Maps: subscriptionKey -> subscription object
16
+ * @private
17
+ */
18
+ const globalSubscriptions = new Map();
19
+
20
+ /**
21
+ * Single-path subscription manager (for nostrSubscribe).
22
+ * Maps: subscriptionKey -> { subscription, callbacks: [] }
23
+ * @private
24
+ */
25
+ const singlePathSubscriptions = new Map();
26
+
27
+ /**
28
+ * Query deduplication for nostrGet - prevents duplicate relay queries.
29
+ * Maps: queryKey -> { promise, timestamp, callbacks: [] }
30
+ * @private
31
+ */
32
+ const pendingQueries = new Map();
33
+
34
+ /**
35
+ * Time window for query deduplication (2 seconds).
36
+ * @private
37
+ * @constant {number}
38
+ */
39
+ const QUERY_DEDUP_WINDOW = 2000;
40
+
41
+ /**
42
+ * Write data as Nostr event (parameterized replaceable event).
43
+ *
44
+ * @param {Object} client - NostrClient instance
45
+ * @param {string} path - Path identifier (encoded in d-tag)
46
+ * @param {Object} data - Data to store
47
+ * @param {number} [kind=30000] - Event kind (default: 30000 for parameterized replaceable)
48
+ * @returns {Promise&lt;Object>} Published event result with relay responses
49
+ * @example
50
+ * const result = await nostrPut(client, 'myapp/holon123/items/item1', { name: 'Test' });
51
+ * console.log(result.event.id); // Event ID
52
+ */
53
+ export async function nostrPut(client, path, data, kind = 30000) {
54
+ const dataEvent = {
55
+ kind,
56
+ created_at: Math.floor(Date.now() / 1000),
57
+ tags: [
58
+ ['d', path], // d-tag for parameterized replaceable events
59
+ ],
60
+ content: JSON.stringify(data),
61
+ };
62
+
63
+ const result = await client.publish(dataEvent);
64
+ return result;
65
+ }
66
+
67
+ /**
68
+ * Read data from Nostr (query by d-tag).
69
+ *
70
+ * LOCAL-FIRST: Checks persistent storage first, never blocks on network.
71
+ * Uses query deduplication to prevent duplicate relay queries within a time window.
72
+ *
73
+ * @param {Object} client - NostrClient instance
74
+ * @param {string} path - Path identifier
75
+ * @param {number} [kind=30000] - Event kind (default: 30000)
76
+ * @param {Object} [options={}] - Query options
77
+ * @param {string[]} [options.authors] - Array of public keys to query (default: [client.publicKey])
78
+ * @param {boolean} [options.includeAuthor=false] - If true, adds _author field to returned data
79
+ * @param {boolean} [options.skipPersistent=false] - If true, skip persistent storage check
80
+ * @param {number} [options.timeout=30000] - Query timeout in milliseconds
81
+ * @returns {Promise&lt;Object|null>} Data or null if not found
82
+ * @example
83
+ * const data = await nostrGet(client, 'myapp/holon1/items/item1');
84
+ * if (data) {
85
+ * console.log(data.name);
86
+ * }
87
+ */
88
+ export async function nostrGet(client, path, kind = 30000, options = {}) {
89
+ const timeout = options.timeout !== undefined ? options.timeout : 30000;
90
+ const authors = options.authors || [client.publicKey];
91
+
92
+ // LOCAL-FIRST: Check persistent storage FIRST (never blocks on network)
93
+ if (!options.skipPersistent &amp;&amp; client.persistentGet) {
94
+ const persistedEvent = await client.persistentGet(path);
95
+ if (persistedEvent &amp;&amp; persistedEvent.content) {
96
+ // Verify author is in requested authors list (persistent storage may have cached events from other authors)
97
+ if (!authors.includes(persistedEvent.pubkey)) {
98
+ // Author mismatch - fall through to relay query
99
+ } else {
100
+ try {
101
+ const data = JSON.parse(persistedEvent.content);
102
+
103
+ // Skip null/undefined or deleted items
104
+ if (!data || data._deleted) {
105
+ return null;
106
+ }
107
+
108
+ // Optionally include author information
109
+ if (options.includeAuthor) {
110
+ data._author = persistedEvent.pubkey;
111
+ }
112
+
113
+ // Trigger background refresh from relays (fire-and-forget)
114
+ if (client.refreshPathInBackground) {
115
+ client.refreshPathInBackground(path, kind, { authors, timeout });
116
+ }
117
+
118
+ return data;
119
+ } catch (error) {
120
+ // Fall through to relay query if parsing fails
121
+ console.warn('[nostrGet] Failed to parse persisted event:', error);
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ // Query deduplication: Check if same query is already pending
128
+ const queryKey = `get:${client.publicKey}:${kind}:${path}:${authors.join(',')}`;
129
+ const pending = pendingQueries.get(queryKey);
130
+
131
+ if (pending &amp;&amp; Date.now() - pending.timestamp &lt; QUERY_DEDUP_WINDOW) {
132
+ // Reuse pending query result
133
+ return pending.promise;
134
+ }
135
+
136
+ // Create new query with deduplication
137
+ const queryPromise = _executeNostrGet(client, path, kind, authors, timeout, options);
138
+
139
+ pendingQueries.set(queryKey, {
140
+ promise: queryPromise,
141
+ timestamp: Date.now(),
142
+ });
143
+
144
+ // Clean up after promise resolves
145
+ queryPromise.finally(() => {
146
+ // Remove from pending after a short delay to allow coalescing
147
+ setTimeout(() => {
148
+ const current = pendingQueries.get(queryKey);
149
+ if (current &amp;&amp; current.promise === queryPromise) {
150
+ pendingQueries.delete(queryKey);
151
+ }
152
+ }, QUERY_DEDUP_WINDOW);
153
+ });
154
+
155
+ return queryPromise;
156
+ }
157
+
158
+ /**
159
+ * Internal function to execute nostrGet query.
160
+ *
161
+ * @private
162
+ * @param {Object} client - NostrClient instance
163
+ * @param {string} path - Path identifier
164
+ * @param {number} kind - Event kind
165
+ * @param {string[]} authors - Array of author public keys
166
+ * @param {number} timeout - Query timeout
167
+ * @param {Object} options - Query options
168
+ * @returns {Promise&lt;Object|null>} Data or null
169
+ */
170
+ async function _executeNostrGet(client, path, kind, authors, timeout, options) {
171
+ const filter = {
172
+ kinds: [kind],
173
+ authors: authors, // Support multiple authors for cross-holosphere queries
174
+ '#d': [path],
175
+ limit: authors.length, // Increase limit to get events from all authors
176
+ };
177
+
178
+ const events = await client.query(filter, { timeout });
179
+
180
+ // Filter by author (relays may not respect authors filter)
181
+ const authoredEvents = events.filter(event => authors.includes(event.pubkey));
182
+
183
+ if (authoredEvents.length === 0) {
184
+ return null;
185
+ }
186
+
187
+ // Get most recent event (across allowed authors)
188
+ const event = authoredEvents.sort((a, b) => b.created_at - a.created_at)[0];
189
+
190
+ try {
191
+ const data = JSON.parse(event.content);
192
+ // Skip null/undefined or deleted items
193
+ if (!data || data._deleted) {
194
+ return null;
195
+ }
196
+ // Optionally include author information
197
+ if (options.includeAuthor) {
198
+ data._author = event.pubkey;
199
+ }
200
+ return data;
201
+ } catch (error) {
202
+ // Silent - return null for unparseable events
203
+ return null;
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Query all events under a path prefix.
209
+ *
210
+ * LOCAL-FIRST: Checks persistent storage first, never blocks on network.
211
+ * Uses query deduplication to prevent duplicate relay queries within a time window.
212
+ *
213
+ * @param {Object} client - NostrClient instance
214
+ * @param {string} pathPrefix - Path prefix to match
215
+ * @param {number} [kind=30000] - Event kind (default: 30000)
216
+ * @param {Object} [options={}] - Query options
217
+ * @param {string[]} [options.authors] - Array of public keys to query (default: [client.publicKey])
218
+ * @param {boolean} [options.includeAuthor=false] - If true, adds _author field to returned data
219
+ * @param {boolean} [options.skipPersistent=false] - If true, skip persistent storage check
220
+ * @param {number} [options.timeout=30000] - Query timeout in milliseconds
221
+ * @param {number} [options.limit=1000] - Maximum number of events to retrieve
222
+ * @returns {Promise&lt;Array>} Array of data objects
223
+ * @example
224
+ * const items = await nostrGetAll(client, 'myapp/holon1/items/');
225
+ * console.log(`Found ${items.length} items`);
226
+ */
227
+ export async function nostrGetAll(client, pathPrefix, kind = 30000, options = {}) {
228
+ const timeout = options.timeout !== undefined ? options.timeout : 30000;
229
+ const limit = options.limit || 1000; // Increased limit to get more events
230
+ const authors = options.authors || [client.publicKey];
231
+
232
+ // LOCAL-FIRST: Check persistent storage FIRST (never blocks on network)
233
+ if (!options.skipPersistent &amp;&amp; client.persistentGetAll) {
234
+ const persistedEvents = await client.persistentGetAll(pathPrefix);
235
+ if (persistedEvents.length > 0) {
236
+ // Parse content and group by d-tag (keep latest only)
237
+ const byPath = new Map();
238
+ for (const event of persistedEvents) {
239
+ if (!event || !event.tags) continue;
240
+
241
+ // Verify author is in requested authors list (persistent storage may have cached events from other authors)
242
+ if (!authors.includes(event.pubkey)) continue;
243
+
244
+ const dTag = event.tags.find(t => t[0] === 'd');
245
+ if (!dTag || !dTag[1] || !dTag[1].startsWith(pathPrefix)) continue;
246
+
247
+ const path = dTag[1];
248
+ const existing = byPath.get(path);
249
+
250
+ if (!existing || event.created_at > existing.created_at) {
251
+ try {
252
+ const data = JSON.parse(event.content);
253
+
254
+ // Handle null/undefined or deleted items - remove from map if this is newer
255
+ if (!data || data._deleted) {
256
+ byPath.delete(path);
257
+ continue;
258
+ }
259
+
260
+ // Optionally include author information
261
+ if (options.includeAuthor) {
262
+ data._author = event.pubkey;
263
+ }
264
+ byPath.set(path, { data, created_at: event.created_at });
265
+ } catch (error) {
266
+ // Skip invalid events
267
+ }
268
+ }
269
+ }
270
+
271
+ // Trigger background refresh from relays (fire-and-forget)
272
+ if (client.refreshPrefixInBackground) {
273
+ client.refreshPrefixInBackground(pathPrefix, kind, { authors, timeout, limit });
274
+ }
275
+
276
+ // Return array of data objects
277
+ return Array.from(byPath.values()).map(item => item.data);
278
+ }
279
+ }
280
+
281
+ // Query deduplication: Check if same query is already pending
282
+ const queryKey = `getAll:${client.publicKey}:${kind}:${pathPrefix}:${authors.join(',')}`;
283
+ const pending = pendingQueries.get(queryKey);
284
+
285
+ if (pending &amp;&amp; Date.now() - pending.timestamp &lt; QUERY_DEDUP_WINDOW) {
286
+ // Reuse pending query result
287
+ return pending.promise;
288
+ }
289
+
290
+ // Create new query with deduplication
291
+ const queryPromise = _executeNostrGetAll(client, pathPrefix, kind, authors, timeout, limit, options);
292
+
293
+ pendingQueries.set(queryKey, {
294
+ promise: queryPromise,
295
+ timestamp: Date.now(),
296
+ });
297
+
298
+ // Clean up after promise resolves
299
+ queryPromise.finally(() => {
300
+ setTimeout(() => {
301
+ const current = pendingQueries.get(queryKey);
302
+ if (current &amp;&amp; current.promise === queryPromise) {
303
+ pendingQueries.delete(queryKey);
304
+ }
305
+ }, QUERY_DEDUP_WINDOW);
306
+ });
307
+
308
+ return queryPromise;
309
+ }
310
+
311
+ /**
312
+ * Internal function to execute nostrGetAll query.
313
+ *
314
+ * @private
315
+ * @param {Object} client - NostrClient instance
316
+ * @param {string} pathPrefix - Path prefix to match
317
+ * @param {number} kind - Event kind
318
+ * @param {string[]} authors - Array of author public keys
319
+ * @param {number} timeout - Query timeout
320
+ * @param {number} limit - Maximum results
321
+ * @param {Object} options - Query options
322
+ * @returns {Promise&lt;Array>} Array of data objects
323
+ */
324
+ async function _executeNostrGetAll(client, pathPrefix, kind, authors, timeout, limit, options) {
325
+ const filter = {
326
+ kinds: [kind],
327
+ authors: authors,
328
+ limit,
329
+ };
330
+
331
+ const events = await client.query(filter, { timeout });
332
+
333
+ // Filter by path prefix AND verify author (relays may not respect authors filter)
334
+ const matching = events.filter(event => {
335
+ const dTag = event.tags.find(t => t[0] === 'd');
336
+ const pathMatches = dTag &amp;&amp; dTag[1] &amp;&amp; dTag[1].startsWith(pathPrefix);
337
+ const authorAllowed = authors.includes(event.pubkey);
338
+ return pathMatches &amp;&amp; authorAllowed;
339
+ });
340
+
341
+ // Parse content and group by d-tag (keep latest only, across all authors)
342
+ const byPath = new Map();
343
+ for (const event of matching) {
344
+ const dTag = event.tags.find(t => t[0] === 'd')[1];
345
+ const existing = byPath.get(dTag);
346
+
347
+ if (!existing || event.created_at > existing.created_at) {
348
+ try {
349
+ const data = JSON.parse(event.content);
350
+
351
+ // Handle null/undefined or deleted items - remove from map if this is newer
352
+ if (!data || data._deleted) {
353
+ byPath.delete(dTag);
354
+ continue;
355
+ }
356
+
357
+ // Optionally include author information
358
+ if (options.includeAuthor) {
359
+ data._author = event.pubkey;
360
+ }
361
+ byPath.set(dTag, { data, created_at: event.created_at });
362
+ } catch (error) {
363
+ // Silent - skip unparseable events
364
+ }
365
+ }
366
+ }
367
+
368
+ // Return array of data objects
369
+ return Array.from(byPath.values()).map(item => item.data);
370
+ }
371
+
372
+ /**
373
+ * Query all events under a path prefix (HYBRID MODE - local + relay).
374
+ *
375
+ * Checks local cache first, then merges with relay data.
376
+ *
377
+ * @param {Object} client - NostrClient instance
378
+ * @param {string} pathPrefix - Path prefix to match
379
+ * @param {number} [kind=30000] - Event kind (default: 30000)
380
+ * @param {Object} [options={}] - Query options
381
+ * @param {string[]} [options.authors] - Array of public keys to query (default: [client.publicKey])
382
+ * @param {boolean} [options.includeAuthor=false] - If true, adds _author field to returned data
383
+ * @param {number} [options.timeout=30000] - Query timeout in milliseconds
384
+ * @param {number} [options.limit=1000] - Maximum number of events to retrieve
385
+ * @returns {Promise&lt;Array>} Array of data objects (merged from local + relay)
386
+ */
387
+ export async function nostrGetAllHybrid(client, pathPrefix, kind = 30000, options = {}) {
388
+ const timeout = options.timeout !== undefined ? options.timeout : 30000;
389
+ const limit = options.limit || 1000;
390
+ const authors = options.authors || [client.publicKey];
391
+
392
+ // Use hybrid query if available
393
+ const queryMethod = client.queryHybrid || client.query;
394
+
395
+ const filter = {
396
+ kinds: [kind],
397
+ authors: authors,
398
+ limit,
399
+ };
400
+
401
+ const events = await queryMethod.call(client, filter, { timeout });
402
+
403
+ // Filter by path prefix AND verify author (relays may not respect authors filter)
404
+ const matching = events.filter(event => {
405
+ const dTag = event.tags.find(t => t[0] === 'd');
406
+ const pathMatches = dTag &amp;&amp; dTag[1] &amp;&amp; dTag[1].startsWith(pathPrefix);
407
+ const authorAllowed = authors.includes(event.pubkey);
408
+ return pathMatches &amp;&amp; authorAllowed;
409
+ });
410
+
411
+ // Parse content and group by d-tag (keep latest only)
412
+ const byPath = new Map();
413
+ for (const event of matching) {
414
+ const dTag = event.tags.find(t => t[0] === 'd')[1];
415
+ const existing = byPath.get(dTag);
416
+
417
+ if (!existing || event.created_at > existing.created_at) {
418
+ try {
419
+ const data = JSON.parse(event.content);
420
+ // Skip null or non-object content
421
+ if (data === null || typeof data !== 'object') {
422
+ continue;
423
+ }
424
+ // Handle deleted items - remove from map if this is newer
425
+ if (data._deleted) {
426
+ byPath.delete(dTag);
427
+ continue;
428
+ }
429
+ // Optionally include author information
430
+ if (options.includeAuthor) {
431
+ data._author = event.pubkey;
432
+ }
433
+ byPath.set(dTag, { data, created_at: event.created_at });
434
+ } catch (error) {
435
+ // Silent - skip unparseable events
436
+ }
437
+ }
438
+ }
439
+
440
+ // Return array of data objects
441
+ return Array.from(byPath.values()).map(item => item.data);
442
+ }
443
+
444
+ /**
445
+ * Delete data (publish deletion event - NIP-09).
446
+ *
447
+ * Publishes a tombstone event and a NIP-09 deletion event to mark data as deleted.
448
+ *
449
+ * @param {Object} client - NostrClient instance
450
+ * @param {string} path - Path identifier
451
+ * @param {number} [kind=30000] - Original event kind (default: 30000)
452
+ * @returns {Promise&lt;Object>} Deletion event result with status
453
+ * @example
454
+ * const result = await nostrDelete(client, 'myapp/holon1/items/item1');
455
+ * if (result.reason !== 'not_found') {
456
+ * console.log('Item deleted successfully');
457
+ * }
458
+ */
459
+ export async function nostrDelete(client, path, kind = 30000) {
460
+ // Read existing data first
461
+ const existing = await nostrGet(client, path, kind);
462
+
463
+ if (!existing) {
464
+ return { reason: 'not_found', results: [] };
465
+ }
466
+
467
+ // Create minimal tombstone - just the deleted flag, no original data
468
+ const tombstone = {
469
+ _deleted: true,
470
+ _deletedAt: Date.now()
471
+ };
472
+
473
+ // Publish tombstone as replacement event
474
+ // This ensures reads will see _deleted flag
475
+ const result = await nostrPut(client, path, tombstone, kind);
476
+
477
+ // Also delete from persistent storage to prevent resurrection on restart
478
+ if (client.persistentStorage) {
479
+ try {
480
+ await client.persistentStorage.delete(path);
481
+ } catch (e) {
482
+ // Ignore storage deletion errors
483
+ }
484
+ }
485
+
486
+ // Clear from memory cache
487
+ if (client.clearCache) {
488
+ client.clearCache(path);
489
+ }
490
+
491
+ // Also publish NIP-09 deletion event for relay compliance
492
+ const coordinate = `${kind}:${client.publicKey}:${path}`;
493
+ const deletionEvent = {
494
+ kind: 5, // NIP-09 deletion event
495
+ created_at: Math.floor(Date.now() / 1000),
496
+ tags: [
497
+ ['a', coordinate], // 'a' tag for parameterized replaceable events
498
+ ],
499
+ content: '', // Optional deletion reason/note
500
+ };
501
+
502
+ // Publish deletion event (best effort, don't block on failure)
503
+ try {
504
+ await client.publish(deletionEvent);
505
+ // Silent success - deletion queued
506
+ } catch (error) {
507
+ // Silent - deletion will be retried
508
+ }
509
+
510
+ return result;
511
+ }
512
+
513
+ /**
514
+ * Delete all data with path prefix (publish deletion events - NIP-09).
515
+ *
516
+ * @param {Object} client - NostrClient instance
517
+ * @param {string} pathPrefix - Path prefix to delete all items under
518
+ * @param {number} [kind=30000] - Original event kind (default: 30000)
519
+ * @returns {Promise&lt;Object>} Deletion results with success count
520
+ * @example
521
+ * const result = await nostrDeleteAll(client, 'myapp/holon1/items/');
522
+ * console.log(`Deleted ${result.count} items`);
523
+ */
524
+ export async function nostrDeleteAll(client, pathPrefix, kind = 30000) {
525
+ // Query events from relay
526
+ const filter = {
527
+ kinds: [kind],
528
+ authors: [client.publicKey],
529
+ limit: 1000,
530
+ };
531
+
532
+ const relayEvents = await client.query(filter, { timeout: 30000 });
533
+
534
+ // Also get events from persistent storage (may have events not yet synced to relay)
535
+ let persistentEvents = [];
536
+ if (client.persistentStorage) {
537
+ try {
538
+ persistentEvents = await client.persistentStorage.getAll(pathPrefix);
539
+ } catch (e) {
540
+ // Ignore storage read errors
541
+ }
542
+ }
543
+
544
+ // Merge events from both sources, using d-tag as key
545
+ const eventsByDTag = new Map();
546
+
547
+ // Add relay events
548
+ for (const event of relayEvents) {
549
+ const dTag = event.tags?.find(t => t[0] === 'd');
550
+ if (dTag &amp;&amp; dTag[1] &amp;&amp; dTag[1].startsWith(pathPrefix)) {
551
+ eventsByDTag.set(dTag[1], event);
552
+ }
553
+ }
554
+
555
+ // Add persistent storage events (these might be newer or only exist locally)
556
+ for (const event of persistentEvents) {
557
+ const dTag = event.tags?.find(t => t[0] === 'd');
558
+ if (dTag &amp;&amp; dTag[1] &amp;&amp; dTag[1].startsWith(pathPrefix)) {
559
+ const existing = eventsByDTag.get(dTag[1]);
560
+ // Use the persistent event if it's newer or doesn't exist in relay results
561
+ if (!existing || event.created_at > existing.created_at) {
562
+ eventsByDTag.set(dTag[1], event);
563
+ }
564
+ }
565
+ }
566
+
567
+ const matching = Array.from(eventsByDTag.values());
568
+
569
+ if (matching.length === 0) {
570
+ return { success: true, count: 0, results: [] };
571
+ }
572
+
573
+ // Publish tombstone events for each matching item
574
+ const tombstoneResults = [];
575
+ for (const event of matching) {
576
+ const dTag = event.tags.find(t => t[0] === 'd')[1];
577
+
578
+ try {
579
+ // Create minimal tombstone - just the deleted flag, no original data
580
+ const tombstone = {
581
+ _deleted: true,
582
+ _deletedAt: Date.now()
583
+ };
584
+
585
+ // Publish tombstone replacement
586
+ const result = await nostrPut(client, dTag, tombstone, kind);
587
+ tombstoneResults.push(result);
588
+
589
+ // Also delete from persistent storage to prevent resurrection on restart
590
+ if (client.persistentStorage) {
591
+ try {
592
+ await client.persistentStorage.delete(dTag);
593
+ } catch (e) {
594
+ // Ignore storage deletion errors
595
+ }
596
+ }
597
+
598
+ // Clear from memory cache
599
+ if (client.clearCache) {
600
+ client.clearCache(dTag);
601
+ }
602
+ } catch (error) {
603
+ console.error(`Failed to delete item ${dTag}:`, error);
604
+ }
605
+ }
606
+
607
+ // Collect all coordinates for NIP-09 deletion event
608
+ const coordinates = matching.map(event => {
609
+ const dTag = event.tags.find(t => t[0] === 'd')[1];
610
+ return `${kind}:${client.publicKey}:${dTag}`;
611
+ });
612
+
613
+ // Publish a single kind 5 deletion event with all coordinates
614
+ // This is for relay compliance (best effort)
615
+ try {
616
+ const deletionEvent = {
617
+ kind: 5, // NIP-09 deletion event
618
+ created_at: Math.floor(Date.now() / 1000),
619
+ tags: coordinates.map(coord => ['a', coord]),
620
+ content: '', // Optional deletion reason/note
621
+ };
622
+
623
+ await client.publish(deletionEvent);
624
+ // Silent success - bulk deletion queued
625
+ } catch (error) {
626
+ // Silent - bulk deletion will be retried
627
+ }
628
+
629
+ return {
630
+ success: true,
631
+ count: matching.length,
632
+ results: tombstoneResults,
633
+ };
634
+ }
635
+
636
+ /**
637
+ * Subscribe to path changes.
638
+ *
639
+ * Uses subscription deduplication - multiple subscribers to same path share one relay subscription.
640
+ *
641
+ * @param {Object} client - NostrClient instance
642
+ * @param {string} path - Path to subscribe to
643
+ * @param {Function} callback - Callback function (data, event) => void
644
+ * @param {Object} [options={}] - Subscription options
645
+ * @param {number} [options.kind=30000] - Event kind to subscribe to
646
+ * @returns {Object} Subscription object with unsubscribe method
647
+ * @example
648
+ * const sub = nostrSubscribe(client, 'myapp/holon1/items/item1', (data, event) => {
649
+ * console.log('Item updated:', data);
650
+ * });
651
+ * // Later: sub.unsubscribe();
652
+ */
653
+ export function nostrSubscribe(client, path, callback, options = {}) {
654
+ const kind = options.kind || 30000;
655
+
656
+ // Create unique key for this subscription
657
+ const subscriptionKey = `single:${client.publicKey}:${kind}:${path}`;
658
+
659
+ // Check if we already have an active subscription for this path
660
+ const existing = singlePathSubscriptions.get(subscriptionKey);
661
+ if (existing) {
662
+ // Add callback to existing subscription
663
+ existing.callbacks.push(callback);
664
+
665
+ // Return wrapper that removes only this callback on unsubscribe
666
+ return {
667
+ unsubscribe: () => {
668
+ const idx = existing.callbacks.indexOf(callback);
669
+ if (idx > -1) {
670
+ existing.callbacks.splice(idx, 1);
671
+ }
672
+
673
+ // If no more callbacks, unsubscribe the whole thing
674
+ if (existing.callbacks.length === 0) {
675
+ existing.subscription.unsubscribe();
676
+ singlePathSubscriptions.delete(subscriptionKey);
677
+ }
678
+ }
679
+ };
680
+ }
681
+
682
+ // Create new subscription
683
+ const callbacks = [callback];
684
+ const subscriptionInfo = {
685
+ callbacks,
686
+ subscription: null,
687
+ };
688
+
689
+ // Store before creating subscription to handle race conditions
690
+ singlePathSubscriptions.set(subscriptionKey, subscriptionInfo);
691
+
692
+ const filter = {
693
+ kinds: [kind],
694
+ authors: [client.publicKey], // Filter by our public key
695
+ '#d': [path],
696
+ limit: 10, // Limit results for single item subscription
697
+ };
698
+
699
+ const subscription = client.subscribe(
700
+ filter,
701
+ (event) => {
702
+ // Verify event is from our public key (relay may not respect author filter)
703
+ if (event.pubkey !== client.publicKey) {
704
+ return;
705
+ }
706
+
707
+ try {
708
+ const data = JSON.parse(event.content);
709
+
710
+ // Skip null/undefined or deleted items - don't send tombstones to subscribers
711
+ if (!data || data._deleted) {
712
+ return;
713
+ }
714
+
715
+ // Dispatch to all registered callbacks
716
+ for (const cb of callbacks) {
717
+ try {
718
+ cb(data, event);
719
+ } catch (err) {
720
+ console.error('Subscription callback error:', err);
721
+ }
722
+ }
723
+ } catch (error) {
724
+ console.error('Failed to parse event in subscription:', error);
725
+ }
726
+ },
727
+ {
728
+ onEOSE: () => {
729
+ // EOSE received
730
+ },
731
+ }
732
+ );
733
+
734
+ subscriptionInfo.subscription = subscription;
735
+
736
+ return {
737
+ unsubscribe: () => {
738
+ const idx = callbacks.indexOf(callback);
739
+ if (idx > -1) {
740
+ callbacks.splice(idx, 1);
741
+ }
742
+
743
+ // If no more callbacks, unsubscribe the whole thing
744
+ if (callbacks.length === 0) {
745
+ subscription.unsubscribe();
746
+ singlePathSubscriptions.delete(subscriptionKey);
747
+ }
748
+ }
749
+ };
750
+ }
751
+
752
+ /**
753
+ * Subscribe to path prefix (multiple paths).
754
+ *
755
+ * Subscribes to data events and uses Page Visibility API to refresh when tab becomes visible.
756
+ * Note: Nostr relays do not broadcast replaceable event updates to active subscriptions.
757
+ *
758
+ * @param {Object} client - NostrClient instance
759
+ * @param {string} pathPrefix - Path prefix to match
760
+ * @param {Function} callback - Callback function (data, path, event) => void
761
+ * @param {Object} [options={}] - Subscription options
762
+ * @param {number} [options.kind=30000] - Event kind to subscribe to
763
+ * @returns {Promise&lt;Object>} Subscription object with unsubscribe method
764
+ * @example
765
+ * const sub = await nostrSubscribeMany(client, 'myapp/holon1/items/', (data, path, event) => {
766
+ * console.log('Item event:', data);
767
+ * });
768
+ * // Later: sub.unsubscribe();
769
+ */
770
+ export async function nostrSubscribeMany(client, pathPrefix, callback, options = {}) {
771
+ const kind = options.kind || 30000;
772
+
773
+ // Create unique key for this subscription
774
+ const subscriptionKey = `${client.publicKey}:${kind}:${pathPrefix}`;
775
+
776
+ // Check if we already have an active subscription for this path
777
+ const existingSub = globalSubscriptions.get(subscriptionKey);
778
+ if (existingSub) {
779
+ // Register this callback with the existing subscription
780
+ existingSub.callbacks.push(callback);
781
+
782
+ // Return a wrapper that removes only this callback on unsubscribe
783
+ return {
784
+ unsubscribe: () => {
785
+ const idx = existingSub.callbacks.indexOf(callback);
786
+ if (idx > -1) {
787
+ existingSub.callbacks.splice(idx, 1);
788
+ }
789
+
790
+ // If no more callbacks, unsubscribe the whole thing
791
+ if (existingSub.callbacks.length === 0) {
792
+ existingSub.actualSubscription.unsubscribe();
793
+ globalSubscriptions.delete(subscriptionKey);
794
+ }
795
+ }
796
+ };
797
+ }
798
+
799
+ const seenEventIds = new Set(); // Track event IDs to prevent duplicate callbacks
800
+ const callbacks = [callback]; // Array of callbacks to notify
801
+
802
+ // Track rejected events for metrics
803
+ let rejectedCount = 0;
804
+ let acceptedCount = 0;
805
+ let lastLogTime = Date.now();
806
+ const LOG_INTERVAL = 10000; // Log summary every 10 seconds
807
+
808
+ // Handler for data events (kind 30000)
809
+ const handleDataEvent = (event) => {
810
+ // Skip duplicates
811
+ if (seenEventIds.has(event.id)) {
812
+ return;
813
+ }
814
+ seenEventIds.add(event.id);
815
+
816
+ // Check if event is from a different author (relay not respecting filter)
817
+ if (event.pubkey !== client.publicKey) {
818
+ rejectedCount++;
819
+
820
+ // Only log periodically to avoid spam
821
+ const now = Date.now();
822
+ if (now - lastLogTime > LOG_INTERVAL) {
823
+ console.warn('[nostrSubscribeMany] ⚠️ Relay not respecting authors filter!', {
824
+ rejectedCount,
825
+ acceptedCount,
826
+ expected: client.publicKey,
827
+ message: 'Consider using a different relay or implementing private relay'
828
+ });
829
+ lastLogTime = now;
830
+ }
831
+ return; // Skip events from other authors
832
+ }
833
+
834
+ // Extract d-tag
835
+ const dTagArray = event.tags.find(t => t[0] === 'd');
836
+ const dTag = dTagArray?.[1];
837
+
838
+ // Client-side prefix filter
839
+ if (dTag &amp;&amp; dTag.startsWith(pathPrefix)) {
840
+ try {
841
+ const data = JSON.parse(event.content);
842
+
843
+ // Skip null/undefined data or deleted items - don't send tombstones to subscribers
844
+ if (!data || data._deleted) {
845
+ return;
846
+ }
847
+
848
+ acceptedCount++;
849
+ // Notify all registered callbacks
850
+ for (const cb of callbacks) {
851
+ cb(data, dTag, event);
852
+ }
853
+ } catch (error) {
854
+ console.error('[nostrSubscribeMany] Failed to parse event:', error);
855
+ }
856
+ }
857
+ };
858
+
859
+ // Subscribe to data events (kind 30000) for initial load
860
+ // Use 'since' to only get events from subscription time onward for real-time updates
861
+ const subscriptionStartTime = Math.floor(Date.now() / 1000);
862
+ const dataFilter = {
863
+ kinds: [kind],
864
+ authors: [client.publicKey],
865
+ since: subscriptionStartTime // Only get new events after subscription
866
+ };
867
+ const dataSubscription = await client.subscribe(dataFilter, handleDataEvent);
868
+
869
+ // Use Page Visibility API to refresh when tab becomes visible
870
+ let isDocumentHidden = typeof document !== 'undefined' &amp;&amp; document.hidden;
871
+ let lastVisibilityCheck = subscriptionStartTime;
872
+
873
+ const handleVisibilityChange = async () => {
874
+ if (typeof document === 'undefined') return;
875
+
876
+ const wasHidden = isDocumentHidden;
877
+ isDocumentHidden = document.hidden;
878
+
879
+ // Tab became visible - only check for new events since we were hidden
880
+ if (wasHidden &amp;&amp; !isDocumentHidden) {
881
+ const now = Math.floor(Date.now() / 1000);
882
+ try {
883
+ const visibilityFilter = {
884
+ ...dataFilter,
885
+ since: lastVisibilityCheck, // Only events since last check
886
+ until: now
887
+ };
888
+ const events = await client.query(visibilityFilter, { timeout: 30000 });
889
+
890
+ for (const event of events) {
891
+ handleDataEvent(event);
892
+ }
893
+ lastVisibilityCheck = now;
894
+ } catch (error) {
895
+ // Silently handle visibility refresh errors
896
+ }
897
+ }
898
+ };
899
+
900
+ // Only add listener in browser environment
901
+ if (typeof document !== 'undefined') {
902
+ document.addEventListener('visibilitychange', handleVisibilityChange);
903
+ }
904
+
905
+ // Store subscription info for reuse
906
+ const actualSubscription = {
907
+ unsubscribe: () => {
908
+ if (dataSubscription &amp;&amp; dataSubscription.unsubscribe) {
909
+ dataSubscription.unsubscribe();
910
+ }
911
+ if (typeof document !== 'undefined') {
912
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
913
+ }
914
+ globalSubscriptions.delete(subscriptionKey);
915
+ }
916
+ };
917
+
918
+ const subscriptionInfo = {
919
+ callbacks,
920
+ actualSubscription
921
+ };
922
+
923
+ globalSubscriptions.set(subscriptionKey, subscriptionInfo);
924
+
925
+ return actualSubscription;
926
+ }
927
+
928
+ /**
929
+ * Update data (merge with existing).
930
+ *
931
+ * @param {Object} client - NostrClient instance
932
+ * @param {string} path - Path identifier
933
+ * @param {Object} updates - Fields to update
934
+ * @param {number} [kind=30000] - Event kind (default: 30000)
935
+ * @returns {Promise&lt;Object>} Updated event result
936
+ * @throws {Error} If no data found at path
937
+ * @example
938
+ * await nostrUpdate(client, 'myapp/holon1/items/item1', { status: 'completed' });
939
+ */
940
+ export async function nostrUpdate(client, path, updates, kind = 30000) {
941
+ // Read existing data
942
+ const existing = await nostrGet(client, path, kind);
943
+
944
+ if (!existing) {
945
+ throw new Error(`No data found at path: ${path}`);
946
+ }
947
+
948
+ // Merge updates
949
+ const merged = { ...existing, ...updates };
950
+
951
+ // Publish updated event
952
+ return nostrPut(client, path, merged, kind);
953
+ }
954
+
955
+ /**
956
+ * Batch read multiple paths.
957
+ *
958
+ * @param {Object} client - NostrClient instance
959
+ * @param {string[]} paths - Array of paths
960
+ * @param {number} [kind=30000] - Event kind (default: 30000)
961
+ * @returns {Promise&lt;Object>} Object mapping paths to data
962
+ */
963
+ export async function nostrBatchGet(client, paths, kind = 30000) {
964
+ const filter = {
965
+ kinds: [kind],
966
+ '#d': paths,
967
+ limit: paths.length,
968
+ };
969
+
970
+ const events = await client.query(filter);
971
+
972
+ // Group by d-tag (keep latest only)
973
+ const byPath = new Map();
974
+ for (const event of events) {
975
+ const dTag = event.tags.find(t => t[0] === 'd');
976
+ if (!dTag || !dTag[1]) continue;
977
+
978
+ const path = dTag[1];
979
+ const existing = byPath.get(path);
980
+
981
+ if (!existing || event.created_at > existing.created_at) {
982
+ try {
983
+ const data = JSON.parse(event.content);
984
+ byPath.set(path, data);
985
+ } catch (error) {
986
+ console.error('Failed to parse event content:', error);
987
+ }
988
+ }
989
+ }
990
+
991
+ // Return object mapping paths to data
992
+ const result = {};
993
+ for (const path of paths) {
994
+ result[path] = byPath.get(path) || null;
995
+ }
996
+
997
+ return result;
998
+ }
999
+
1000
+ /**
1001
+ * Batch write multiple paths.
1002
+ *
1003
+ * @param {Object} client - NostrClient instance
1004
+ * @param {Object} pathDataMap - Object mapping paths to data
1005
+ * @param {number} [kind=30000] - Event kind (default: 30000)
1006
+ * @returns {Promise&lt;Array>} Array of publish results
1007
+ */
1008
+ export async function nostrBatchPut(client, pathDataMap, kind = 30000) {
1009
+ const promises = Object.entries(pathDataMap).map(([path, data]) =>
1010
+ nostrPut(client, path, data, kind)
1011
+ );
1012
+
1013
+ return Promise.all(promises);
1014
+ }
1015
+
1016
+ /**
1017
+ * Retry operation with exponential backoff.
1018
+ *
1019
+ * @param {Function} operation - Async function to retry
1020
+ * @param {number} [maxRetries=3] - Max retry attempts
1021
+ * @param {number} [baseDelay=100] - Base delay in ms
1022
+ * @returns {Promise&lt;any>} Promise resolving to operation result
1023
+ * @throws {Error} Last error if all retries fail
1024
+ */
1025
+ export async function nostrRetry(operation, maxRetries = 3, baseDelay = 100) {
1026
+ let lastError;
1027
+
1028
+ for (let attempt = 0; attempt &lt;= maxRetries; attempt++) {
1029
+ try {
1030
+ return await operation();
1031
+ } catch (error) {
1032
+ lastError = error;
1033
+ if (attempt &lt; maxRetries) {
1034
+ const delay = baseDelay * Math.pow(2, attempt);
1035
+ await new Promise(resolve => setTimeout(resolve, delay));
1036
+ }
1037
+ }
1038
+ }
1039
+
1040
+ throw lastError;
1041
+ }
1042
+
1043
+ /**
1044
+ * Wait for specific condition on data.
1045
+ *
1046
+ * @param {Object} client - NostrClient instance
1047
+ * @param {string} path - Path to watch
1048
+ * @param {Function} predicate - Condition function (data) => boolean
1049
+ * @param {number} [timeout=5000] - Timeout in ms
1050
+ * @returns {Promise&lt;any>} Promise resolving when condition is met
1051
+ * @throws {Error} If timeout occurs before condition is met
1052
+ */
1053
+ export async function nostrWaitFor(client, path, predicate, timeout = 5000) {
1054
+ return new Promise((resolve, reject) => {
1055
+ let timeoutId;
1056
+ let subscription;
1057
+
1058
+ const cleanup = () => {
1059
+ if (timeoutId) clearTimeout(timeoutId);
1060
+ if (subscription) subscription.unsubscribe();
1061
+ };
1062
+
1063
+ subscription = nostrSubscribe(client, path, (data) => {
1064
+ if (predicate(data)) {
1065
+ cleanup();
1066
+ resolve(data);
1067
+ }
1068
+ });
1069
+
1070
+ timeoutId = setTimeout(() => {
1071
+ cleanup();
1072
+ reject(new Error('Timeout waiting for condition'));
1073
+ }, timeout);
1074
+ });
1075
+ }
1076
+ </code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai.html">ai</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation.html">ai/aggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.html">ai/breakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.html">ai/classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.html">ai/council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.html">ai/embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.html">ai/federation-ai</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.html">ai/h3-ai</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.html">ai/json-ops</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.html">ai/llm-service</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.html">ai/nl-query</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.html">ai/relationships</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.html">ai/schema-extractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.html">ai/spatial</a></div><div class="sidebar-section-children"><a href="module-ai_tts.html">ai/tts</a></div><div class="sidebar-section-children"><a href="module-content_social-protocols.html">content/social-protocols</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.html">core/holosphere</a></div><div class="sidebar-section-children"><a href="module-crypto_nostr-utils.html">crypto/nostr-utils</a></div><div class="sidebar-section-children"><a href="module-crypto_secp256k1.html">crypto/secp256k1</a></div><div class="sidebar-section-children"><a href="module-federation_hologram.html">federation/hologram</a></div><div class="sidebar-section-children"><a href="module-hierarchical_upcast.html">hierarchical/upcast</a></div><div class="sidebar-section-children"><a href="module-holosphere.html">holosphere</a></div><div class="sidebar-section-children"><a href="module-lib_ai-methods.html">lib/ai-methods</a></div><div class="sidebar-section-children"><a href="module-lib_contract-methods.html">lib/contract-methods</a></div><div class="sidebar-section-children"><a href="module-lib_errors.html">lib/errors</a></div><div class="sidebar-section-children"><a href="module-lib_federation-methods.html">lib/federation-methods</a></div><div class="sidebar-section-children"><a href="module-lib_index.html">lib/index</a></div><div class="sidebar-section-children"><a href="module-schema_validator.html">schema/validator</a></div><div class="sidebar-section-children"><a href="module-spatial_h3-operations.html">spatial/h3-operations</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.html">storage/backend-factory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.html">storage/backend-interface</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.html">storage/backends/activitypub-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.html">storage/backends/activitypub/server</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.html">storage/backends/gundb-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.html">storage/backends/nostr-backend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.html">storage/filesystem-storage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.html">storage/filesystem-storage-browser</a></div><div class="sidebar-section-children"><a href="module-storage_global-tables.html">storage/global-tables</a></div><div class="sidebar-section-children"><a href="module-storage_gun-async.html">storage/gun-async</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.html">storage/gun-auth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-federation.html">storage/gun-federation</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.html">storage/gun-references</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.html">storage/gun-schema</a></div><div class="sidebar-section-children"><a href="module-storage_gun-wrapper.html">storage/gun-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.html">storage/indexeddb-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage.html">storage/key-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage-simple.html">storage/key-storage-simple</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.html">storage/memory-storage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.html">storage/migration</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-async.html">storage/nostr-async</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.html">storage/nostr-client</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-wrapper.html">storage/nostr-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.html">storage/outbox-queue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage.html">storage/persistent-storage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.html">storage/sync-service</a></div><div class="sidebar-section-children"><a href="module-storage_unified-storage.html">storage/unified-storage</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.html">subscriptions/manager</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai_aggregation.SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation-SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown-TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_classifier-Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_council-Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings-Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai-FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai-H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops-JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service-LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query-NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships-RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor-SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_spatial-SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_tts.TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-ai_tts-TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-core_holosphere-HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-lib_errors.AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.BackendFactory.html">BackendFactory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface-StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend-ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server-ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend-GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend-NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth-GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references-GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema-GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage-IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage-MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_migration-MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-LRUCache.html">LRUCache</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue-OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage-PersistentStorage.html">PersistentStorage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service-SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.SubscriptionRegistry.html">SubscriptionRegistry</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#FederationRequestPayload">FederationRequestPayload</a></div><div class="sidebar-section-children"><a href="global.html#FederationResponsePayload">FederationResponsePayload</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#addFederatedPartner">addFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#cleanupExpiredCapabilities">cleanupExpiredCapabilities</a></div><div class="sidebar-section-children"><a href="global.html#createFederationRequest">createFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#createFederationResponse">createFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#declineFederationRequest">declineFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#getCapabilityForAuthor">getCapabilityForAuthor</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthors">getFederatedAuthors</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthorsForScope">getFederatedAuthorsForScope</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedPartner">getFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#getFederationRegistry">getFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#getPendingFederationRequests">getPendingFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#initiateFederationHandshake">initiateFederationHandshake</a></div><div class="sidebar-section-children"><a href="global.html#isFederationRequest">isFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#isFederationResponse">isFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#rejectFederationRequest">rejectFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#removeFederatedPartner">removeFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#revokeOutboundCapability">revokeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#saveFederationRegistry">saveFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationResponse">sendFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#storeInboundCapability">storeInboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#storeOutboundCapability">storeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationAcceptances">subscribeFederationAcceptances</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationDeclines">subscribeFederationDeclines</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationRequests">subscribeFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#subscribeToFederationDMs">subscribeToFederationDMs</a></div><div class="sidebar-section-children"><a href="global.html#updateDiscoverySettings">updateDiscoverySettings</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>