feat: add hostname to hello + local/remote peer locality detection
Peers report os.hostname() in the hello handshake. list_peers shows [local] or [remote] tag per peer. MCP instructions teach AI to read local peers' files directly via filesystem instead of relay. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,7 @@ interface PeerConn {
|
|||||||
sessionPubkey: string | null;
|
sessionPubkey: string | null;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
cwd: string;
|
cwd: string;
|
||||||
|
hostname?: string;
|
||||||
peerType?: "ai" | "human" | "connector";
|
peerType?: "ai" | "human" | "connector";
|
||||||
channel?: string;
|
channel?: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
@@ -920,6 +921,7 @@ async function handleHello(
|
|||||||
sessionPubkey: hello.sessionPubkey ?? null,
|
sessionPubkey: hello.sessionPubkey ?? null,
|
||||||
displayName: effectiveDisplayName,
|
displayName: effectiveDisplayName,
|
||||||
cwd: hello.cwd,
|
cwd: hello.cwd,
|
||||||
|
hostname: hello.hostname,
|
||||||
peerType: hello.peerType,
|
peerType: hello.peerType,
|
||||||
channel: hello.channel,
|
channel: hello.channel,
|
||||||
model: hello.model,
|
model: hello.model,
|
||||||
@@ -1138,6 +1140,7 @@ function handleConnection(ws: WebSocket): void {
|
|||||||
sessionId: p.sessionId,
|
sessionId: p.sessionId,
|
||||||
connectedAt: p.connectedAt.toISOString(),
|
connectedAt: p.connectedAt.toISOString(),
|
||||||
cwd: pc?.cwd ?? p.cwd,
|
cwd: pc?.cwd ?? p.cwd,
|
||||||
|
...(pc?.hostname ? { hostname: pc.hostname } : {}),
|
||||||
...(pc?.peerType ? { peerType: pc.peerType } : {}),
|
...(pc?.peerType ? { peerType: pc.peerType } : {}),
|
||||||
...(pc?.channel ? { channel: pc.channel } : {}),
|
...(pc?.channel ? { channel: pc.channel } : {}),
|
||||||
...(pc?.model ? { model: pc.model } : {}),
|
...(pc?.model ? { model: pc.model } : {}),
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ export interface WSHelloMessage {
|
|||||||
sessionId: string;
|
sessionId: string;
|
||||||
pid: number;
|
pid: number;
|
||||||
cwd: string;
|
cwd: string;
|
||||||
|
/** OS hostname — used to detect same-machine peers for direct file access. */
|
||||||
|
hostname?: string;
|
||||||
/** Peer type: ai session, human user, or external connector. */
|
/** Peer type: ai session, human user, or external connector. */
|
||||||
peerType?: "ai" | "human" | "connector";
|
peerType?: "ai" | "human" | "connector";
|
||||||
/** Channel the peer connected from (e.g. "claude-code", "telegram", "slack", "web"). */
|
/** Channel the peer connected from (e.g. "claude-code", "telegram", "slack", "web"). */
|
||||||
@@ -226,6 +228,7 @@ export interface WSPeersListMessage {
|
|||||||
sessionId: string;
|
sessionId: string;
|
||||||
connectedAt: string;
|
connectedAt: string;
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
|
hostname?: string;
|
||||||
peerType?: "ai" | "human" | "connector";
|
peerType?: "ai" | "human" | "connector";
|
||||||
channel?: string;
|
channel?: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
|
|||||||
@@ -228,6 +228,11 @@ Persistent knowledge that survives across sessions. Use remember(content, tags?)
|
|||||||
share_file for persistent references, send_message(file:) for ephemeral attachments.
|
share_file for persistent references, send_message(file:) for ephemeral attachments.
|
||||||
Tags on shared files make them searchable. Use list_files to find what peers shared.
|
Tags on shared files make them searchable. Use list_files to find what peers shared.
|
||||||
|
|
||||||
|
## Peer project files
|
||||||
|
read_peer_file and list_peer_files request files from remote peers through the mesh (1MB limit, base64 relay).
|
||||||
|
**Same-machine shortcut:** If a peer's \`hostname\` matches yours (visible in list_peers), they are a LOCAL peer — read their files directly via the filesystem using their \`cwd\` path. Faster, no size limit, no relay. Use read_peer_file only for REMOTE peers (different hostname).
|
||||||
|
Each peer in list_peers shows a \`locality\` tag: "local" (same machine, direct filesystem access) or "remote" (different machine, use read_peer_file).
|
||||||
|
|
||||||
## Vectors
|
## Vectors
|
||||||
Store and search semantic embeddings. Use vector_store to index content, vector_search to find similar content.
|
Store and search semantic embeddings. Use vector_store to index content, vector_search to find similar content.
|
||||||
|
|
||||||
@@ -342,10 +347,12 @@ Your message mode is "${messageMode}".
|
|||||||
if (p.model) meta.push(`model:${p.model}`);
|
if (p.model) meta.push(`model:${p.model}`);
|
||||||
const metaStr = meta.length ? ` {${meta.join(", ")}}` : "";
|
const metaStr = meta.length ? ` {${meta.join(", ")}}` : "";
|
||||||
const cwdStr = p.cwd ? ` cwd:${p.cwd}` : "";
|
const cwdStr = p.cwd ? ` cwd:${p.cwd}` : "";
|
||||||
|
const locality = p.hostname && p.hostname === require("os").hostname() ? "local" : "remote";
|
||||||
|
const localityTag = ` [${locality}]`;
|
||||||
const profileAvatar = p.profile?.avatar ? `${p.profile.avatar} ` : "";
|
const profileAvatar = p.profile?.avatar ? `${p.profile.avatar} ` : "";
|
||||||
const profileTitle = p.profile?.title ? ` (${p.profile.title})` : "";
|
const profileTitle = p.profile?.title ? ` (${p.profile.title})` : "";
|
||||||
const hiddenTag = p.visible === false ? " [hidden]" : "";
|
const hiddenTag = p.visible === false ? " [hidden]" : "";
|
||||||
return `- ${profileAvatar}**${p.displayName}**${profileTitle} [${p.status}]${hiddenTag}${groupsStr}${metaStr} (${p.pubkey.slice(0, 12)}…)${cwdStr}${summary}`;
|
return `- ${profileAvatar}**${p.displayName}**${profileTitle} [${p.status}]${localityTag}${hiddenTag}${groupsStr}${metaStr} (${p.pubkey.slice(0, 12)}…)${cwdStr}${summary}`;
|
||||||
});
|
});
|
||||||
sections.push(`${header}\n${peerLines.join("\n")}`);
|
sections.push(`${header}\n${peerLines.join("\n")}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export interface PeerInfo {
|
|||||||
sessionId: string;
|
sessionId: string;
|
||||||
connectedAt: string;
|
connectedAt: string;
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
|
hostname?: string;
|
||||||
peerType?: "ai" | "human" | "connector";
|
peerType?: "ai" | "human" | "connector";
|
||||||
channel?: string;
|
channel?: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
@@ -194,6 +195,7 @@ export class BrokerClient {
|
|||||||
sessionId: `${process.pid}-${Date.now()}`,
|
sessionId: `${process.pid}-${Date.now()}`,
|
||||||
pid: process.pid,
|
pid: process.pid,
|
||||||
cwd: process.cwd(),
|
cwd: process.cwd(),
|
||||||
|
hostname: require("os").hostname(),
|
||||||
peerType: "ai" as const,
|
peerType: "ai" as const,
|
||||||
channel: "claude-code",
|
channel: "claude-code",
|
||||||
model: process.env.CLAUDE_MODEL || undefined,
|
model: process.env.CLAUDE_MODEL || undefined,
|
||||||
|
|||||||
Reference in New Issue
Block a user