@gorlitzer-labs/apiary 1.13.5 → 1.13.7

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.
@@ -352,7 +352,7 @@ function foundationInit(cwd) {
352
352
  if (existsSync3(join(dir, "docs", "QUEUE.md"))) return { ok: true, how: "already" };
353
353
  const attempts = [
354
354
  { cmd: "foundation", args: ["init", dir], how: "local" },
355
- { cmd: "npx", args: ["--yes", "github:gorlitzer-labs/foundation", "init", dir], how: "npx" }
355
+ { cmd: "npx", args: ["--yes", "@gorlitzer-labs/foundation", "init", dir], how: "npx" }
356
356
  ];
357
357
  for (const a of attempts) {
358
358
  try {
@@ -1096,4 +1096,4 @@ export {
1096
1096
  spawnDaemonServer,
1097
1097
  writeInvite
1098
1098
  };
1099
- //# sourceMappingURL=room-IHVB5CWO.js.map
1099
+ //# sourceMappingURL=room-ID4DQDPT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/room.ts","../src/cli/new-repo.ts","../src/cli/repoPicker.ts","../src/cli/foundation.ts"],"sourcesContent":["/**\n * apiary room create / resume / list\n *\n * Interactive room management — the human-friendly entry point.\n * Daemon pattern: server spawns as a detached child process so the TUI\n * can exit (Ctrl+C) without killing the room.\n */\n\nimport { spawn, execFileSync } from \"node:child_process\";\nimport {\n existsSync, mkdirSync, writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\nimport { createInterface } from \"node:readline\";\n\nimport { buildShareUrl, extractToken } from \"./auth.js\";\nimport { agentEmoji, roomEmoji } from \"./config.js\";\nimport { askRepoPath, askRuntime, askReach, shortenPath } from \"./repoPicker.js\";\nimport { tailnetAddress, lanAddress, ALL_INTERFACES, LOOPBACK } from \"./bind.js\";\nimport { foundationInit } from \"./foundation.js\";\nimport type { AuthorityLevel } from \"../core/types.js\";\nimport type { EngagementMode } from \"../agent/engagement.js\";\nimport { roomRulesPath } from \"../core/rules.js\";\nimport {\n listRoomSessions, saveRoomSession, removeRoomSession, INVITES_DIR,\n type PersistedRoomSession,\n} from \"./serve.js\";\nimport {\n tmuxAvailable, tmuxSessionExists, tmuxKillSession,\n} from \"./tmux.js\";\n\n/** 7 days in ms — default share token TTL for persistent daemon sessions. */\nconst DAEMON_SHARE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\n// ── Readline prompt helper ────────────────────────────────────────────────────\n\ninterface Prompter {\n ask: (q: string) => Promise<string>;\n close: () => void;\n}\n\n// ── Alias-spec parser ────────────────────────────────────────────────────────\n//\n// The wizard accepts `alias[:token][:token...]` where each suffix token\n// modifies one independent axis:\n// - type: `human` (default `agent`)\n// - tier: `owner` (= product_owner), `admin`, `guest` (default `member`)\n// - mode: `standby` (= standby-everyone), or any engagement mode verbatim\n// - role: any unrecognized token is preserved as a cosmetic role label.\n//\n// Examples:\n// `cane` → agent / member\n// `bob:human` → human / member\n// `cane:owner` → agent / product_owner (\"the agent in charge\")\n// `bob:human:admin` → human / admin\n// `cane:owner:human` → human / product_owner (order doesn't matter)\n// `bf:opus` → agent / member, claude --model opus\n// `anvil:sonnet:owner`→ agent / product_owner, claude --model sonnet\n// `cane:standby` → agent / member, only wakes when addressed\n//\n// Model tokens: short aliases (opus, sonnet, haiku) map to the latest of each\n// family — claude resolves them. Full model ids also pass through verbatim.\n\nconst TIER_TOKENS: Record<string, AuthorityLevel> = {\n owner: \"product_owner\",\n product_owner: \"product_owner\",\n admin: \"admin\",\n member: \"member\",\n guest: \"guest\",\n};\nconst TYPE_TOKENS: Record<string, \"agent\" | \"human\"> = {\n agent: \"agent\",\n human: \"human\",\n};\n// Engagement mode. `standby` is the shorthand people actually want: quiet\n// until addressed, by anyone. The full mode names pass through verbatim.\nconst MODE_TOKENS: Record<string, EngagementMode> = {\n standby: \"standby-everyone\",\n \"standby-everyone\": \"standby-everyone\",\n \"standby-people\": \"standby-people\",\n \"standby-agents\": \"standby-agents\",\n active: \"everyone\",\n everyone: \"everyone\",\n people: \"people\",\n agents: \"agents\",\n};\nconst MODEL_TOKENS = new Set([\n \"opus\", \"sonnet\", \"haiku\",\n // also accept full model ids verbatim\n]);\nfunction isModelToken(tok: string): boolean {\n const lc = tok.toLowerCase();\n if (MODEL_TOKENS.has(lc)) return true;\n // Full model id pattern: claude-{opus|sonnet|haiku}-N-M[(...)]\n return /^claude-(opus|sonnet|haiku)-\\d/.test(lc);\n}\n\nexport function parseAliasSpec(input: string): {\n alias: string;\n type: \"agent\" | \"human\";\n tier: AuthorityLevel;\n role: string;\n model?: string;\n mode?: EngagementMode;\n} | null {\n const parts = input.split(\":\").map((p) => p.trim()).filter(Boolean);\n if (parts.length === 0) return null;\n const alias = parts[0];\n let type: \"agent\" | \"human\" = \"agent\";\n let tier: AuthorityLevel = \"member\";\n let role = \"agent\";\n let model: string | undefined;\n let mode: EngagementMode | undefined;\n for (const tok of parts.slice(1)) {\n const lc = tok.toLowerCase();\n if (TYPE_TOKENS[lc]) {\n type = TYPE_TOKENS[lc];\n role = type;\n } else if (TIER_TOKENS[lc]) {\n tier = TIER_TOKENS[lc];\n } else if (MODE_TOKENS[lc]) {\n mode = MODE_TOKENS[lc];\n } else if (isModelToken(tok)) {\n model = lc;\n } else {\n role = lc;\n }\n }\n return { alias, type, tier, role, model, mode };\n}\n\n/**\n * Keep the first agent listening, quiet the rest.\n *\n * In an active mode every agent evaluates every message, so an unaddressed\n * remark in a room of five costs five agent turns and yields five answers to\n * one question. Standby is the fix, but making it the blanket default means a\n * room that ignores you until you remember to @mention somebody.\n *\n * So exactly one agent stays active: whatever you say lands with someone who\n * can answer, or pull in the others by @mentioning them. The rest wake only\n * when addressed — @mentioned, pinged, or whispered to.\n *\n * An explicit `:standby` / `:active` suffix always wins; this only fills in\n * agents that said nothing. Solo-agent rooms are untouched (that one agent is\n * the first), and humans are never assigned a mode.\n *\n * Exported for tests.\n */\nexport function applyDefaultModes(\n participants: Array<{ role: string; mode?: EngagementMode }>,\n): void {\n let seenActiveAgent = false;\n for (const p of participants) {\n if (p.role !== \"agent\") continue;\n if (p.mode !== undefined) {\n // An explicit active mode counts as the listener, so we don't then\n // promote a second agent and end up with two.\n if (!p.mode.startsWith(\"standby-\")) seenActiveAgent = true;\n continue;\n }\n if (!seenActiveAgent) {\n p.mode = \"everyone\";\n seenActiveAgent = true;\n } else {\n p.mode = \"standby-everyone\";\n }\n }\n}\n\nfunction makePrompt(): Prompter {\n // Per-question readline: open → ask → close. Lets the repo picker (which\n // toggles raw mode on stdin) own input cleanly between questions, with no\n // listener contention from a long-lived readline interface.\n return {\n ask: (q: string) => new Promise((res) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(q, (a) => {\n rl.close();\n res(a.trim());\n });\n }),\n close: () => {},\n };\n}\n\n// ── Daemon server spawn ───────────────────────────────────────────────────────\n\ninterface DaemonResult {\n serverUrl: string;\n publicUrl: string;\n roomName: string;\n adminToken: string;\n memberToken: string;\n savePath: string;\n pid: number;\n}\n\nexport interface DaemonSpawnFailure {\n reason: string; // human-readable summary\n stderr?: string; // raw child stderr if captured\n portInUse?: boolean; // EADDRINUSE on the requested port\n}\n\nexport async function spawnDaemonServer(opts: {\n room?: string;\n port?: number;\n share?: boolean;\n expose?: boolean;\n /** Already-resolved listen address (see cli/bind.ts). */\n bind?: string;\n shareTtlMs?: number;\n}): Promise<DaemonResult | DaemonSpawnFailure> {\n const scriptPath = process.argv[1];\n const ttl = opts.shareTtlMs ?? DAEMON_SHARE_TTL_MS;\n\n const args = [\"serve\", \"--headless\", \"--share-token-ttl\", String(ttl)];\n if (opts.room) args.push(\"--room\", opts.room);\n if (opts.port) args.push(\"--port\", String(opts.port));\n if (opts.share) args.push(\"--share\");\n if (opts.expose) args.push(\"--expose\");\n if (opts.bind) args.push(\"--bind\", opts.bind);\n\n return new Promise((resolve) => {\n const child = spawn(process.execPath, [scriptPath, ...args], {\n detached: true,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdoutBuf = \"\";\n let stderrBuf = \"\";\n let settled = false;\n const settle = (v: DaemonResult | DaemonSpawnFailure) => {\n if (settled) return;\n settled = true;\n resolve(v);\n };\n\n child.stdout!.on(\"data\", (chunk: Buffer) => {\n stdoutBuf += chunk.toString();\n const line = stdoutBuf.split(\"\\n\").find((l) => l.trim().startsWith(\"{\"));\n if (line) {\n try {\n const result = JSON.parse(line.trim());\n child.unref();\n settle({ ...result, pid: child.pid! });\n } catch {\n /* keep buffering */\n }\n }\n });\n\n child.stderr!.on(\"data\", (chunk: Buffer) => { stderrBuf += chunk.toString(); });\n\n child.on(\"error\", (err) => settle({ reason: err.message, stderr: stderrBuf }));\n child.on(\"exit\", (code) => {\n if (code !== 0) {\n const portInUse = /EADDRINUSE|already in use/i.test(stderrBuf);\n settle({\n reason: portInUse\n ? `port ${opts.port ?? 7890} already in use`\n : `daemon exited with code ${code}`,\n stderr: stderrBuf,\n portInUse,\n });\n }\n });\n setTimeout(() => settle({ reason: \"timed out waiting for daemon startup\", stderr: stderrBuf }), 15_000);\n });\n}\n\n/** Type guard — `true` if spawnDaemonServer returned a successful DaemonResult. */\nexport function isDaemonResult(v: DaemonResult | DaemonSpawnFailure): v is DaemonResult {\n return \"serverUrl\" in v;\n}\n\n// ── Invite file helpers ───────────────────────────────────────────────────────\n\nexport function writeInvite(alias: string, joinUrl: string): void {\n mkdirSync(INVITES_DIR, { recursive: true });\n writeFileSync(pathJoin(INVITES_DIR, alias), joinUrl, { mode: 0o600 });\n}\n\nfunction isLocalPath(p: string): boolean {\n try {\n return existsSync(p.replace(/^~/, homedir()));\n } catch {\n return false;\n }\n}\n\n// ── Lightweight HTTP helpers (no TUI) ─────────────────────────────────────────\n\n/** Join a room as a transient agent and return the session token. */\nasync function httpJoin(\n serverUrl: string,\n shareToken: string,\n name = \"[system]\",\n): Promise<string | null> {\n try {\n const res = await fetch(`${serverUrl}/join`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ shareToken, name, type: \"agent\" }),\n });\n if (!res.ok) return null;\n const data = await res.json() as { sessionToken?: string };\n return data.sessionToken ?? null;\n } catch {\n return null;\n }\n}\n\n/** Disconnect a participant by session token. */\nasync function httpDisconnect(serverUrl: string, sessionToken: string): Promise<void> {\n await fetch(`${serverUrl}/disconnect`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n }).catch(() => {});\n}\n\n/**\n * Post a system message to the room as a transient participant.\n * Joins with the admin share token, posts, then immediately disconnects.\n */\nasync function postSystemMessage(\n serverUrl: string,\n adminShareToken: string,\n content: string,\n): Promise<void> {\n const sessionToken = await httpJoin(serverUrl, adminShareToken, \"[system]\");\n if (!sessionToken) return;\n await fetch(`${serverUrl}/message`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n body: JSON.stringify({ content }),\n }).catch(() => {});\n await httpDisconnect(serverUrl, sessionToken);\n}\n\n/**\n * Open a single transient admin session and fetch both fresh share tokens\n * and the currently connected participant names.\n *\n * GET /participants and POST /share both require a session token (not a share\n * token), so we join once, make both calls, then immediately disconnect.\n */\nasync function fetchServerState(\n serverUrl: string,\n adminShareToken: string,\n publicUrl: string,\n): Promise<{ memberToken?: string; connectedNames: Set<string> }> {\n const sessionToken = await httpJoin(serverUrl, adminShareToken, \"[system]\");\n if (!sessionToken) return { connectedNames: new Set() };\n\n let memberToken: string | undefined;\n let connectedNames: Set<string> = new Set();\n\n try {\n const [shareRes, participantsRes] = await Promise.all([\n fetch(`${serverUrl}/share`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n body: JSON.stringify({}),\n }),\n fetch(`${serverUrl}/participants`, {\n headers: { Authorization: `Bearer ${sessionToken}` },\n }),\n ]);\n\n if (shareRes.ok) {\n const data = await shareRes.json() as { links?: Record<string, string> };\n const memberUrl = data.links?.[\"member\"];\n if (memberUrl) memberToken = extractToken(memberUrl) ?? undefined;\n }\n\n if (participantsRes.ok) {\n const data = await participantsRes.json() as { participants: Array<{ name: string }> };\n connectedNames = new Set(data.participants.map((p) => p.name.toLowerCase()));\n }\n } finally {\n await httpDisconnect(serverUrl, sessionToken);\n }\n\n return { memberToken, connectedNames };\n}\n\n// ── Runtime detection ─────────────────────────────────────────────────────────\n\n// Unix/macOS only — `which` is not available on Windows; both return false there (graceful, no auto-spawn).\nfunction detectRuntimes(): { claude: boolean; codex: boolean } {\n const has = (cmd: string) => {\n try { execFileSync(\"which\", [cmd], { stdio: \"ignore\" }); return true; } catch { return false; }\n };\n return { claude: has(\"claude\"), codex: has(\"codex\") };\n}\n\n// ── ASCII bee banner ──────────────────────────────────────────────────────────\n\nconst A = \"\\x1b[33m\"; // amber\nconst RESET = \"\\x1b[0m\";\n\nconst BEE_BANNER = [\n `${A} _ \\\\ \\\\${RESET}`,\n `${A} ____ _____ (_)___ ________ __ \\\\ \\\\ \\\\${RESET}`,\n `${A} / __ \\`/ __ \\\\/ / __ \\`/ ___/ / / / (o o)${RESET}`,\n `${A}/ /_/ / /_/ / / /_/ / / / /_/ / )=BzZz=(${RESET}`,\n `${A}\\\\__,_/ .___/_/\\\\__,_/_/ \\\\__, / / / /${RESET}`,\n `${A} /_/ /____/ / / /${RESET}`,\n].join(\"\\n\");\n\n// ── Agent background spawn ────────────────────────────────────────────────────\n\n/**\n * Spawn `apiary <runtime> <alias> --background` as a detached child process in\n * the participant's cwd. The child creates its own tmux session and runs until\n * SIGTERM (sent by `roomStop`).\n *\n * Returns why it failed rather than a bare false: the caller only logged the\n * success case, so a participant pointed at a directory that did not exist\n * produced no agent and no message — you were left guessing.\n */\n/** Why an agent did not start, so the caller can say so. */\ntype SpawnAgentResult = { ok: true } | { ok: false; reason: string };\n\nfunction spawnAgentBackground(\n alias: string,\n cwd: string,\n runtime: string,\n tier: AuthorityLevel = \"member\",\n model?: string,\n mode?: string,\n): SpawnAgentResult {\n const resolvedCwd = cwd.replace(/^~/, homedir());\n if (!existsSync(resolvedCwd)) return { ok: false, reason: `${shortenPath(cwd)} doesn't exist` };\n // For agents at admin or product_owner tier, pass --admin so the local MCP\n // server exposes the privileged tool set. The server still enforces the\n // real tier via the share token; --admin only affects which tools the\n // agent's process *advertises*.\n const args = [process.argv[1], runtime, alias, \"--background\"];\n if (tier === \"admin\" || tier === \"product_owner\") args.push(\"--admin\");\n if (model) args.push(\"--model\", model);\n if (mode) args.push(\"--mode\", mode);\n try {\n const child = spawn(process.execPath, args, {\n detached: true,\n stdio: \"ignore\",\n cwd: resolvedCwd,\n });\n child.unref();\n return { ok: true };\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : \"spawn failed\" };\n }\n}\n\n/**\n * Mint share tokens for each non-member tier the wizard needs. Opens a single\n * transient admin session, posts to `/share` once per tier, then disconnects.\n *\n * Returns a map { tier → join URL } for the tiers successfully minted. Tiers\n * that fail to mint (network error, server rejects) are omitted; the caller\n * falls back to the member URL.\n */\nasync function mintTierTokens(\n serverUrl: string,\n adminShareToken: string,\n shareBase: string,\n tiers: AuthorityLevel[],\n): Promise<Partial<Record<AuthorityLevel, string>>> {\n const result: Partial<Record<AuthorityLevel, string>> = {};\n const sessionToken = await httpJoin(serverUrl, adminShareToken, \"[system]\");\n if (!sessionToken) return result;\n try {\n for (const tier of tiers) {\n try {\n const res = await fetch(`${serverUrl}/share`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n body: JSON.stringify({ authority: tier }),\n });\n if (!res.ok) continue;\n const data = await res.json() as { links?: Record<string, string>; token?: string };\n // Some endpoints return a token; others a URL. Handle both.\n const linkForTier = data.links?.[tier];\n const token = linkForTier ? extractToken(linkForTier) : data.token;\n if (token) result[tier] = buildShareUrl(shareBase, token);\n } catch {\n /* tier failed — skip; caller falls back to memberJoinUrl */\n }\n }\n } finally {\n await httpDisconnect(serverUrl, sessionToken);\n }\n return result;\n}\n\n// ── Print invite for one participant ─────────────────────────────────────────\n\nfunction printInvite(alias: string, joinUrl: string, sameHost: boolean): void {\n const C = \"\\x1b[36m\";\n const D = \"\\x1b[2m\";\n const G = \"\\x1b[32m\";\n const R = \"\\x1b[0m\";\n\n if (sameHost) {\n writeInvite(alias, joinUrl);\n console.log(` ${G}✓${R} ${alias} ${D}(invite queued — auto-consumed on next launch)${R}`);\n } else {\n console.log(` ${alias}:`);\n }\n console.log(` ${C}apiary join${R} \"${joinUrl}\"`);\n}\n\n// ── apiary room create ────────────────────────────────────────────────────────\n\nexport async function roomCreate(opts: {\n room?: string;\n port?: number;\n share?: boolean;\n expose?: boolean;\n /** Already-resolved listen address (see cli/bind.ts). Beats expose. */\n bind?: string;\n /** Bootstrap the Foundation project workflow into each repo (default on). --no-foundation opts out. */\n foundation?: boolean;\n}): Promise<void> {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const D = \"\\x1b[2m\";\n const C = \"\\x1b[36m\";\n const R = \"\\x1b[0m\";\n\n const { ask, close } = makePrompt();\n\n console.log(`\\n${BEE_BANNER}\\n`);\n console.log(` ${Y}${B}apiary${R} — create room\\n`);\n\n const roomName = opts.room ?? ((await ask(` Room name ${D}[random]${R}: `)) || undefined);\n\n const hostName = (await ask(` Your name ${D}[random]${R}: `)) || undefined;\n\n const ttlInput = await ask(` Session duration ${D}[7d]${R}: `);\n const shareTtlMs = parseDuration(ttlInput) ?? DAEMON_SHARE_TTL_MS;\n\n const rts = detectRuntimes();\n const availableRuntimes = [...(rts.claude ? [\"claude\"] : []), ...(rts.codex ? [\"codex\"] : [])];\n if (availableRuntimes.length === 0) {\n console.log(`\\n ${D}(neither claude nor codex found in PATH — agents will need to join manually)${R}`);\n } else if (availableRuntimes.length === 1) {\n console.log(`\\n ${D}Runtime auto-detected: ${availableRuntimes[0]}${R}`);\n }\n\n const participants: Array<{\n alias: string;\n cwd: string;\n role: string;\n runtime?: string;\n tier: AuthorityLevel;\n model?: string;\n mode?: EngagementMode;\n }> = [];\n const G = \"\\x1b[32m\";\n const M = \"\\x1b[35m\";\n const divider = ` ${D}${\"─\".repeat(56)}${R}`;\n console.log(`\\n ${B}Invite participants${R}`);\n console.log(divider);\n while (true) {\n const n = participants.length + 1;\n console.log(`\\n 🐝 ${M}${B}Participant ${n}${R}`);\n const aliasInput = await ask(\n ` ${C}→${R} Alias ${D}(blank ↵ to finish · suffix :human, :owner, :admin, :guest, :standby)${R}: `,\n );\n if (!aliasInput) {\n const count = participants.length;\n const summary = count === 0\n ? `${D}no participants — starting an empty room${R}`\n : `${G}✓${R} ${B}${count}${R} participant${count === 1 ? \"\" : \"s\"} ready — starting room…`;\n console.log(` ${summary}`);\n break;\n }\n const spec = parseAliasSpec(aliasInput);\n if (!spec) continue;\n const { alias, role, tier, model, mode } = spec;\n const cwd = await askRepoPath({ alias, defaultPath: process.cwd(), ask });\n const runtime = role === \"agent\"\n ? await askRuntime({ alias, available: availableRuntimes, ask })\n : undefined;\n participants.push({ alias, cwd, role, runtime, tier, model, mode });\n const bug = role === \"agent\" ? agentEmoji(alias) : role === \"human\" ? \"👤\" : \"✎\";\n const runtimeBadge = runtime ? ` · ${C}${runtime}${R}` : \"\";\n const modelBadge = model ? ` ${Y}[${model}]${R}` : \"\";\n const tierBadge = tier !== \"member\" ? ` ${Y}[${tier === \"product_owner\" ? \"owner\" : tier}]${R}` : \"\";\n const modeBadge = mode ? ` ${Y}[${mode}]${R}` : \"\";\n console.log(\n ` ${G}✅${R} ${bug} ${B}${alias}${R}${tierBadge}${modelBadge}${modeBadge} ${D}${role}${R}${runtimeBadge} ${D}${shortenPath(cwd)}${R}`,\n );\n console.log(divider);\n }\n\n applyDefaultModes(participants);\n\n // Network reach. Skipped entirely when --bind/--expose already said so on\n // the command line, so scripted use is unaffected.\n let bindAddress = opts.bind;\n if (!bindAddress && !opts.expose) {\n const ts = tailnetAddress();\n const lan = lanAddress();\n const reach = await askReach({\n ask,\n options: [\n { label: \"This machine only\", value: LOOPBACK, hint: \"safest default\" },\n ...(ts ? [{\n label: `Tailnet ${D}(${ts})${R}`,\n value: ts,\n // The room is on your VPN only: reachable from your other devices\n // anywhere, invisible to whatever wifi this machine is on.\n hint: \"your devices anywhere, via Tailscale — not the local network\",\n }] : []),\n ...(lan ? [{\n label: `This network ${D}(${lan})${R}`,\n value: lan,\n hint: \"anyone on the same wifi\",\n }] : []),\n { label: \"All interfaces\", value: ALL_INTERFACES, hint: \"including untrusted networks — rarely what you want\" },\n ],\n });\n if (reach !== LOOPBACK) bindAddress = reach;\n }\n\n close();\n\n // ── Foundation: bootstrap the project workflow into each repo (always follows) ──\n if (opts.foundation !== false) {\n const seen = new Set<string>();\n for (const p of participants) {\n if (!isLocalPath(p.cwd)) continue;\n const key = p.cwd.replace(/^~/, homedir());\n if (seen.has(key)) continue;\n seen.add(key);\n const r = foundationInit(p.cwd);\n const where = shortenPath(p.cwd);\n if (r.how === \"already\") console.log(` ${D}Foundation already set up in ${where}${R}`);\n else if (r.ok) console.log(` ${G}✓${R} Foundation installed in ${D}${where}${R} ${D}(${r.how})${R}`);\n else console.log(` ${D}Foundation skipped for ${where} — run: foundation init${R}`);\n }\n }\n\n console.log(`\\n Starting server in background...`);\n\n const daemonRes = await spawnDaemonServer({\n room: roomName,\n port: opts.port,\n share: opts.share,\n expose: opts.expose,\n bind: bindAddress,\n shareTtlMs,\n });\n if (!isDaemonResult(daemonRes)) {\n console.error(`\\n ${Y}✗${R} Failed to start server: ${B}${daemonRes.reason}${R}`);\n if (daemonRes.portInUse) {\n console.error(` ${D}A previous room daemon is probably still bound. Inspect with:${R} ${C}apiary ps${R}`);\n console.error(` ${D}Stop it with:${R} ${C}apiary stop --all${R} ${D}(or ${R}${C}apiary stop <room>${R}${D})${R}`);\n } else if (daemonRes.stderr?.trim()) {\n console.error(` ${D}stderr:${R}\\n${daemonRes.stderr.split(\"\\n\").map((l) => \" \" + l).join(\"\\n\")}`);\n }\n process.exit(1);\n }\n const daemon = daemonRes;\n\n saveRoomSession({\n roomName: daemon.roomName,\n serverUrl: daemon.serverUrl,\n publicUrl: daemon.publicUrl,\n adminToken: daemon.adminToken,\n memberToken: daemon.memberToken,\n pid: daemon.pid,\n lastActive: Date.now(),\n hostName,\n participants,\n });\n\n const shareBase = daemon.publicUrl !== daemon.serverUrl ? daemon.publicUrl : daemon.serverUrl;\n const memberJoinUrl = buildShareUrl(shareBase, daemon.memberToken);\n\n // Mint per-tier share tokens for any participant whose tier isn't \"member\".\n // The daemon's startup payload only includes adminToken + memberToken; we\n // need a fresh token per non-default tier. POST /share with the admin\n // session — once per distinct tier — covers every participant cheaply.\n const tieredJoinUrls: Partial<Record<AuthorityLevel, string>> = { member: memberJoinUrl };\n const nonMemberTiers = Array.from(\n new Set(participants.map((p) => p.tier).filter((t) => t !== \"member\")),\n );\n if (nonMemberTiers.length > 0) {\n const mintedUrls = await mintTierTokens(daemon.serverUrl, daemon.adminToken, shareBase, nonMemberTiers);\n Object.assign(tieredJoinUrls, mintedUrls);\n }\n\n const canSpawn = tmuxAvailable();\n if (participants.length > 0) {\n console.log(`\\n ${B}Invite links:${R}\\n`);\n const hasRuntimeParticipants = participants.some((p) => p.runtime);\n if (!canSpawn && hasRuntimeParticipants) {\n console.log(` ${D}(tmux not found — agents will need to join manually via the invite links below)${R}\\n`);\n }\n const allLocal = participants.every((p) => isLocalPath(p.cwd));\n for (const p of participants) {\n const sameHost = allLocal || isLocalPath(p.cwd);\n const joinUrl = tieredJoinUrls[p.tier] ?? memberJoinUrl;\n printInvite(p.alias, joinUrl, sameHost);\n if (sameHost && canSpawn && p.runtime) {\n const spawned = spawnAgentBackground(p.alias, p.cwd, p.runtime, p.tier, p.model, p.mode);\n if (spawned.ok) {\n const modeNote = p.mode?.startsWith(\"standby-\")\n ? ` ${D}·${R} ${Y}standby${R} ${D}(wakes on @mention, /ping or a whisper)${R}`\n : p.mode ? ` ${D}· listening to everything${R}` : \"\";\n console.log(` ${D}→ spawned ${p.runtime} session (tmux attach -t apiary_${p.alias})${R}${modeNote}`);\n } else {\n console.log(` ${Y}✗${R} ${B}${p.alias}${R} not started — ${spawned.reason}.`);\n console.log(` ${D}Create it, then: ${R}${C}apiary room resume ${roomName}${R}`);\n }\n }\n }\n // A room that answers only when addressed is surprising if nobody said so.\n if (participants.some((p) => p.role === \"agent\" && p.mode?.startsWith(\"standby-\"))) {\n console.log(\n `\\n ${D}Only the first agent listens to everything — the rest wake when addressed,${R}` +\n `\\n ${D}so one remark costs one agent turn instead of all of them.${R}` +\n `\\n ${D}Change any of it live with ${R}${C}/setmode <name> <mode>${R}${D}, or up front with ${R}${C}alias:standby${R}${D} / ${R}${C}alias:active${R}${D}.${R}`,\n );\n }\n console.log(\"\");\n } else {\n console.log(`\\n ${D}Member join link:${R} ${C}${memberJoinUrl}${R}\\n`);\n }\n\n // Tell the user where the rules file lives. Defaults are seeded server-side\n // on first boot; users edit the file by hand and the daemon hot-reloads.\n console.log(` ${D}Rules:${R} ${C}${shortenPath(roomRulesPath(daemon.roomName))}${R} ${D}(edit to customize — hot-reloads)${R}`);\n console.log(` Press Ctrl+C to leave — server keeps running.\\n`);\n\n const { join } = await import(\"./join.js\");\n const adminJoinUrl = buildShareUrl(daemon.serverUrl, daemon.adminToken);\n // Agents the wizard spawned in tmux but who haven't joined the room yet —\n // surface them in the TUI footer as `⏳ booting` so the user knows we're\n // waiting on them, instead of staring at an empty footer for 5–15s.\n const expectedAgents = participants\n .filter((p) => p.role === \"agent\")\n .map((p) => p.alias);\n await join({ server: adminJoinUrl, name: hostName, expectedAgents });\n\n console.log(`\\n Server still running ${roomEmoji(daemon.roomName)} ${Y}${daemon.roomName}${R}`);\n console.log(` Rejoin: ${C}apiary room resume ${daemon.roomName}${R}\\n`);\n}\n\n// ── apiary room resume ────────────────────────────────────────────────────────\n\nexport async function roomResume(name: string): Promise<void> {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const D = \"\\x1b[2m\";\n const C = \"\\x1b[36m\";\n const G = \"\\x1b[32m\";\n const W = \"\\x1b[33m\";\n const R = \"\\x1b[0m\";\n\n const sessions = listRoomSessions();\n const session = sessions.find((s) => s.roomName === name);\n\n if (!session) {\n console.error(` No saved session for room \"${name}\".`);\n console.error(` Run: ${C}apiary room list${R} to see saved rooms.`);\n process.exit(1);\n }\n\n let serverUrl = session.serverUrl;\n let adminToken = session.adminToken;\n let memberToken = session.memberToken;\n let publicUrl = session.publicUrl;\n let pid = session.pid;\n\n const alive = isServerAlive(session);\n\n let connectedNames: Set<string> = new Set();\n\n if (alive) {\n console.log(`\\n ${Y}${B}${name}${R} ${D}server running (PID ${pid})${R}\\n`);\n\n // One transient admin session to refresh share tokens + fetch connected participants.\n // GET /participants and POST /share both require a session token, so we join once,\n // call both in parallel, then immediately disconnect. Falls back to stored memberToken\n // if the refresh fails (e.g. stored adminToken already expired — restart the room).\n const state = await fetchServerState(serverUrl, adminToken, publicUrl);\n if (state.memberToken) memberToken = state.memberToken;\n connectedNames = state.connectedNames;\n } else {\n console.log(`\\n ${Y}${B}${name}${R} ${D}server stopped — restarting...${R}\\n`);\n\n // Carry the original bind forward, or a tailnet room resumes on localhost.\n const daemonRes = await spawnDaemonServer({ room: name, bind: session.bind });\n if (!isDaemonResult(daemonRes)) {\n console.error(`\\n ${W}✗${R} Failed to restart server: ${B}${daemonRes.reason}${R}`);\n if (daemonRes.portInUse) {\n console.error(` ${D}Inspect:${R} ${C}apiary ps${R} ${D}Stop:${R} ${C}apiary stop --all${R}`);\n } else if (daemonRes.stderr?.trim()) {\n console.error(` ${D}stderr:${R}\\n${daemonRes.stderr.split(\"\\n\").map((l) => \" \" + l).join(\"\\n\")}`);\n }\n process.exit(1);\n }\n const daemon = daemonRes;\n\n serverUrl = daemon.serverUrl;\n adminToken = daemon.adminToken;\n memberToken = daemon.memberToken;\n publicUrl = daemon.publicUrl;\n pid = daemon.pid;\n\n saveRoomSession({\n ...session,\n serverUrl,\n publicUrl,\n adminToken,\n memberToken,\n pid,\n lastActive: Date.now(),\n });\n }\n\n // Compute invite URLs from the (possibly updated) server values\n const shareBase = publicUrl !== serverUrl ? publicUrl : serverUrl;\n const memberJoinUrl = buildShareUrl(shareBase, memberToken);\n\n // Distribute invites + post a single in-room system message for connected participants\n if (session.participants && session.participants.length > 0) {\n // connectedNames was populated by fetchServerState above (alive path).\n // Name matching is convention-based: participants are expected to join using\n // their alias as display name (as the bootstrap script and room create do).\n const allLocal = session.participants.every((p) => isLocalPath(p.cwd));\n let hasConnected = false;\n let hasDisconnected = false;\n\n for (const p of session.participants) {\n const connected = connectedNames.has(p.alias.toLowerCase());\n if (connected) {\n if (!hasConnected) console.log(` ${B}Connected:${R}`);\n hasConnected = true;\n console.log(` ${G}●${R} ${p.alias}`);\n } else {\n if (!hasDisconnected) {\n console.log(`\\n ${B}Rejoin links:${R}\\n`);\n if (!tmuxAvailable() && session.participants?.some((pp) => pp.runtime)) {\n console.log(` ${D}(tmux not found — agents will need to join manually via the invite links below)${R}\\n`);\n }\n }\n hasDisconnected = true;\n console.log(` ${W}○${R} ${p.alias} ${D}disconnected${R}`);\n const sameHost = allLocal || isLocalPath(p.cwd);\n printInvite(p.alias, memberJoinUrl, sameHost);\n if (sameHost && tmuxAvailable() && p.runtime && !tmuxSessionExists(`apiary_${p.alias}`)) {\n const spawned = spawnAgentBackground(p.alias, p.cwd, p.runtime, p.tier, p.model, p.mode);\n if (spawned.ok) {\n console.log(` ${D}→ respawned ${p.runtime} session (tmux attach -t apiary_${p.alias})${R}`);\n } else {\n console.log(` ${W}✗${R} ${B}${p.alias}${R} not restarted — ${spawned.reason}.`);\n }\n }\n }\n }\n\n // Single in-room system message for all connected participants at once\n if (hasConnected && alive) {\n await postSystemMessage(\n serverUrl,\n adminToken,\n `[SYSTEM] Session resumed by admin. You are still connected.`,\n );\n }\n console.log(\"\");\n }\n\n // Restore the original host display name so admin identity survives reconnect.\n // Without this the user gets a random name (e.g. Roux-9321) and agents lose\n // the continuity needed to recognize them as the same admin.\n // Older sessions (pre-hostName persistence) won't have it — ask once and\n // persist for next time.\n let resumeHostName = session.hostName;\n if (!resumeHostName) {\n const { ask, close } = makePrompt();\n resumeHostName = (await ask(` Your name ${D}[random]${R}: `)) || undefined;\n close();\n if (resumeHostName) {\n saveRoomSession({ ...session, hostName: resumeHostName, lastActive: Date.now() });\n }\n }\n\n console.log(` Press Ctrl+C to leave — server keeps running.\\n`);\n\n const { join } = await import(\"./join.js\");\n const adminJoinUrl = buildShareUrl(serverUrl, adminToken);\n await join({ server: adminJoinUrl, name: resumeHostName });\n\n console.log(`\\n Server still running (room: ${Y}${name}${R})`);\n console.log(` Rejoin: ${C}apiary room resume ${name}${R}\\n`);\n}\n\n// ── apiary room list ──────────────────────────────────────────────────────────\n\nexport function roomList(): void {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const D = \"\\x1b[2m\";\n const C = \"\\x1b[36m\";\n const G = \"\\x1b[32m\";\n const X = \"\\x1b[31m\";\n const R = \"\\x1b[0m\";\n\n const sessions = listRoomSessions();\n if (sessions.length === 0) {\n console.log(\" No saved rooms. Run: apiary room create\");\n return;\n }\n\n console.log(\"\");\n for (const s of sessions) {\n const alive = isServerAlive(s);\n const status = alive ? `${G}running${R} ${D}(PID ${s.pid})${R}` : `${X}stopped${R}`;\n const lastActive = s.lastActive\n ? `${D}last active: ${formatRelativeTime(s.lastActive)}${R}`\n : \"\";\n\n console.log(` ${Y}${B}${s.roomName}${R} ${status} ${lastActive}`);\n\n if (s.participants && s.participants.length > 0) {\n const names = s.participants.map((p) => `${p.alias} ${D}[${p.role}]${R}`).join(\" \");\n console.log(` ${D}Participants:${R} ${names}`);\n } else {\n console.log(` ${D}(no participant metadata — created with older apiary)${R}`);\n }\n\n console.log(` ${D}Resume:${R} ${C}apiary room resume ${s.roomName}${R}`);\n if (alive) {\n const shareBase = s.publicUrl !== s.serverUrl ? s.publicUrl : s.serverUrl;\n const joinUrl = buildShareUrl(shareBase, s.memberToken);\n console.log(` ${D}Join:${R} ${C}${joinUrl}${R}`);\n }\n console.log(\"\");\n }\n}\n\n// ── apiary room stop ──────────────────────────────────────────────────────────\n\nexport interface RoomStopOptions {\n /** Pre-loaded session record (avoids re-reading every session file). */\n session?: PersistedRoomSession;\n /** When true, silently remove the session record if the server is already dead. */\n quietIfDead?: boolean;\n}\n\nexport async function roomStop(name: string, options: RoomStopOptions = {}): Promise<void> {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const G = \"\\x1b[32m\";\n const D = \"\\x1b[2m\";\n const R = \"\\x1b[0m\";\n\n const session = options.session ?? listRoomSessions().find((s) => s.roomName === name);\n\n if (!session) {\n console.error(` No saved session for room \"${name}\".`);\n console.error(` Run: apiary room list to see saved rooms.`);\n process.exit(1);\n }\n\n const alive = isServerAlive(session);\n if (!alive && options.quietIfDead) {\n removeRoomSession(name);\n return;\n }\n\n console.log(`\\n Stopping ${Y}${B}${name}${R}...\\n`);\n\n // Kill agent tmux sessions (SIGTERM via tmux kill-session)\n if (session.participants && tmuxAvailable()) {\n for (const p of session.participants) {\n const tsName = `apiary_${p.alias}`;\n if (tmuxSessionExists(tsName)) {\n tmuxKillSession(tsName);\n console.log(` ${G}✓${R} ${p.alias} ${D}agent stopped${R}`);\n }\n }\n }\n\n // Stop server daemon\n if (alive) {\n try {\n process.kill(session.pid, \"SIGTERM\");\n console.log(` ${G}✓${R} server ${D}(PID ${session.pid}) stopped${R}`);\n } catch { /* already gone */ }\n }\n\n removeRoomSession(name);\n console.log(`\\n Room \"${name}\" stopped. Start fresh: apiary room create\\n`);\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nexport function isServerAlive(session: PersistedRoomSession): boolean {\n try { process.kill(session.pid, 0); return true; } catch { return false; }\n}\n\n\nfunction parseDuration(input: string): number | null {\n if (!input) return null;\n const m = input.trim().match(/^(\\d+)\\s*(d|h|m)?$/i);\n if (!m) return null;\n const n = parseInt(m[1], 10);\n const unit = (m[2] ?? \"d\").toLowerCase();\n if (unit === \"d\") return n * 24 * 60 * 60 * 1000;\n if (unit === \"h\") return n * 60 * 60 * 1000;\n if (unit === \"m\") return n * 60 * 1000;\n return null;\n}\n\nfunction formatRelativeTime(ts: number): string {\n const diff = Date.now() - ts;\n const mins = Math.floor(diff / 60_000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n return `${Math.floor(hours / 24)}d ago`;\n}\n","/**\n * Create the directory an agent is about to work in.\n *\n * The wizard let you *type* a path but never created it, and\n * `spawnAgentBackground` silently returned false for a directory that did not\n * exist — so naming a repo you had not made yet produced an agent that never\n * appeared, with nothing printed to say why. Starting a room for a project\n * that does not exist yet is a completely reasonable thing to want.\n *\n * `git init` is offered because apiary's own default room rules tell agents\n * \"never push to main, open a PR\" and \"no force-push, no git reset --hard\" —\n * instructions that mean nothing outside a repo.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync } from \"node:fs\";\n\n/**\n * Ceiling on the git subprocesses here. Generous for the work (init and\n * rev-parse are milliseconds) and short enough that a misconfigured machine\n * fails loudly instead of wedging the wizard.\n */\nconst GIT_TIMEOUT_MS = 15_000;\n\nexport type CreateRepoOutcome =\n | { ok: true; created: boolean; gitInitialised: boolean }\n | { ok: false; error: string };\n\n/** True if `dir` is inside a git work tree (its own, or an ancestor's). */\nexport function isInsideGitRepo(dir: string): boolean {\n try {\n const out = execFileSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd: dir,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n // execFileSync blocks the event loop, so a git that waits on something\n // (a credential or editor prompt on a machine configured differently)\n // hangs the whole process — and in a test run nothing can interrupt it,\n // because a synchronous hang never trips vitest's own timeout.\n timeout: GIT_TIMEOUT_MS,\n });\n return out.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/** True if the directory exists and has something in it. */\nexport function isNonEmptyDir(dir: string): boolean {\n try {\n return existsSync(dir) && readdirSync(dir).length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Ensure `dir` exists, optionally initialising a git repo in it.\n *\n * `git init` is skipped when the directory is already inside a work tree —\n * creating a nested repo inside an existing one is almost never what someone\n * means, and it quietly breaks the outer repo's view of those files.\n */\nexport function createRepoDir(\n dir: string,\n opts?: { gitInit?: boolean },\n): CreateRepoOutcome {\n let created = false;\n try {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n created = true;\n }\n } catch (err) {\n return { ok: false, error: `could not create ${dir}: ${err instanceof Error ? err.message : String(err)}` };\n }\n\n if (!opts?.gitInit) return { ok: true, created, gitInitialised: false };\n\n // Covers both \"already a repo\" and \"inside someone else's repo\". Nesting a\n // repo inside an existing work tree silently removes those files from the\n // outer repo's control, which is never what \"git init\" is meant to do here.\n if (isInsideGitRepo(dir)) return { ok: true, created, gitInitialised: false };\n\n try {\n execFileSync(\"git\", [\"init\", \"--quiet\"], { cwd: dir, stdio: \"ignore\", timeout: GIT_TIMEOUT_MS });\n return { ok: true, created, gitInitialised: true };\n } catch {\n // A directory without a repo still works; the agent just cannot open PRs.\n return { ok: true, created, gitInitialised: false };\n }\n}\n","/**\n * Interactive prompts for the `apiary room create` wizard:\n * - `askRepoPath` — repo path picker (current dir + recents + discovered git repos + custom)\n * - `askRuntime` — claude / codex (driven by detected runtimes)\n *\n * All three share a generic arrow-key picker primitive (`pickFromList`) that\n * falls back to plain text input when stdin isn't a TTY or the user hits ESC.\n */\n\nimport { createRepoDir, isInsideGitRepo, isNonEmptyDir } from \"./new-repo.js\";\nimport {\n existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, statSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join as pathJoin, resolve } from \"node:path\";\n\nconst APIARY_DIR = pathJoin(homedir(), \".apiary\");\nconst RECENT_PATH = pathJoin(APIARY_DIR, \"recent_repos.json\");\nconst MAX_RECENT = 10;\nconst MAX_VISIBLE = 12;\nconst SCAN_ROOTS = [\"\", \"Desktop\", \"code\", \"Projects\", \"dev\", \"src\", \"work\", \"repos\"];\n\nconst KEY_CTRL_C = \"\\u0003\";\nconst KEY_ESC = \"\\u001b\";\nconst KEY_ESC_ALT = \"\\u001b\\u001b\";\nconst KEY_UP = \"\\u001b[A\";\nconst KEY_DOWN = \"\\u001b[B\";\n\n// ── ANSI ──────────────────────────────────────────────────────────────────────\n\nconst C = \"\\x1b[36m\"; // cyan\nconst D = \"\\x1b[2m\"; // dim\nconst B = \"\\x1b[1m\"; // bold\nconst G = \"\\x1b[32m\"; // green\nconst Y = \"\\x1b[33m\"; // yellow\nconst M = \"\\x1b[35m\"; // magenta\nconst R = \"\\x1b[0m\";\n\n// ── Path utilities ────────────────────────────────────────────────────────────\n\nfunction expandTilde(p: string): string {\n if (p === \"~\") return homedir();\n if (p.startsWith(\"~/\")) return pathJoin(homedir(), p.slice(2));\n return p;\n}\n\nfunction isGitRepo(p: string): boolean {\n try {\n const s = statSync(pathJoin(p, \".git\"));\n return s.isDirectory() || s.isFile(); // .git can be a file (worktrees, submodules)\n } catch {\n return false;\n }\n}\n\nexport function shortenPath(p: string): string {\n const home = homedir();\n if (p === home) return \"~\";\n if (p.startsWith(home + \"/\")) return \"~/\" + p.slice(home.length + 1);\n return p;\n}\n\n// ── Recent-repos persistence ──────────────────────────────────────────────────\n\nfunction loadRecent(): string[] {\n try {\n const data = JSON.parse(readFileSync(RECENT_PATH, \"utf-8\")) as { paths?: unknown };\n return Array.isArray(data.paths)\n ? data.paths.filter((p): p is string => typeof p === \"string\" && existsSync(p))\n : [];\n } catch {\n return [];\n }\n}\n\nexport function recordRecentRepo(path: string): void {\n const resolved = resolve(path);\n const existing = loadRecent().filter((p) => p !== resolved);\n const next = [resolved, ...existing].slice(0, MAX_RECENT);\n try {\n if (!existsSync(APIARY_DIR)) mkdirSync(APIARY_DIR, { recursive: true });\n writeFileSync(RECENT_PATH, JSON.stringify({ paths: next }, null, 2));\n } catch {\n /* non-fatal */\n }\n}\n\nfunction discoverRepos(): string[] {\n const found: string[] = [];\n const home = homedir();\n for (const sub of SCAN_ROOTS) {\n const root = sub ? pathJoin(home, sub) : home;\n let entries: string[];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.startsWith(\".\")) continue;\n const full = pathJoin(root, entry);\n try {\n if (!statSync(full).isDirectory()) continue;\n if (isGitRepo(full)) found.push(full);\n } catch {\n /* skip */\n }\n }\n }\n return found;\n}\n\n// ── Generic arrow-key picker ──────────────────────────────────────────────────\n\nexport interface PickerItem<T> {\n label: string;\n value: T;\n hint?: string;\n}\n\nconst CUSTOM = Symbol(\"custom\");\nconst NEW_REPO = Symbol(\"new-repo\");\n\nfunction arrowPicker<T>(\n items: PickerItem<T | typeof CUSTOM>[],\n header: string,\n escHint: string,\n): Promise<PickerItem<T | typeof CUSTOM> | null> {\n return new Promise((resolve) => {\n const stdin = process.stdin;\n const stdout = process.stdout;\n\n let idx = 0;\n let printed = 0;\n const visible = Math.min(items.length, MAX_VISIBLE);\n\n const wasRaw = stdin.isRaw ?? false;\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n\n const render = () => {\n if (printed > 0) stdout.write(`\\x1b[${printed}A\\r`);\n stdout.write(\"\\x1b[J\");\n stdout.write(header + \"\\n\");\n const start = Math.max(0, Math.min(idx - Math.floor(visible / 2), items.length - visible));\n const end = Math.min(start + visible, items.length);\n for (let i = start; i < end; i++) {\n const it = items[i];\n const isCursor = i === idx;\n const marker = isCursor ? `${Y}❯${R}` : \" \";\n const label = isCursor ? `${C}${B}${it.label}${R}` : it.label;\n const hint = it.hint ? ` ${D}${it.hint}${R}` : \"\";\n stdout.write(` ${marker} ${label}${hint}\\n`);\n }\n const more = items.length > visible\n ? ` ${D}(${items.length} options — ↑/↓ scrolls)${R}\\n`\n : \"\";\n stdout.write(more);\n stdout.write(` ${D}↑/↓ navigate · enter select · esc ${escHint}${R}\\n`);\n printed = (end - start) + 1 + (more ? 1 : 0) + 1;\n };\n\n const cleanup = () => {\n stdin.removeListener(\"data\", onData);\n if (!wasRaw) stdin.setRawMode(false);\n stdin.pause();\n };\n\n const onData = (key: string) => {\n if (key === KEY_CTRL_C) {\n cleanup();\n process.exit(130);\n }\n if (key === KEY_ESC || key === KEY_ESC_ALT) {\n cleanup();\n stdout.write(\"\\n\");\n resolve(null);\n return;\n }\n if (key === \"\\r\" || key === \"\\n\") {\n cleanup();\n stdout.write(\"\\n\");\n resolve(items[idx]);\n return;\n }\n if (key === KEY_UP || key === \"k\") {\n idx = (idx - 1 + items.length) % items.length;\n render();\n return;\n }\n if (key === KEY_DOWN || key === \"j\") {\n idx = (idx + 1) % items.length;\n render();\n return;\n }\n };\n\n stdin.on(\"data\", onData);\n render();\n });\n}\n\ntype Asker = (q: string) => Promise<string>;\n\n// ── askRepoPath ───────────────────────────────────────────────────────────────\n\nexport interface AskRepoPathOpts {\n alias: string;\n defaultPath: string;\n ask: Asker;\n}\n\nexport async function askRepoPath(opts: AskRepoPathOpts): Promise<string> {\n const cwd = resolve(opts.defaultPath);\n const recent = loadRecent();\n const discovered = discoverRepos();\n\n const seen = new Set<string>();\n const items: PickerItem<string | typeof CUSTOM | typeof NEW_REPO>[] = [];\n const add = (path: string, hint?: string) => {\n const r = resolve(path);\n if (seen.has(r)) return;\n seen.add(r);\n items.push({ label: shortenPath(r), value: r, hint });\n };\n\n add(cwd, \"current dir\");\n for (const p of recent) add(p, \"recent\");\n for (const p of discovered) add(p);\n\n items.push({ label: `${M}✎${R} Type a custom path…`, value: CUSTOM });\n items.push({ label: `${M}✚${R} New project…`, value: NEW_REPO, hint: \"creates the folder\" });\n\n const header = ` 📁 ${B}Repo${R} ${D}for ${opts.alias}${R}`;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n const typed = await opts.ask(` Repo path ${D}[${shortenPath(cwd)}]${R}: `);\n const final = typed ? resolve(expandTilde(typed)) : cwd;\n recordRecentRepo(final);\n return final;\n }\n\n const picked = await arrowPicker(items, header, \"to type a path\");\n\n let final: string;\n if (picked && picked.value === NEW_REPO) {\n final = await askNewRepoPath(opts, cwd);\n } else if (!picked || picked.value === CUSTOM) {\n const typed = await opts.ask(` Custom repo path ${D}[${shortenPath(cwd)}]${R}: `);\n final = typed ? resolve(expandTilde(typed)) : cwd;\n // A typed path is just as likely to be somewhere that does not exist yet.\n await ensureExists(final, opts);\n } else {\n final = picked.value as string;\n }\n\n recordRecentRepo(final);\n return final;\n}\n\n/** Ask where the new project goes, create it, and offer to `git init`. */\nasync function askNewRepoPath(opts: AskRepoPathOpts, cwd: string): Promise<string> {\n const typed = await opts.ask(` New project path ${D}(e.g. ~/Desktop/my-thing)${R}: `);\n const target = typed ? resolve(expandTilde(typed)) : cwd;\n await ensureExists(target, opts, { assumeNew: true });\n return target;\n}\n\n/**\n * Create `dir` if it is missing, having said so, and offer a git repo.\n *\n * Silence here is what made this worth fixing: the wizard accepted a path it\n * never created, and the agent spawn then failed with no message at all.\n */\nasync function ensureExists(\n dir: string,\n opts: AskRepoPathOpts,\n hints?: { assumeNew?: boolean },\n): Promise<void> {\n if (existsSync(dir)) {\n if (!hints?.assumeNew) return;\n if (isNonEmptyDir(dir)) console.log(` ${D}${shortenPath(dir)} already exists — using it.${R}`);\n return;\n }\n\n const answer = hints?.assumeNew\n ? \"y\"\n : (await opts.ask(` ${shortenPath(dir)} doesn't exist. Create it? ${D}[Y/n]${R}: `)) || \"y\";\n if (!/^y(es)?$/i.test(answer.trim())) {\n console.log(` ${D}Left alone — the agent for this repo won't start until it exists.${R}`);\n return;\n }\n\n const wantsGit = isInsideGitRepo(dir) ? false\n : /^y(es)?$/i.test(((await opts.ask(` Run git init in it? ${D}[Y/n]${R}: `)) || \"y\").trim());\n\n const res = createRepoDir(dir, { gitInit: wantsGit });\n if (!res.ok) {\n console.log(` ${M}✗${R} ${res.error}`);\n return;\n }\n const bits = [res.created ? \"created\" : \"exists\"];\n if (res.gitInitialised) bits.push(\"git initialised\");\n console.log(` ${G}✓${R} ${shortenPath(dir)} ${D}(${bits.join(\", \")})${R}`);\n}\n\n// ── askRuntime ────────────────────────────────────────────────────────────────\n\nexport interface AskRuntimeOpts {\n alias: string;\n available: string[]; // subset of [\"claude\", \"codex\"]\n ask: Asker;\n}\n\nconst RUNTIME_HINTS: Record<string, string> = {\n claude: \"Claude Code\",\n codex: \"OpenAI Codex CLI\",\n};\n\nexport async function askRuntime(opts: AskRuntimeOpts): Promise<string | undefined> {\n if (opts.available.length === 0) return undefined;\n if (opts.available.length === 1) return opts.available[0];\n\n const runtimeGlyph: Record<string, string> = { claude: \"🧠\", codex: \"⌨️ \" };\n const items: PickerItem<string | typeof CUSTOM>[] = opts.available.map((rt) => ({\n label: `${runtimeGlyph[rt] ?? \"⚙️ \"} ${rt}`,\n value: rt,\n hint: RUNTIME_HINTS[rt],\n }));\n const header = ` ⚙️ ${B}Runtime${R} ${D}for ${opts.alias}${R}`;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n const typed = (await opts.ask(` Runtime ${D}[claude]${R} ${D}(${opts.available.join(\"/\")})${R}: `)) || \"claude\";\n return opts.available.includes(typed) ? typed : \"claude\";\n }\n\n const picked = await arrowPicker(items, header, \"to skip\");\n return picked ? (picked.value as string) : opts.available[0];\n}\n\n// ── askReach ──────────────────────────────────────────────────────────────────\n\nexport interface ReachOption {\n label: string;\n value: string;\n hint?: string;\n}\n\nexport interface AskReachOpts {\n options: ReachOption[];\n ask: Asker;\n}\n\n/**\n * Ask who should be able to reach the room.\n *\n * Worth a question rather than a flag people have to discover: the default\n * (this machine only) is not what anyone wants once they have a phone and a\n * VPN, and the wrong answer is invisible — you find out when a join link does\n * not work from somewhere else.\n */\nexport async function askReach(opts: AskReachOpts): Promise<string> {\n const items: PickerItem<string>[] = opts.options.map((o) => ({\n label: o.label, value: o.value, hint: o.hint,\n }));\n const header = ` 🌐 ${B}Who can reach this room?${R}`;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) return opts.options[0].value;\n\n const picked = await arrowPicker(items, header, \"for this machine only\");\n if (!picked || typeof picked.value !== \"string\") return opts.options[0].value;\n return picked.value;\n}\n","/**\n * Foundation hook — best-effort bootstrap of the Foundation project workflow into a repo.\n *\n * apiary is the transport; Foundation (gorlitzer-labs/foundation) is the project substrate the hive\n * coordinates over. When a room is created, we install Foundation into each participant's repo so\n * the workflow \"always follows\". Entirely optional and non-fatal: if Foundation isn't reachable the\n * room still starts. apiary does not depend on Foundation at build time — this only shells out.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nexport type FoundationResult = { ok: boolean; how: \"local\" | \"npx\" | \"already\" | \"unavailable\" | \"no-dir\" };\n\n/** Install Foundation into `cwd`. Never throws. Idempotent (skips a repo already set up). */\nexport function foundationInit(cwd: string): FoundationResult {\n const dir = cwd.replace(/^~/, homedir());\n if (!existsSync(dir)) return { ok: false, how: \"no-dir\" };\n if (existsSync(join(dir, \"docs\", \"QUEUE.md\"))) return { ok: true, how: \"already\" };\n // Prefer a locally-installed `foundation`; otherwise npx the (private) GitHub repo.\n const attempts: Array<{ cmd: string; args: string[]; how: FoundationResult[\"how\"] }> = [\n { cmd: \"foundation\", args: [\"init\", dir], how: \"local\" },\n { cmd: \"npx\", args: [\"--yes\", \"github:gorlitzer-labs/foundation\", \"init\", dir], how: \"npx\" },\n ];\n for (const a of attempts) {\n try {\n execFileSync(a.cmd, a.args, { stdio: \"ignore\", timeout: 90_000 });\n return { ok: true, how: a.how };\n } catch {\n /* try the next transport */\n }\n }\n return { ok: false, how: \"unavailable\" };\n}\n"],"mappings":"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","names":["execFileSync","existsSync","mkdirSync","writeFileSync","homedir","pathJoin","existsSync","readdirSync","mkdirSync","resolve","final","execFileSync","existsSync","homedir","resolve","mkdirSync","writeFileSync","pathJoin","existsSync","homedir","execFileSync","C","D","G","R","Y","B","M","join"]}
1
+ {"version":3,"sources":["../src/cli/room.ts","../src/cli/new-repo.ts","../src/cli/repoPicker.ts","../src/cli/foundation.ts"],"sourcesContent":["/**\n * apiary room create / resume / list\n *\n * Interactive room management — the human-friendly entry point.\n * Daemon pattern: server spawns as a detached child process so the TUI\n * can exit (Ctrl+C) without killing the room.\n */\n\nimport { spawn, execFileSync } from \"node:child_process\";\nimport {\n existsSync, mkdirSync, writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join as pathJoin } from \"node:path\";\nimport { createInterface } from \"node:readline\";\n\nimport { buildShareUrl, extractToken } from \"./auth.js\";\nimport { agentEmoji, roomEmoji } from \"./config.js\";\nimport { askRepoPath, askRuntime, askReach, shortenPath } from \"./repoPicker.js\";\nimport { tailnetAddress, lanAddress, ALL_INTERFACES, LOOPBACK } from \"./bind.js\";\nimport { foundationInit } from \"./foundation.js\";\nimport type { AuthorityLevel } from \"../core/types.js\";\nimport type { EngagementMode } from \"../agent/engagement.js\";\nimport { roomRulesPath } from \"../core/rules.js\";\nimport {\n listRoomSessions, saveRoomSession, removeRoomSession, INVITES_DIR,\n type PersistedRoomSession,\n} from \"./serve.js\";\nimport {\n tmuxAvailable, tmuxSessionExists, tmuxKillSession,\n} from \"./tmux.js\";\n\n/** 7 days in ms — default share token TTL for persistent daemon sessions. */\nconst DAEMON_SHARE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\n// ── Readline prompt helper ────────────────────────────────────────────────────\n\ninterface Prompter {\n ask: (q: string) => Promise<string>;\n close: () => void;\n}\n\n// ── Alias-spec parser ────────────────────────────────────────────────────────\n//\n// The wizard accepts `alias[:token][:token...]` where each suffix token\n// modifies one independent axis:\n// - type: `human` (default `agent`)\n// - tier: `owner` (= product_owner), `admin`, `guest` (default `member`)\n// - mode: `standby` (= standby-everyone), or any engagement mode verbatim\n// - role: any unrecognized token is preserved as a cosmetic role label.\n//\n// Examples:\n// `cane` → agent / member\n// `bob:human` → human / member\n// `cane:owner` → agent / product_owner (\"the agent in charge\")\n// `bob:human:admin` → human / admin\n// `cane:owner:human` → human / product_owner (order doesn't matter)\n// `bf:opus` → agent / member, claude --model opus\n// `anvil:sonnet:owner`→ agent / product_owner, claude --model sonnet\n// `cane:standby` → agent / member, only wakes when addressed\n//\n// Model tokens: short aliases (opus, sonnet, haiku) map to the latest of each\n// family — claude resolves them. Full model ids also pass through verbatim.\n\nconst TIER_TOKENS: Record<string, AuthorityLevel> = {\n owner: \"product_owner\",\n product_owner: \"product_owner\",\n admin: \"admin\",\n member: \"member\",\n guest: \"guest\",\n};\nconst TYPE_TOKENS: Record<string, \"agent\" | \"human\"> = {\n agent: \"agent\",\n human: \"human\",\n};\n// Engagement mode. `standby` is the shorthand people actually want: quiet\n// until addressed, by anyone. The full mode names pass through verbatim.\nconst MODE_TOKENS: Record<string, EngagementMode> = {\n standby: \"standby-everyone\",\n \"standby-everyone\": \"standby-everyone\",\n \"standby-people\": \"standby-people\",\n \"standby-agents\": \"standby-agents\",\n active: \"everyone\",\n everyone: \"everyone\",\n people: \"people\",\n agents: \"agents\",\n};\nconst MODEL_TOKENS = new Set([\n \"opus\", \"sonnet\", \"haiku\",\n // also accept full model ids verbatim\n]);\nfunction isModelToken(tok: string): boolean {\n const lc = tok.toLowerCase();\n if (MODEL_TOKENS.has(lc)) return true;\n // Full model id pattern: claude-{opus|sonnet|haiku}-N-M[(...)]\n return /^claude-(opus|sonnet|haiku)-\\d/.test(lc);\n}\n\nexport function parseAliasSpec(input: string): {\n alias: string;\n type: \"agent\" | \"human\";\n tier: AuthorityLevel;\n role: string;\n model?: string;\n mode?: EngagementMode;\n} | null {\n const parts = input.split(\":\").map((p) => p.trim()).filter(Boolean);\n if (parts.length === 0) return null;\n const alias = parts[0];\n let type: \"agent\" | \"human\" = \"agent\";\n let tier: AuthorityLevel = \"member\";\n let role = \"agent\";\n let model: string | undefined;\n let mode: EngagementMode | undefined;\n for (const tok of parts.slice(1)) {\n const lc = tok.toLowerCase();\n if (TYPE_TOKENS[lc]) {\n type = TYPE_TOKENS[lc];\n role = type;\n } else if (TIER_TOKENS[lc]) {\n tier = TIER_TOKENS[lc];\n } else if (MODE_TOKENS[lc]) {\n mode = MODE_TOKENS[lc];\n } else if (isModelToken(tok)) {\n model = lc;\n } else {\n role = lc;\n }\n }\n return { alias, type, tier, role, model, mode };\n}\n\n/**\n * Keep the first agent listening, quiet the rest.\n *\n * In an active mode every agent evaluates every message, so an unaddressed\n * remark in a room of five costs five agent turns and yields five answers to\n * one question. Standby is the fix, but making it the blanket default means a\n * room that ignores you until you remember to @mention somebody.\n *\n * So exactly one agent stays active: whatever you say lands with someone who\n * can answer, or pull in the others by @mentioning them. The rest wake only\n * when addressed — @mentioned, pinged, or whispered to.\n *\n * An explicit `:standby` / `:active` suffix always wins; this only fills in\n * agents that said nothing. Solo-agent rooms are untouched (that one agent is\n * the first), and humans are never assigned a mode.\n *\n * Exported for tests.\n */\nexport function applyDefaultModes(\n participants: Array<{ role: string; mode?: EngagementMode }>,\n): void {\n let seenActiveAgent = false;\n for (const p of participants) {\n if (p.role !== \"agent\") continue;\n if (p.mode !== undefined) {\n // An explicit active mode counts as the listener, so we don't then\n // promote a second agent and end up with two.\n if (!p.mode.startsWith(\"standby-\")) seenActiveAgent = true;\n continue;\n }\n if (!seenActiveAgent) {\n p.mode = \"everyone\";\n seenActiveAgent = true;\n } else {\n p.mode = \"standby-everyone\";\n }\n }\n}\n\nfunction makePrompt(): Prompter {\n // Per-question readline: open → ask → close. Lets the repo picker (which\n // toggles raw mode on stdin) own input cleanly between questions, with no\n // listener contention from a long-lived readline interface.\n return {\n ask: (q: string) => new Promise((res) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(q, (a) => {\n rl.close();\n res(a.trim());\n });\n }),\n close: () => {},\n };\n}\n\n// ── Daemon server spawn ───────────────────────────────────────────────────────\n\ninterface DaemonResult {\n serverUrl: string;\n publicUrl: string;\n roomName: string;\n adminToken: string;\n memberToken: string;\n savePath: string;\n pid: number;\n}\n\nexport interface DaemonSpawnFailure {\n reason: string; // human-readable summary\n stderr?: string; // raw child stderr if captured\n portInUse?: boolean; // EADDRINUSE on the requested port\n}\n\nexport async function spawnDaemonServer(opts: {\n room?: string;\n port?: number;\n share?: boolean;\n expose?: boolean;\n /** Already-resolved listen address (see cli/bind.ts). */\n bind?: string;\n shareTtlMs?: number;\n}): Promise<DaemonResult | DaemonSpawnFailure> {\n const scriptPath = process.argv[1];\n const ttl = opts.shareTtlMs ?? DAEMON_SHARE_TTL_MS;\n\n const args = [\"serve\", \"--headless\", \"--share-token-ttl\", String(ttl)];\n if (opts.room) args.push(\"--room\", opts.room);\n if (opts.port) args.push(\"--port\", String(opts.port));\n if (opts.share) args.push(\"--share\");\n if (opts.expose) args.push(\"--expose\");\n if (opts.bind) args.push(\"--bind\", opts.bind);\n\n return new Promise((resolve) => {\n const child = spawn(process.execPath, [scriptPath, ...args], {\n detached: true,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdoutBuf = \"\";\n let stderrBuf = \"\";\n let settled = false;\n const settle = (v: DaemonResult | DaemonSpawnFailure) => {\n if (settled) return;\n settled = true;\n resolve(v);\n };\n\n child.stdout!.on(\"data\", (chunk: Buffer) => {\n stdoutBuf += chunk.toString();\n const line = stdoutBuf.split(\"\\n\").find((l) => l.trim().startsWith(\"{\"));\n if (line) {\n try {\n const result = JSON.parse(line.trim());\n child.unref();\n settle({ ...result, pid: child.pid! });\n } catch {\n /* keep buffering */\n }\n }\n });\n\n child.stderr!.on(\"data\", (chunk: Buffer) => { stderrBuf += chunk.toString(); });\n\n child.on(\"error\", (err) => settle({ reason: err.message, stderr: stderrBuf }));\n child.on(\"exit\", (code) => {\n if (code !== 0) {\n const portInUse = /EADDRINUSE|already in use/i.test(stderrBuf);\n settle({\n reason: portInUse\n ? `port ${opts.port ?? 7890} already in use`\n : `daemon exited with code ${code}`,\n stderr: stderrBuf,\n portInUse,\n });\n }\n });\n setTimeout(() => settle({ reason: \"timed out waiting for daemon startup\", stderr: stderrBuf }), 15_000);\n });\n}\n\n/** Type guard — `true` if spawnDaemonServer returned a successful DaemonResult. */\nexport function isDaemonResult(v: DaemonResult | DaemonSpawnFailure): v is DaemonResult {\n return \"serverUrl\" in v;\n}\n\n// ── Invite file helpers ───────────────────────────────────────────────────────\n\nexport function writeInvite(alias: string, joinUrl: string): void {\n mkdirSync(INVITES_DIR, { recursive: true });\n writeFileSync(pathJoin(INVITES_DIR, alias), joinUrl, { mode: 0o600 });\n}\n\nfunction isLocalPath(p: string): boolean {\n try {\n return existsSync(p.replace(/^~/, homedir()));\n } catch {\n return false;\n }\n}\n\n// ── Lightweight HTTP helpers (no TUI) ─────────────────────────────────────────\n\n/** Join a room as a transient agent and return the session token. */\nasync function httpJoin(\n serverUrl: string,\n shareToken: string,\n name = \"[system]\",\n): Promise<string | null> {\n try {\n const res = await fetch(`${serverUrl}/join`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ shareToken, name, type: \"agent\" }),\n });\n if (!res.ok) return null;\n const data = await res.json() as { sessionToken?: string };\n return data.sessionToken ?? null;\n } catch {\n return null;\n }\n}\n\n/** Disconnect a participant by session token. */\nasync function httpDisconnect(serverUrl: string, sessionToken: string): Promise<void> {\n await fetch(`${serverUrl}/disconnect`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n }).catch(() => {});\n}\n\n/**\n * Post a system message to the room as a transient participant.\n * Joins with the admin share token, posts, then immediately disconnects.\n */\nasync function postSystemMessage(\n serverUrl: string,\n adminShareToken: string,\n content: string,\n): Promise<void> {\n const sessionToken = await httpJoin(serverUrl, adminShareToken, \"[system]\");\n if (!sessionToken) return;\n await fetch(`${serverUrl}/message`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n body: JSON.stringify({ content }),\n }).catch(() => {});\n await httpDisconnect(serverUrl, sessionToken);\n}\n\n/**\n * Open a single transient admin session and fetch both fresh share tokens\n * and the currently connected participant names.\n *\n * GET /participants and POST /share both require a session token (not a share\n * token), so we join once, make both calls, then immediately disconnect.\n */\nasync function fetchServerState(\n serverUrl: string,\n adminShareToken: string,\n publicUrl: string,\n): Promise<{ memberToken?: string; connectedNames: Set<string> }> {\n const sessionToken = await httpJoin(serverUrl, adminShareToken, \"[system]\");\n if (!sessionToken) return { connectedNames: new Set() };\n\n let memberToken: string | undefined;\n let connectedNames: Set<string> = new Set();\n\n try {\n const [shareRes, participantsRes] = await Promise.all([\n fetch(`${serverUrl}/share`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n body: JSON.stringify({}),\n }),\n fetch(`${serverUrl}/participants`, {\n headers: { Authorization: `Bearer ${sessionToken}` },\n }),\n ]);\n\n if (shareRes.ok) {\n const data = await shareRes.json() as { links?: Record<string, string> };\n const memberUrl = data.links?.[\"member\"];\n if (memberUrl) memberToken = extractToken(memberUrl) ?? undefined;\n }\n\n if (participantsRes.ok) {\n const data = await participantsRes.json() as { participants: Array<{ name: string }> };\n connectedNames = new Set(data.participants.map((p) => p.name.toLowerCase()));\n }\n } finally {\n await httpDisconnect(serverUrl, sessionToken);\n }\n\n return { memberToken, connectedNames };\n}\n\n// ── Runtime detection ─────────────────────────────────────────────────────────\n\n// Unix/macOS only — `which` is not available on Windows; both return false there (graceful, no auto-spawn).\nfunction detectRuntimes(): { claude: boolean; codex: boolean } {\n const has = (cmd: string) => {\n try { execFileSync(\"which\", [cmd], { stdio: \"ignore\" }); return true; } catch { return false; }\n };\n return { claude: has(\"claude\"), codex: has(\"codex\") };\n}\n\n// ── ASCII bee banner ──────────────────────────────────────────────────────────\n\nconst A = \"\\x1b[33m\"; // amber\nconst RESET = \"\\x1b[0m\";\n\nconst BEE_BANNER = [\n `${A} _ \\\\ \\\\${RESET}`,\n `${A} ____ _____ (_)___ ________ __ \\\\ \\\\ \\\\${RESET}`,\n `${A} / __ \\`/ __ \\\\/ / __ \\`/ ___/ / / / (o o)${RESET}`,\n `${A}/ /_/ / /_/ / / /_/ / / / /_/ / )=BzZz=(${RESET}`,\n `${A}\\\\__,_/ .___/_/\\\\__,_/_/ \\\\__, / / / /${RESET}`,\n `${A} /_/ /____/ / / /${RESET}`,\n].join(\"\\n\");\n\n// ── Agent background spawn ────────────────────────────────────────────────────\n\n/**\n * Spawn `apiary <runtime> <alias> --background` as a detached child process in\n * the participant's cwd. The child creates its own tmux session and runs until\n * SIGTERM (sent by `roomStop`).\n *\n * Returns why it failed rather than a bare false: the caller only logged the\n * success case, so a participant pointed at a directory that did not exist\n * produced no agent and no message — you were left guessing.\n */\n/** Why an agent did not start, so the caller can say so. */\ntype SpawnAgentResult = { ok: true } | { ok: false; reason: string };\n\nfunction spawnAgentBackground(\n alias: string,\n cwd: string,\n runtime: string,\n tier: AuthorityLevel = \"member\",\n model?: string,\n mode?: string,\n): SpawnAgentResult {\n const resolvedCwd = cwd.replace(/^~/, homedir());\n if (!existsSync(resolvedCwd)) return { ok: false, reason: `${shortenPath(cwd)} doesn't exist` };\n // For agents at admin or product_owner tier, pass --admin so the local MCP\n // server exposes the privileged tool set. The server still enforces the\n // real tier via the share token; --admin only affects which tools the\n // agent's process *advertises*.\n const args = [process.argv[1], runtime, alias, \"--background\"];\n if (tier === \"admin\" || tier === \"product_owner\") args.push(\"--admin\");\n if (model) args.push(\"--model\", model);\n if (mode) args.push(\"--mode\", mode);\n try {\n const child = spawn(process.execPath, args, {\n detached: true,\n stdio: \"ignore\",\n cwd: resolvedCwd,\n });\n child.unref();\n return { ok: true };\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : \"spawn failed\" };\n }\n}\n\n/**\n * Mint share tokens for each non-member tier the wizard needs. Opens a single\n * transient admin session, posts to `/share` once per tier, then disconnects.\n *\n * Returns a map { tier → join URL } for the tiers successfully minted. Tiers\n * that fail to mint (network error, server rejects) are omitted; the caller\n * falls back to the member URL.\n */\nasync function mintTierTokens(\n serverUrl: string,\n adminShareToken: string,\n shareBase: string,\n tiers: AuthorityLevel[],\n): Promise<Partial<Record<AuthorityLevel, string>>> {\n const result: Partial<Record<AuthorityLevel, string>> = {};\n const sessionToken = await httpJoin(serverUrl, adminShareToken, \"[system]\");\n if (!sessionToken) return result;\n try {\n for (const tier of tiers) {\n try {\n const res = await fetch(`${serverUrl}/share`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${sessionToken}` },\n body: JSON.stringify({ authority: tier }),\n });\n if (!res.ok) continue;\n const data = await res.json() as { links?: Record<string, string>; token?: string };\n // Some endpoints return a token; others a URL. Handle both.\n const linkForTier = data.links?.[tier];\n const token = linkForTier ? extractToken(linkForTier) : data.token;\n if (token) result[tier] = buildShareUrl(shareBase, token);\n } catch {\n /* tier failed — skip; caller falls back to memberJoinUrl */\n }\n }\n } finally {\n await httpDisconnect(serverUrl, sessionToken);\n }\n return result;\n}\n\n// ── Print invite for one participant ─────────────────────────────────────────\n\nfunction printInvite(alias: string, joinUrl: string, sameHost: boolean): void {\n const C = \"\\x1b[36m\";\n const D = \"\\x1b[2m\";\n const G = \"\\x1b[32m\";\n const R = \"\\x1b[0m\";\n\n if (sameHost) {\n writeInvite(alias, joinUrl);\n console.log(` ${G}✓${R} ${alias} ${D}(invite queued — auto-consumed on next launch)${R}`);\n } else {\n console.log(` ${alias}:`);\n }\n console.log(` ${C}apiary join${R} \"${joinUrl}\"`);\n}\n\n// ── apiary room create ────────────────────────────────────────────────────────\n\nexport async function roomCreate(opts: {\n room?: string;\n port?: number;\n share?: boolean;\n expose?: boolean;\n /** Already-resolved listen address (see cli/bind.ts). Beats expose. */\n bind?: string;\n /** Bootstrap the Foundation project workflow into each repo (default on). --no-foundation opts out. */\n foundation?: boolean;\n}): Promise<void> {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const D = \"\\x1b[2m\";\n const C = \"\\x1b[36m\";\n const R = \"\\x1b[0m\";\n\n const { ask, close } = makePrompt();\n\n console.log(`\\n${BEE_BANNER}\\n`);\n console.log(` ${Y}${B}apiary${R} — create room\\n`);\n\n const roomName = opts.room ?? ((await ask(` Room name ${D}[random]${R}: `)) || undefined);\n\n const hostName = (await ask(` Your name ${D}[random]${R}: `)) || undefined;\n\n const ttlInput = await ask(` Session duration ${D}[7d]${R}: `);\n const shareTtlMs = parseDuration(ttlInput) ?? DAEMON_SHARE_TTL_MS;\n\n const rts = detectRuntimes();\n const availableRuntimes = [...(rts.claude ? [\"claude\"] : []), ...(rts.codex ? [\"codex\"] : [])];\n if (availableRuntimes.length === 0) {\n console.log(`\\n ${D}(neither claude nor codex found in PATH — agents will need to join manually)${R}`);\n } else if (availableRuntimes.length === 1) {\n console.log(`\\n ${D}Runtime auto-detected: ${availableRuntimes[0]}${R}`);\n }\n\n const participants: Array<{\n alias: string;\n cwd: string;\n role: string;\n runtime?: string;\n tier: AuthorityLevel;\n model?: string;\n mode?: EngagementMode;\n }> = [];\n const G = \"\\x1b[32m\";\n const M = \"\\x1b[35m\";\n const divider = ` ${D}${\"─\".repeat(56)}${R}`;\n console.log(`\\n ${B}Invite participants${R}`);\n console.log(divider);\n while (true) {\n const n = participants.length + 1;\n console.log(`\\n 🐝 ${M}${B}Participant ${n}${R}`);\n const aliasInput = await ask(\n ` ${C}→${R} Alias ${D}(blank ↵ to finish · suffix :human, :owner, :admin, :guest, :standby)${R}: `,\n );\n if (!aliasInput) {\n const count = participants.length;\n const summary = count === 0\n ? `${D}no participants — starting an empty room${R}`\n : `${G}✓${R} ${B}${count}${R} participant${count === 1 ? \"\" : \"s\"} ready — starting room…`;\n console.log(` ${summary}`);\n break;\n }\n const spec = parseAliasSpec(aliasInput);\n if (!spec) continue;\n const { alias, role, tier, model, mode } = spec;\n const cwd = await askRepoPath({ alias, defaultPath: process.cwd(), ask });\n const runtime = role === \"agent\"\n ? await askRuntime({ alias, available: availableRuntimes, ask })\n : undefined;\n participants.push({ alias, cwd, role, runtime, tier, model, mode });\n const bug = role === \"agent\" ? agentEmoji(alias) : role === \"human\" ? \"👤\" : \"✎\";\n const runtimeBadge = runtime ? ` · ${C}${runtime}${R}` : \"\";\n const modelBadge = model ? ` ${Y}[${model}]${R}` : \"\";\n const tierBadge = tier !== \"member\" ? ` ${Y}[${tier === \"product_owner\" ? \"owner\" : tier}]${R}` : \"\";\n const modeBadge = mode ? ` ${Y}[${mode}]${R}` : \"\";\n console.log(\n ` ${G}✅${R} ${bug} ${B}${alias}${R}${tierBadge}${modelBadge}${modeBadge} ${D}${role}${R}${runtimeBadge} ${D}${shortenPath(cwd)}${R}`,\n );\n console.log(divider);\n }\n\n applyDefaultModes(participants);\n\n // Network reach. Skipped entirely when --bind/--expose already said so on\n // the command line, so scripted use is unaffected.\n let bindAddress = opts.bind;\n if (!bindAddress && !opts.expose) {\n const ts = tailnetAddress();\n const lan = lanAddress();\n const reach = await askReach({\n ask,\n options: [\n { label: \"This machine only\", value: LOOPBACK, hint: \"safest default\" },\n ...(ts ? [{\n label: `Tailnet ${D}(${ts})${R}`,\n value: ts,\n // The room is on your VPN only: reachable from your other devices\n // anywhere, invisible to whatever wifi this machine is on.\n hint: \"your devices anywhere, via Tailscale — not the local network\",\n }] : []),\n ...(lan ? [{\n label: `This network ${D}(${lan})${R}`,\n value: lan,\n hint: \"anyone on the same wifi\",\n }] : []),\n { label: \"All interfaces\", value: ALL_INTERFACES, hint: \"including untrusted networks — rarely what you want\" },\n ],\n });\n if (reach !== LOOPBACK) bindAddress = reach;\n }\n\n close();\n\n // ── Foundation: bootstrap the project workflow into each repo (always follows) ──\n if (opts.foundation !== false) {\n const seen = new Set<string>();\n for (const p of participants) {\n if (!isLocalPath(p.cwd)) continue;\n const key = p.cwd.replace(/^~/, homedir());\n if (seen.has(key)) continue;\n seen.add(key);\n const r = foundationInit(p.cwd);\n const where = shortenPath(p.cwd);\n if (r.how === \"already\") console.log(` ${D}Foundation already set up in ${where}${R}`);\n else if (r.ok) console.log(` ${G}✓${R} Foundation installed in ${D}${where}${R} ${D}(${r.how})${R}`);\n else console.log(` ${D}Foundation skipped for ${where} — run: foundation init${R}`);\n }\n }\n\n console.log(`\\n Starting server in background...`);\n\n const daemonRes = await spawnDaemonServer({\n room: roomName,\n port: opts.port,\n share: opts.share,\n expose: opts.expose,\n bind: bindAddress,\n shareTtlMs,\n });\n if (!isDaemonResult(daemonRes)) {\n console.error(`\\n ${Y}✗${R} Failed to start server: ${B}${daemonRes.reason}${R}`);\n if (daemonRes.portInUse) {\n console.error(` ${D}A previous room daemon is probably still bound. Inspect with:${R} ${C}apiary ps${R}`);\n console.error(` ${D}Stop it with:${R} ${C}apiary stop --all${R} ${D}(or ${R}${C}apiary stop <room>${R}${D})${R}`);\n } else if (daemonRes.stderr?.trim()) {\n console.error(` ${D}stderr:${R}\\n${daemonRes.stderr.split(\"\\n\").map((l) => \" \" + l).join(\"\\n\")}`);\n }\n process.exit(1);\n }\n const daemon = daemonRes;\n\n saveRoomSession({\n roomName: daemon.roomName,\n serverUrl: daemon.serverUrl,\n publicUrl: daemon.publicUrl,\n adminToken: daemon.adminToken,\n memberToken: daemon.memberToken,\n pid: daemon.pid,\n lastActive: Date.now(),\n hostName,\n participants,\n });\n\n const shareBase = daemon.publicUrl !== daemon.serverUrl ? daemon.publicUrl : daemon.serverUrl;\n const memberJoinUrl = buildShareUrl(shareBase, daemon.memberToken);\n\n // Mint per-tier share tokens for any participant whose tier isn't \"member\".\n // The daemon's startup payload only includes adminToken + memberToken; we\n // need a fresh token per non-default tier. POST /share with the admin\n // session — once per distinct tier — covers every participant cheaply.\n const tieredJoinUrls: Partial<Record<AuthorityLevel, string>> = { member: memberJoinUrl };\n const nonMemberTiers = Array.from(\n new Set(participants.map((p) => p.tier).filter((t) => t !== \"member\")),\n );\n if (nonMemberTiers.length > 0) {\n const mintedUrls = await mintTierTokens(daemon.serverUrl, daemon.adminToken, shareBase, nonMemberTiers);\n Object.assign(tieredJoinUrls, mintedUrls);\n }\n\n const canSpawn = tmuxAvailable();\n if (participants.length > 0) {\n console.log(`\\n ${B}Invite links:${R}\\n`);\n const hasRuntimeParticipants = participants.some((p) => p.runtime);\n if (!canSpawn && hasRuntimeParticipants) {\n console.log(` ${D}(tmux not found — agents will need to join manually via the invite links below)${R}\\n`);\n }\n const allLocal = participants.every((p) => isLocalPath(p.cwd));\n for (const p of participants) {\n const sameHost = allLocal || isLocalPath(p.cwd);\n const joinUrl = tieredJoinUrls[p.tier] ?? memberJoinUrl;\n printInvite(p.alias, joinUrl, sameHost);\n if (sameHost && canSpawn && p.runtime) {\n const spawned = spawnAgentBackground(p.alias, p.cwd, p.runtime, p.tier, p.model, p.mode);\n if (spawned.ok) {\n const modeNote = p.mode?.startsWith(\"standby-\")\n ? ` ${D}·${R} ${Y}standby${R} ${D}(wakes on @mention, /ping or a whisper)${R}`\n : p.mode ? ` ${D}· listening to everything${R}` : \"\";\n console.log(` ${D}→ spawned ${p.runtime} session (tmux attach -t apiary_${p.alias})${R}${modeNote}`);\n } else {\n console.log(` ${Y}✗${R} ${B}${p.alias}${R} not started — ${spawned.reason}.`);\n console.log(` ${D}Create it, then: ${R}${C}apiary room resume ${roomName}${R}`);\n }\n }\n }\n // A room that answers only when addressed is surprising if nobody said so.\n if (participants.some((p) => p.role === \"agent\" && p.mode?.startsWith(\"standby-\"))) {\n console.log(\n `\\n ${D}Only the first agent listens to everything — the rest wake when addressed,${R}` +\n `\\n ${D}so one remark costs one agent turn instead of all of them.${R}` +\n `\\n ${D}Change any of it live with ${R}${C}/setmode <name> <mode>${R}${D}, or up front with ${R}${C}alias:standby${R}${D} / ${R}${C}alias:active${R}${D}.${R}`,\n );\n }\n console.log(\"\");\n } else {\n console.log(`\\n ${D}Member join link:${R} ${C}${memberJoinUrl}${R}\\n`);\n }\n\n // Tell the user where the rules file lives. Defaults are seeded server-side\n // on first boot; users edit the file by hand and the daemon hot-reloads.\n console.log(` ${D}Rules:${R} ${C}${shortenPath(roomRulesPath(daemon.roomName))}${R} ${D}(edit to customize — hot-reloads)${R}`);\n console.log(` Press Ctrl+C to leave — server keeps running.\\n`);\n\n const { join } = await import(\"./join.js\");\n const adminJoinUrl = buildShareUrl(daemon.serverUrl, daemon.adminToken);\n // Agents the wizard spawned in tmux but who haven't joined the room yet —\n // surface them in the TUI footer as `⏳ booting` so the user knows we're\n // waiting on them, instead of staring at an empty footer for 5–15s.\n const expectedAgents = participants\n .filter((p) => p.role === \"agent\")\n .map((p) => p.alias);\n await join({ server: adminJoinUrl, name: hostName, expectedAgents });\n\n console.log(`\\n Server still running ${roomEmoji(daemon.roomName)} ${Y}${daemon.roomName}${R}`);\n console.log(` Rejoin: ${C}apiary room resume ${daemon.roomName}${R}\\n`);\n}\n\n// ── apiary room resume ────────────────────────────────────────────────────────\n\nexport async function roomResume(name: string): Promise<void> {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const D = \"\\x1b[2m\";\n const C = \"\\x1b[36m\";\n const G = \"\\x1b[32m\";\n const W = \"\\x1b[33m\";\n const R = \"\\x1b[0m\";\n\n const sessions = listRoomSessions();\n const session = sessions.find((s) => s.roomName === name);\n\n if (!session) {\n console.error(` No saved session for room \"${name}\".`);\n console.error(` Run: ${C}apiary room list${R} to see saved rooms.`);\n process.exit(1);\n }\n\n let serverUrl = session.serverUrl;\n let adminToken = session.adminToken;\n let memberToken = session.memberToken;\n let publicUrl = session.publicUrl;\n let pid = session.pid;\n\n const alive = isServerAlive(session);\n\n let connectedNames: Set<string> = new Set();\n\n if (alive) {\n console.log(`\\n ${Y}${B}${name}${R} ${D}server running (PID ${pid})${R}\\n`);\n\n // One transient admin session to refresh share tokens + fetch connected participants.\n // GET /participants and POST /share both require a session token, so we join once,\n // call both in parallel, then immediately disconnect. Falls back to stored memberToken\n // if the refresh fails (e.g. stored adminToken already expired — restart the room).\n const state = await fetchServerState(serverUrl, adminToken, publicUrl);\n if (state.memberToken) memberToken = state.memberToken;\n connectedNames = state.connectedNames;\n } else {\n console.log(`\\n ${Y}${B}${name}${R} ${D}server stopped — restarting...${R}\\n`);\n\n // Carry the original bind forward, or a tailnet room resumes on localhost.\n const daemonRes = await spawnDaemonServer({ room: name, bind: session.bind });\n if (!isDaemonResult(daemonRes)) {\n console.error(`\\n ${W}✗${R} Failed to restart server: ${B}${daemonRes.reason}${R}`);\n if (daemonRes.portInUse) {\n console.error(` ${D}Inspect:${R} ${C}apiary ps${R} ${D}Stop:${R} ${C}apiary stop --all${R}`);\n } else if (daemonRes.stderr?.trim()) {\n console.error(` ${D}stderr:${R}\\n${daemonRes.stderr.split(\"\\n\").map((l) => \" \" + l).join(\"\\n\")}`);\n }\n process.exit(1);\n }\n const daemon = daemonRes;\n\n serverUrl = daemon.serverUrl;\n adminToken = daemon.adminToken;\n memberToken = daemon.memberToken;\n publicUrl = daemon.publicUrl;\n pid = daemon.pid;\n\n saveRoomSession({\n ...session,\n serverUrl,\n publicUrl,\n adminToken,\n memberToken,\n pid,\n lastActive: Date.now(),\n });\n }\n\n // Compute invite URLs from the (possibly updated) server values\n const shareBase = publicUrl !== serverUrl ? publicUrl : serverUrl;\n const memberJoinUrl = buildShareUrl(shareBase, memberToken);\n\n // Distribute invites + post a single in-room system message for connected participants\n if (session.participants && session.participants.length > 0) {\n // connectedNames was populated by fetchServerState above (alive path).\n // Name matching is convention-based: participants are expected to join using\n // their alias as display name (as the bootstrap script and room create do).\n const allLocal = session.participants.every((p) => isLocalPath(p.cwd));\n let hasConnected = false;\n let hasDisconnected = false;\n\n for (const p of session.participants) {\n const connected = connectedNames.has(p.alias.toLowerCase());\n if (connected) {\n if (!hasConnected) console.log(` ${B}Connected:${R}`);\n hasConnected = true;\n console.log(` ${G}●${R} ${p.alias}`);\n } else {\n if (!hasDisconnected) {\n console.log(`\\n ${B}Rejoin links:${R}\\n`);\n if (!tmuxAvailable() && session.participants?.some((pp) => pp.runtime)) {\n console.log(` ${D}(tmux not found — agents will need to join manually via the invite links below)${R}\\n`);\n }\n }\n hasDisconnected = true;\n console.log(` ${W}○${R} ${p.alias} ${D}disconnected${R}`);\n const sameHost = allLocal || isLocalPath(p.cwd);\n printInvite(p.alias, memberJoinUrl, sameHost);\n if (sameHost && tmuxAvailable() && p.runtime && !tmuxSessionExists(`apiary_${p.alias}`)) {\n const spawned = spawnAgentBackground(p.alias, p.cwd, p.runtime, p.tier, p.model, p.mode);\n if (spawned.ok) {\n console.log(` ${D}→ respawned ${p.runtime} session (tmux attach -t apiary_${p.alias})${R}`);\n } else {\n console.log(` ${W}✗${R} ${B}${p.alias}${R} not restarted — ${spawned.reason}.`);\n }\n }\n }\n }\n\n // Single in-room system message for all connected participants at once\n if (hasConnected && alive) {\n await postSystemMessage(\n serverUrl,\n adminToken,\n `[SYSTEM] Session resumed by admin. You are still connected.`,\n );\n }\n console.log(\"\");\n }\n\n // Restore the original host display name so admin identity survives reconnect.\n // Without this the user gets a random name (e.g. Roux-9321) and agents lose\n // the continuity needed to recognize them as the same admin.\n // Older sessions (pre-hostName persistence) won't have it — ask once and\n // persist for next time.\n let resumeHostName = session.hostName;\n if (!resumeHostName) {\n const { ask, close } = makePrompt();\n resumeHostName = (await ask(` Your name ${D}[random]${R}: `)) || undefined;\n close();\n if (resumeHostName) {\n saveRoomSession({ ...session, hostName: resumeHostName, lastActive: Date.now() });\n }\n }\n\n console.log(` Press Ctrl+C to leave — server keeps running.\\n`);\n\n const { join } = await import(\"./join.js\");\n const adminJoinUrl = buildShareUrl(serverUrl, adminToken);\n await join({ server: adminJoinUrl, name: resumeHostName });\n\n console.log(`\\n Server still running (room: ${Y}${name}${R})`);\n console.log(` Rejoin: ${C}apiary room resume ${name}${R}\\n`);\n}\n\n// ── apiary room list ──────────────────────────────────────────────────────────\n\nexport function roomList(): void {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const D = \"\\x1b[2m\";\n const C = \"\\x1b[36m\";\n const G = \"\\x1b[32m\";\n const X = \"\\x1b[31m\";\n const R = \"\\x1b[0m\";\n\n const sessions = listRoomSessions();\n if (sessions.length === 0) {\n console.log(\" No saved rooms. Run: apiary room create\");\n return;\n }\n\n console.log(\"\");\n for (const s of sessions) {\n const alive = isServerAlive(s);\n const status = alive ? `${G}running${R} ${D}(PID ${s.pid})${R}` : `${X}stopped${R}`;\n const lastActive = s.lastActive\n ? `${D}last active: ${formatRelativeTime(s.lastActive)}${R}`\n : \"\";\n\n console.log(` ${Y}${B}${s.roomName}${R} ${status} ${lastActive}`);\n\n if (s.participants && s.participants.length > 0) {\n const names = s.participants.map((p) => `${p.alias} ${D}[${p.role}]${R}`).join(\" \");\n console.log(` ${D}Participants:${R} ${names}`);\n } else {\n console.log(` ${D}(no participant metadata — created with older apiary)${R}`);\n }\n\n console.log(` ${D}Resume:${R} ${C}apiary room resume ${s.roomName}${R}`);\n if (alive) {\n const shareBase = s.publicUrl !== s.serverUrl ? s.publicUrl : s.serverUrl;\n const joinUrl = buildShareUrl(shareBase, s.memberToken);\n console.log(` ${D}Join:${R} ${C}${joinUrl}${R}`);\n }\n console.log(\"\");\n }\n}\n\n// ── apiary room stop ──────────────────────────────────────────────────────────\n\nexport interface RoomStopOptions {\n /** Pre-loaded session record (avoids re-reading every session file). */\n session?: PersistedRoomSession;\n /** When true, silently remove the session record if the server is already dead. */\n quietIfDead?: boolean;\n}\n\nexport async function roomStop(name: string, options: RoomStopOptions = {}): Promise<void> {\n const Y = \"\\x1b[33m\";\n const B = \"\\x1b[1m\";\n const G = \"\\x1b[32m\";\n const D = \"\\x1b[2m\";\n const R = \"\\x1b[0m\";\n\n const session = options.session ?? listRoomSessions().find((s) => s.roomName === name);\n\n if (!session) {\n console.error(` No saved session for room \"${name}\".`);\n console.error(` Run: apiary room list to see saved rooms.`);\n process.exit(1);\n }\n\n const alive = isServerAlive(session);\n if (!alive && options.quietIfDead) {\n removeRoomSession(name);\n return;\n }\n\n console.log(`\\n Stopping ${Y}${B}${name}${R}...\\n`);\n\n // Kill agent tmux sessions (SIGTERM via tmux kill-session)\n if (session.participants && tmuxAvailable()) {\n for (const p of session.participants) {\n const tsName = `apiary_${p.alias}`;\n if (tmuxSessionExists(tsName)) {\n tmuxKillSession(tsName);\n console.log(` ${G}✓${R} ${p.alias} ${D}agent stopped${R}`);\n }\n }\n }\n\n // Stop server daemon\n if (alive) {\n try {\n process.kill(session.pid, \"SIGTERM\");\n console.log(` ${G}✓${R} server ${D}(PID ${session.pid}) stopped${R}`);\n } catch { /* already gone */ }\n }\n\n removeRoomSession(name);\n console.log(`\\n Room \"${name}\" stopped. Start fresh: apiary room create\\n`);\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nexport function isServerAlive(session: PersistedRoomSession): boolean {\n try { process.kill(session.pid, 0); return true; } catch { return false; }\n}\n\n\nfunction parseDuration(input: string): number | null {\n if (!input) return null;\n const m = input.trim().match(/^(\\d+)\\s*(d|h|m)?$/i);\n if (!m) return null;\n const n = parseInt(m[1], 10);\n const unit = (m[2] ?? \"d\").toLowerCase();\n if (unit === \"d\") return n * 24 * 60 * 60 * 1000;\n if (unit === \"h\") return n * 60 * 60 * 1000;\n if (unit === \"m\") return n * 60 * 1000;\n return null;\n}\n\nfunction formatRelativeTime(ts: number): string {\n const diff = Date.now() - ts;\n const mins = Math.floor(diff / 60_000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n return `${Math.floor(hours / 24)}d ago`;\n}\n","/**\n * Create the directory an agent is about to work in.\n *\n * The wizard let you *type* a path but never created it, and\n * `spawnAgentBackground` silently returned false for a directory that did not\n * exist — so naming a repo you had not made yet produced an agent that never\n * appeared, with nothing printed to say why. Starting a room for a project\n * that does not exist yet is a completely reasonable thing to want.\n *\n * `git init` is offered because apiary's own default room rules tell agents\n * \"never push to main, open a PR\" and \"no force-push, no git reset --hard\" —\n * instructions that mean nothing outside a repo.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync } from \"node:fs\";\n\n/**\n * Ceiling on the git subprocesses here. Generous for the work (init and\n * rev-parse are milliseconds) and short enough that a misconfigured machine\n * fails loudly instead of wedging the wizard.\n */\nconst GIT_TIMEOUT_MS = 15_000;\n\nexport type CreateRepoOutcome =\n | { ok: true; created: boolean; gitInitialised: boolean }\n | { ok: false; error: string };\n\n/** True if `dir` is inside a git work tree (its own, or an ancestor's). */\nexport function isInsideGitRepo(dir: string): boolean {\n try {\n const out = execFileSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd: dir,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n // execFileSync blocks the event loop, so a git that waits on something\n // (a credential or editor prompt on a machine configured differently)\n // hangs the whole process — and in a test run nothing can interrupt it,\n // because a synchronous hang never trips vitest's own timeout.\n timeout: GIT_TIMEOUT_MS,\n });\n return out.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/** True if the directory exists and has something in it. */\nexport function isNonEmptyDir(dir: string): boolean {\n try {\n return existsSync(dir) && readdirSync(dir).length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Ensure `dir` exists, optionally initialising a git repo in it.\n *\n * `git init` is skipped when the directory is already inside a work tree —\n * creating a nested repo inside an existing one is almost never what someone\n * means, and it quietly breaks the outer repo's view of those files.\n */\nexport function createRepoDir(\n dir: string,\n opts?: { gitInit?: boolean },\n): CreateRepoOutcome {\n let created = false;\n try {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n created = true;\n }\n } catch (err) {\n return { ok: false, error: `could not create ${dir}: ${err instanceof Error ? err.message : String(err)}` };\n }\n\n if (!opts?.gitInit) return { ok: true, created, gitInitialised: false };\n\n // Covers both \"already a repo\" and \"inside someone else's repo\". Nesting a\n // repo inside an existing work tree silently removes those files from the\n // outer repo's control, which is never what \"git init\" is meant to do here.\n if (isInsideGitRepo(dir)) return { ok: true, created, gitInitialised: false };\n\n try {\n execFileSync(\"git\", [\"init\", \"--quiet\"], { cwd: dir, stdio: \"ignore\", timeout: GIT_TIMEOUT_MS });\n return { ok: true, created, gitInitialised: true };\n } catch {\n // A directory without a repo still works; the agent just cannot open PRs.\n return { ok: true, created, gitInitialised: false };\n }\n}\n","/**\n * Interactive prompts for the `apiary room create` wizard:\n * - `askRepoPath` — repo path picker (current dir + recents + discovered git repos + custom)\n * - `askRuntime` — claude / codex (driven by detected runtimes)\n *\n * All three share a generic arrow-key picker primitive (`pickFromList`) that\n * falls back to plain text input when stdin isn't a TTY or the user hits ESC.\n */\n\nimport { createRepoDir, isInsideGitRepo, isNonEmptyDir } from \"./new-repo.js\";\nimport {\n existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, statSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join as pathJoin, resolve } from \"node:path\";\n\nconst APIARY_DIR = pathJoin(homedir(), \".apiary\");\nconst RECENT_PATH = pathJoin(APIARY_DIR, \"recent_repos.json\");\nconst MAX_RECENT = 10;\nconst MAX_VISIBLE = 12;\nconst SCAN_ROOTS = [\"\", \"Desktop\", \"code\", \"Projects\", \"dev\", \"src\", \"work\", \"repos\"];\n\nconst KEY_CTRL_C = \"\\u0003\";\nconst KEY_ESC = \"\\u001b\";\nconst KEY_ESC_ALT = \"\\u001b\\u001b\";\nconst KEY_UP = \"\\u001b[A\";\nconst KEY_DOWN = \"\\u001b[B\";\n\n// ── ANSI ──────────────────────────────────────────────────────────────────────\n\nconst C = \"\\x1b[36m\"; // cyan\nconst D = \"\\x1b[2m\"; // dim\nconst B = \"\\x1b[1m\"; // bold\nconst G = \"\\x1b[32m\"; // green\nconst Y = \"\\x1b[33m\"; // yellow\nconst M = \"\\x1b[35m\"; // magenta\nconst R = \"\\x1b[0m\";\n\n// ── Path utilities ────────────────────────────────────────────────────────────\n\nfunction expandTilde(p: string): string {\n if (p === \"~\") return homedir();\n if (p.startsWith(\"~/\")) return pathJoin(homedir(), p.slice(2));\n return p;\n}\n\nfunction isGitRepo(p: string): boolean {\n try {\n const s = statSync(pathJoin(p, \".git\"));\n return s.isDirectory() || s.isFile(); // .git can be a file (worktrees, submodules)\n } catch {\n return false;\n }\n}\n\nexport function shortenPath(p: string): string {\n const home = homedir();\n if (p === home) return \"~\";\n if (p.startsWith(home + \"/\")) return \"~/\" + p.slice(home.length + 1);\n return p;\n}\n\n// ── Recent-repos persistence ──────────────────────────────────────────────────\n\nfunction loadRecent(): string[] {\n try {\n const data = JSON.parse(readFileSync(RECENT_PATH, \"utf-8\")) as { paths?: unknown };\n return Array.isArray(data.paths)\n ? data.paths.filter((p): p is string => typeof p === \"string\" && existsSync(p))\n : [];\n } catch {\n return [];\n }\n}\n\nexport function recordRecentRepo(path: string): void {\n const resolved = resolve(path);\n const existing = loadRecent().filter((p) => p !== resolved);\n const next = [resolved, ...existing].slice(0, MAX_RECENT);\n try {\n if (!existsSync(APIARY_DIR)) mkdirSync(APIARY_DIR, { recursive: true });\n writeFileSync(RECENT_PATH, JSON.stringify({ paths: next }, null, 2));\n } catch {\n /* non-fatal */\n }\n}\n\nfunction discoverRepos(): string[] {\n const found: string[] = [];\n const home = homedir();\n for (const sub of SCAN_ROOTS) {\n const root = sub ? pathJoin(home, sub) : home;\n let entries: string[];\n try {\n entries = readdirSync(root);\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.startsWith(\".\")) continue;\n const full = pathJoin(root, entry);\n try {\n if (!statSync(full).isDirectory()) continue;\n if (isGitRepo(full)) found.push(full);\n } catch {\n /* skip */\n }\n }\n }\n return found;\n}\n\n// ── Generic arrow-key picker ──────────────────────────────────────────────────\n\nexport interface PickerItem<T> {\n label: string;\n value: T;\n hint?: string;\n}\n\nconst CUSTOM = Symbol(\"custom\");\nconst NEW_REPO = Symbol(\"new-repo\");\n\nfunction arrowPicker<T>(\n items: PickerItem<T | typeof CUSTOM>[],\n header: string,\n escHint: string,\n): Promise<PickerItem<T | typeof CUSTOM> | null> {\n return new Promise((resolve) => {\n const stdin = process.stdin;\n const stdout = process.stdout;\n\n let idx = 0;\n let printed = 0;\n const visible = Math.min(items.length, MAX_VISIBLE);\n\n const wasRaw = stdin.isRaw ?? false;\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n\n const render = () => {\n if (printed > 0) stdout.write(`\\x1b[${printed}A\\r`);\n stdout.write(\"\\x1b[J\");\n stdout.write(header + \"\\n\");\n const start = Math.max(0, Math.min(idx - Math.floor(visible / 2), items.length - visible));\n const end = Math.min(start + visible, items.length);\n for (let i = start; i < end; i++) {\n const it = items[i];\n const isCursor = i === idx;\n const marker = isCursor ? `${Y}❯${R}` : \" \";\n const label = isCursor ? `${C}${B}${it.label}${R}` : it.label;\n const hint = it.hint ? ` ${D}${it.hint}${R}` : \"\";\n stdout.write(` ${marker} ${label}${hint}\\n`);\n }\n const more = items.length > visible\n ? ` ${D}(${items.length} options — ↑/↓ scrolls)${R}\\n`\n : \"\";\n stdout.write(more);\n stdout.write(` ${D}↑/↓ navigate · enter select · esc ${escHint}${R}\\n`);\n printed = (end - start) + 1 + (more ? 1 : 0) + 1;\n };\n\n const cleanup = () => {\n stdin.removeListener(\"data\", onData);\n if (!wasRaw) stdin.setRawMode(false);\n stdin.pause();\n };\n\n const onData = (key: string) => {\n if (key === KEY_CTRL_C) {\n cleanup();\n process.exit(130);\n }\n if (key === KEY_ESC || key === KEY_ESC_ALT) {\n cleanup();\n stdout.write(\"\\n\");\n resolve(null);\n return;\n }\n if (key === \"\\r\" || key === \"\\n\") {\n cleanup();\n stdout.write(\"\\n\");\n resolve(items[idx]);\n return;\n }\n if (key === KEY_UP || key === \"k\") {\n idx = (idx - 1 + items.length) % items.length;\n render();\n return;\n }\n if (key === KEY_DOWN || key === \"j\") {\n idx = (idx + 1) % items.length;\n render();\n return;\n }\n };\n\n stdin.on(\"data\", onData);\n render();\n });\n}\n\ntype Asker = (q: string) => Promise<string>;\n\n// ── askRepoPath ───────────────────────────────────────────────────────────────\n\nexport interface AskRepoPathOpts {\n alias: string;\n defaultPath: string;\n ask: Asker;\n}\n\nexport async function askRepoPath(opts: AskRepoPathOpts): Promise<string> {\n const cwd = resolve(opts.defaultPath);\n const recent = loadRecent();\n const discovered = discoverRepos();\n\n const seen = new Set<string>();\n const items: PickerItem<string | typeof CUSTOM | typeof NEW_REPO>[] = [];\n const add = (path: string, hint?: string) => {\n const r = resolve(path);\n if (seen.has(r)) return;\n seen.add(r);\n items.push({ label: shortenPath(r), value: r, hint });\n };\n\n add(cwd, \"current dir\");\n for (const p of recent) add(p, \"recent\");\n for (const p of discovered) add(p);\n\n items.push({ label: `${M}✎${R} Type a custom path…`, value: CUSTOM });\n items.push({ label: `${M}✚${R} New project…`, value: NEW_REPO, hint: \"creates the folder\" });\n\n const header = ` 📁 ${B}Repo${R} ${D}for ${opts.alias}${R}`;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n const typed = await opts.ask(` Repo path ${D}[${shortenPath(cwd)}]${R}: `);\n const final = typed ? resolve(expandTilde(typed)) : cwd;\n recordRecentRepo(final);\n return final;\n }\n\n const picked = await arrowPicker(items, header, \"to type a path\");\n\n let final: string;\n if (picked && picked.value === NEW_REPO) {\n final = await askNewRepoPath(opts, cwd);\n } else if (!picked || picked.value === CUSTOM) {\n const typed = await opts.ask(` Custom repo path ${D}[${shortenPath(cwd)}]${R}: `);\n final = typed ? resolve(expandTilde(typed)) : cwd;\n // A typed path is just as likely to be somewhere that does not exist yet.\n await ensureExists(final, opts);\n } else {\n final = picked.value as string;\n }\n\n recordRecentRepo(final);\n return final;\n}\n\n/** Ask where the new project goes, create it, and offer to `git init`. */\nasync function askNewRepoPath(opts: AskRepoPathOpts, cwd: string): Promise<string> {\n const typed = await opts.ask(` New project path ${D}(e.g. ~/Desktop/my-thing)${R}: `);\n const target = typed ? resolve(expandTilde(typed)) : cwd;\n await ensureExists(target, opts, { assumeNew: true });\n return target;\n}\n\n/**\n * Create `dir` if it is missing, having said so, and offer a git repo.\n *\n * Silence here is what made this worth fixing: the wizard accepted a path it\n * never created, and the agent spawn then failed with no message at all.\n */\nasync function ensureExists(\n dir: string,\n opts: AskRepoPathOpts,\n hints?: { assumeNew?: boolean },\n): Promise<void> {\n if (existsSync(dir)) {\n if (!hints?.assumeNew) return;\n if (isNonEmptyDir(dir)) console.log(` ${D}${shortenPath(dir)} already exists — using it.${R}`);\n return;\n }\n\n const answer = hints?.assumeNew\n ? \"y\"\n : (await opts.ask(` ${shortenPath(dir)} doesn't exist. Create it? ${D}[Y/n]${R}: `)) || \"y\";\n if (!/^y(es)?$/i.test(answer.trim())) {\n console.log(` ${D}Left alone — the agent for this repo won't start until it exists.${R}`);\n return;\n }\n\n const wantsGit = isInsideGitRepo(dir) ? false\n : /^y(es)?$/i.test(((await opts.ask(` Run git init in it? ${D}[Y/n]${R}: `)) || \"y\").trim());\n\n const res = createRepoDir(dir, { gitInit: wantsGit });\n if (!res.ok) {\n console.log(` ${M}✗${R} ${res.error}`);\n return;\n }\n const bits = [res.created ? \"created\" : \"exists\"];\n if (res.gitInitialised) bits.push(\"git initialised\");\n console.log(` ${G}✓${R} ${shortenPath(dir)} ${D}(${bits.join(\", \")})${R}`);\n}\n\n// ── askRuntime ────────────────────────────────────────────────────────────────\n\nexport interface AskRuntimeOpts {\n alias: string;\n available: string[]; // subset of [\"claude\", \"codex\"]\n ask: Asker;\n}\n\nconst RUNTIME_HINTS: Record<string, string> = {\n claude: \"Claude Code\",\n codex: \"OpenAI Codex CLI\",\n};\n\nexport async function askRuntime(opts: AskRuntimeOpts): Promise<string | undefined> {\n if (opts.available.length === 0) return undefined;\n if (opts.available.length === 1) return opts.available[0];\n\n const runtimeGlyph: Record<string, string> = { claude: \"🧠\", codex: \"⌨️ \" };\n const items: PickerItem<string | typeof CUSTOM>[] = opts.available.map((rt) => ({\n label: `${runtimeGlyph[rt] ?? \"⚙️ \"} ${rt}`,\n value: rt,\n hint: RUNTIME_HINTS[rt],\n }));\n const header = ` ⚙️ ${B}Runtime${R} ${D}for ${opts.alias}${R}`;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n const typed = (await opts.ask(` Runtime ${D}[claude]${R} ${D}(${opts.available.join(\"/\")})${R}: `)) || \"claude\";\n return opts.available.includes(typed) ? typed : \"claude\";\n }\n\n const picked = await arrowPicker(items, header, \"to skip\");\n return picked ? (picked.value as string) : opts.available[0];\n}\n\n// ── askReach ──────────────────────────────────────────────────────────────────\n\nexport interface ReachOption {\n label: string;\n value: string;\n hint?: string;\n}\n\nexport interface AskReachOpts {\n options: ReachOption[];\n ask: Asker;\n}\n\n/**\n * Ask who should be able to reach the room.\n *\n * Worth a question rather than a flag people have to discover: the default\n * (this machine only) is not what anyone wants once they have a phone and a\n * VPN, and the wrong answer is invisible — you find out when a join link does\n * not work from somewhere else.\n */\nexport async function askReach(opts: AskReachOpts): Promise<string> {\n const items: PickerItem<string>[] = opts.options.map((o) => ({\n label: o.label, value: o.value, hint: o.hint,\n }));\n const header = ` 🌐 ${B}Who can reach this room?${R}`;\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) return opts.options[0].value;\n\n const picked = await arrowPicker(items, header, \"for this machine only\");\n if (!picked || typeof picked.value !== \"string\") return opts.options[0].value;\n return picked.value;\n}\n","/**\n * Foundation hook — best-effort bootstrap of the Foundation project workflow into a repo.\n *\n * apiary is the transport; Foundation (gorlitzer-labs/foundation) is the project substrate the hive\n * coordinates over. When a room is created, we install Foundation into each participant's repo so\n * the workflow \"always follows\". Entirely optional and non-fatal: if Foundation isn't reachable the\n * room still starts. apiary does not depend on Foundation at build time — this only shells out.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nexport type FoundationResult = { ok: boolean; how: \"local\" | \"npx\" | \"already\" | \"unavailable\" | \"no-dir\" };\n\n/** Install Foundation into `cwd`. Never throws. Idempotent (skips a repo already set up). */\nexport function foundationInit(cwd: string): FoundationResult {\n const dir = cwd.replace(/^~/, homedir());\n if (!existsSync(dir)) return { ok: false, how: \"no-dir\" };\n if (existsSync(join(dir, \"docs\", \"QUEUE.md\"))) return { ok: true, how: \"already\" };\n // Prefer a locally-installed `foundation`; otherwise npx it from npm. (The standalone\n // github:gorlitzer-labs/foundation repo was retired into the monorepo — that address 404s.)\n const attempts: Array<{ cmd: string; args: string[]; how: FoundationResult[\"how\"] }> = [\n { cmd: \"foundation\", args: [\"init\", dir], how: \"local\" },\n { cmd: \"npx\", args: [\"--yes\", \"@gorlitzer-labs/foundation\", \"init\", dir], how: \"npx\" },\n ];\n for (const a of attempts) {\n try {\n execFileSync(a.cmd, a.args, { stdio: \"ignore\", timeout: 90_000 });\n return { ok: true, how: a.how };\n } catch {\n /* try the next transport */\n }\n }\n return { ok: false, how: \"unavailable\" };\n}\n"],"mappings":"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","names":["execFileSync","existsSync","mkdirSync","writeFileSync","homedir","pathJoin","existsSync","readdirSync","mkdirSync","resolve","final","execFileSync","existsSync","homedir","resolve","mkdirSync","writeFileSync","pathJoin","existsSync","homedir","execFileSync","C","D","G","R","Y","B","M","join"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gorlitzer-labs/apiary",
3
- "version": "1.13.5",
3
+ "version": "1.13.7",
4
4
  "description": "Multiplayer rooms for AI agents",
5
5
  "keywords": [
6
6
  "ai",