feat(cli): 1.32.0 — multi-session UX bundle (self-identity, --self fan-out, broker welcome)
Nine UX bugs surfaced from a real two-session interconnect smoke test, shipped together. Self-identity is visible - peer list now shows the caller as (this session), sorted to top. Daemon path resolves session pubkey via /v1/sessions/me so isThisSession is set correctly warm. - whoami shows session pubkey, session id, mesh, role, groups, cwd, pid when run inside a launched session. Sibling-session disambiguation - peer list rows carry sid:<short> tag so visually-identical rows can be told apart at a glance. Daemon hidden by default - claudemesh-daemon presence rows hidden from peer list by default. --all opts back in. Header shows N daemon hidden when applicable. --self flag works end-to-end - Argv parser was greedy: --self ate the next arg as its value. BOOLEAN_FLAGS set in cli/argv.ts now lists known no-value switches. - message send subcommand now passes self through (only legacy send was wired before). - Help text lists --self. Member-pubkey fan-out - Sending to your own member pubkey with --self now resolves to every connected sibling session and sends one message per recipient. Required because the broker drain matches target_spec only against full session pubkeys; member-pubkey sends queued but never drained. Broker welcome at launch - After the launch banner, one line confirms WS state, peer count, and unread inbox count. Best-effort — falls back gracefully. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,25 +1,51 @@
|
||||
import { whoAmI } from "~/services/auth/facade.js";
|
||||
import { getSessionInfo } from "~/services/session/resolve.js";
|
||||
import { render } from "~/ui/render.js";
|
||||
import { bold, clay, dim } from "~/ui/styles.js";
|
||||
import { bold, clay, dim, yellow } from "~/ui/styles.js";
|
||||
import { EXIT } from "~/constants/exit-codes.js";
|
||||
|
||||
export async function whoami(opts: { json?: boolean }): Promise<number> {
|
||||
const result = await whoAmI();
|
||||
// 1.32.0+: surface the calling session's identity when whoami is run
|
||||
// from inside a `claudemesh launch`-spawned shell. Previously the
|
||||
// command only reported web sign-in + local mesh memberships, and a
|
||||
// launched session had to dig env vars + parse config.json to figure
|
||||
// out its own session pubkey.
|
||||
const session = await getSessionInfo();
|
||||
|
||||
if (opts.json) {
|
||||
console.log(JSON.stringify({ schema_version: "1.0", ...result }, null, 2));
|
||||
return result.signed_in || result.local ? EXIT.SUCCESS : EXIT.AUTH_FAILED;
|
||||
console.log(JSON.stringify({ schema_version: "1.0", ...result, session }, null, 2));
|
||||
return result.signed_in || result.local || session ? EXIT.SUCCESS : EXIT.AUTH_FAILED;
|
||||
}
|
||||
|
||||
// Show whatever we have. Both the web session and the local mesh
|
||||
// config are independent surfaces of identity; suppress sections that
|
||||
// are empty.
|
||||
if (!result.signed_in && !result.local) {
|
||||
// Show whatever we have. Web session, local mesh config, and the
|
||||
// launched-session identity are three independent surfaces.
|
||||
if (!result.signed_in && !result.local && !session) {
|
||||
render.err("Not signed in", "Run `claudemesh login` to sign in or `claudemesh <invite>` to join.");
|
||||
return EXIT.AUTH_FAILED;
|
||||
}
|
||||
|
||||
render.section("whoami");
|
||||
|
||||
if (session) {
|
||||
const sessionPk = session.presence?.sessionPubkey;
|
||||
const groups = (session.groups ?? []).join(", ") || dim("(none)");
|
||||
render.kv([
|
||||
["this session", `${yellow(session.displayName)} on ${bold(session.mesh)}`],
|
||||
["session id", dim(session.sessionId)],
|
||||
...(sessionPk
|
||||
? [["session pubkey", dim(`${sessionPk.slice(0, 16)}… (full: ${sessionPk})`)] as [string, string]]
|
||||
: []),
|
||||
...(session.role
|
||||
? [["role", session.role] as [string, string]]
|
||||
: []),
|
||||
["groups", groups],
|
||||
...(session.cwd ? [["cwd", dim(session.cwd)] as [string, string]] : []),
|
||||
["pid", String(session.pid)],
|
||||
]);
|
||||
render.blank();
|
||||
}
|
||||
|
||||
if (result.signed_in) {
|
||||
render.kv([
|
||||
["user", `${bold(result.user!.display_name)} ${dim(`(${result.user!.email})`)}`],
|
||||
|
||||
Reference in New Issue
Block a user