feat(plugin): SessionStart hook discovers and announces active peers
session-announce now calls /v1/list with the session's X-Mailbox header, which both registers the session with the daemon and returns all known mailboxes in one round-trip. The output appends an "Active peers" block listing mailboxes seen within the last hour (configurable via --peer-window-minutes), capped at 10 entries by default. Self is filtered out; the list is sorted most-recent-first. So when the user says "I started a second session, coordinate with it", Claude already has the peer's mailbox name in context — no manual list_mailboxes call needed. The peer-formatting logic is extracted into formatActivePeerList for unit testing; CLI tests now pin --url to an unreachable port to keep assertions stable on machines that have a real daemon running.
This commit is contained in:
@@ -79,6 +79,8 @@ describe("`check --hook` CLI behavior", () => {
|
||||
});
|
||||
|
||||
describe("`session-announce` CLI behavior", () => {
|
||||
const UNREACHABLE = "http://127.0.0.1:1";
|
||||
|
||||
beforeAll(() => {
|
||||
if (!existsSync(cliPath)) {
|
||||
throw new Error(`CLI not built. Run \`npm run build\` first. Missing: ${cliPath}`);
|
||||
@@ -86,7 +88,7 @@ describe("`session-announce` CLI behavior", () => {
|
||||
});
|
||||
|
||||
it("prints the derived mailbox name from a SessionStart payload", () => {
|
||||
const r = runCli(["session-announce"], {
|
||||
const r = runCli(["session-announce", "--url", UNREACHABLE], {
|
||||
env: { CLAUDE_MAILBOX_NAME: undefined },
|
||||
stdin: HOOK_STDIN,
|
||||
});
|
||||
@@ -97,7 +99,7 @@ describe("`session-announce` CLI behavior", () => {
|
||||
});
|
||||
|
||||
it("uses base prefix when set", () => {
|
||||
const r = runCli(["session-announce"], {
|
||||
const r = runCli(["session-announce", "--url", UNREACHABLE], {
|
||||
env: { CLAUDE_MAILBOX_NAME: "backend" },
|
||||
stdin: HOOK_STDIN,
|
||||
});
|
||||
@@ -105,8 +107,17 @@ describe("`session-announce` CLI behavior", () => {
|
||||
expect(r.stdout).toContain("`backend-abc12345`");
|
||||
});
|
||||
|
||||
it("emits daemon-not-reachable hint when daemon is down", () => {
|
||||
const r = runCli(["session-announce", "--url", UNREACHABLE], {
|
||||
env: { CLAUDE_MAILBOX_NAME: undefined },
|
||||
stdin: HOOK_STDIN,
|
||||
});
|
||||
expect(r.status).toBe(0);
|
||||
expect(r.stdout).toContain("[Claude-Mailbox] Daemon not reachable");
|
||||
});
|
||||
|
||||
it("stays silent when no session_id in stdin", () => {
|
||||
const r = runCli(["session-announce"], {
|
||||
const r = runCli(["session-announce", "--url", UNREACHABLE], {
|
||||
env: { CLAUDE_MAILBOX_NAME: undefined },
|
||||
stdin: JSON.stringify({ hook_event_name: "SessionStart" }),
|
||||
});
|
||||
@@ -115,7 +126,9 @@ describe("`session-announce` CLI behavior", () => {
|
||||
});
|
||||
|
||||
it("stays silent when no stdin at all", () => {
|
||||
const r = runCli(["session-announce"], { env: { CLAUDE_MAILBOX_NAME: undefined } });
|
||||
const r = runCli(["session-announce", "--url", UNREACHABLE], {
|
||||
env: { CLAUDE_MAILBOX_NAME: undefined },
|
||||
});
|
||||
expect(r.status).toBe(0);
|
||||
expect(r.stdout).toBe("");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user