Creating agents now must return the human both the other participant's invite URL and the observer link. Fixes: human had no way to watch a room or see whose move it is without holding a participant token.
This commit is contained in:
@@ -10,11 +10,12 @@ import {
|
||||
Store,
|
||||
} from './store.js';
|
||||
import { LIMITS } from './limits.js';
|
||||
import { availableActions, computeAdvice } from './advice.js';
|
||||
import { availableActions, computeAdvice, computeTurn } from './advice.js';
|
||||
import {
|
||||
CreateRoomInput,
|
||||
CreatedRoom,
|
||||
MessageView,
|
||||
ObserverView,
|
||||
ParticipantView,
|
||||
QuestionView,
|
||||
RendezvousError,
|
||||
@@ -80,16 +81,17 @@ export class RendezvousService {
|
||||
|
||||
const created: { id: string; role: string; token: string }[] = [];
|
||||
const insertRoom = this.db.prepare(
|
||||
`INSERT INTO rooms (id, title, brief, goal, status, created_at, expires_at) VALUES (?, ?, ?, ?, 'open', ?, ?)`,
|
||||
`INSERT INTO rooms (id, title, brief, goal, status, created_at, expires_at, observer_token) VALUES (?, ?, ?, ?, 'open', ?, ?, ?)`,
|
||||
);
|
||||
const insertParticipant = this.db.prepare(
|
||||
`INSERT INTO participants (id, room_id, role, display_name, token, knows, needs_to_determine, instructions, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
);
|
||||
|
||||
const observerToken = newToken();
|
||||
this.db.exec('BEGIN');
|
||||
try {
|
||||
insertRoom.run(roomId, title, input.brief ?? '', input.goal ?? '', createdAt, expiresAt);
|
||||
insertRoom.run(roomId, title, input.brief ?? '', input.goal ?? '', createdAt, expiresAt, observerToken);
|
||||
for (const p of ps) {
|
||||
const pid = newId('prt');
|
||||
const token = newToken();
|
||||
@@ -118,6 +120,7 @@ export class RendezvousService {
|
||||
expires_at: expiresAt,
|
||||
participants: created,
|
||||
invite_urls: created.map((p) => `${baseUrl}/r/${roomId}/${p.token}`),
|
||||
observer_url: `${baseUrl}/o/${roomId}/${observerToken}`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -283,6 +286,58 @@ export class RendezvousService {
|
||||
};
|
||||
}
|
||||
|
||||
/** Read-only view for the human observer: room state + whose turn it is. */
|
||||
getObserverView(roomId: string, observerToken: string): ObserverView {
|
||||
const room = this.getRoomRow(roomId);
|
||||
if (room.observer_token !== observerToken) {
|
||||
throw new RendezvousError('forbidden', 'invalid observer token');
|
||||
}
|
||||
const participants = this.listParticipants(roomId);
|
||||
const conversation = this.listMessages(roomId);
|
||||
const questions = this.listQuestions(roomId);
|
||||
const openQuestions = questions.filter((q) => q.status === 'open');
|
||||
const resolvedQuestions = questions.filter((q) => q.status === 'resolved');
|
||||
const agreements = this.db
|
||||
.prepare(
|
||||
`SELECT a.participant_id, a.contract_version FROM agreements a
|
||||
JOIN participants p ON p.id = a.participant_id WHERE a.room_id = ?`,
|
||||
)
|
||||
.all(roomId) as { participant_id: string; contract_version: number }[];
|
||||
const contract =
|
||||
room.contract_version > 0
|
||||
? {
|
||||
version: room.contract_version,
|
||||
markdown: room.contract_markdown,
|
||||
updated_at: room.contract_updated_at,
|
||||
agreements: agreements.map((a) => ({
|
||||
participant_id: a.participant_id,
|
||||
role: participants.find((p) => p.id === a.participant_id)?.role ?? '?',
|
||||
version: a.contract_version,
|
||||
})),
|
||||
}
|
||||
: null;
|
||||
const status = room.status as 'open' | 'agreed' | 'expired';
|
||||
const viewStatus = new Date(room.expires_at).getTime() < Date.now() ? 'expired' : status;
|
||||
return {
|
||||
room: {
|
||||
id: room.id,
|
||||
title: room.title,
|
||||
brief: room.brief,
|
||||
goal: room.goal,
|
||||
status,
|
||||
created_at: room.created_at,
|
||||
expires_at: room.expires_at,
|
||||
},
|
||||
participants,
|
||||
conversation,
|
||||
open_questions: openQuestions,
|
||||
resolved_questions: resolvedQuestions,
|
||||
current_contract: contract,
|
||||
room_status: viewStatus,
|
||||
turn: computeTurn(viewStatus, participants, openQuestions, contract),
|
||||
};
|
||||
}
|
||||
|
||||
// ---------- writes ----------
|
||||
|
||||
postMessage(roomId: string, token: string, content: string): MessageView {
|
||||
|
||||
Reference in New Issue
Block a user