stoops 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -4,22 +4,22 @@ import {
4
4
  Room,
5
5
  randomName,
6
6
  randomRoomName
7
- } from "../chunk-HKFCJO7V.js";
7
+ } from "../chunk-KY524S5X.js";
8
8
  import {
9
9
  EventProcessor,
10
10
  RemoteRoomDataSource,
11
11
  SseMultiplexer
12
- } from "../chunk-OA3CODNP.js";
13
- import "../chunk-5ADJGMXQ.js";
12
+ } from "../chunk-ZO6SITQN.js";
13
+ import "../chunk-QUSAD4P5.js";
14
14
  import {
15
15
  buildCatchUpLines,
16
16
  contentPartsToString,
17
17
  createRuntimeMcpServer,
18
18
  formatTimestamp
19
- } from "../chunk-66EFQ2XO.js";
19
+ } from "../chunk-TODXZFII.js";
20
20
  import {
21
21
  createEvent
22
- } from "../chunk-EPLQQF6S.js";
22
+ } from "../chunk-YGROOQFE.js";
23
23
 
24
24
  // src/cli/serve.ts
25
25
  import { createServer } from "http";
@@ -79,8 +79,8 @@ var TokenManager = class {
79
79
  };
80
80
  var TIER_ORDER = {
81
81
  admin: 2,
82
- participant: 1,
83
- observer: 0
82
+ member: 1,
83
+ guest: 0
84
84
  };
