Expand experimental, supercomputer, pear, collab, and messaging modules
Add manual API helpers across categories: entropy spiral prune, paradox clock compare/clear, mycelium pool borrow checks, pheromone and memetic batch helpers, phase-shift align, paradox merge all-open, mirror realm clear, work-stealer and thermal clearAll, cache warmBatch, GPU releaseAll, disk stripe completion, pear worker-pipe and channel registry, OTA history clear, import-map has/count, collab whiteboard batch and line locks, cursor presence, gossip mesh publishBatch, dedup allSeen, key rotation revokeAll, similarity LSH embedBatch, and bandwidth offer listing. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -64,6 +64,23 @@ class HyperP2PCursorPresence extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cursorCount (docId = null) {
|
||||||
|
if (!docId) return this._cursors.size
|
||||||
|
return this.listCursors(docId).length
|
||||||
|
}
|
||||||
|
|
||||||
|
clearDoc (docId) {
|
||||||
|
assertNonEmpty(docId, 'docId')
|
||||||
|
let n = 0
|
||||||
|
for (const [key, c] of this._cursors) {
|
||||||
|
if (c.docId === docId) {
|
||||||
|
this._cursors.delete(key)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
removeCursor (docId, peerHex = this.peerHex) {
|
removeCursor (docId, peerHex = this.peerHex) {
|
||||||
const key = `${docId}:${peerHex}`
|
const key = `${docId}:${peerHex}`
|
||||||
const ok = this._cursors.delete(key)
|
const ok = this._cursors.delete(key)
|
||||||
|
|||||||
@@ -62,6 +62,28 @@ class HyperP2PDocumentLineLock extends EventEmitter {
|
|||||||
return this._locks.get(this._key(docId, line)) || null
|
return this._locks.get(this._key(docId, line)) || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listLocks (docId) {
|
||||||
|
assertNonEmpty(docId, 'docId')
|
||||||
|
return [...this._locks.values()].filter((l) => l.docId === docId)
|
||||||
|
}
|
||||||
|
|
||||||
|
lockCount (docId = null) {
|
||||||
|
if (!docId) return this._locks.size
|
||||||
|
return this.listLocks(docId).length
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseAll (docId) {
|
||||||
|
assertNonEmpty(docId, 'docId')
|
||||||
|
let n = 0
|
||||||
|
for (const [key, lock] of this._locks) {
|
||||||
|
if (lock.docId === docId && lock.holder === this.holderHex) {
|
||||||
|
this._locks.delete(key)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
this._stats.gossipIn++
|
this._stats.gossipIn++
|
||||||
|
|||||||
@@ -79,6 +79,19 @@ class HyperP2PWhiteboardOp extends EventEmitter {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batchApply (roomId, ops) {
|
||||||
|
assertNonEmpty(roomId, 'roomId')
|
||||||
|
if (!Array.isArray(ops)) throw new Error('ops array required')
|
||||||
|
return ops.map((op) => this.apply(roomId, op))
|
||||||
|
}
|
||||||
|
|
||||||
|
clearRoom (roomId) {
|
||||||
|
assertNonEmpty(roomId, 'roomId')
|
||||||
|
const before = this._log.length
|
||||||
|
this._log = this._log.filter((e) => e.roomId !== roomId)
|
||||||
|
return before - this._log.length
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (data && data.type === 'wb-op' && data.entry) this.mergeRemote(data.entry)
|
if (data && data.type === 'wb-op' && data.entry) this.mergeRemote(data.entry)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,17 @@ class HyperP2PEntropySpiral extends EventEmitter {
|
|||||||
return this._state.turn
|
return this._state.turn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sampleCount () {
|
||||||
|
return this._state.samples.length
|
||||||
|
}
|
||||||
|
|
||||||
|
pruneSamples (keep = 32) {
|
||||||
|
const n = Math.max(0, keep | 0)
|
||||||
|
const removed = Math.max(0, this._state.samples.length - n)
|
||||||
|
if (removed > 0) this._state.samples = this._state.samples.slice(-n)
|
||||||
|
return removed
|
||||||
|
}
|
||||||
|
|
||||||
_gossip (data) {
|
_gossip (data) {
|
||||||
if (!this._peerMsgs) return
|
if (!this._peerMsgs) return
|
||||||
gossipSend(this, data)
|
gossipSend(this, data)
|
||||||
|
|||||||
@@ -81,6 +81,15 @@ class HyperP2PMemeticSpread extends EventEmitter {
|
|||||||
return [...this._memes.keys()]
|
return [...this._memes.keys()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memeCount () {
|
||||||
|
return this._memes.size
|
||||||
|
}
|
||||||
|
|
||||||
|
infectBatch (memeId, peers) {
|
||||||
|
if (!Array.isArray(peers)) throw new Error('peers array required')
|
||||||
|
return peers.map((peer) => this.infect(memeId, peer))
|
||||||
|
}
|
||||||
|
|
||||||
_gossip (data) {
|
_gossip (data) {
|
||||||
if (!this._peerMsgs) return
|
if (!this._peerMsgs) return
|
||||||
gossipSend(this, data)
|
gossipSend(this, data)
|
||||||
|
|||||||
@@ -107,6 +107,17 @@ class HyperP2PMirrorRealm extends EventEmitter {
|
|||||||
return this._realm(realm).size
|
return this._realm(realm).size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearRealm (realm) {
|
||||||
|
const m = this._realm(realm)
|
||||||
|
const n = m.size
|
||||||
|
m.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
hasDiff (key) {
|
||||||
|
return this.diffKeys().includes(String(key))
|
||||||
|
}
|
||||||
|
|
||||||
toJSON () {
|
toJSON () {
|
||||||
return {
|
return {
|
||||||
realmA: [...this._realmA.values()],
|
realmA: [...this._realmA.values()],
|
||||||
|
|||||||
@@ -95,6 +95,17 @@ class HyperP2PMyceliumPool extends EventEmitter {
|
|||||||
return this._balances.delete(this._pid(peerId))
|
return this._balances.delete(this._pid(peerId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canBorrow (peerId, n) {
|
||||||
|
return this.balance(peerId) >= n
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._balances.size
|
||||||
|
this._balances.clear()
|
||||||
|
this._loans = []
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -96,6 +96,23 @@ class HyperP2PParadoxClock extends EventEmitter {
|
|||||||
return this._stamps.size
|
return this._stamps.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compareEvents (eventA, eventB) {
|
||||||
|
const a = this.getStamp(eventA)
|
||||||
|
const b = this.getStamp(eventB)
|
||||||
|
if (!a || !b) return null
|
||||||
|
const w = this.resolve(a, b)
|
||||||
|
if (w === a && w !== b) return -1
|
||||||
|
if (w === b && w !== a) return 1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._stamps.size
|
||||||
|
this._stamps.clear()
|
||||||
|
this._logical = 0
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "hyper-p2p-paradox-clock",
|
"name": "hyper-p2p-paradox-clock",
|
||||||
"version": "0.3.1",
|
"version": "0.3.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "hyper-p2p-paradox-clock",
|
"name": "hyper-p2p-paradox-clock",
|
||||||
"version": "0.3.1",
|
"version": "0.3.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"b4a": "^1.6.7",
|
"b4a": "^1.6.7",
|
||||||
|
|||||||
@@ -69,6 +69,18 @@ class HyperP2PParadoxMerge extends EventEmitter {
|
|||||||
return this._resolved.size
|
return this._resolved.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mergeAllOpen () {
|
||||||
|
const out = []
|
||||||
|
for (const id of this.listOpen()) {
|
||||||
|
out.push(this.mergeBranches(id))
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
isResolved (id) {
|
||||||
|
return this._resolved.has(String(id))
|
||||||
|
}
|
||||||
|
|
||||||
_gossip (data) {
|
_gossip (data) {
|
||||||
if (!this._peerMsgs) return
|
if (!this._peerMsgs) return
|
||||||
gossipSend(this, data)
|
gossipSend(this, data)
|
||||||
|
|||||||
@@ -73,6 +73,20 @@ class HyperP2PPhaseShiftClock extends EventEmitter {
|
|||||||
return max
|
return max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alignToPeer (peer) {
|
||||||
|
const remote = this._peerPhases.get(peer)
|
||||||
|
if (remote == null) return this._phaseMs
|
||||||
|
this._phaseMs = remote
|
||||||
|
this.emit('align', { peer, phaseMs: this._phaseMs })
|
||||||
|
return this._phaseMs
|
||||||
|
}
|
||||||
|
|
||||||
|
clearPeerPhases () {
|
||||||
|
const n = this._peerPhases.size
|
||||||
|
this._peerPhases.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_gossip (data) {
|
_gossip (data) {
|
||||||
if (!this._peerMsgs) return
|
if (!this._peerMsgs) return
|
||||||
gossipSend(this, data)
|
gossipSend(this, data)
|
||||||
|
|||||||
@@ -103,6 +103,17 @@ class HyperP2PPheromoneTrail extends EventEmitter {
|
|||||||
return this.evaporationRate
|
return this.evaporationRate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongestForDest (dest) {
|
||||||
|
const ranked = this.rankPaths(dest, 1)
|
||||||
|
return ranked.length ? ranked[0] : null
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._trails.size
|
||||||
|
this._trails.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -150,6 +150,18 @@ class HyperP2PSimilarityLsh extends EventEmitter {
|
|||||||
return this._vectors.size
|
return this._vectors.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear () {
|
||||||
|
const n = this._vectors.size
|
||||||
|
this._vectors.clear()
|
||||||
|
this._buckets.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
embedBatch (items) {
|
||||||
|
if (!Array.isArray(items)) throw new Error('items array required')
|
||||||
|
return items.map((it) => this.embed(it.id, it.vector))
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return {
|
return {
|
||||||
...this._stats,
|
...this._stats,
|
||||||
|
|||||||
@@ -163,6 +163,11 @@ class HyperP2PDedupFilter extends EventEmitter {
|
|||||||
return ids.filter((id) => !this.seen(id))
|
return ids.filter((id) => !this.seen(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allSeen (ids) {
|
||||||
|
if (!Array.isArray(ids)) throw new Error('ids must be an array')
|
||||||
|
return ids.every((id) => this.seen(id))
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return {
|
return {
|
||||||
...this._stats,
|
...this._stats,
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ class HyperP2PGossipMesh extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishBatch (messages, opts = {}) {
|
||||||
|
if (!Array.isArray(messages)) throw new Error('messages array required')
|
||||||
|
return messages.map((msg) => this.publish(msg, opts))
|
||||||
|
}
|
||||||
|
|
||||||
_receive (envelope) {
|
_receive (envelope) {
|
||||||
if (!envelope || envelope.ttl <= 0) return
|
if (!envelope || envelope.ttl <= 0) return
|
||||||
if (this.dedupFilter && this.dedupFilter.seen(envelope.id)) return
|
if (this.dedupFilter && this.dedupFilter.seen(envelope.id)) return
|
||||||
|
|||||||
@@ -87,6 +87,14 @@ class HyperBareImportMap extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has (specifier) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(this._imports, String(specifier))
|
||||||
|
}
|
||||||
|
|
||||||
|
entryCount () {
|
||||||
|
return Object.keys(this._imports).length
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return platformStats(this._stats, PROTOCOL, { entries: Object.keys(this._imports).length })
|
return platformStats(this._stats, PROTOCOL, { entries: Object.keys(this._imports).length })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,16 @@ class HyperPearChannelRegistry extends EventEmitter {
|
|||||||
return stale.length
|
return stale.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channelNames () {
|
||||||
|
return [...this._channels.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
|
unregisterAll () {
|
||||||
|
const names = [...this._channels.keys()]
|
||||||
|
for (const n of names) this.unregister(n)
|
||||||
|
return names.length
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return platformStats(this._stats, PROTOCOL, {
|
return platformStats(this._stats, PROTOCOL, {
|
||||||
channels: this._channels.size,
|
channels: this._channels.size,
|
||||||
|
|||||||
@@ -82,6 +82,12 @@ class HyperPearOtaState extends EventEmitter {
|
|||||||
return this.setProgress(this._state.progress + (Number(delta) || 0))
|
return this.setProgress(this._state.progress + (Number(delta) || 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearHistory () {
|
||||||
|
const n = this._log.length
|
||||||
|
this._log = []
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return platformStats(this._stats, PROTOCOL, {
|
return platformStats(this._stats, PROTOCOL, {
|
||||||
state: this._state.phase,
|
state: this._state.phase,
|
||||||
|
|||||||
@@ -91,6 +91,16 @@ class HyperPearWorkerPipe extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openPipes () {
|
||||||
|
return [...this._pipes.values()].filter((p) => p.open)
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAll () {
|
||||||
|
const ids = [...this._pipes.keys()]
|
||||||
|
for (const id of ids) this.close(id)
|
||||||
|
return ids.length
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return platformStats(this._stats, PROTOCOL, { pipes: this._pipes.size })
|
return platformStats(this._stats, PROTOCOL, { pipes: this._pipes.size })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,14 @@ class HyperP2PBandwidthShare extends EventEmitter {
|
|||||||
return best
|
return best
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offerCount () {
|
||||||
|
return this._offers.size
|
||||||
|
}
|
||||||
|
|
||||||
|
listOffers () {
|
||||||
|
return [...this._offers.values()]
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -109,6 +109,18 @@ class HyperP2PCacheFarm extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
warmBatch (entries) {
|
||||||
|
if (!Array.isArray(entries)) throw new Error('entries array required')
|
||||||
|
let n = 0
|
||||||
|
for (const e of entries) {
|
||||||
|
if (e && e.key != null) {
|
||||||
|
this.put(e.key, e.value, e.ttlMs)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -125,6 +125,14 @@ class HyperP2PDiskStripe extends EventEmitter {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isComplete (stripeId) {
|
||||||
|
return this.missingShards(stripeId).length === 0 && this.progress(stripeId) >= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
stripeIds () {
|
||||||
|
return [...this._stripes.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return clusterStats(this._stats, PROTOCOL, {
|
return clusterStats(this._stats, PROTOCOL, {
|
||||||
open: this._stripes.size,
|
open: this._stripes.size,
|
||||||
|
|||||||
@@ -95,6 +95,18 @@ class HyperP2PGpuSlot extends EventEmitter {
|
|||||||
return s && s.state === 'reserved' ? s.holder : null
|
return s && s.state === 'reserved' ? s.holder : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
releaseAll (holder = null) {
|
||||||
|
const who = holder || this.peerId
|
||||||
|
let n = 0
|
||||||
|
for (const s of this._slots.values()) {
|
||||||
|
if (s.state === 'reserved' && s.holder === who) {
|
||||||
|
this.release(s.slotId)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ class HyperP2PThermalGuard extends EventEmitter {
|
|||||||
return this._samples.size
|
return this._samples.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._samples.size
|
||||||
|
this._samples.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -99,6 +99,13 @@ class HyperP2PWorkStealer extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
let n = 0
|
||||||
|
for (const q of this._queues.values()) n += q.length
|
||||||
|
this._queues.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -74,6 +74,19 @@ class HyperP2PKeyRotation extends EventEmitter {
|
|||||||
return (this._pending.get(keyId) || []).length
|
return (this._pending.get(keyId) || []).length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revokeAll () {
|
||||||
|
const n = this._active.size
|
||||||
|
this._active.clear()
|
||||||
|
this._pending.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
nextActivation (keyId) {
|
||||||
|
const list = this._pending.get(String(keyId)) || []
|
||||||
|
if (!list.length) return null
|
||||||
|
return list.reduce((a, b) => (a.activateAt < b.activateAt ? a : b))
|
||||||
|
}
|
||||||
|
|
||||||
_maybeActivate (keyId, now = Date.now()) {
|
_maybeActivate (keyId, now = Date.now()) {
|
||||||
const list = this._pending.get(keyId) || []
|
const list = this._pending.get(keyId) || []
|
||||||
for (const e of list) {
|
for (const e of list) {
|
||||||
|
|||||||
Reference in New Issue
Block a user