mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-02 09:24:43 +08:00
Let a learner pick one element on the classroom whiteboard and ask about
it, alongside the existing PPT element and interactive component
references behind the courseware-reference flag.
- Add a `whiteboard_element` reference: { kind, whiteboardId, elementId }.
The Host resolves it only from this request's Stage snapshot
(`stage.whiteboard[0]`), projects the element with the existing slide
element projection, and passes it through the existing Director ->
call_agent evidence path. It grants no Spotlight or other tool access.
- Reuse the playback pick overlay inside the whiteboard, scoped to the
whiteboard DOM so pan/zoom and overlapping elements resolve correctly,
and keep a highlight on the selected element.
- Share one displayed-whiteboard selector for display, picking, and the
pre-send check. A runtime (RuntimeStore) whiteboard disables picking;
runtime-board references are out of scope.
- Before sending, re-check the reference against the snapshot actually
POSTed; if it is stale, keep the learner's text and ask them to pick
again. Server rejections carry a `whiteboard_reference_changed` reason.
- Describe whiteboard references correctly next to page-reported state,
and rename the entry to "Reference content" in all locales.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
30 lines
1.2 KiB
TypeScript
30 lines
1.2 KiB
TypeScript
import type { Stage, Whiteboard } from '@/lib/types/stage';
|
|
import type { WhiteboardElementReference } from '@/lib/types/chat';
|
|
|
|
/** Use the same authority for displaying and selecting a whiteboard. An empty
|
|
* durable board is authoritative too; it must not reveal the legacy board. */
|
|
export function getDisplayedWhiteboard(
|
|
stage: Stage | null,
|
|
projection: { stageId: string; lastSeq: number | null; whiteboard: Whiteboard | null } | null,
|
|
) {
|
|
const runtimeAuthoritative =
|
|
projection != null && projection.stageId === stage?.id && projection.lastSeq !== null;
|
|
return {
|
|
source: runtimeAuthoritative ? ('runtime_store' as const) : ('stage_snapshot' as const),
|
|
whiteboard: runtimeAuthoritative ? projection.whiteboard : stage?.whiteboard?.[0],
|
|
};
|
|
}
|
|
|
|
export function isWhiteboardReferenceAvailable(
|
|
reference: WhiteboardElementReference,
|
|
stage: Stage | null,
|
|
projection: Parameters<typeof getDisplayedWhiteboard>[1],
|
|
): boolean {
|
|
const { source, whiteboard } = getDisplayedWhiteboard(stage, projection);
|
|
return (
|
|
source === 'stage_snapshot' &&
|
|
whiteboard?.id === reference.whiteboardId &&
|
|
whiteboard.elements.filter((element) => element.id === reference.elementId).length === 1
|
|
);
|
|
}
|