feat(communication): Agent Mesh Network — comunicação P2P descentralizada entre agentes#577
feat(communication): Agent Mesh Network — comunicação P2P descentralizada entre agentes#577nikolasdehor wants to merge 0 commit intoSynkraAI:mainfrom
Conversation
|
@nikolasdehor is attempting to deploy a commit to the Pedro Valério Lopez's projects Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThis PR introduces two major core features: an Agent Mesh Network implementation providing peer-to-peer mesh networking with discovery, pub/sub, routing, rate limiting, and health monitoring; and a Decision Memory system for persistent storage and pattern detection of agent decisions. Both include comprehensive test suites and registry updates. Changes
Sequence Diagram(s)sequenceDiagram
participant PeerA as Peer A
participant Router as Mesh Router
participant PeerB as Peer B
participant Queue as Message Queue
PeerA->>Router: send(peerId, message)
alt Adjacent Peer
Router->>PeerB: deliver message
PeerB->>PeerB: emit messageReceived
else Non-Adjacent Peer
Router->>Router: compute shortest path (BFS)
Router->>Router: find intermediary peers
loop For each hop
Router->>Queue: enqueue if offline
Router->>Router: forward to next peer
end
end
PeerB-->>PeerA: messageSent event
sequenceDiagram
participant Agent as Agent
participant Memory as Decision Memory
participant Store as JSON Persistence
participant Detector as Pattern Detector
Agent->>Memory: recordDecision(task, action, context)
Memory->>Memory: auto-detect category
Memory->>Memory: extract keywords
Memory->>Memory: emit decisionRecorded
Memory->>Store: save to decisions.json
Agent->>Memory: getRelevantDecisions(task)
Memory->>Memory: compute keyword similarity
Memory->>Memory: apply time decay
Memory->>Memory: filter by outcome/category
Memory-->>Agent: return ranked decisions
Memory->>Detector: detectPatterns(category)
Detector->>Detector: identify recurring decisions
Detector->>Memory: emit patternDetected
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (5)
.aios-core/core/communication/agent-mesh-network.js (1)
1-2: Use an absolute module path for the compatibility wrapper.This re-export works, but the
../../../...traversal hard-codes the directory layout and violates the repo import rule.Proposed change
+const path = require('path'); + // Wrapper retrocompativel — modulo real em .aiox-core/ -module.exports = require('../../../.aiox-core/core/communication/agent-mesh-network'); +module.exports = require(path.resolve(__dirname, '../../../.aiox-core/core/communication/agent-mesh-network'));As per coding guidelines, "
**/*.{js,jsx,ts,tsx}: Use absolute imports instead of relative imports in all code".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aios-core/core/communication/agent-mesh-network.js around lines 1 - 2, Replace the hard-coded relative require in the compatibility wrapper: instead of module.exports = require('../../../.aiox-core/core/communication/agent-mesh-network'); use the project's absolute module import for the aiox-core package (e.g., the canonical package alias defined in the repo's module resolution) so the wrapper re-exports the same module via an absolute path; update the single module.exports line to require/import the absolute module identifier per the repo import rule.tests/core/memory/decision-memory.test.js (1)
1-9: Use an absolute module path in the test import.This relative traverse into
.aiox-coreviolates the repo import rule and makes the suite brittle to directory layout changes.Proposed change
const path = require('path'); const fs = require('fs'); +const decisionMemoryModule = path.resolve(__dirname, '../../../.aiox-core/core/memory/decision-memory'); const { DecisionMemory, DecisionCategory, Outcome, Events, CONFIG, -} = require('../../../.aiox-core/core/memory/decision-memory'); +} = require(decisionMemoryModule);As per coding guidelines, "
**/*.{js,jsx,ts,tsx}: Use absolute imports instead of relative imports in all code".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/memory/decision-memory.test.js` around lines 1 - 9, The test currently imports DecisionMemory, DecisionCategory, Outcome, Events, and CONFIG via a relative path that traverses into .aiox-core; update the import to use the project's absolute module path (the package or export that exposes DecisionMemory, DecisionCategory, Outcome, Events, CONFIG) so the test imports those symbols via an absolute module name instead of "../../../.aiox-core/core/memory/decision-memory"; locate the import line referencing DecisionMemory/DecisionCategory/Outcome/Events/CONFIG and replace it with the corresponding absolute import according to your repo's module aliases/exports.tests/core/communication/agent-mesh-network.test.js (3)
442-446: Remove unusedsentEventsvariable and handler.The
sentEventsarray is populated by the event handler but never used in any assertions. This appears to be dead code that should be removed.const promise = mesh.request('a1', 'a2', { q: 'status?' }); - // Pegar o messageId da request enviada - const sentEvents = []; - mesh.on(MeshEvent.MESSAGE_SENT, (e) => sentEvents.push(e)); - // O promise ja foi criado, precisamos encontrar o pending request const [requestId] = Array.from(mesh.pendingRequests.keys());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/communication/agent-mesh-network.test.js` around lines 442 - 446, Remove the dead event handler and array by deleting the sentEvents declaration and the mesh.on(MeshEvent.MESSAGE_SENT, (e) => sentEvents.push(e)) line; this cleans up unused variables and listeners (search for sentEvents and the MeshEvent.MESSAGE_SENT handler in the test to locate the exact lines to remove).
36-42: Consider logging or documenting suppressed errors in cleanup.The empty catch block silently ignores all errors during directory cleanup. While acceptable for test cleanup, consider adding a brief comment explaining the intent or logging at debug level for easier troubleshooting.
function cleanupDir(dir) { try { fs.rmSync(dir, { recursive: true, force: true }); - } catch { - // ignore + } catch (err) { + // Cleanup errors are non-fatal in tests; directory may already be removed } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/communication/agent-mesh-network.test.js` around lines 36 - 42, The catch in function cleanupDir currently swallows all errors silently; update the catch block in cleanupDir to either log the caught error at debug/verbose level (e.g., using console.debug or the project test logger) or add a clear comment explaining that errors are intentionally ignored for test teardown; ensure you reference the caught error (e.g., catch (err)) so the logger or comment can include context like the dir path and error message for easier debugging.
11-11: Use absolute import instead of relative import.The coding guidelines require absolute imports. This relative path traverses multiple directories, making it harder to maintain and refactor.
-const AgentMeshNetwork = require('../../../.aiox-core/core/communication/agent-mesh-network'); +const AgentMeshNetwork = require('.aiox-core/core/communication/agent-mesh-network');As per coding guidelines: "Use absolute imports instead of relative imports in all code."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/communication/agent-mesh-network.test.js` at line 11, The test currently uses a relative require('../../../.aiox-core/core/communication/agent-mesh-network') for AgentMeshNetwork; replace it with the project’s absolute import path/alias (e.g. require('core/communication/agent-mesh-network') or the configured package alias like require('@aiox/core/communication/agent-mesh-network')) so the test uses the canonical absolute module import for AgentMeshNetwork and follows the coding guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.aiox-core/core/communication/agent-mesh-network.js:
- Around line 32-44: DEFAULT_OPTIONS sets autoStart: true but the constructor
never triggers the heartbeat machinery; update the constructor of the
AgentMeshNetwork class (or whatever constructor initializes DEFAULT_OPTIONS) to
check options.autoStart and call this.startHeartbeat() when true, ensuring
startHeartbeat() is idempotent and that it wires up heartbeat pruning, TTL
cleanup and partition detection as currently implemented; also preserve existing
behavior when autoStart is false so callers who expect manual start still work.
- Around line 868-890: The save() method currently writes topology.json directly
and can corrupt state on I/O failure; update save() (and the related persist
call path used by _schedulePersist) to use the existing atomicWriteSync from
core/synapse/utils/atomic-write (require it at top) and replace
fs.writeFileSync(filePath, ...) with atomicWriteSync(filePath,
JSON.stringify(data, null, 2), 'utf-8'); wrap the atomic write in a try/catch
that logs or re-throws a contextual error (include filePath and operation)
instead of silently swallowing it so callers/_schedulePersist can observe
failures.
- Around line 910-924: The heartbeat logic can permanently isolate peers because
lastSeen is only updated on outbound activity; update _deliverMessage to call
the same last-seen/activation path as _updateLastSeen (or call _updateLastSeen
directly) so inbound traffic refreshes lastSeen/state and triggers adjacency
restoration; modify _runHeartbeat to, when re-activating a peer via
_updateLastSeen or similar, also rebuild adjacency/edges and flush any queued
messages for that peer (ensure queued messages are drained when state becomes
ACTIVE), and audit other occurrences noted (around lines referenced: 946-964,
986-991, 1030-1045) to apply the same fix where inbound messages should refresh
lastSeen and restore routing/queued-message delivery.
- Around line 681-725: detectPartitions() should be a pure reader: remove the
side-effects inside detectPartitions by deleting the stats increment
(this.stats.partitionsDetected++) and the event emission
(this._emitSafe(MeshEvent.PARTITION_DETECTED, ...)); leave the algorithm that
computes and returns partitions unchanged. Ensure callers that need to
record/emit on partition detection (e.g., getNetworkHealth(), getMeshStats())
explicitly check the returned partitions length and perform the stats increment
and this._emitSafe(MeshEvent.PARTITION_DETECTED, { partitions }) there instead.
In @.aiox-core/core/memory/decision-memory.js:
- Around line 138-181: The save() method currently writes decisions.json
in-place and can corrupt the file on partial writes; update save() to use the
existing atomic write helper by requiring atomicWriteSync from
'../synapse/utils/atomic-write' and replace fs.writeFileSync(filePath,
JSON.stringify(...), 'utf-8') with an atomicWriteSync(filePath,
JSON.stringify(data, null, 2), 'utf-8') call; keep the existing directory
creation logic, and ensure any I/O errors from atomicWriteSync are allowed to
surface or are caught and logged consistently with the class's error handling
(refer to the save() and load() methods and the atomicWriteSync symbol to locate
changes).
In @.aiox-core/data/entity-registry.yaml:
- Around line 12781-12797: The registry entry for agent-mesh-network (path
.aiox-core/core/communication/agent-mesh-network.js) is missing the standard
fields `externalDeps`, `plannedDeps`, and `lifecycle`; add those keys to the
entry using the same shapes as sibling entries (e.g., `externalDeps: []`,
`plannedDeps: []` and a `lifecycle` object with the usual lifecycle properties
your registry uses) so the record matches the expected schema and
validators/consumers do not need special-casing for agent-mesh-network.
---
Nitpick comments:
In @.aios-core/core/communication/agent-mesh-network.js:
- Around line 1-2: Replace the hard-coded relative require in the compatibility
wrapper: instead of module.exports =
require('../../../.aiox-core/core/communication/agent-mesh-network'); use the
project's absolute module import for the aiox-core package (e.g., the canonical
package alias defined in the repo's module resolution) so the wrapper re-exports
the same module via an absolute path; update the single module.exports line to
require/import the absolute module identifier per the repo import rule.
In `@tests/core/communication/agent-mesh-network.test.js`:
- Around line 442-446: Remove the dead event handler and array by deleting the
sentEvents declaration and the mesh.on(MeshEvent.MESSAGE_SENT, (e) =>
sentEvents.push(e)) line; this cleans up unused variables and listeners (search
for sentEvents and the MeshEvent.MESSAGE_SENT handler in the test to locate the
exact lines to remove).
- Around line 36-42: The catch in function cleanupDir currently swallows all
errors silently; update the catch block in cleanupDir to either log the caught
error at debug/verbose level (e.g., using console.debug or the project test
logger) or add a clear comment explaining that errors are intentionally ignored
for test teardown; ensure you reference the caught error (e.g., catch (err)) so
the logger or comment can include context like the dir path and error message
for easier debugging.
- Line 11: The test currently uses a relative
require('../../../.aiox-core/core/communication/agent-mesh-network') for
AgentMeshNetwork; replace it with the project’s absolute import path/alias (e.g.
require('core/communication/agent-mesh-network') or the configured package alias
like require('@aiox/core/communication/agent-mesh-network')) so the test uses
the canonical absolute module import for AgentMeshNetwork and follows the coding
guideline.
In `@tests/core/memory/decision-memory.test.js`:
- Around line 1-9: The test currently imports DecisionMemory, DecisionCategory,
Outcome, Events, and CONFIG via a relative path that traverses into .aiox-core;
update the import to use the project's absolute module path (the package or
export that exposes DecisionMemory, DecisionCategory, Outcome, Events, CONFIG)
so the test imports those symbols via an absolute module name instead of
"../../../.aiox-core/core/memory/decision-memory"; locate the import line
referencing DecisionMemory/DecisionCategory/Outcome/Events/CONFIG and replace it
with the corresponding absolute import according to your repo's module
aliases/exports.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 08afb71f-f4bc-4a88-84bd-b23095ea08a5
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (7)
.aios-core/core/communication/agent-mesh-network.js.aiox-core/core/communication/agent-mesh-network.js.aiox-core/core/memory/decision-memory.js.aiox-core/data/entity-registry.yaml.aiox-core/install-manifest.yamltests/core/communication/agent-mesh-network.test.jstests/core/memory/decision-memory.test.js
| const DEFAULT_OPTIONS = { | ||
| heartbeatInterval: 30000, | ||
| peerTimeout: 90000, | ||
| maxQueueSize: 100, | ||
| messageTTL: 300000, | ||
| requestTimeout: 10000, | ||
| rateLimit: { | ||
| tokensPerInterval: 50, | ||
| interval: 60000, | ||
| }, | ||
| persistenceDir: '.aiox/mesh', | ||
| autoStart: true, | ||
| }; |
There was a problem hiding this comment.
Honor the documented autoStart default.
DEFAULT_OPTIONS.autoStart is true, but the constructor never calls startHeartbeat(). As written, heartbeat pruning, TTL cleanup, and partition detection stay off unless every caller remembers to start them manually.
Proposed change
/** `@type` {Promise} Cadeia de persistencia serializada */
this._writeChain = Promise.resolve();
this._started = false;
+
+ if (this.options.autoStart) {
+ this.startHeartbeat();
+ }
}As per coding guidelines, ".aiox-core/core/**: Ensure backwards compatibility — core modules are consumed by all agents."
Also applies to: 89-141
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/communication/agent-mesh-network.js around lines 32 - 44,
DEFAULT_OPTIONS sets autoStart: true but the constructor never triggers the
heartbeat machinery; update the constructor of the AgentMeshNetwork class (or
whatever constructor initializes DEFAULT_OPTIONS) to check options.autoStart and
call this.startHeartbeat() when true, ensuring startHeartbeat() is idempotent
and that it wires up heartbeat pruning, TTL cleanup and partition detection as
currently implemented; also preserve existing behavior when autoStart is false
so callers who expect manual start still work.
| detectPartitions() { | ||
| const visited = new Set(); | ||
| const partitions = []; | ||
|
|
||
| const activePeers = Array.from(this.peers.entries()) | ||
| .filter(([, p]) => p.state === PeerState.ACTIVE) | ||
| .map(([id]) => id); | ||
|
|
||
| for (const peerId of activePeers) { | ||
| if (visited.has(peerId)) continue; | ||
|
|
||
| const component = []; | ||
| const stack = [peerId]; | ||
|
|
||
| while (stack.length > 0) { | ||
| const current = stack.pop(); | ||
| if (visited.has(current)) continue; | ||
| visited.add(current); | ||
| component.push(current); | ||
|
|
||
| const neighbors = this.adjacency.get(current); | ||
| if (neighbors) { | ||
| for (const neighbor of neighbors) { | ||
| if (!visited.has(neighbor)) { | ||
| const neighborPeer = this.peers.get(neighbor); | ||
| if (neighborPeer && neighborPeer.state === PeerState.ACTIVE) { | ||
| stack.push(neighbor); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (component.length > 0) { | ||
| partitions.push(component.sort()); | ||
| } | ||
| } | ||
|
|
||
| if (partitions.length > 1) { | ||
| this.stats.partitionsDetected++; | ||
| this._emitSafe(MeshEvent.PARTITION_DETECTED, { partitions }); | ||
| } | ||
|
|
||
| return partitions; | ||
| } |
There was a problem hiding this comment.
Make detectPartitions() a pure read.
This method increments stats.partitionsDetected and emits PARTITION_DETECTED every time it finds multiple components. Since getNetworkHealth() and getMeshStats() call it, simple health polling will inflate metrics and spam partition events.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/communication/agent-mesh-network.js around lines 681 - 725,
detectPartitions() should be a pure reader: remove the side-effects inside
detectPartitions by deleting the stats increment
(this.stats.partitionsDetected++) and the event emission
(this._emitSafe(MeshEvent.PARTITION_DETECTED, ...)); leave the algorithm that
computes and returns partitions unchanged. Ensure callers that need to
record/emit on partition detection (e.g., getNetworkHealth(), getMeshStats())
explicitly check the returned partitions length and perform the stats increment
and this._emitSafe(MeshEvent.PARTITION_DETECTED, { partitions }) there instead.
| async save() { | ||
| const filePath = this._getTopologyPath(); | ||
| const dir = path.dirname(filePath); | ||
|
|
||
| const data = { | ||
| schemaVersion: 'agent-mesh-v1', | ||
| version: '1.0.0', | ||
| savedAt: new Date().toISOString(), | ||
| peers: Array.from(this.peers.values()).map(p => ({ | ||
| id: p.id, | ||
| capabilities: p.capabilities, | ||
| topics: Array.from(p.topics), | ||
| state: p.state, | ||
| joinedAt: p.joinedAt, | ||
| })), | ||
| stats: this.stats, | ||
| }; | ||
|
|
||
| if (!fs.existsSync(dir)) { | ||
| fs.mkdirSync(dir, { recursive: true }); | ||
| } | ||
| fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8'); | ||
| } |
There was a problem hiding this comment.
Don't silently lose topology state on failed writes.
save() overwrites topology.json directly, and _schedulePersist() discards any resulting error. A crash or I/O failure can therefore leave a truncated file with no signal to the caller. The repo already has .aiox-core/core/synapse/utils/atomic-write.js for this write pattern.
Proposed change
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
+ atomicWriteSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
@@
- this._writeChain = this._writeChain.then(() => this.save()).catch(() => {
- // Falha silenciosa na persistencia
- });
+ this._writeChain = this._writeChain
+ .then(() => this.save())
+ .catch((error) => {
+ this._emitSafe('error', new Error(`Failed to persist mesh topology: ${error.message}`));
+ });const { atomicWriteSync } = require(path.resolve(__dirname, '../synapse/utils/atomic-write'));As per coding guidelines, ".aiox-core/core/**: Verify error handling is comprehensive with proper try/catch and error context."
Also applies to: 1059-1063
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/communication/agent-mesh-network.js around lines 868 - 890,
The save() method currently writes topology.json directly and can corrupt state
on I/O failure; update save() (and the related persist call path used by
_schedulePersist) to use the existing atomicWriteSync from
core/synapse/utils/atomic-write (require it at top) and replace
fs.writeFileSync(filePath, ...) with atomicWriteSync(filePath,
JSON.stringify(data, null, 2), 'utf-8'); wrap the atomic write in a try/catch
that logs or re-throws a contextual error (include filePath and operation)
instead of silently swallowing it so callers/_schedulePersist can observe
failures.
| _deliverMessage(msg) { | ||
| const toPeer = this.peers.get(msg.to); | ||
| if (toPeer) { | ||
| toPeer.messageCount++; | ||
| } | ||
|
|
||
| this.stats.messagesReceived++; | ||
| this._emitSafe(MeshEvent.MESSAGE_RECEIVED, { | ||
| messageId: msg.id, | ||
| from: msg.from, | ||
| to: msg.to, | ||
| type: msg.type, | ||
| payload: msg.payload, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Heartbeat can permanently isolate healthy peers.
lastSeen only changes on outbound activity, so a peer that only receives traffic will eventually time out. After that, _runHeartbeat() clears its adjacency, but _updateLastSeen() only flips state back to ACTIVE; it never rebuilds edges or drain queued messages. Once a peer times out, routing to/from that peer stays broken and queued traffic never flushes.
Proposed change
_deliverMessage(msg) {
const toPeer = this.peers.get(msg.to);
if (toPeer) {
toPeer.messageCount++;
+ this._updateLastSeen(msg.to);
}
@@
_updateLastSeen(agentId) {
const peer = this.peers.get(agentId);
if (peer) {
+ const wasInactive = peer.state !== PeerState.ACTIVE;
peer.lastSeen = Date.now();
peer.state = PeerState.ACTIVE;
+
+ if (wasInactive) {
+ if (!this.adjacency.has(agentId)) {
+ this.adjacency.set(agentId, new Set());
+ }
+
+ for (const [otherId, otherPeer] of this.peers) {
+ if (otherId !== agentId && otherPeer.state === PeerState.ACTIVE) {
+ this.adjacency.get(agentId).add(otherId);
+ this.adjacency.get(otherId)?.add(agentId);
+ }
+ }
+
+ this._drainQueue(agentId);
+ }
}
}Also applies to: 946-964, 986-991, 1030-1045
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/communication/agent-mesh-network.js around lines 910 - 924,
The heartbeat logic can permanently isolate peers because lastSeen is only
updated on outbound activity; update _deliverMessage to call the same
last-seen/activation path as _updateLastSeen (or call _updateLastSeen directly)
so inbound traffic refreshes lastSeen/state and triggers adjacency restoration;
modify _runHeartbeat to, when re-activating a peer via _updateLastSeen or
similar, also rebuild adjacency/edges and flush any queued messages for that
peer (ensure queued messages are drained when state becomes ACTIVE), and audit
other occurrences noted (around lines referenced: 946-964, 986-991, 1030-1045)
to apply the same fix where inbound messages should refresh lastSeen and restore
routing/queued-message delivery.
| async load() { | ||
| const filePath = path.resolve(this.projectRoot, this.config.decisionsJsonPath); | ||
|
|
||
| try { | ||
| if (fs.existsSync(filePath)) { | ||
| const raw = fs.readFileSync(filePath, 'utf-8'); | ||
| const data = JSON.parse(raw); | ||
|
|
||
| if (data.schemaVersion === this.config.schemaVersion) { | ||
| this.decisions = data.decisions || []; | ||
| this.patterns = data.patterns || []; | ||
| } | ||
| } | ||
| } catch { | ||
| // Corrupted file — start fresh | ||
| this.decisions = []; | ||
| this.patterns = []; | ||
| } | ||
|
|
||
| this._loaded = true; | ||
| } | ||
|
|
||
| /** | ||
| * Save decisions to disk | ||
| * @returns {Promise<void>} | ||
| */ | ||
| async save() { | ||
| const filePath = path.resolve(this.projectRoot, this.config.decisionsJsonPath); | ||
| const dir = path.dirname(filePath); | ||
|
|
||
| if (!fs.existsSync(dir)) { | ||
| fs.mkdirSync(dir, { recursive: true }); | ||
| } | ||
|
|
||
| const data = { | ||
| schemaVersion: this.config.schemaVersion, | ||
| version: this.config.version, | ||
| updatedAt: new Date().toISOString(), | ||
| stats: this.getStats(), | ||
| decisions: this.decisions.slice(-this.config.maxDecisions), | ||
| patterns: this.patterns, | ||
| }; | ||
|
|
||
| fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8'); |
There was a problem hiding this comment.
Make decision persistence crash-safe.
save() replaces .aiox/decisions.json in place, while load() treats parse failures as "start fresh". A partial write will therefore wipe the decision history on the next startup. Reuse the existing atomic write helper here too.
Proposed change
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
+ atomicWriteSync(filePath, JSON.stringify(data, null, 2), 'utf-8');const { atomicWriteSync } = require(path.resolve(__dirname, '../synapse/utils/atomic-write'));As per coding guidelines, ".aiox-core/core/**: Verify error handling is comprehensive with proper try/catch and error context."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/memory/decision-memory.js around lines 138 - 181, The save()
method currently writes decisions.json in-place and can corrupt the file on
partial writes; update save() to use the existing atomic write helper by
requiring atomicWriteSync from '../synapse/utils/atomic-write' and replace
fs.writeFileSync(filePath, JSON.stringify(...), 'utf-8') with an
atomicWriteSync(filePath, JSON.stringify(data, null, 2), 'utf-8') call; keep the
existing directory creation logic, and ensure any I/O errors from
atomicWriteSync are allowed to surface or are caught and logged consistently
with the class's error handling (refer to the save() and load() methods and the
atomicWriteSync symbol to locate changes).
.aiox-core/data/entity-registry.yaml
Outdated
| agent-mesh-network: | ||
| path: .aiox-core/core/communication/agent-mesh-network.js | ||
| layer: L1 | ||
| type: module | ||
| purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js | ||
| keywords: | ||
| - agent | ||
| - mesh | ||
| - network | ||
| usedBy: [] | ||
| dependencies: [] | ||
| adaptability: | ||
| score: 0.4 | ||
| constraints: [] | ||
| extensionPoints: [] | ||
| checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d | ||
| lastVerified: '2026-03-10T14:29:32.610Z' |
There was a problem hiding this comment.
Add the missing standard registry fields.
This entry is missing externalDeps, plannedDeps, and lifecycle, while sibling entities in this file include them. Leaving this row with a different shape makes registry consumers and validators handle a special case for just this module.
Suggested fix
agent-mesh-network:
path: .aiox-core/core/communication/agent-mesh-network.js
layer: L1
type: module
purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js
keywords:
- agent
- mesh
- network
usedBy: []
dependencies: []
+ externalDeps: []
+ plannedDeps: []
+ lifecycle: production
adaptability:
score: 0.4
constraints: []
extensionPoints: []
checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| agent-mesh-network: | |
| path: .aiox-core/core/communication/agent-mesh-network.js | |
| layer: L1 | |
| type: module | |
| purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js | |
| keywords: | |
| - agent | |
| - mesh | |
| - network | |
| usedBy: [] | |
| dependencies: [] | |
| adaptability: | |
| score: 0.4 | |
| constraints: [] | |
| extensionPoints: [] | |
| checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d | |
| lastVerified: '2026-03-10T14:29:32.610Z' | |
| agent-mesh-network: | |
| path: .aiox-core/core/communication/agent-mesh-network.js | |
| layer: L1 | |
| type: module | |
| purpose: Entity at .aiox-core/core/communication/agent-mesh-network.js | |
| keywords: | |
| - agent | |
| - mesh | |
| - network | |
| usedBy: [] | |
| dependencies: [] | |
| externalDeps: [] | |
| plannedDeps: [] | |
| lifecycle: production | |
| adaptability: | |
| score: 0.4 | |
| constraints: [] | |
| extensionPoints: [] | |
| checksum: sha256:9149abe1f1cc874d8c5d48d4e00846c617eaf416c93bc0f075a78def17b1e99d | |
| lastVerified: '2026-03-10T14:29:32.610Z' |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/data/entity-registry.yaml around lines 12781 - 12797, The
registry entry for agent-mesh-network (path
.aiox-core/core/communication/agent-mesh-network.js) is missing the standard
fields `externalDeps`, `plannedDeps`, and `lifecycle`; add those keys to the
entry using the same shapes as sibling entries (e.g., `externalDeps: []`,
`plannedDeps: []` and a `lifecycle` object with the usual lifecycle properties
your registry uses) so the record matches the expected schema and
validators/consumers do not need special-casing for agent-mesh-network.
|
@Pedrovaleriolopez @oalanicolas, Agent Mesh Network — comunicação P2P descentralizada entre agentes com roteamento BFS, detecção de partições, rate limiting por token bucket, e pub/sub por tópicos. 103 testes. Junto com o Immortality Protocol (#576), fecha o ciclo de resiliência do framework. |
aa89169 to
ff711c1
Compare
Resumo
Rede mesh descentralizada para comunicação peer-to-peer entre agentes. Sem orquestrador central — agentes se descobrem, formam grupos ad-hoc, enviam mensagens e roteiam através da mesh.
Funcionalidades
Arquivos
.aiox-core/core/communication/agent-mesh-network.js.aios-core/core/communication/agent-mesh-network.jstests/core/communication/agent-mesh-network.test.jsTest plan
Summary by CodeRabbit
New Features
Tests