Nests: team rooms with core crows and borrowing
- Server: nests API, persistence, core-first picking, borrowed flag (built by the backend agent against EVENTS.md; tests pass with -race) - UI: nests in the sidebar, one feed per nest, header shows the core team, New nest dialog, borrowed crows labeled, per-nest waiting count - start.command: one-click local server in controlled mode (mock crows, localhost only, state in .crows/) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF
This commit is contained in:
14 files changed
+782
-62
No files matched your search
+34
-2
@@ -5,11 +5,11 @@ export type PostListResult =
|
||||
| { ok: false; pranked: true; message: string; cooldownS: number }
|
||||
| { ok: false; pranked: false; message: string };
|
||||
|
||||
export async function postList(text: string, requester: string): Promise<PostListResult> {
|
||||
export async function postList(text: string, requester: string, nestId: string): Promise<PostListResult> {
|
||||
const res = await fetch("/api/lists", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ text, requester }),
|
||||
body: JSON.stringify({ text, requester, nest_id: nestId }),
|
||||
});
|
||||
const body = await res.json().catch(() => ({}));
|
||||
if (res.ok) return { ok: true, listId: String(body.list_id) };
|
||||
@@ -43,3 +43,35 @@ export async function getTrust(): Promise<TrustLevels> {
|
||||
export function listEvents(listId: string): EventSource {
|
||||
return new EventSource(`/api/events?list_id=${encodeURIComponent(listId)}`);
|
||||
}
|
||||
|
||||
// ---------- nests ----------
|
||||
export type Nest = { nestId: string; name: string; crows: string[] };
|
||||
export type Nests = { roster: string[]; nests: Nest[] };
|
||||
|
||||
const DEFAULT_ROSTER = ["Hugin", "Munin", "Corvina", "Soot", "Pepper", "Inky", "Edgar", "Jet"];
|
||||
|
||||
export async function getNests(): Promise<Nests> {
|
||||
try {
|
||||
const res = await fetch("/api/nests");
|
||||
if (!res.ok) throw new Error(String(res.status));
|
||||
const body = await res.json();
|
||||
return {
|
||||
roster: (body.roster ?? DEFAULT_ROSTER).map(String),
|
||||
nests: (body.nests ?? []).map((n: any) => ({ nestId: String(n.nest_id), name: String(n.name), crows: (n.crows ?? []).map(String) })),
|
||||
};
|
||||
} catch {
|
||||
// A server without nests still has the default room.
|
||||
return { roster: DEFAULT_ROSTER, nests: [{ nestId: "todo", name: "todo", crows: [] }] };
|
||||
}
|
||||
}
|
||||
|
||||
export async function createNest(name: string, crows: string[]): Promise<Nest> {
|
||||
const res = await fetch("/api/nests", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name, crows }),
|
||||
});
|
||||
const body = await res.json().catch(() => ({}));
|
||||
if (!res.ok) throw new Error(String(body.message ?? `Couldn't build that nest (${res.status}).`));
|
||||
return { nestId: String(body.nest_id), name: String(body.name), crows: (body.crows ?? []).map(String) };
|
||||
}
|
||||
Reference in new issue
Block a user