Skip to content

Commit a79e76c

Browse files
Release v0.1.8 — P2P Bridge & Cortex 0.3.8 (#21)
## Summary - P2P config parsing and sidecar flag forwarding for native QUIC transport - CortexClient P2P methods: status, list/add/remove peers, probe - Dual sync mode in cortex-sync: native (QUIC gossip) vs polled (REST) with graceful degradation - Sync CLI enhancements with native P2P info display - Bumped to v0.1.8, requires Cortex >= 0.3.8 ## Test plan - [x] `pnpm test` — 907 files, 7859 tests all pass - [x] Full E2E: Mayros CLI + CortexClient against live Cortex with P2P (8 steps verified) - [x] `pnpm build` clean
2 parents 1d652a7 + a3df352 commit a79e76c

File tree

69 files changed

+1587
-73
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1587
-73
lines changed

extensions/agent-mesh/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-agent-mesh",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"private": true,
55
"description": "Mayros multi-agent coordination mesh with shared namespaces, delegation, and knowledge fusion",
66
"type": "module",

extensions/analytics/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-analytics",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"private": true,
55
"type": "module",
66
"main": "index.ts",

extensions/bash-sandbox/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-bash-sandbox",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"private": true,
55
"description": "Bash command sandbox with domain allowlist, command blocklist, and dangerous pattern detection",
66
"type": "module",

extensions/bluebubbles/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-bluebubbles",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"description": "Mayros BlueBubbles channel plugin",
55
"license": "MIT",
66
"type": "module",

extensions/ci-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-ci-plugin",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"description": "CI/CD pipeline integration for Mayros — GitHub Actions and GitLab CI providers",
55
"type": "module",
66
"dependencies": {

extensions/code-indexer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-code-indexer",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"private": true,
55
"description": "Mayros code indexer plugin — regex-based codebase scanning with RDF triple storage in Cortex",
66
"type": "module",

extensions/code-tools/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-code-tools",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"private": true,
55
"type": "module",
66
"dependencies": {

extensions/copilot-proxy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apilium/mayros-copilot-proxy",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"private": true,
55
"description": "Mayros Copilot Proxy provider plugin",
66
"type": "module",
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* Tests for cortex-sync configuration parsing, including P2P bridge (B3).
3+
*/
4+
5+
import { describe, expect, it } from "vitest";
6+
import { parseCortexSyncConfig, type CortexSyncConfig } from "./config.js";
7+
8+
describe("parseCortexSyncConfig", () => {
9+
it("returns defaults for empty input", () => {
10+
const cfg = parseCortexSyncConfig({});
11+
expect(cfg.namespace).toBe("mayros");
12+
expect(cfg.sync.intervalSeconds).toBe(300);
13+
expect(cfg.sync.autoSync).toBe(false);
14+
expect(cfg.sync.conflictStrategy).toBe("last-writer-wins");
15+
expect(cfg.sync.maxTriplesPerSync).toBe(5000);
16+
expect(cfg.sync.syncTimeoutMs).toBe(30000);
17+
expect(cfg.sync.nativeP2pPreferred).toBe(true);
18+
expect(cfg.discovery.bonjourEnabled).toBe(false);
19+
expect(cfg.discovery.manualPeers).toEqual([]);
20+
});
21+
22+
it("nativeP2pPreferred defaults to true", () => {
23+
const cfg = parseCortexSyncConfig({});
24+
expect(cfg.sync.nativeP2pPreferred).toBe(true);
25+
});
26+
27+
it("nativeP2pPreferred can be set to false", () => {
28+
const cfg = parseCortexSyncConfig({
29+
sync: { nativeP2pPreferred: false },
30+
});
31+
expect(cfg.sync.nativeP2pPreferred).toBe(false);
32+
});
33+
34+
it("nativeP2pPreferred true is respected", () => {
35+
const cfg = parseCortexSyncConfig({
36+
sync: { nativeP2pPreferred: true },
37+
});
38+
expect(cfg.sync.nativeP2pPreferred).toBe(true);
39+
});
40+
41+
it("clamps intervalSeconds to range", () => {
42+
const cfg1 = parseCortexSyncConfig({ sync: { intervalSeconds: 1 } });
43+
expect(cfg1.sync.intervalSeconds).toBe(10);
44+
45+
const cfg2 = parseCortexSyncConfig({ sync: { intervalSeconds: 100000 } });
46+
expect(cfg2.sync.intervalSeconds).toBe(86400);
47+
});
48+
49+
it("clamps maxTriplesPerSync to range", () => {
50+
const cfg1 = parseCortexSyncConfig({ sync: { maxTriplesPerSync: 1 } });
51+
expect(cfg1.sync.maxTriplesPerSync).toBe(100);
52+
53+
const cfg2 = parseCortexSyncConfig({ sync: { maxTriplesPerSync: 100000 } });
54+
expect(cfg2.sync.maxTriplesPerSync).toBe(50000);
55+
});
56+
57+
it("parses valid conflictStrategy", () => {
58+
const cfg = parseCortexSyncConfig({
59+
sync: { conflictStrategy: "keep-both" },
60+
});
61+
expect(cfg.sync.conflictStrategy).toBe("keep-both");
62+
});
63+
64+
it("falls back to default for invalid conflictStrategy", () => {
65+
const cfg = parseCortexSyncConfig({
66+
sync: { conflictStrategy: "invalid" },
67+
});
68+
expect(cfg.sync.conflictStrategy).toBe("last-writer-wins");
69+
});
70+
71+
it("parses manual peers", () => {
72+
const cfg = parseCortexSyncConfig({
73+
discovery: {
74+
manualPeers: [
75+
{
76+
nodeId: "node1",
77+
endpoint: "http://localhost:8080",
78+
namespaces: ["ns1"],
79+
enabled: true,
80+
},
81+
],
82+
},
83+
});
84+
expect(cfg.discovery.manualPeers).toHaveLength(1);
85+
expect(cfg.discovery.manualPeers[0].nodeId).toBe("node1");
86+
});
87+
88+
it("filters invalid manual peers (missing nodeId or endpoint)", () => {
89+
const cfg = parseCortexSyncConfig({
90+
discovery: {
91+
manualPeers: [
92+
{ nodeId: "", endpoint: "http://localhost:8080" },
93+
{ nodeId: "valid", endpoint: "" },
94+
{ nodeId: "ok", endpoint: "http://valid" },
95+
],
96+
},
97+
});
98+
expect(cfg.discovery.manualPeers).toHaveLength(1);
99+
expect(cfg.discovery.manualPeers[0].nodeId).toBe("ok");
100+
});
101+
102+
it("rejects unknown sync keys", () => {
103+
expect(() => parseCortexSyncConfig({ sync: { bogus: true } })).toThrow("unknown keys");
104+
});
105+
});

extensions/cortex-sync/config.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type SyncConfig = {
3636
conflictStrategy: ConflictStrategy;
3737
maxTriplesPerSync: number;
3838
syncTimeoutMs: number;
39+
nativeP2pPreferred: boolean;
3940
};
4041

4142
export type DiscoveryConfig = {
@@ -80,7 +81,14 @@ function parseSyncConfig(raw: unknown): SyncConfig {
8081
if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
8182
assertAllowedKeys(
8283
sync,
83-
["intervalSeconds", "autoSync", "conflictStrategy", "maxTriplesPerSync", "syncTimeoutMs"],
84+
[
85+
"intervalSeconds",
86+
"autoSync",
87+
"conflictStrategy",
88+
"maxTriplesPerSync",
89+
"syncTimeoutMs",
90+
"nativeP2pPreferred",
91+
],
8492
"sync config",
8593
);
8694
}
@@ -110,7 +118,17 @@ function parseSyncConfig(raw: unknown): SyncConfig {
110118
? Math.max(5000, Math.min(120000, Math.floor(sync.syncTimeoutMs)))
111119
: DEFAULT_SYNC_TIMEOUT_MS;
112120

113-
return { intervalSeconds, autoSync, conflictStrategy, maxTriplesPerSync, syncTimeoutMs };
121+
const nativeP2pPreferred =
122+
typeof sync.nativeP2pPreferred === "boolean" ? sync.nativeP2pPreferred : true;
123+
124+
return {
125+
intervalSeconds,
126+
autoSync,
127+
conflictStrategy,
128+
maxTriplesPerSync,
129+
syncTimeoutMs,
130+
nativeP2pPreferred,
131+
};
114132
}
115133

116134
function parsePeerConfig(raw: unknown): SyncPeerConfig {
@@ -195,5 +213,10 @@ export const cortexSyncConfigUiHints = {
195213
default: DEFAULT_BONJOUR_ENABLED,
196214
description: "Enable local network peer discovery",
197215
},
216+
"sync.nativeP2pPreferred": {
217+
type: "boolean",
218+
default: true,
219+
description: "Prefer native P2P gossip over REST polling when available",
220+
},
198221
"discovery.manualPeers": { type: "array", description: "Manually configured peers" },
199222
} as const;

0 commit comments

Comments
 (0)