claudemesh-cli 1.0.0-alpha.41 → 1.0.0-alpha.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1317,6 +1317,7 @@ class BrokerClient {
1317
1317
  return this._serviceCatalog;
1318
1318
  }
1319
1319
  closed = false;
1320
+ terminalClose = null;
1320
1321
  reconnectAttempt = 0;
1321
1322
  helloTimer = null;
1322
1323
  reconnectTimer = null;
@@ -1444,12 +1445,22 @@ class BrokerClient {
1444
1445
  }
1445
1446
  this.handleServerMessage(msg);
1446
1447
  };
1447
- const onClose = () => {
1448
+ const onClose = (code, reasonBuf) => {
1448
1449
  if (this.helloTimer)
1449
1450
  clearTimeout(this.helloTimer);
1450
1451
  this.helloTimer = null;
1451
1452
  if (this.ws === ws)
1452
1453
  this.ws = null;
1454
+ const reason = reasonBuf?.toString("utf-8") ?? "";
1455
+ if (code === 4001 || code === 4002) {
1456
+ this.closed = true;
1457
+ this.setConnStatus("closed");
1458
+ this.terminalClose = { code, reason };
1459
+ if (this._status !== "open") {
1460
+ reject(new Error(`ws terminal close ${code}: ${reason || "session ended"}`));
1461
+ }
1462
+ return;
1463
+ }
1453
1464
  if (this._status !== "open" && this._status !== "reconnecting") {
1454
1465
  reject(new Error("ws closed before hello_ack"));
1455
1466
  }
@@ -3132,6 +3143,9 @@ class BrokerClient {
3132
3143
  }
3133
3144
  if (msg.type === "error") {
3134
3145
  this.debug(`broker error: ${msg.code} ${msg.message}`);
3146
+ if (msg.code === "revoked") {
3147
+ this.terminalClose = { code: 4002, reason: String(msg.message ?? "revoked") };
3148
+ }
3135
3149
  const id = msg.id ? String(msg.id) : null;
3136
3150
  let handledByPendingSend = false;
3137
3151
  if (id) {
@@ -3372,6 +3386,25 @@ async function withMesh(opts, fn) {
3372
3386
  await client.connect();
3373
3387
  const result = await fn(client, mesh);
3374
3388
  return result;
3389
+ } catch (e) {
3390
+ if (client.terminalClose) {
3391
+ const { code, reason } = client.terminalClose;
3392
+ if (code === 4002) {
3393
+ console.error(`
3394
+ ✘ ${reason}
3395
+ `);
3396
+ } else if (code === 4001) {
3397
+ console.error(`
3398
+ ✘ Kicked from this mesh. Run \`claudemesh\` to rejoin.
3399
+ `);
3400
+ } else {
3401
+ console.error(`
3402
+ ✘ Broker closed connection: ${reason}
3403
+ `);
3404
+ }
3405
+ process.exit(1);
3406
+ }
3407
+ throw e;
3375
3408
  } finally {
3376
3409
  client.close();
3377
3410
  }
@@ -3525,7 +3558,7 @@ __export(exports_urls, {
3525
3558
  VERSION: () => VERSION,
3526
3559
  URLS: () => URLS
3527
3560
  });
3528
- var URLS, VERSION = "1.0.0-alpha.41", env;
3561
+ var URLS, VERSION = "1.0.0-alpha.43", env;
3529
3562
  var init_urls = __esm(() => {
3530
3563
  URLS = {
3531
3564
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -4442,7 +4475,7 @@ async function resolveClient(to) {
4442
4475
  target = rest;
4443
4476
  }
4444
4477
  }
4445
- if (/^[0-9a-f]{64}$/.test(target) || target.startsWith("#") || target.startsWith("@") || target === "*") {
4478
+ if (target.startsWith("#") || target.startsWith("@") || target === "*") {
4446
4479
  if (targetClients.length === 1) {
4447
4480
  return { client: targetClients[0], targetSpec: target };
4448
4481
  }
@@ -4452,21 +4485,95 @@ async function resolveClient(to) {
4452
4485
  error: `multiple meshes joined; prefix target with "<mesh-slug>:" (joined: ${clients2.map((c) => c.meshSlug).join(", ")})`
4453
4486
  };
4454
4487
  }
4488
+ if (/^[0-9a-f]{8,64}$/.test(target)) {
4489
+ const hits = [];
4490
+ for (const c of targetClients) {
4491
+ const peers = await c.listPeers();
4492
+ for (const p of peers) {
4493
+ if (p.pubkey.startsWith(target)) {
4494
+ hits.push({ mesh: c, pubkey: p.pubkey, displayName: p.displayName });
4495
+ }
4496
+ }
4497
+ }
4498
+ if (hits.length === 1) {
4499
+ return { client: hits[0].mesh, targetSpec: hits[0].pubkey };
4500
+ }
4501
+ if (hits.length > 1) {
4502
+ const lines = hits.map((h) => ` - ${h.displayName} @ ${h.mesh.meshSlug} · pubkey ${h.pubkey.slice(0, 20)}…`).join(`
4503
+ `);
4504
+ return {
4505
+ client: null,
4506
+ targetSpec: target,
4507
+ error: `ambiguous pubkey prefix "${target}" matches ${hits.length} peers:
4508
+ ${lines}
4509
+ Use a longer prefix.`
4510
+ };
4511
+ }
4512
+ if (target.length === 64) {
4513
+ if (targetClients.length === 1) {
4514
+ return { client: targetClients[0], targetSpec: target };
4515
+ }
4516
+ return {
4517
+ client: null,
4518
+ targetSpec: target,
4519
+ error: `multiple meshes joined; prefix target with "<mesh-slug>:" (joined: ${clients2.map((c) => c.meshSlug).join(", ")})`
4520
+ };
4521
+ }
4522
+ return {
4523
+ client: null,
4524
+ targetSpec: target,
4525
+ error: `no online peer's pubkey starts with "${target}".`
4526
+ };
4527
+ }
4455
4528
  const nameLower = target.toLowerCase();
4456
4529
  const candidates = [];
4530
+ const exactMatches = [];
4531
+ const partialMatches = [];
4457
4532
  for (const c of targetClients) {
4533
+ const ownSession = c.getSessionPubkey();
4458
4534
  const peers = await c.listPeers();
4459
4535
  candidates.push({ mesh: c.meshSlug, peers });
4460
- const match = peers.find((p) => p.displayName.toLowerCase() === nameLower);
4461
- if (match)
4462
- return { client: c, targetSpec: match.pubkey };
4463
- const partials = peers.filter((p) => p.displayName.toLowerCase().includes(nameLower));
4464
- if (partials.length === 1) {
4465
- process.stderr.write(`[claudemesh] resolved "${target}" "${partials[0].displayName}" (partial match)
4466
- `);
4467
- return { client: c, targetSpec: partials[0].pubkey };
4536
+ for (const p of peers) {
4537
+ if (ownSession && p.pubkey === ownSession)
4538
+ continue;
4539
+ const nameLow = p.displayName.toLowerCase();
4540
+ if (nameLow === nameLower) {
4541
+ exactMatches.push({ mesh: c, pubkey: p.pubkey, displayName: p.displayName, cwd: p.cwd });
4542
+ } else if (nameLow.includes(nameLower)) {
4543
+ partialMatches.push({ mesh: c, pubkey: p.pubkey, displayName: p.displayName, cwd: p.cwd });
4544
+ }
4468
4545
  }
4469
4546
  }
4547
+ if (exactMatches.length === 1) {
4548
+ return { client: exactMatches[0].mesh, targetSpec: exactMatches[0].pubkey };
4549
+ }
4550
+ if (exactMatches.length > 1) {
4551
+ const lines = exactMatches.map((m) => ` - ${m.displayName} · pubkey ${m.pubkey.slice(0, 16)}…${m.cwd ? ` · cwd ${m.cwd}` : ""}`).join(`
4552
+ `);
4553
+ return {
4554
+ client: null,
4555
+ targetSpec: target,
4556
+ error: `"${target}" is ambiguous — ${exactMatches.length} peers share that display name:
4557
+ ${lines}
4558
+ ` + `Disambiguate by pubkey prefix (e.g. send to "${exactMatches[0].pubkey.slice(0, 12)}…").`
4559
+ };
4560
+ }
4561
+ if (partialMatches.length === 1) {
4562
+ process.stderr.write(`[claudemesh] resolved "${target}" → "${partialMatches[0].displayName}" (partial match)
4563
+ `);
4564
+ return { client: partialMatches[0].mesh, targetSpec: partialMatches[0].pubkey };
4565
+ }
4566
+ if (partialMatches.length > 1) {
4567
+ const lines = partialMatches.map((m) => ` - ${m.displayName} · pubkey ${m.pubkey.slice(0, 16)}…`).join(`
4568
+ `);
4569
+ return {
4570
+ client: null,
4571
+ targetSpec: target,
4572
+ error: `"${target}" partially matches ${partialMatches.length} peers:
4573
+ ${lines}
4574
+ Be more specific, or use a pubkey prefix.`
4575
+ };
4576
+ }
4470
4577
  const known = candidates.flatMap((c) => c.peers.map((p) => `${c.mesh}/${p.displayName}`));
4471
4578
  return {
4472
4579
  client: null,
@@ -4849,7 +4956,7 @@ No peers connected.`);
4849
4956
  const hiddenTag = p.visible === false ? " [hidden]" : "";
4850
4957
  const sameKeyCount = pubkeyCounts.get(p.pubkey) ?? 1;
4851
4958
  const sameKeyTag = sameKeyCount > 1 ? ` [shares key with ${sameKeyCount - 1} other session(s)]` : "";
4852
- return `- ${profileAvatar}**${p.displayName}**${profileTitle} [${p.status}]${localityTag}${hiddenTag}${sameKeyTag}${groupsStr}${metaStr} (${p.pubkey.slice(0, 12)}…)${cwdStr}${summary}`;
4959
+ return `- ${profileAvatar}**${p.displayName}**${profileTitle} [${p.status}]${localityTag}${hiddenTag}${sameKeyTag}${groupsStr}${metaStr} (pubkey: ${p.pubkey.slice(0, 16)}…)${cwdStr}${summary}`;
4853
4960
  });
4854
4961
  sections.push(`${header}
4855
4962
  ${peerLines.join(`
@@ -6559,4 +6666,4 @@ startMcpServer().catch((err) => {
6559
6666
  process.exit(1);
6560
6667
  });
6561
6668
 
6562
- //# debugId=384C31621EECEF0164756E2164756E21
6669
+ //# debugId=BEB2D087B169664064756E2164756E21