Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions src/bridges/claude-code/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,15 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

import {
MeshStore,
CommsTool,
createBridgeMesh,
buildAction,
ensureRegistered,
extractStreamingBehavior,
formatDeliveryEvent,
isActionableEvent,
MCP_TOOL_PARAMS,
} from "../../core/index.js";
import { TlsTransport } from "../../core/tls-transport.js";
import {
loadOrCreateIdentity,
releaseIdentityLock,
type IdentitySlot,
} from "../../core/identity-store.js";
Expand Down Expand Up @@ -155,17 +152,12 @@ function drainPending(filePath: string): string[] {
}

export async function run(): Promise<void> {
// Persistent identity for this slot: a stable fingerprint means the agent
// ID survives restarts, so peers can keep targeting us
// Persistent identity for this slot: a stable device-id means the agent ID survives restarts, so peers can keep targeting us
const identitySlot: IdentitySlot = {
harness: "claude-code",
cwd: process.cwd(),
};
const identity = loadOrCreateIdentity(identitySlot);
const store = new MeshStore();
store.peerId = identity.fingerprint;
store.setTransport(new TlsTransport(store.events, identity));
const tool = new CommsTool(store, store.discovery);
const { store, tool } = createBridgeMesh(identitySlot);
let agentId: string | undefined;

const claudeCodePid = findClaudeCodePid();
Expand Down
19 changes: 4 additions & 15 deletions src/bridges/codex/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,13 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

import {
MeshStore,
CommsTool,
createBridgeMesh,
buildAction,
ensureRegistered,
drainAndFormat,
MCP_TOOL_PARAMS,
} from "../../core/index.js";
import { TlsTransport } from "../../core/tls-transport.js";
import {
loadOrCreateIdentity,
type IdentitySlot,
} from "../../core/identity-store.js";
import type { IdentitySlot } from "../../core/identity-store.js";
import { tryStartWebServer } from "../user/web/server.js";
import { nanoid } from "../../core/nanoid.js";

Expand All @@ -32,15 +27,9 @@ function isRecord(value: unknown): value is Record<string, unknown> {
}

export async function run(): Promise<void> {
// Persistent identity for this slot: a stable fingerprint means the agent
// ID survives restarts, so peers can keep targeting us. The stdio server
// has no graceful shutdown hook; a stale lock self-heals via the pid probe.
// Persistent identity for this slot: a stable device-id means the agent ID survives restarts, so peers can keep targeting us. The stdio server has no graceful shutdown hook; a stale lock self-heals via the pid probe.
const identitySlot: IdentitySlot = { harness: "codex", cwd: process.cwd() };
const identity = loadOrCreateIdentity(identitySlot);
const store = new MeshStore();
store.peerId = identity.fingerprint;
store.setTransport(new TlsTransport(store.events, identity));
const tool = new CommsTool(store, store.discovery);
const { store, tool } = createBridgeMesh(identitySlot);
Comment thread
Mearman marked this conversation as resolved.
let agentId: string | undefined;

const mcp = new McpServer(
Expand Down
17 changes: 4 additions & 13 deletions src/bridges/opencode/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,17 @@
*/

import {
MeshStore,
createBridgeMesh,
ensureRegistered,
formatDeliveryEvent,
} from "../../core/index.js";
import { TlsTransport } from "../../core/tls-transport.js";
import {
loadOrCreateIdentity,
type IdentitySlot,
} from "../../core/identity-store.js";
import type { IdentitySlot } from "../../core/identity-store.js";
import { tryStartWebServer } from "../user/web/server.js";
import { nanoid } from "../../core/nanoid.js";

// Persistent identity for this slot: a stable fingerprint means the agent
// ID survives restarts, so peers can keep targeting us. A plugin unload has
// no hook here; a stale lock self-heals via the pid probe.
// Persistent identity for this slot: a stable device-id means the agent ID survives restarts, so peers can keep targeting us. A plugin unload has no hook here; a stale lock self-heals via the pid probe.
const identitySlot: IdentitySlot = { harness: "opencode", cwd: process.cwd() };
const identity = loadOrCreateIdentity(identitySlot);
const store = new MeshStore();
store.peerId = identity.fingerprint;
store.setTransport(new TlsTransport(store.events, identity));
const { store } = createBridgeMesh(identitySlot);

// Minimal interface for the OpenCode SDK client we actually use
interface OpenCodeClient {
Expand Down
14 changes: 3 additions & 11 deletions src/bridges/pi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,15 @@ import { Type } from "typebox";
import { StringEnum } from "@mariozechner/pi-ai";

import {
MeshStore,
CommsTool,
createBridgeMesh,
buildAction,
ensureProjectRoom,
ensureRegistered,
extractStreamingBehavior,
formatDeliveryEvent,
isActionableEvent,
} from "../../core/index.js";
import { TlsTransport } from "../../core/tls-transport.js";
import {
loadOrCreateIdentity,
releaseIdentityLock,
type IdentitySlot,
} from "../../core/identity-store.js";
Expand All @@ -45,14 +42,9 @@ function getWebPort(handle: WebServerHandle): number | undefined {
}

export default function (pi: ExtensionAPI) {
// Persistent identity for this slot: a stable fingerprint means the agent
// ID survives restarts, so peers can keep targeting us
// Persistent identity for this slot: a stable device-id means the agent ID survives restarts, so peers can keep targeting us
const identitySlot: IdentitySlot = { harness: "pi", cwd: process.cwd() };
const identity = loadOrCreateIdentity(identitySlot);
const store = new MeshStore();
store.peerId = identity.fingerprint;
store.setTransport(new TlsTransport(store.events, identity));
const tool = new CommsTool(store, store.discovery);
const { store, tool } = createBridgeMesh(identitySlot);

let agentId: string | undefined;
let webHandle: WebServerHandle | undefined;
Expand Down
14 changes: 5 additions & 9 deletions src/bridges/user/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import { EventEmitter } from "node:events";
import {
MeshStore,
CommsTool,
createBridgeMesh,
ensureRegistered,
formatDeliveryEvent,
} from "../../core/index.js";
import { TlsTransport } from "../../core/tls-transport.js";
import {
loadOrCreateIdentity,
releaseIdentityLock,
type IdentitySlot,
} from "../../core/identity-store.js";
Expand Down Expand Up @@ -48,15 +47,12 @@ export class ChatController extends EventEmitter {
coordinatorPort?: number,
) {
super();
// Persistent identity for the web user's slot so the chat identity
// survives relaunches of the standalone web CLI
// Persistent identity for the web user's slot so the chat identity survives relaunches of the standalone web CLI
const identitySlot: IdentitySlot = { harness: "user", cwd: process.cwd() };
this.ownedIdentitySlot = identitySlot;
const identity = loadOrCreateIdentity(identitySlot);
this.store = new MeshStore(coordinatorPort);
this.store.peerId = identity.fingerprint;
this.store.setTransport(new TlsTransport(this.store.events, identity));
this.tool = new CommsTool(this.store, this.store.discovery);
const { store, tool } = createBridgeMesh(identitySlot, coordinatorPort);
this.store = store;
this.tool = tool;

// Push delivery events to UIs
this.store.onDelivery = (_agentId: string, event: DeliveryEvent) => {
Expand Down
23 changes: 9 additions & 14 deletions src/test/approval.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,9 @@ function findFreePort(): Promise<number> {
});
}

/** Unique port counter to avoid reusing ports across sequential tests. */
let portOffset = 0;

/** Find a free port with a unique offset to avoid conflicts. */
async function uniquePort(): Promise<number> {
portOffset += 10;
const base = await findFreePort();
return base + portOffset;
/** Find a free port for a single test's use. An alias for findFreePort(): asking the OS for a fresh ephemeral port each call already guarantees distinctness from any other currently-bound port, so no arithmetic offset is layered on top -- a prior +offset scheme could push an already-high OS-assigned port past 65535 and fail with ERR_SOCKET_BAD_PORT. */
function uniquePort(): Promise<number> {
return findFreePort();
}

function sleep(ms: number): Promise<void> {
Expand All @@ -45,7 +40,7 @@ function sleep(ms: number): Promise<void> {
describe("connection approval", () => {
void test("coordinator receives connection_request from connecting peer", async () => {
const portA = await uniquePort();
const portB = portA + 100;
const portB = await uniquePort();

// Set up coordinator (store A)
const storeA = new MeshStore(portA);
Expand Down Expand Up @@ -121,7 +116,7 @@ describe("connection approval", () => {

void test("accept establishes the peer connection", async () => {
const portA = await uniquePort();
const portB = portA + 100;
const portB = await uniquePort();

const storeA = new MeshStore(portA);
wireTestTransport(storeA);
Expand Down Expand Up @@ -200,7 +195,7 @@ describe("connection approval", () => {

void test("reject closes with reason", async () => {
const portA = await uniquePort();
const portB = portA + 100;
const portB = await uniquePort();

const storeA = new MeshStore(portA);
wireTestTransport(storeA);
Expand Down Expand Up @@ -273,7 +268,7 @@ describe("connection approval", () => {

void test("mesh_pending lists pending connections", async () => {
const portA = await uniquePort();
const portB = portA + 100;
const portB = await uniquePort();

const storeA = new MeshStore(portA);
wireTestTransport(storeA);
Expand Down Expand Up @@ -351,7 +346,7 @@ describe("connection approval", () => {

void test("tool handles mesh_connect/mesh_accept/mesh_reject/mesh_pending actions", async () => {
const portA = await uniquePort();
const portB = portA + 100;
const portB = await uniquePort();

const storeA = new MeshStore(portA);
wireTestTransport(storeA);
Expand Down Expand Up @@ -503,7 +498,7 @@ describe("connection approval", () => {

void test("tool mesh_reject returns error message", async () => {
const portA = await uniquePort();
const portB = portA + 100;
const portB = await uniquePort();

const storeA = new MeshStore(portA);
wireTestTransport(storeA);
Expand Down