85
85
  function canGrant(callerLevel, targetLevel) {
86
86
  return TIER_ORDER[callerLevel] >= TIER_ORDER[targetLevel];
@@ -128,7 +128,7 @@ async function serve(options) {
128
128
  const room = new Room(roomName, storage);
129
129
  const tokens = new TokenManager();
130
130
  const participants = /* @__PURE__ */ new Map();
131
- const observers = /* @__PURE__ */ new Map();
131
+ const guests = /* @__PURE__ */ new Map();
132
132
  const idToSession = /* @__PURE__ */ new Map();
133
133
  const sseConnections = /* @__PURE__ */ new Map();
134
134
  async function parseBody(req) {
@@ -144,8 +144,8 @@ async function serve(options) {
144
144
  if (!token) return null;
145
145
  const p = participants.get(token);
146
146
  if (p) return { ...p, kind: "participant" };
147
- const o = observers.get(token);
148
- if (o) return { ...o, kind: "observer" };
147
+ const g = guests.get(token);
148
+ if (g) return { ...g, kind: "guest" };
149
149
  return null;
150
150
  }
151
151
  function jsonError(res, status, error) {
@@ -201,7 +201,7 @@ async function serve(options) {
201
201
  id: p.id,
202
202
  name: p.name,
203
203
  type: p.type,
204
- authority: p.authority ?? "participant"
204
+ authority: p.authority ?? "member"
205
205
  }));
206
206
  res.writeHead(200, { "Content-Type": "application/json" });
207
207
  res.end(JSON.stringify({ participants: list }));
@@ -258,25 +258,25 @@ async function serve(options) {
258
258
  if (!tokenAuthority) return jsonError(res, 403, "Invalid share token");
259
259
  authority = tokenAuthority;
260
260
  } else if (legacyType === "guest") {
261
- authority = "observer";
261
+ authority = "guest";
262
262
  } else if (legacyType === "human") {
263
- authority = "participant";
263
+ authority = "member";
264
264
  } else {
265
- authority = "participant";
265
+ authority = "member";
266
266
  }
267
267
  const participantType = String(body.type ?? "human");
268
268
  const name = String(body.name ?? randomName());
269
- if (authority === "observer") {
269
+ if (authority === "guest") {
270
270
  const id2 = `obs_${randomUUID().slice(0, 8)}`;
271
271
  const channel2 = room.observe();
272
- const sessionToken3 = tokens.createSessionToken(id2, "observer");
273
- observers.set(sessionToken3, { id: id2, authority: "observer", channel: channel2, sessionToken: sessionToken3 });
272
+ const sessionToken3 = tokens.createSessionToken(id2, "guest");
273
+ guests.set(sessionToken3, { id: id2, authority: "guest", channel: channel2, sessionToken: sessionToken3 });
274
274
  idToSession.set(id2, sessionToken3);
275
275
  const participantList2 = room.listParticipants().map((p) => ({
276
276
  id: p.id,
277
277
  name: p.name,
278
278
  type: p.type,
279
- authority: p.authority ?? "participant"
279
+ authority: p.authority ?? "member"
280
280
  }));
281
281
  res.writeHead(200, { "Content-Type": "application/json" });
282
282
  res.end(JSON.stringify({
@@ -285,7 +285,7 @@ async function serve(options) {
285
285
  roomName,
286
286
  roomId: room.roomId,
287
287
  participants: participantList2,
288
- authority: "observer"
288
+ authority: "guest"
289
289
  }));
290
290
  return;
291
291
  }
@@ -298,7 +298,7 @@ async function serve(options) {
298
298
  id: p.id,
299
299
  name: p.name,
300
300
  type: p.type,
301
- authority: p.authority ?? "participant"
301
+ authority: p.authority ?? "member"
302
302
  }));
303
303
  log(`${name} joined (${authority})`);
304
304
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -316,7 +316,7 @@ async function serve(options) {
316
316
  const session = getSession(sessionToken);
317
317
  if (url.pathname === "/message") {
318
318
  if (!session) return jsonError(res, 401, "Invalid session token");
319
- if (session.authority === "observer") return jsonError(res, 403, "Observers cannot send messages");
319
+ if (session.authority === "guest") return jsonError(res, 403, "Guests cannot send messages");
320
320
  const content = String(body.content ?? "");
321
321
  const replyTo = body.replyTo ? String(body.replyTo) : void 0;
322
322
  if (!content) return jsonError(res, 400, "Empty message");
@@ -328,7 +328,7 @@ async function serve(options) {
328
328
  }
329
329
  if (url.pathname === "/event") {
330
330
  if (!session) return jsonError(res, 401, "Invalid session token");
331
- if (session.authority === "observer") return jsonError(res, 403, "Observers cannot emit events");
331
+ if (session.authority === "guest") return jsonError(res, 403, "Guests cannot emit events");
332
332
  const event = body.event;
333
333
  if (!event) return jsonError(res, 400, "Missing event");
334
334
  const p = participants.get(sessionToken);
@@ -364,8 +364,8 @@ async function serve(options) {
364
364
  const targetId = String(body.participantId ?? "");
365
365
  const newAuthority = String(body.authority ?? "");
366
366
  if (!targetId) return jsonError(res, 400, "Missing participantId");
367
- if (!["admin", "participant", "observer"].includes(newAuthority)) {
368
- return jsonError(res, 400, "Invalid authority. Must be admin, participant, or observer.");
367
+ if (!["admin", "member", "guest"].includes(newAuthority)) {
368
+ return jsonError(res, 400, "Invalid authority. Must be admin, member, or guest.");
369
369
  }
370
370
  if (targetId === session.id) return jsonError(res, 400, "Cannot change own authority");
371
371
  const targetSession = idToSession.get(targetId);
@@ -399,7 +399,7 @@ async function serve(options) {
399
399
  if (!targetId) return jsonError(res, 400, "Missing participantId");
400
400
  const targetSession = idToSession.get(targetId);
401
401
  if (targetSession) {
402
- const target = participants.get(targetSession) ?? observers.get(targetSession);
402
+ const target = participants.get(targetSession) ?? guests.get(targetSession);
403
403
  if (target) {
404
404
  const adminP = participants.get(sessionToken);
405
405
  const targetParticipant = room.listParticipants().find((p) => p.id === targetId);
@@ -415,7 +415,7 @@ async function serve(options) {
415
415
  }
416
416
  await target.channel.disconnect(true);
417
417
  participants.delete(targetSession);
418
- observers.delete(targetSession);
418
+ guests.delete(targetSession);
419
419
  idToSession.delete(targetId);
420
420
  tokens.revokeSessionToken(targetSession);
421
421
  const sse = sseConnections.get(targetId);
@@ -431,7 +431,7 @@ async function serve(options) {
431
431
  }
432
432
  if (url.pathname === "/share") {
433
433
  if (!session) return jsonError(res, 401, "Invalid session token");
434
- if (session.authority === "observer") return jsonError(res, 403, "Observers cannot create share links");
434
+ if (session.authority === "guest") return jsonError(res, 403, "Guests cannot create share links");
435
435
  const targetAuthority = body.authority ?? void 0;
436
436
  const links = {};
437
437
  if (targetAuthority) {
@@ -439,7 +439,7 @@ async function serve(options) {
439
439
  if (!token) return jsonError(res, 403, `Cannot generate ${targetAuthority} link`);
440
440
  links[targetAuthority] = buildShareUrl(publicUrl, token);
441
441
  } else {
442
- const tiers = ["admin", "participant", "observer"];
442
+ const tiers = ["admin", "member", "guest"];
443
443
  for (const tier of tiers) {
444
444
  const token = tokens.generateShareToken(session.authority, tier);
445
445
  if (token) links[tier] = buildShareUrl(publicUrl, token);
@@ -470,16 +470,16 @@ async function serve(options) {
470
470
  }
471
471
  log(`${p.name} disconnected`);
472
472
  }
473
- const o = observers.get(targetToken);
474
- if (o) {
475
- await o.channel.disconnect();
476
- observers.delete(targetToken);
477
- idToSession.delete(o.id);
473
+ const g = guests.get(targetToken);
474
+ if (g) {
475
+ await g.channel.disconnect();
476
+ guests.delete(targetToken);
477
+ idToSession.delete(g.id);
478
478
  tokens.revokeSessionToken(targetToken);
479
- const sse = sseConnections.get(o.id);
479
+ const sse = sseConnections.get(g.id);
480
480
  if (sse) {
481
481
  sse.end();
482
- sseConnections.delete(o.id);
482
+ sseConnections.delete(g.id);
483
483
  }
484
484
  }
485
485
  }
@@ -511,9 +511,9 @@ Port ${port} is already in use. Another stoops instance may be running.`);
511
511
  }
512
512
  }
513
513
  const adminToken = tokens.generateShareToken("admin", "admin");
514
- const participantToken = tokens.generateShareToken("admin", "participant");
514
+ const memberToken = tokens.generateShareToken("admin", "member");
515
515
  if (options.headless) {
516
- process.stdout.write(JSON.stringify({ serverUrl, publicUrl, roomName, adminToken, participantToken }) + "\n");
516
+ process.stdout.write(JSON.stringify({ serverUrl, publicUrl, roomName, adminToken, memberToken }) + "\n");
517
517
  } else if (!options.quiet) {
518
518
  let version = process.env.npm_package_version ?? "";
519
519
  if (!version) {
@@ -526,7 +526,7 @@ Port ${port} is already in use. Another stoops instance may be running.`);
526
526
  }
527
527
  }
528
528
  const adminUrl = buildShareUrl(publicUrl, adminToken);
529
- const joinUrl = buildShareUrl(publicUrl, participantToken);
529
+ const joinUrl = buildShareUrl(publicUrl, memberToken);
530
530
  console.log(`
531
531
  stoops v${version}
532
532
 
@@ -553,8 +553,8 @@ Port ${port} is already in use. Another stoops instance may be running.`);
553
553
  await p.channel.disconnect().catch(() => {
554
554
  });
555
555
  }
556
- for (const o of observers.values()) {
557
- await o.channel.disconnect().catch(() => {
556
+ for (const g of guests.values()) {
557
+ await g.channel.disconnect().catch(() => {
558
558
  });
559
559
  }
560
560
  await new Promise((resolve, reject) => {
@@ -564,7 +564,7 @@ Port ${port} is already in use. Another stoops instance may be running.`);
564
564
  };
565
565
  process.on("SIGINT", shutdown);
566
566
  process.on("SIGTERM", shutdown);
567
- return { serverUrl, publicUrl, roomName, adminToken, participantToken };
567
+ return { serverUrl, publicUrl, roomName, adminToken, memberToken };
568
568
  }
569
569
  function logServer(message) {
570
570
  console.log(` [${formatTimestamp(/* @__PURE__ */ new Date())}] ${message}`);
@@ -668,10 +668,10 @@ var SLASH_COMMANDS = [
668
668
  { name: "/kick", description: "Remove a participant", adminOnly: true, params: [
669
669
  { label: "name", completions: "participants" }
670
670
  ] },
671
- { name: "/mute", description: "Make read-only (observer)", adminOnly: true, params: [
671
+ { name: "/mute", description: "Make read-only (guest)", adminOnly: true, params: [
672
672
  { label: "name", completions: "participants" }
673
673
  ] },
674
- { name: "/unmute", description: "Restore to participant", adminOnly: true, params: [
674
+ { name: "/unmute", description: "Restore to member", adminOnly: true, params: [
675
675
  { label: "name", completions: "participants" }
676
676
  ] },
677
677
  { name: "/setmode", description: "Set engagement mode", adminOnly: true, params: [
@@ -1053,7 +1053,7 @@ async function join(options) {
1053
1053
  sessionToken = String(data.sessionToken ?? "");
1054
1054
  participantId = String(data.participantId);
1055
1055
  roomName = String(data.roomName);
1056
- authority = data.authority ?? "participant";
1056
+ authority = data.authority ?? "member";
1057
1057
  participants = data.participants ?? [];
1058
1058
  } catch {
1059
1059
  console.error(`Cannot reach stoops server at ${serverUrl}. Is it running?`);
@@ -1091,7 +1091,7 @@ async function join(options) {
1091
1091
  const rl = createInterface({ input: process.stdin, terminal: false });
1092
1092
  rl.on("line", async (line) => {
1093
1093
  const content = line.trim();
1094
- if (!content || authority === "observer") return;
1094
+ if (!content || authority === "guest") return;
1095
1095
  try {
1096
1096
  await fetch(`${serverUrl}/message`, {
1097
1097
  method: "POST",
@@ -1138,7 +1138,7 @@ async function join(options) {
1138
1138
  }
1139
1139
  process.exit(0);
1140
1140
  }
1141
- const isReadOnly = authority === "observer" || isGuest;
1141
+ const isReadOnly = authority === "guest" || isGuest;
1142
1142
  function systemEvent(content) {
1143
1143
  tui.push({
1144
1144
  id: randomUUID2(),
@@ -1162,7 +1162,7 @@ async function join(options) {
1162
1162
  }
1163
1163
  const data = await res.json();
1164
1164
  const lines = data.participants.map((p) => {
1165
- const auth = p.authority ?? "participant";
1165
+ const auth = p.authority ?? "member";
1166
1166
  return ` ${p.type === "agent" ? "agent" : "human"} ${p.name} (${auth})`;
1167
1167
  });
1168
1168
  systemEvent(`Participants:
@@ -1243,13 +1243,13 @@ ${lines.join("\n")}`);
1243
1243
  const authRes = await fetch(`${serverUrl}/set-authority`, {
1244
1244
  method: "POST",
1245
1245
  headers: { "Content-Type": "application/json" },
1246
- body: JSON.stringify({ token: sessionToken, participantId: target.id, authority: "observer" })
1246
+ body: JSON.stringify({ token: sessionToken, participantId: target.id, authority: "guest" })
1247
1247
  });
1248
1248
  if (!authRes.ok) {
1249
1249
  systemEvent(`Failed to mute: ${await authRes.text()}`);
1250
1250
  return;
1251
1251
  }
1252
- systemEvent(`Muted ${targetName} (observer).`);
1252
+ systemEvent(`Muted ${targetName} (guest).`);
1253
1253
  } catch {
1254
1254
  systemEvent("Failed to reach server.");
1255
1255
  }
@@ -1281,13 +1281,13 @@ ${lines.join("\n")}`);
1281
1281
  const authRes = await fetch(`${serverUrl}/set-authority`, {
1282
1282
  method: "POST",
1283
1283
  headers: { "Content-Type": "application/json" },
1284
- body: JSON.stringify({ token: sessionToken, participantId: target.id, authority: "participant" })
1284
+ body: JSON.stringify({ token: sessionToken, participantId: target.id, authority: "member" })
1285
1285
  });
1286
1286
  if (!authRes.ok) {
1287
1287
  systemEvent(`Failed to unmute: ${await authRes.text()}`);
1288
1288
  return;
1289
1289
  }
1290
- systemEvent(`Unmuted ${targetName} (participant).`);
1290
+ systemEvent(`Unmuted ${targetName} (member).`);
1291
1291
  } catch {
1292
1292
  systemEvent("Failed to reach server.");
1293
1293
  }
@@ -1334,8 +1334,8 @@ ${lines.join("\n")}`);
1334
1334
  }
1335
1335
  // ── /share [--as <tier>] ──────────────────────────────────────
1336
1336
  case "share": {
1337
- if (authority === "observer") {
1338
- systemEvent("Observers cannot create share links.");
1337
+ if (authority === "guest") {
1338
+ systemEvent("Guests cannot create share links.");
1339
1339
  return;
1340
1340
  }
1341
1341
  let targetAuthority;
@@ -1548,10 +1548,10 @@ function toDisplayEvent(event, selfId, participantTypes) {
1548
1548
  };
1549
1549
  case "AuthorityChanged": {
1550
1550
  const name = event.participant.name;
1551
- if (event.new_authority === "observer") {
1551
+ if (event.new_authority === "guest") {
1552
1552
  return { id: randomUUID2(), ts, kind: "system", content: `${name} was muted` };
1553
1553
  }
1554
- if (event.new_authority === "participant") {
1554
+ if (event.new_authority === "member") {
1555
1555
  return { id: randomUUID2(), ts, kind: "system", content: `${name} was unmuted` };
1556
1556
  }
1557
1557
  return { id: randomUUID2(), ts, kind: "system", content: `${name} \u2192 ${event.new_authority}` };
@@ -1925,7 +1925,7 @@ async function setupAgentRuntime(options) {
1925
1925
  const sessionToken = String(data.sessionToken ?? "");
1926
1926
  const roomName = alias ?? String(data.roomName ?? "");
1927
1927
  const roomId = String(data.roomId ?? "");
1928
- const authority = String(data.authority ?? "participant");
1928
+ const authority = String(data.authority ?? "member");
1929
1929
  const participants = data.participants ?? [];
1930
1930
  const newParticipantId = String(data.participantId ?? "");
1931
1931
  const dataSource = new RemoteRoomDataSource(serverUrl, sessionToken, roomId);
@@ -1965,7 +1965,7 @@ async function setupAgentRuntime(options) {
1965
1965
  agentName,
1966
1966
  authority,
1967
1967
  mode,
1968
- participants: participants.filter((p) => p.id !== newParticipantId).map((p) => ({ name: p.name, authority: p.authority ?? "participant" })),
1968
+ participants: participants.filter((p) => p.id !== newParticipantId).map((p) => ({ name: p.name, authority: p.authority ?? "member" })),
1969
1969
  recentLines
1970
1970
  };
1971
1971
  } catch (err) {
@@ -2022,7 +2022,7 @@ async function setupAgentRuntime(options) {
2022
2022
  const res = await fetch(`${ds.serverUrl}/set-authority`, {
2023
2023
  method: "POST",
2024
2024
  headers: { "Content-Type": "application/json" },
2025
- body: JSON.stringify({ token: ds.sessionToken, participantId: p.id, authority: "observer" })
2025
+ body: JSON.stringify({ token: ds.sessionToken, participantId: p.id, authority: "guest" })
2026
2026
  });
2027
2027
  if (!res.ok) return { success: false, error: await res.text() };
2028
2028
  return { success: true };
@@ -2040,7 +2040,7 @@ async function setupAgentRuntime(options) {
2040
2040
  const res = await fetch(`${ds.serverUrl}/set-authority`, {
2041
2041
  method: "POST",
2042
2042
  headers: { "Content-Type": "application/json" },
2043
- body: JSON.stringify({ token: ds.sessionToken, participantId: p.id, authority: "participant" })
2043
+ body: JSON.stringify({ token: ds.sessionToken, participantId: p.id, authority: "member" })
2044
2044
  });
2045
2045
  if (!res.ok) return { success: false, error: await res.text() };
2046
2046
  return { success: true };
@@ -2469,7 +2469,7 @@ async function main() {
2469
2469
  const adminJoinUrl = buildShareUrl(result.serverUrl, result.adminToken);
2470
2470
  const participantShareUrl = buildShareUrl(
2471
2471
  result.publicUrl !== result.serverUrl ? result.publicUrl : result.serverUrl,
2472
- result.participantToken
2472
+ result.memberToken
2473
2473
  );
2474
2474
  await join({
2475
2475
  server: adminJoinUrl,