claudemesh-cli 1.10.0 → 1.12.0

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.
@@ -88,7 +88,7 @@ __export(exports_urls, {
88
88
  VERSION: () => VERSION,
89
89
  URLS: () => URLS
90
90
  });
91
- var URLS, VERSION = "1.10.0", env;
91
+ var URLS, VERSION = "1.12.0", env;
92
92
  var init_urls = __esm(() => {
93
93
  URLS = {
94
94
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -362,12 +362,11 @@ async function request(opts) {
362
362
  signal: controller.signal
363
363
  });
364
364
  if (!res.ok) {
365
- let body;
365
+ const text2 = await res.text();
366
+ let body = text2;
366
367
  try {
367
- body = await res.json();
368
- } catch {
369
- body = await res.text();
370
- }
368
+ body = JSON.parse(text2);
369
+ } catch {}
371
370
  throw new ApiError(res.status, res.statusText, body);
372
371
  }
373
372
  const text = await res.text();
@@ -12288,6 +12287,8 @@ var init_notification = __esm(() => {
12288
12287
  // src/commands/me.ts
12289
12288
  var exports_me = {};
12290
12289
  __export(exports_me, {
12290
+ runMeTopics: () => runMeTopics,
12291
+ runMeNotifications: () => runMeNotifications,
12291
12292
  runMe: () => runMe
12292
12293
  });
12293
12294
  async function runMe(flags) {
@@ -12329,6 +12330,99 @@ async function runMe(flags) {
12329
12330
  return EXIT.SUCCESS;
12330
12331
  });
12331
12332
  }
12333
+ async function runMeTopics(flags) {
12334
+ return withRestKey({
12335
+ meshSlug: flags.mesh ?? null,
12336
+ purpose: "workspace-topics",
12337
+ capabilities: ["read"]
12338
+ }, async ({ secret }) => {
12339
+ const ws = await request({
12340
+ path: "/api/v1/me/topics",
12341
+ token: secret
12342
+ });
12343
+ const visible = flags.unread ? ws.topics.filter((t) => t.unread > 0) : ws.topics;
12344
+ if (flags.json) {
12345
+ console.log(JSON.stringify({ topics: visible, totals: ws.totals }, null, 2));
12346
+ return EXIT.SUCCESS;
12347
+ }
12348
+ render.section(`${clay("topics")} — ${ws.totals.topics} across all meshes ${dim(ws.totals.unread > 0 ? `· ${ws.totals.unread} unread` : "· all read")}`);
12349
+ if (visible.length === 0) {
12350
+ process.stdout.write(dim(flags.unread ? ` no unread topics
12351
+ ` : " no topics — run `claudemesh topic create #general`\n"));
12352
+ return EXIT.SUCCESS;
12353
+ }
12354
+ const slugWidth = Math.max(...visible.map((t) => t.meshSlug.length), 6);
12355
+ const nameWidth = Math.max(...visible.map((t) => t.name.length), 8);
12356
+ for (const t of visible) {
12357
+ const slug = dim(t.meshSlug.padEnd(slugWidth));
12358
+ const name = cyan(t.name.padEnd(nameWidth));
12359
+ const unread = t.unread > 0 ? yellow(`${t.unread} unread`.padStart(10)) : dim("·".padStart(10));
12360
+ const last = t.lastMessageAt ? dim(formatRelativeTime(t.lastMessageAt)) : dim("never");
12361
+ process.stdout.write(` ${slug} ${name} ${unread} ${last}
12362
+ `);
12363
+ }
12364
+ return EXIT.SUCCESS;
12365
+ });
12366
+ }
12367
+ async function runMeNotifications(flags) {
12368
+ return withRestKey({
12369
+ meshSlug: flags.mesh ?? null,
12370
+ purpose: "workspace-notifications",
12371
+ capabilities: ["read"]
12372
+ }, async ({ secret }) => {
12373
+ const params = new URLSearchParams;
12374
+ if (flags.all)
12375
+ params.set("include", "all");
12376
+ if (flags.since)
12377
+ params.set("since", flags.since);
12378
+ const path = "/api/v1/me/notifications" + (params.toString() ? `?${params.toString()}` : "");
12379
+ const ws = await request({
12380
+ path,
12381
+ token: secret
12382
+ });
12383
+ if (flags.json) {
12384
+ console.log(JSON.stringify(ws, null, 2));
12385
+ return EXIT.SUCCESS;
12386
+ }
12387
+ const headerLabel = flags.all ? "@-mentions (all)" : "@-mentions (unread)";
12388
+ render.section(`${clay(headerLabel)} — ${ws.totals.total} ${dim(ws.totals.unread > 0 ? `· ${ws.totals.unread} unread` : "· nothing pending")}`);
12389
+ if (ws.notifications.length === 0) {
12390
+ process.stdout.write(dim(flags.all ? ` no @-mentions in window
12391
+ ` : ` inbox zero — nothing waiting
12392
+ `));
12393
+ return EXIT.SUCCESS;
12394
+ }
12395
+ const slugWidth = Math.max(...ws.notifications.map((n) => n.meshSlug.length), 6);
12396
+ for (const n of ws.notifications) {
12397
+ const slug = dim(n.meshSlug.padEnd(slugWidth));
12398
+ const topic = cyan(`#${n.topicName}`);
12399
+ const sender = n.senderName ? `from ${n.senderName}` : "from ?";
12400
+ const ago = formatRelativeTime(n.createdAt);
12401
+ const dot = n.read ? dim("·") : yellow("●");
12402
+ const snippet = n.snippet ?? (n.ciphertext ? dim("[encrypted]") : dim("[empty]"));
12403
+ process.stdout.write(` ${dot} ${slug} ${topic} ${dim(sender)} ${dim(ago)}
12404
+ ` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
12405
+ `);
12406
+ }
12407
+ return EXIT.SUCCESS;
12408
+ });
12409
+ }
12410
+ function formatRelativeTime(iso) {
12411
+ const then = new Date(iso).getTime();
12412
+ const now = Date.now();
12413
+ const sec = Math.max(0, Math.floor((now - then) / 1000));
12414
+ if (sec < 60)
12415
+ return `${sec}s ago`;
12416
+ if (sec < 3600)
12417
+ return `${Math.floor(sec / 60)}m ago`;
12418
+ if (sec < 86400)
12419
+ return `${Math.floor(sec / 3600)}h ago`;
12420
+ if (sec < 86400 * 30)
12421
+ return `${Math.floor(sec / 86400)}d ago`;
12422
+ if (sec < 86400 * 365)
12423
+ return `${Math.floor(sec / (86400 * 30))}mo ago`;
12424
+ return `${Math.floor(sec / (86400 * 365))}y ago`;
12425
+ }
12332
12426
  var init_me = __esm(() => {
12333
12427
  init_with_rest_key();
12334
12428
  init_client();
@@ -13977,6 +14071,8 @@ Topic (conversation scope, v0.2.0)
13977
14071
  claudemesh topic post <t> <msg> encrypted REST post (v0.3.0 v2) [--reply-to <id>]
13978
14072
  claudemesh send "#topic" "msg" send to a topic (WS path, v1 plaintext)
13979
14073
  claudemesh me cross-mesh workspace overview (v0.4.0)
14074
+ claudemesh me topics cross-mesh topic list [--unread]
14075
+ claudemesh me notifications cross-mesh @-mentions [--all] [--since=ISO]
13980
14076
  claudemesh member list mesh roster with online state [--online]
13981
14077
  claudemesh notification list recent @-mentions of you [--since <ISO>]
13982
14078
 
@@ -14843,8 +14939,23 @@ async function main() {
14843
14939
  if (!sub || sub === "workspace" || sub === "overview") {
14844
14940
  const { runMe: runMe2 } = await Promise.resolve().then(() => (init_me(), exports_me));
14845
14941
  process.exit(await runMe2(f));
14942
+ } else if (sub === "topics") {
14943
+ const { runMeTopics: runMeTopics2 } = await Promise.resolve().then(() => (init_me(), exports_me));
14944
+ process.exit(await runMeTopics2({ ...f, unread: !!flags.unread }));
14945
+ } else if (sub === "notifications" || sub === "notifs") {
14946
+ const { runMeNotifications: runMeNotifications2 } = await Promise.resolve().then(() => (init_me(), exports_me));
14947
+ process.exit(await runMeNotifications2({
14948
+ ...f,
14949
+ all: !!flags.all,
14950
+ since: flags.since
14951
+ }));
14846
14952
  } else {
14847
- console.error("Usage: claudemesh me (cross-mesh overview; future: me topics, me notifications, me activity)");
14953
+ console.error(`Usage: claudemesh me (cross-mesh overview)
14954
+ claudemesh me topics (cross-mesh topic list)
14955
+ claudemesh me topics --unread (only unread topics)
14956
+ claudemesh me notifications (unread @-mentions, last 7d)
14957
+ claudemesh me notifications --all (include already-read)
14958
+ claudemesh me notifications --since=ISO (custom window)`);
14848
14959
  process.exit(EXIT.INVALID_ARGS);
14849
14960
  }
14850
14961
  break;
@@ -14914,4 +15025,4 @@ main().catch((err) => {
14914
15025
  process.exit(EXIT.INTERNAL_ERROR);
14915
15026
  });
14916
15027
 
14917
- //# debugId=0FC51F4D5C410DB364756E2164756E21
15028
+ //# debugId=2102749345F189DF64756E2164756E21