feat(agents,messaging-pubsub): manually expand memory and subscription lease APIs

- agent-memory: recallByTag, forget, exportSnapshot for agent workflows
- subscription-lease: extend, conflicts, isHeld, leaseCount parity with topic-lease

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-05-21 02:15:00 -04:00
co-authored by Cursor
parent f62eaaac13
commit 33a630fe83
2 changed files with 56 additions and 1 deletions
@@ -402,7 +402,33 @@ class HyperP2PAgentMemory extends EventEmitter {
memoryCount () { return this.memories.size } memoryCount () { return this.memories.size }
tagList () { return [...this.tagIndex.keys()] } tagList () {
return [...this.tagIndex.keys()]
}
recallByTag (tag, limit = 50) {
return this.recall({ tags: [tag], limit })
}
forget (memoryId) {
const entry = this.memories.get(memoryId)
if (!entry) return false
this.memories.delete(memoryId)
for (const tag of (entry.tags || [])) {
const set = this.tagIndex.get(tag)
if (set) {
set.delete(memoryId)
if (!set.size) this.tagIndex.delete(tag)
}
}
this.causalLinks.delete(memoryId)
this.emit('forgot', { id: memoryId })
return true
}
exportSnapshot (limit = 100) {
return this.recall({ limit, includeExpired: true })
}
getStats () { getStats () {
return { return {
@@ -77,6 +77,35 @@ class HyperP2PSubscriptionLease extends EventEmitter {
return [...this._leases.values()].filter((l) => l.expiresAt > now) return [...this._leases.values()].filter((l) => l.expiresAt > now)
} }
isHeld (channel) {
return this.holder(channel) != null
}
extend (channel, extraMs) {
const lease = this._leases.get(channel)
if (!lease || lease.holder !== this.ownerHex) return false
const delta = Number(extraMs)
if (!Number.isFinite(delta) || delta < 0) throw new Error('extraMs must be non-negative')
lease.expiresAt += delta
if (this._peerMsgs) {
gossipSend(this, { type: 'sub-lease', lease })
this._stats.gossipOut++
}
this.emit('extend', lease)
return true
}
conflicts (channel) {
const lease = this._leases.get(channel)
if (!lease || lease.expiresAt < Date.now()) return null
if (lease.holder === this.ownerHex) return null
return { holder: lease.holder, expiresAt: lease.expiresAt }
}
leaseCount () {
return this.activeLeases().length
}
_expireSweep () { _expireSweep () {
const now = Date.now() const now = Date.now()
for (const [ch, lease] of this._leases) { for (const [ch, lease] of this._leases) {