claudemesh-cli 1.13.0 → 1.15.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.
- package/dist/entrypoints/cli.js +289 -192
- package/dist/entrypoints/cli.js.map +5 -5
- package/dist/entrypoints/mcp.js +2 -2
- package/dist/entrypoints/mcp.js.map +1 -1
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -88,7 +88,7 @@ __export(exports_urls, {
|
|
|
88
88
|
VERSION: () => VERSION,
|
|
89
89
|
URLS: () => URLS
|
|
90
90
|
});
|
|
91
|
-
var URLS, VERSION = "1.
|
|
91
|
+
var URLS, VERSION = "1.15.0", env;
|
|
92
92
|
var init_urls = __esm(() => {
|
|
93
93
|
URLS = {
|
|
94
94
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -11766,6 +11766,270 @@ var init_with_rest_key = __esm(() => {
|
|
|
11766
11766
|
init_connect();
|
|
11767
11767
|
});
|
|
11768
11768
|
|
|
11769
|
+
// src/commands/me.ts
|
|
11770
|
+
var exports_me = {};
|
|
11771
|
+
__export(exports_me, {
|
|
11772
|
+
runMeTopics: () => runMeTopics,
|
|
11773
|
+
runMeSearch: () => runMeSearch,
|
|
11774
|
+
runMeNotifications: () => runMeNotifications,
|
|
11775
|
+
runMeActivity: () => runMeActivity,
|
|
11776
|
+
runMe: () => runMe
|
|
11777
|
+
});
|
|
11778
|
+
function resolveMeshForMint(explicit) {
|
|
11779
|
+
if (explicit)
|
|
11780
|
+
return explicit;
|
|
11781
|
+
const cfg = readConfig();
|
|
11782
|
+
return cfg.meshes[0]?.slug ?? null;
|
|
11783
|
+
}
|
|
11784
|
+
async function runMe(flags) {
|
|
11785
|
+
return withRestKey({
|
|
11786
|
+
meshSlug: resolveMeshForMint(flags.mesh),
|
|
11787
|
+
purpose: "workspace-overview",
|
|
11788
|
+
capabilities: ["read"]
|
|
11789
|
+
}, async ({ secret }) => {
|
|
11790
|
+
const ws = await request({
|
|
11791
|
+
path: "/api/v1/me/workspace",
|
|
11792
|
+
token: secret
|
|
11793
|
+
});
|
|
11794
|
+
if (flags.json) {
|
|
11795
|
+
console.log(JSON.stringify(ws, null, 2));
|
|
11796
|
+
return EXIT.SUCCESS;
|
|
11797
|
+
}
|
|
11798
|
+
render.section(`${clay("workspace")} — ${bold(ws.userId.slice(0, 8))} ${dim(`· ${ws.totals.meshes} mesh${ws.totals.meshes === 1 ? "" : "es"}`)}`);
|
|
11799
|
+
const totalsLine = [
|
|
11800
|
+
`${green(String(ws.totals.online))}/${ws.totals.peers} online`,
|
|
11801
|
+
`${ws.totals.topics} topic${ws.totals.topics === 1 ? "" : "s"}`,
|
|
11802
|
+
ws.totals.unreadMentions > 0 ? yellow(`${ws.totals.unreadMentions} unread @you`) : dim("0 unread @you")
|
|
11803
|
+
].join(dim(" · "));
|
|
11804
|
+
process.stdout.write(" " + totalsLine + `
|
|
11805
|
+
|
|
11806
|
+
`);
|
|
11807
|
+
if (ws.meshes.length === 0) {
|
|
11808
|
+
process.stdout.write(dim(" no meshes joined — run `claudemesh new` or accept an invite\n"));
|
|
11809
|
+
return EXIT.SUCCESS;
|
|
11810
|
+
}
|
|
11811
|
+
const slugWidth = Math.max(...ws.meshes.map((m) => m.slug.length), 8);
|
|
11812
|
+
for (const m of ws.meshes) {
|
|
11813
|
+
const slug = cyan(m.slug.padEnd(slugWidth));
|
|
11814
|
+
const peers = `${m.online}/${m.peers}`;
|
|
11815
|
+
const role = dim(m.myRole);
|
|
11816
|
+
const unread = m.unreadMentions > 0 ? " " + yellow(`${m.unreadMentions} @you`) : "";
|
|
11817
|
+
process.stdout.write(` ${slug} ${peers.padStart(5)} online ${dim(String(m.topics).padStart(2) + " topics")} ${role}${unread}
|
|
11818
|
+
`);
|
|
11819
|
+
}
|
|
11820
|
+
return EXIT.SUCCESS;
|
|
11821
|
+
});
|
|
11822
|
+
}
|
|
11823
|
+
async function runMeTopics(flags) {
|
|
11824
|
+
return withRestKey({
|
|
11825
|
+
meshSlug: resolveMeshForMint(flags.mesh),
|
|
11826
|
+
purpose: "workspace-topics",
|
|
11827
|
+
capabilities: ["read"]
|
|
11828
|
+
}, async ({ secret }) => {
|
|
11829
|
+
const ws = await request({
|
|
11830
|
+
path: "/api/v1/me/topics",
|
|
11831
|
+
token: secret
|
|
11832
|
+
});
|
|
11833
|
+
const visible = flags.unread ? ws.topics.filter((t) => t.unread > 0) : ws.topics;
|
|
11834
|
+
if (flags.json) {
|
|
11835
|
+
console.log(JSON.stringify({ topics: visible, totals: ws.totals }, null, 2));
|
|
11836
|
+
return EXIT.SUCCESS;
|
|
11837
|
+
}
|
|
11838
|
+
render.section(`${clay("topics")} — ${ws.totals.topics} across all meshes ${dim(ws.totals.unread > 0 ? `· ${ws.totals.unread} unread` : "· all read")}`);
|
|
11839
|
+
if (visible.length === 0) {
|
|
11840
|
+
process.stdout.write(dim(flags.unread ? ` no unread topics
|
|
11841
|
+
` : " no topics — run `claudemesh topic create #general`\n"));
|
|
11842
|
+
return EXIT.SUCCESS;
|
|
11843
|
+
}
|
|
11844
|
+
const slugWidth = Math.max(...visible.map((t) => t.meshSlug.length), 6);
|
|
11845
|
+
const nameWidth = Math.max(...visible.map((t) => t.name.length), 8);
|
|
11846
|
+
for (const t of visible) {
|
|
11847
|
+
const slug = dim(t.meshSlug.padEnd(slugWidth));
|
|
11848
|
+
const name = cyan(t.name.padEnd(nameWidth));
|
|
11849
|
+
const unread = t.unread > 0 ? yellow(`${t.unread} unread`.padStart(10)) : dim("·".padStart(10));
|
|
11850
|
+
const last = t.lastMessageAt ? dim(formatRelativeTime(t.lastMessageAt)) : dim("never");
|
|
11851
|
+
process.stdout.write(` ${slug} ${name} ${unread} ${last}
|
|
11852
|
+
`);
|
|
11853
|
+
}
|
|
11854
|
+
return EXIT.SUCCESS;
|
|
11855
|
+
});
|
|
11856
|
+
}
|
|
11857
|
+
async function runMeNotifications(flags) {
|
|
11858
|
+
return withRestKey({
|
|
11859
|
+
meshSlug: resolveMeshForMint(flags.mesh),
|
|
11860
|
+
purpose: "workspace-notifications",
|
|
11861
|
+
capabilities: ["read"]
|
|
11862
|
+
}, async ({ secret }) => {
|
|
11863
|
+
const params = new URLSearchParams;
|
|
11864
|
+
if (flags.all)
|
|
11865
|
+
params.set("include", "all");
|
|
11866
|
+
if (flags.since)
|
|
11867
|
+
params.set("since", flags.since);
|
|
11868
|
+
const path = "/api/v1/me/notifications" + (params.toString() ? `?${params.toString()}` : "");
|
|
11869
|
+
const ws = await request({
|
|
11870
|
+
path,
|
|
11871
|
+
token: secret
|
|
11872
|
+
});
|
|
11873
|
+
if (flags.json) {
|
|
11874
|
+
console.log(JSON.stringify(ws, null, 2));
|
|
11875
|
+
return EXIT.SUCCESS;
|
|
11876
|
+
}
|
|
11877
|
+
const headerLabel = flags.all ? "@-mentions (all)" : "@-mentions (unread)";
|
|
11878
|
+
render.section(`${clay(headerLabel)} — ${ws.totals.total} ${dim(ws.totals.unread > 0 ? `· ${ws.totals.unread} unread` : "· nothing pending")}`);
|
|
11879
|
+
if (ws.notifications.length === 0) {
|
|
11880
|
+
process.stdout.write(dim(flags.all ? ` no @-mentions in window
|
|
11881
|
+
` : ` inbox zero — nothing waiting
|
|
11882
|
+
`));
|
|
11883
|
+
return EXIT.SUCCESS;
|
|
11884
|
+
}
|
|
11885
|
+
const slugWidth = Math.max(...ws.notifications.map((n) => n.meshSlug.length), 6);
|
|
11886
|
+
for (const n of ws.notifications) {
|
|
11887
|
+
const slug = dim(n.meshSlug.padEnd(slugWidth));
|
|
11888
|
+
const topic = cyan(`#${n.topicName}`);
|
|
11889
|
+
const sender = n.senderName ? `from ${n.senderName}` : "from ?";
|
|
11890
|
+
const ago = formatRelativeTime(n.createdAt);
|
|
11891
|
+
const dot = n.read ? dim("·") : yellow("●");
|
|
11892
|
+
const snippet = n.snippet ?? (n.ciphertext ? dim("[encrypted]") : dim("[empty]"));
|
|
11893
|
+
process.stdout.write(` ${dot} ${slug} ${topic} ${dim(sender)} ${dim(ago)}
|
|
11894
|
+
` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
|
|
11895
|
+
`);
|
|
11896
|
+
}
|
|
11897
|
+
return EXIT.SUCCESS;
|
|
11898
|
+
});
|
|
11899
|
+
}
|
|
11900
|
+
async function runMeActivity(flags) {
|
|
11901
|
+
return withRestKey({
|
|
11902
|
+
meshSlug: resolveMeshForMint(flags.mesh),
|
|
11903
|
+
purpose: "workspace-activity",
|
|
11904
|
+
capabilities: ["read"]
|
|
11905
|
+
}, async ({ secret }) => {
|
|
11906
|
+
const params = new URLSearchParams;
|
|
11907
|
+
if (flags.since)
|
|
11908
|
+
params.set("since", flags.since);
|
|
11909
|
+
const path = "/api/v1/me/activity" + (params.toString() ? `?${params.toString()}` : "");
|
|
11910
|
+
const ws = await request({
|
|
11911
|
+
path,
|
|
11912
|
+
token: secret
|
|
11913
|
+
});
|
|
11914
|
+
if (flags.json) {
|
|
11915
|
+
console.log(JSON.stringify(ws, null, 2));
|
|
11916
|
+
return EXIT.SUCCESS;
|
|
11917
|
+
}
|
|
11918
|
+
render.section(`${clay("activity")} — ${ws.totals.events} ${dim(flags.since ? `since ${flags.since}` : "in the last 24h")}`);
|
|
11919
|
+
if (ws.activity.length === 0) {
|
|
11920
|
+
process.stdout.write(dim(` quiet — no activity in window
|
|
11921
|
+
`));
|
|
11922
|
+
return EXIT.SUCCESS;
|
|
11923
|
+
}
|
|
11924
|
+
const slugWidth = Math.max(...ws.activity.map((a) => a.meshSlug.length), 6);
|
|
11925
|
+
for (const a of ws.activity) {
|
|
11926
|
+
const slug = dim(a.meshSlug.padEnd(slugWidth));
|
|
11927
|
+
const topic = cyan(`#${a.topicName}`);
|
|
11928
|
+
const sender = a.senderName ?? "?";
|
|
11929
|
+
const ago = formatRelativeTime(a.createdAt);
|
|
11930
|
+
const snippet = a.snippet ?? (a.ciphertext ? dim("[encrypted]") : dim("[empty]"));
|
|
11931
|
+
process.stdout.write(` ${slug} ${topic} ${dim(sender + " ·")} ${dim(ago)}
|
|
11932
|
+
` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
|
|
11933
|
+
`);
|
|
11934
|
+
}
|
|
11935
|
+
return EXIT.SUCCESS;
|
|
11936
|
+
});
|
|
11937
|
+
}
|
|
11938
|
+
async function runMeSearch(flags) {
|
|
11939
|
+
if (!flags.query || flags.query.length < 2) {
|
|
11940
|
+
process.stderr.write(`Usage: claudemesh me search <query> (min 2 chars)
|
|
11941
|
+
`);
|
|
11942
|
+
return EXIT.INVALID_ARGS;
|
|
11943
|
+
}
|
|
11944
|
+
return withRestKey({
|
|
11945
|
+
meshSlug: resolveMeshForMint(flags.mesh),
|
|
11946
|
+
purpose: "workspace-search",
|
|
11947
|
+
capabilities: ["read"]
|
|
11948
|
+
}, async ({ secret }) => {
|
|
11949
|
+
const params = new URLSearchParams({ q: flags.query });
|
|
11950
|
+
const ws = await request({
|
|
11951
|
+
path: `/api/v1/me/search?${params.toString()}`,
|
|
11952
|
+
token: secret
|
|
11953
|
+
});
|
|
11954
|
+
if (flags.json) {
|
|
11955
|
+
console.log(JSON.stringify(ws, null, 2));
|
|
11956
|
+
return EXIT.SUCCESS;
|
|
11957
|
+
}
|
|
11958
|
+
render.section(`${clay("search")} — "${flags.query}" ${dim(`${ws.totals.topics} topic${ws.totals.topics === 1 ? "" : "s"}, ` + `${ws.totals.messages} message${ws.totals.messages === 1 ? "" : "s"}`)}`);
|
|
11959
|
+
if (ws.topics.length === 0 && ws.messages.length === 0) {
|
|
11960
|
+
process.stdout.write(dim(` no matches
|
|
11961
|
+
`));
|
|
11962
|
+
return EXIT.SUCCESS;
|
|
11963
|
+
}
|
|
11964
|
+
if (ws.topics.length > 0) {
|
|
11965
|
+
process.stdout.write(dim(`
|
|
11966
|
+
topics
|
|
11967
|
+
`));
|
|
11968
|
+
const slugWidth = Math.max(...ws.topics.map((t) => t.meshSlug.length), 6);
|
|
11969
|
+
for (const t of ws.topics) {
|
|
11970
|
+
const slug = dim(t.meshSlug.padEnd(slugWidth));
|
|
11971
|
+
const name = cyan(`#${t.name}`);
|
|
11972
|
+
const desc = t.description ? dim(` — ${t.description}`) : "";
|
|
11973
|
+
process.stdout.write(` ${slug} ${name}${desc}
|
|
11974
|
+
`);
|
|
11975
|
+
}
|
|
11976
|
+
}
|
|
11977
|
+
if (ws.messages.length > 0) {
|
|
11978
|
+
process.stdout.write(dim(`
|
|
11979
|
+
messages
|
|
11980
|
+
`));
|
|
11981
|
+
const slugWidth = Math.max(...ws.messages.map((m) => m.meshSlug.length), 6);
|
|
11982
|
+
for (const m of ws.messages) {
|
|
11983
|
+
const slug = dim(m.meshSlug.padEnd(slugWidth));
|
|
11984
|
+
const topic = cyan(`#${m.topicName}`);
|
|
11985
|
+
const sender = m.senderName;
|
|
11986
|
+
const ago = formatRelativeTime(m.createdAt);
|
|
11987
|
+
const snippet = m.snippet ?? (m.bodyVersion === 2 ? dim("[encrypted — open the topic to decrypt]") : dim("[empty]"));
|
|
11988
|
+
const highlighted = m.snippet ? highlightMatch(snippet, flags.query) : snippet;
|
|
11989
|
+
process.stdout.write(` ${slug} ${topic} ${dim(sender + " ·")} ${dim(ago)}
|
|
11990
|
+
` + ` ${highlighted}
|
|
11991
|
+
`);
|
|
11992
|
+
}
|
|
11993
|
+
}
|
|
11994
|
+
return EXIT.SUCCESS;
|
|
11995
|
+
});
|
|
11996
|
+
}
|
|
11997
|
+
function highlightMatch(text, query) {
|
|
11998
|
+
if (!query)
|
|
11999
|
+
return text;
|
|
12000
|
+
const idx = text.toLowerCase().indexOf(query.toLowerCase());
|
|
12001
|
+
if (idx === -1)
|
|
12002
|
+
return text;
|
|
12003
|
+
const before = text.slice(0, idx);
|
|
12004
|
+
const match = text.slice(idx, idx + query.length);
|
|
12005
|
+
const after = text.slice(idx + query.length);
|
|
12006
|
+
return `${before}${yellow(match)}${after}`;
|
|
12007
|
+
}
|
|
12008
|
+
function formatRelativeTime(iso) {
|
|
12009
|
+
const then = new Date(iso).getTime();
|
|
12010
|
+
const now = Date.now();
|
|
12011
|
+
const sec = Math.max(0, Math.floor((now - then) / 1000));
|
|
12012
|
+
if (sec < 60)
|
|
12013
|
+
return `${sec}s ago`;
|
|
12014
|
+
if (sec < 3600)
|
|
12015
|
+
return `${Math.floor(sec / 60)}m ago`;
|
|
12016
|
+
if (sec < 86400)
|
|
12017
|
+
return `${Math.floor(sec / 3600)}h ago`;
|
|
12018
|
+
if (sec < 86400 * 30)
|
|
12019
|
+
return `${Math.floor(sec / 86400)}d ago`;
|
|
12020
|
+
if (sec < 86400 * 365)
|
|
12021
|
+
return `${Math.floor(sec / (86400 * 30))}mo ago`;
|
|
12022
|
+
return `${Math.floor(sec / (86400 * 365))}y ago`;
|
|
12023
|
+
}
|
|
12024
|
+
var init_me = __esm(() => {
|
|
12025
|
+
init_with_rest_key();
|
|
12026
|
+
init_client();
|
|
12027
|
+
init_facade();
|
|
12028
|
+
init_render();
|
|
12029
|
+
init_styles();
|
|
12030
|
+
init_exit_codes();
|
|
12031
|
+
});
|
|
12032
|
+
|
|
11769
12033
|
// src/services/crypto/topic-key.ts
|
|
11770
12034
|
function cacheKey(apiKeySecret, topicName) {
|
|
11771
12035
|
return `${apiKeySecret.slice(0, 12)}:${topicName}`;
|
|
@@ -12284,192 +12548,6 @@ var init_notification = __esm(() => {
|
|
|
12284
12548
|
init_exit_codes();
|
|
12285
12549
|
});
|
|
12286
12550
|
|
|
12287
|
-
// src/commands/me.ts
|
|
12288
|
-
var exports_me = {};
|
|
12289
|
-
__export(exports_me, {
|
|
12290
|
-
runMeTopics: () => runMeTopics,
|
|
12291
|
-
runMeNotifications: () => runMeNotifications,
|
|
12292
|
-
runMeActivity: () => runMeActivity,
|
|
12293
|
-
runMe: () => runMe
|
|
12294
|
-
});
|
|
12295
|
-
async function runMe(flags) {
|
|
12296
|
-
return withRestKey({
|
|
12297
|
-
meshSlug: flags.mesh ?? null,
|
|
12298
|
-
purpose: "workspace-overview",
|
|
12299
|
-
capabilities: ["read"]
|
|
12300
|
-
}, async ({ secret }) => {
|
|
12301
|
-
const ws = await request({
|
|
12302
|
-
path: "/api/v1/me/workspace",
|
|
12303
|
-
token: secret
|
|
12304
|
-
});
|
|
12305
|
-
if (flags.json) {
|
|
12306
|
-
console.log(JSON.stringify(ws, null, 2));
|
|
12307
|
-
return EXIT.SUCCESS;
|
|
12308
|
-
}
|
|
12309
|
-
render.section(`${clay("workspace")} — ${bold(ws.userId.slice(0, 8))} ${dim(`· ${ws.totals.meshes} mesh${ws.totals.meshes === 1 ? "" : "es"}`)}`);
|
|
12310
|
-
const totalsLine = [
|
|
12311
|
-
`${green(String(ws.totals.online))}/${ws.totals.peers} online`,
|
|
12312
|
-
`${ws.totals.topics} topic${ws.totals.topics === 1 ? "" : "s"}`,
|
|
12313
|
-
ws.totals.unreadMentions > 0 ? yellow(`${ws.totals.unreadMentions} unread @you`) : dim("0 unread @you")
|
|
12314
|
-
].join(dim(" · "));
|
|
12315
|
-
process.stdout.write(" " + totalsLine + `
|
|
12316
|
-
|
|
12317
|
-
`);
|
|
12318
|
-
if (ws.meshes.length === 0) {
|
|
12319
|
-
process.stdout.write(dim(" no meshes joined — run `claudemesh new` or accept an invite\n"));
|
|
12320
|
-
return EXIT.SUCCESS;
|
|
12321
|
-
}
|
|
12322
|
-
const slugWidth = Math.max(...ws.meshes.map((m) => m.slug.length), 8);
|
|
12323
|
-
for (const m of ws.meshes) {
|
|
12324
|
-
const slug = cyan(m.slug.padEnd(slugWidth));
|
|
12325
|
-
const peers = `${m.online}/${m.peers}`;
|
|
12326
|
-
const role = dim(m.myRole);
|
|
12327
|
-
const unread = m.unreadMentions > 0 ? " " + yellow(`${m.unreadMentions} @you`) : "";
|
|
12328
|
-
process.stdout.write(` ${slug} ${peers.padStart(5)} online ${dim(String(m.topics).padStart(2) + " topics")} ${role}${unread}
|
|
12329
|
-
`);
|
|
12330
|
-
}
|
|
12331
|
-
return EXIT.SUCCESS;
|
|
12332
|
-
});
|
|
12333
|
-
}
|
|
12334
|
-
async function runMeTopics(flags) {
|
|
12335
|
-
return withRestKey({
|
|
12336
|
-
meshSlug: flags.mesh ?? null,
|
|
12337
|
-
purpose: "workspace-topics",
|
|
12338
|
-
capabilities: ["read"]
|
|
12339
|
-
}, async ({ secret }) => {
|
|
12340
|
-
const ws = await request({
|
|
12341
|
-
path: "/api/v1/me/topics",
|
|
12342
|
-
token: secret
|
|
12343
|
-
});
|
|
12344
|
-
const visible = flags.unread ? ws.topics.filter((t) => t.unread > 0) : ws.topics;
|
|
12345
|
-
if (flags.json) {
|
|
12346
|
-
console.log(JSON.stringify({ topics: visible, totals: ws.totals }, null, 2));
|
|
12347
|
-
return EXIT.SUCCESS;
|
|
12348
|
-
}
|
|
12349
|
-
render.section(`${clay("topics")} — ${ws.totals.topics} across all meshes ${dim(ws.totals.unread > 0 ? `· ${ws.totals.unread} unread` : "· all read")}`);
|
|
12350
|
-
if (visible.length === 0) {
|
|
12351
|
-
process.stdout.write(dim(flags.unread ? ` no unread topics
|
|
12352
|
-
` : " no topics — run `claudemesh topic create #general`\n"));
|
|
12353
|
-
return EXIT.SUCCESS;
|
|
12354
|
-
}
|
|
12355
|
-
const slugWidth = Math.max(...visible.map((t) => t.meshSlug.length), 6);
|
|
12356
|
-
const nameWidth = Math.max(...visible.map((t) => t.name.length), 8);
|
|
12357
|
-
for (const t of visible) {
|
|
12358
|
-
const slug = dim(t.meshSlug.padEnd(slugWidth));
|
|
12359
|
-
const name = cyan(t.name.padEnd(nameWidth));
|
|
12360
|
-
const unread = t.unread > 0 ? yellow(`${t.unread} unread`.padStart(10)) : dim("·".padStart(10));
|
|
12361
|
-
const last = t.lastMessageAt ? dim(formatRelativeTime(t.lastMessageAt)) : dim("never");
|
|
12362
|
-
process.stdout.write(` ${slug} ${name} ${unread} ${last}
|
|
12363
|
-
`);
|
|
12364
|
-
}
|
|
12365
|
-
return EXIT.SUCCESS;
|
|
12366
|
-
});
|
|
12367
|
-
}
|
|
12368
|
-
async function runMeNotifications(flags) {
|
|
12369
|
-
return withRestKey({
|
|
12370
|
-
meshSlug: flags.mesh ?? null,
|
|
12371
|
-
purpose: "workspace-notifications",
|
|
12372
|
-
capabilities: ["read"]
|
|
12373
|
-
}, async ({ secret }) => {
|
|
12374
|
-
const params = new URLSearchParams;
|
|
12375
|
-
if (flags.all)
|
|
12376
|
-
params.set("include", "all");
|
|
12377
|
-
if (flags.since)
|
|
12378
|
-
params.set("since", flags.since);
|
|
12379
|
-
const path = "/api/v1/me/notifications" + (params.toString() ? `?${params.toString()}` : "");
|
|
12380
|
-
const ws = await request({
|
|
12381
|
-
path,
|
|
12382
|
-
token: secret
|
|
12383
|
-
});
|
|
12384
|
-
if (flags.json) {
|
|
12385
|
-
console.log(JSON.stringify(ws, null, 2));
|
|
12386
|
-
return EXIT.SUCCESS;
|
|
12387
|
-
}
|
|
12388
|
-
const headerLabel = flags.all ? "@-mentions (all)" : "@-mentions (unread)";
|
|
12389
|
-
render.section(`${clay(headerLabel)} — ${ws.totals.total} ${dim(ws.totals.unread > 0 ? `· ${ws.totals.unread} unread` : "· nothing pending")}`);
|
|
12390
|
-
if (ws.notifications.length === 0) {
|
|
12391
|
-
process.stdout.write(dim(flags.all ? ` no @-mentions in window
|
|
12392
|
-
` : ` inbox zero — nothing waiting
|
|
12393
|
-
`));
|
|
12394
|
-
return EXIT.SUCCESS;
|
|
12395
|
-
}
|
|
12396
|
-
const slugWidth = Math.max(...ws.notifications.map((n) => n.meshSlug.length), 6);
|
|
12397
|
-
for (const n of ws.notifications) {
|
|
12398
|
-
const slug = dim(n.meshSlug.padEnd(slugWidth));
|
|
12399
|
-
const topic = cyan(`#${n.topicName}`);
|
|
12400
|
-
const sender = n.senderName ? `from ${n.senderName}` : "from ?";
|
|
12401
|
-
const ago = formatRelativeTime(n.createdAt);
|
|
12402
|
-
const dot = n.read ? dim("·") : yellow("●");
|
|
12403
|
-
const snippet = n.snippet ?? (n.ciphertext ? dim("[encrypted]") : dim("[empty]"));
|
|
12404
|
-
process.stdout.write(` ${dot} ${slug} ${topic} ${dim(sender)} ${dim(ago)}
|
|
12405
|
-
` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
|
|
12406
|
-
`);
|
|
12407
|
-
}
|
|
12408
|
-
return EXIT.SUCCESS;
|
|
12409
|
-
});
|
|
12410
|
-
}
|
|
12411
|
-
async function runMeActivity(flags) {
|
|
12412
|
-
return withRestKey({
|
|
12413
|
-
meshSlug: flags.mesh ?? null,
|
|
12414
|
-
purpose: "workspace-activity",
|
|
12415
|
-
capabilities: ["read"]
|
|
12416
|
-
}, async ({ secret }) => {
|
|
12417
|
-
const params = new URLSearchParams;
|
|
12418
|
-
if (flags.since)
|
|
12419
|
-
params.set("since", flags.since);
|
|
12420
|
-
const path = "/api/v1/me/activity" + (params.toString() ? `?${params.toString()}` : "");
|
|
12421
|
-
const ws = await request({
|
|
12422
|
-
path,
|
|
12423
|
-
token: secret
|
|
12424
|
-
});
|
|
12425
|
-
if (flags.json) {
|
|
12426
|
-
console.log(JSON.stringify(ws, null, 2));
|
|
12427
|
-
return EXIT.SUCCESS;
|
|
12428
|
-
}
|
|
12429
|
-
render.section(`${clay("activity")} — ${ws.totals.events} ${dim(flags.since ? `since ${flags.since}` : "in the last 24h")}`);
|
|
12430
|
-
if (ws.activity.length === 0) {
|
|
12431
|
-
process.stdout.write(dim(` quiet — no activity in window
|
|
12432
|
-
`));
|
|
12433
|
-
return EXIT.SUCCESS;
|
|
12434
|
-
}
|
|
12435
|
-
const slugWidth = Math.max(...ws.activity.map((a) => a.meshSlug.length), 6);
|
|
12436
|
-
for (const a of ws.activity) {
|
|
12437
|
-
const slug = dim(a.meshSlug.padEnd(slugWidth));
|
|
12438
|
-
const topic = cyan(`#${a.topicName}`);
|
|
12439
|
-
const sender = a.senderName ?? "?";
|
|
12440
|
-
const ago = formatRelativeTime(a.createdAt);
|
|
12441
|
-
const snippet = a.snippet ?? (a.ciphertext ? dim("[encrypted]") : dim("[empty]"));
|
|
12442
|
-
process.stdout.write(` ${slug} ${topic} ${dim(sender + " ·")} ${dim(ago)}
|
|
12443
|
-
` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
|
|
12444
|
-
`);
|
|
12445
|
-
}
|
|
12446
|
-
return EXIT.SUCCESS;
|
|
12447
|
-
});
|
|
12448
|
-
}
|
|
12449
|
-
function formatRelativeTime(iso) {
|
|
12450
|
-
const then = new Date(iso).getTime();
|
|
12451
|
-
const now = Date.now();
|
|
12452
|
-
const sec = Math.max(0, Math.floor((now - then) / 1000));
|
|
12453
|
-
if (sec < 60)
|
|
12454
|
-
return `${sec}s ago`;
|
|
12455
|
-
if (sec < 3600)
|
|
12456
|
-
return `${Math.floor(sec / 60)}m ago`;
|
|
12457
|
-
if (sec < 86400)
|
|
12458
|
-
return `${Math.floor(sec / 3600)}h ago`;
|
|
12459
|
-
if (sec < 86400 * 30)
|
|
12460
|
-
return `${Math.floor(sec / 86400)}d ago`;
|
|
12461
|
-
if (sec < 86400 * 365)
|
|
12462
|
-
return `${Math.floor(sec / (86400 * 30))}mo ago`;
|
|
12463
|
-
return `${Math.floor(sec / (86400 * 365))}y ago`;
|
|
12464
|
-
}
|
|
12465
|
-
var init_me = __esm(() => {
|
|
12466
|
-
init_with_rest_key();
|
|
12467
|
-
init_client();
|
|
12468
|
-
init_render();
|
|
12469
|
-
init_styles();
|
|
12470
|
-
init_exit_codes();
|
|
12471
|
-
});
|
|
12472
|
-
|
|
12473
12551
|
// src/commands/member.ts
|
|
12474
12552
|
var exports_member = {};
|
|
12475
12553
|
__export(exports_member, {
|
|
@@ -14100,7 +14178,7 @@ Bridge (forward a topic between two meshes, v0.2.0)
|
|
|
14100
14178
|
|
|
14101
14179
|
Topic (conversation scope, v0.2.0)
|
|
14102
14180
|
claudemesh topic create <name> create a topic [--description --visibility]
|
|
14103
|
-
claudemesh topic list list topics
|
|
14181
|
+
claudemesh topic list list topics across all meshes (or --mesh <slug>)
|
|
14104
14182
|
claudemesh topic join <topic> subscribe (via name or id)
|
|
14105
14183
|
claudemesh topic leave <topic> unsubscribe
|
|
14106
14184
|
claudemesh topic members <t> list topic subscribers
|
|
@@ -14113,8 +14191,9 @@ Topic (conversation scope, v0.2.0)
|
|
|
14113
14191
|
claudemesh me topics cross-mesh topic list [--unread]
|
|
14114
14192
|
claudemesh me notifications cross-mesh @-mentions [--all] [--since=ISO]
|
|
14115
14193
|
claudemesh me activity cross-mesh recent messages [--since=ISO]
|
|
14194
|
+
claudemesh me search <q> cross-mesh search (topics + messages)
|
|
14116
14195
|
claudemesh member list mesh roster with online state [--online]
|
|
14117
|
-
claudemesh notification list
|
|
14196
|
+
claudemesh notification list @-mentions across all meshes (or --mesh <slug>)
|
|
14118
14197
|
|
|
14119
14198
|
Schedule (resource form)
|
|
14120
14199
|
claudemesh schedule msg <m> one-shot or recurring (alias: remind)
|
|
@@ -14911,6 +14990,10 @@ async function main() {
|
|
|
14911
14990
|
const { runTopicCreate: runTopicCreate2 } = await Promise.resolve().then(() => (init_topic(), exports_topic));
|
|
14912
14991
|
process.exit(await runTopicCreate2(arg, f));
|
|
14913
14992
|
} else if (sub === "list") {
|
|
14993
|
+
if (!f.mesh) {
|
|
14994
|
+
const { runMeTopics: runMeTopics2 } = await Promise.resolve().then(() => (init_me(), exports_me));
|
|
14995
|
+
process.exit(await runMeTopics2({ mesh: undefined, json: f.json, unread: !!flags.unread }));
|
|
14996
|
+
}
|
|
14914
14997
|
const { runTopicList: runTopicList2 } = await Promise.resolve().then(() => (init_topic(), exports_topic));
|
|
14915
14998
|
process.exit(await runTopicList2(f));
|
|
14916
14999
|
} else if (sub === "join") {
|
|
@@ -14962,10 +15045,19 @@ async function main() {
|
|
|
14962
15045
|
since: flags.since
|
|
14963
15046
|
};
|
|
14964
15047
|
if (sub === "list") {
|
|
15048
|
+
if (!f.mesh) {
|
|
15049
|
+
const { runMeNotifications: runMeNotifications2 } = await Promise.resolve().then(() => (init_me(), exports_me));
|
|
15050
|
+
process.exit(await runMeNotifications2({
|
|
15051
|
+
mesh: undefined,
|
|
15052
|
+
json: f.json,
|
|
15053
|
+
all: !!flags.all,
|
|
15054
|
+
since: f.since
|
|
15055
|
+
}));
|
|
15056
|
+
}
|
|
14965
15057
|
const { runNotificationList: runNotificationList2 } = await Promise.resolve().then(() => (init_notification(), exports_notification));
|
|
14966
15058
|
process.exit(await runNotificationList2(f));
|
|
14967
15059
|
} else {
|
|
14968
|
-
console.error("Usage: claudemesh notification list [--since <ISO>]");
|
|
15060
|
+
console.error("Usage: claudemesh notification list [--mesh <slug>] [--since <ISO>] [--all]");
|
|
14969
15061
|
process.exit(EXIT.INVALID_ARGS);
|
|
14970
15062
|
}
|
|
14971
15063
|
break;
|
|
@@ -14995,6 +15087,10 @@ async function main() {
|
|
|
14995
15087
|
...f,
|
|
14996
15088
|
since: flags.since
|
|
14997
15089
|
}));
|
|
15090
|
+
} else if (sub === "search") {
|
|
15091
|
+
const { runMeSearch: runMeSearch2 } = await Promise.resolve().then(() => (init_me(), exports_me));
|
|
15092
|
+
const query = positionals.slice(1).join(" ").trim();
|
|
15093
|
+
process.exit(await runMeSearch2({ ...f, query }));
|
|
14998
15094
|
} else {
|
|
14999
15095
|
console.error(`Usage: claudemesh me (cross-mesh overview)
|
|
15000
15096
|
claudemesh me topics (cross-mesh topic list)
|
|
@@ -15003,7 +15099,8 @@ async function main() {
|
|
|
15003
15099
|
claudemesh me notifications --all (include already-read)
|
|
15004
15100
|
claudemesh me notifications --since=ISO (custom window)
|
|
15005
15101
|
claudemesh me activity (recent messages, last 24h)
|
|
15006
|
-
claudemesh me activity --since=ISO (custom window)
|
|
15102
|
+
claudemesh me activity --since=ISO (custom window)
|
|
15103
|
+
claudemesh me search <query> (cross-mesh search)`);
|
|
15007
15104
|
process.exit(EXIT.INVALID_ARGS);
|
|
15008
15105
|
}
|
|
15009
15106
|
break;
|
|
@@ -15073,4 +15170,4 @@ main().catch((err) => {
|
|
|
15073
15170
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
15074
15171
|
});
|
|
15075
15172
|
|
|
15076
|
-
//# debugId=
|
|
15173
|
+
//# debugId=3168504A6207F58264756E2164756E21
|