reflet-sdk 0.6.9 → 0.7.0

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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"sessions-panel-CaOJ6vWR.js","names":["MONO_FONT"],"sources":["../src/devtools/client/notices.tsx","../src/sessions/recorder/use-recorder-snapshot.ts","../src/sessions/api/proposal-endpoints.ts","../src/sessions/api/recording-endpoints.ts","../src/sessions/api/review-endpoints.ts","../src/sessions/api/session-requests.ts","../src/sessions/api/session-api.ts","../src/storage/indexed-db.ts","../src/sessions/local/stored-payload.ts","../src/sessions/local/indexed-session-store.ts","../src/devtools/client/route/dev-route.ts","../src/sessions/api/session-transports.ts","../src/sessions/local/outbox-operations.ts","../src/sessions/local/outbox.ts","../src/sessions/local/local-sessions.ts","../src/sessions/capture/session-clock.ts","../src/sessions/capture/audio/microphone.ts","../src/sessions/capture/audio/speech-chunker.ts","../src/sessions/capture/audio/wav.ts","../src/sessions/capture/element-ref.ts","../src/sessions/capture/page/interaction-recorder.ts","../src/sessions/capture/page/navigation-watch.ts","../src/sessions/recorder/live/collection-run.ts","../src/sessions/capture/blank-fields.ts","../src/sessions/capture/page/evidence-scheduler.ts","../src/sessions/recorder/live/event-batcher.ts","../src/sessions/recorder/live/session-payloads.ts","../src/sessions/recorder/live/session-quota.ts","../src/sessions/recorder/live/live-session.ts","../src/sessions/recorder/recording-controller.ts","../src/sessions/recorder/session-recorder.ts","../src/sessions/ui/session-workspace.tsx","../src/sessions/ui/session-format.ts","../src/sessions/ui/session-icons.tsx","../src/sessions/ui/recording/level-meter.tsx","../src/sessions/ui/recording/mark-note.tsx","../src/sessions/ui/recording/recording-bar.tsx","../src/sessions/ui/recording/recording-layer.tsx","../src/sessions/ui/sessions-styles.ts","../src/devtools/client/clipboard.ts","../src/devtools/client/devtools-icons.tsx","../src/devtools/client/devtools-bar.tsx","../src/devtools/client/use-sheet-size.ts","../src/devtools/client/devtools-sheet.tsx","../src/devtools/client/devtools-styles.ts","../src/sessions/ui/handoff/zip-archive.ts","../src/sessions/ui/handoff/brief-export.ts","../src/sessions/ui/review/transcript/evidence-thumb.tsx","../src/sessions/ui/handoff/handoff-selection.tsx","../src/sessions/ui/handoff/handoff-view.tsx","../src/sessions/ui/review/proposals/proposal-details.tsx","../src/sessions/ui/review/guarded-save.tsx","../src/sessions/ui/review/use-session-detail.ts","../src/sessions/ui/review/proposals/proposal-editor.tsx","../src/sessions/ui/review/proposals/use-proposal-actions.ts","../src/sessions/ui/review/proposals/verification.tsx","../src/sessions/ui/review/proposals/proposal-card.tsx","../src/sessions/ui/review/proposals/proposals-tab.tsx","../src/sessions/ui/review/review-header.tsx","../src/sessions/ui/review/status-strip.tsx","../src/sessions/ui/review/transcript/attach-link.tsx","../src/sessions/ui/review/transcript/remove-evidence.tsx","../src/sessions/ui/review/transcript/evidence-tab.tsx","../src/sessions/ui/review/transcript/segment-row.tsx","../src/sessions/ui/review/transcript/transcript-tab.tsx","../src/sessions/ui/review/session-review.tsx","../src/sessions/ui/start/session-list.tsx","../src/sessions/ui/start/session-disclosure.tsx","../src/sessions/ui/start/start-session.tsx","../src/sessions/ui/start/sessions-home.tsx","../src/sessions/ui/sessions-panel.tsx"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { CloseIcon } from \"../../feedback/ui/icons\";\n\nexport interface NoticeAction {\n label: string;\n run: () => void;\n}\n\nexport interface Notice {\n action?: NoticeAction;\n id: number;\n kind: \"failure\" | \"status\";\n message: string;\n}\n\nconst STATUS_VISIBLE_MS = 2400;\nconst ACTION_VISIBLE_MS = 6000;\n\nlet notices: Notice[] = [];\nlet nextNoticeId = 1;\nconst listeners = new Set<() => void>();\n\nfunction publish(next: Notice[]) {\n notices = next;\n for (const listener of listeners) {\n listener();\n }\n}\n\nexport function dismissNotice(id: number) {\n publish(notices.filter((notice) => notice.id !== id));\n}\n\n/** Same message twice replaces the first, so a failing retry never stacks up. */\nexport function reportFailure(\n action: string,\n error: unknown,\n retry?: () => void\n) {\n const reason = error instanceof Error ? error.message : \"Unknown error.\";\n const message = `${action}: ${reason}`;\n publish([\n ...notices.filter((notice) => notice.message !== message),\n {\n action: retry && { label: \"Retry\", run: retry },\n id: nextNoticeId++,\n kind: \"failure\",\n message,\n },\n ]);\n}\n\n/** An action (Undo) keeps the notice up long enough to reach it. */\nexport function announce(message: string, action?: NoticeAction) {\n const id = nextNoticeId++;\n publish([\n ...notices.filter((notice) => notice.message !== message),\n { action, id, kind: \"status\", message },\n ]);\n setTimeout(\n () => dismissNotice(id),\n action ? ACTION_VISIBLE_MS : STATUS_VISIBLE_MS\n );\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function Notices() {\n const current = useSyncExternalStore(\n subscribe,\n () => notices,\n () => notices\n );\n return (\n <div aria-live=\"polite\" className=\"dt-notices\">\n {current.map((notice) => (\n <div\n className=\"dt-notice glass\"\n data-kind={notice.kind}\n key={notice.id}\n role={notice.kind === \"failure\" ? \"alert\" : undefined}\n >\n <p>{notice.message}</p>\n {notice.action && (\n <button\n className=\"dt-btn\"\n onClick={() => {\n dismissNotice(notice.id);\n notice.action?.run();\n }}\n type=\"button\"\n >\n {notice.action.label}\n </button>\n )}\n <button\n aria-label=\"Dismiss\"\n className=\"icon-btn\"\n onClick={() => dismissNotice(notice.id)}\n type=\"button\"\n >\n <CloseIcon />\n </button>\n </div>\n ))}\n </div>\n );\n}\n","import { useSyncExternalStore } from \"react\";\nimport type { RecorderSnapshot, SessionRecorder } from \"./session-recorder\";\n\nexport function useRecorderSnapshot(\n recorder: SessionRecorder\n): RecorderSnapshot {\n return useSyncExternalStore(\n recorder.subscribe,\n recorder.getSnapshot,\n recorder.getSnapshot\n );\n}\n","import { z } from \"zod\";\nimport {\n handoffFileSchema,\n type SessionApiPath,\n sessionHandoffSchema,\n sessionProposalSchema,\n} from \"../protocol\";\nimport type { SessionApi } from \"./session-api\";\nimport type { SessionRequests } from \"./session-requests\";\n\nconst proposalResponse = z.object({ proposal: sessionProposalSchema });\n\ntype ProposalEndpoints = Pick<\n SessionApi,\n | \"clarifyProposal\"\n | \"createFeedback\"\n | \"createHandoff\"\n | \"createProposal\"\n | \"decideProposal\"\n | \"editProposal\"\n | \"markHandoffDelivered\"\n | \"mergeProposals\"\n | \"separateProposal\"\n | \"verifyProposal\"\n>;\n\nexport function createProposalEndpoints({\n post,\n}: SessionRequests): ProposalEndpoints {\n const postProposal = async (path: SessionApiPath, body: unknown) =>\n (await post(path, body, proposalResponse)).proposal;\n\n return {\n clarifyProposal: (body) =>\n postProposal(\"/api/v1/sessions/proposals/clarify\", body),\n createFeedback: (proposalId) =>\n post(\n \"/api/v1/sessions/proposals/feedback\",\n { proposalId },\n z.object({ created: z.boolean(), feedbackId: z.string() })\n ),\n createHandoff: (body) =>\n post(\n \"/api/v1/sessions/handoffs\",\n body,\n z.object({\n files: z.array(handoffFileSchema),\n handoff: sessionHandoffSchema,\n })\n ),\n createProposal: (body) =>\n postProposal(\"/api/v1/sessions/proposals/create\", body),\n decideProposal: (body) =>\n postProposal(\"/api/v1/sessions/proposals/decide\", body),\n editProposal: (body) =>\n postProposal(\"/api/v1/sessions/proposals/edit\", body),\n markHandoffDelivered: async (body) =>\n (\n await post(\n \"/api/v1/sessions/handoffs/delivered\",\n body,\n z.object({ handoff: sessionHandoffSchema })\n )\n ).handoff,\n mergeProposals: (body) =>\n postProposal(\"/api/v1/sessions/proposals/merge\", body),\n separateProposal: (proposalId) =>\n postProposal(\"/api/v1/sessions/proposals/separate\", { proposalId }),\n verifyProposal: (body) =>\n postProposal(\"/api/v1/sessions/proposals/verify\", body),\n };\n}\n","import { z } from \"zod\";\nimport {\n sessionEvidenceSchema,\n sessionSegmentSchema,\n sessionSummarySchema,\n} from \"../protocol\";\nimport type { SessionApi } from \"./session-api\";\nimport type { SessionRequests } from \"./session-requests\";\n\nexport const summaryResponse = z.object({ session: sessionSummarySchema });\nexport const segmentResponse = z.object({ segment: sessionSegmentSchema });\n\ntype RecordingEndpoints = Pick<\n SessionApi,\n | \"addEvidence\"\n | \"addVoiceSegment\"\n | \"collection\"\n | \"events\"\n | \"start\"\n | \"uploadUrl\"\n>;\n\nexport function createRecordingEndpoints({\n post,\n}: SessionRequests): RecordingEndpoints {\n return {\n addEvidence: async (body) =>\n (\n await post(\n \"/api/v1/sessions/evidence\",\n body,\n z.object({ evidence: sessionEvidenceSchema })\n )\n ).evidence,\n addVoiceSegment: async (body) =>\n (await post(\"/api/v1/sessions/segments\", body, segmentResponse)).segment,\n collection: async (body) =>\n (await post(\"/api/v1/sessions/collection\", body, summaryResponse))\n .session,\n events: (body) =>\n post(\n \"/api/v1/sessions/events\",\n body,\n z.object({\n accepted: z.number(),\n dropped: z.number(),\n limitReached: z.boolean(),\n })\n ),\n start: async (body) =>\n (await post(\"/api/v1/sessions/start\", body, summaryResponse)).session,\n uploadUrl: async (body) =>\n (\n await post(\n \"/api/v1/sessions/upload-url\",\n body,\n z.object({ uploadUrl: z.string() })\n )\n ).uploadUrl,\n };\n}\n","import { z } from \"zod\";\nimport {\n analysisStatusSchema,\n sessionDetailSchema,\n sessionEvidenceSchema,\n sessionIdentitySchema,\n sessionSummarySchema,\n} from \"../protocol\";\nimport { segmentResponse, summaryResponse } from \"./recording-endpoints\";\nimport type { SessionApi } from \"./session-api\";\nimport type { SessionRequests } from \"./session-requests\";\n\ntype ReviewEndpoints = Pick<\n SessionApi,\n | \"addTypedSegment\"\n | \"analyze\"\n | \"correctSegment\"\n | \"deleteSession\"\n | \"detail\"\n | \"identity\"\n | \"list\"\n | \"removeEvidence\"\n | \"retrySegment\"\n | \"update\"\n>;\n\nexport function createReviewEndpoints({\n get,\n post,\n}: SessionRequests): ReviewEndpoints {\n return {\n addTypedSegment: async (body) =>\n (await post(\"/api/v1/sessions/segments\", body, segmentResponse)).segment,\n analyze: async (sessionId) =>\n (\n await post(\n \"/api/v1/sessions/analyze\",\n { sessionId },\n z.object({ analysis: analysisStatusSchema })\n )\n ).analysis,\n correctSegment: async (body) =>\n (await post(\"/api/v1/sessions/segments/correct\", body, segmentResponse))\n .segment,\n deleteSession: async (sessionId) => {\n await post(\n \"/api/v1/sessions/delete\",\n { sessionId },\n z.object({ deleted: z.literal(true) })\n );\n },\n detail: (sessionId) =>\n get(\"/api/v1/sessions/detail\", sessionDetailSchema, { sessionId }),\n identity: () => get(\"/api/v1/sessions/identity\", sessionIdentitySchema),\n list: async () =>\n (\n await get(\n \"/api/v1/sessions/list\",\n z.object({ sessions: z.array(sessionSummarySchema) })\n )\n ).sessions,\n removeEvidence: async (evidenceId) =>\n (\n await post(\n \"/api/v1/sessions/evidence/remove\",\n { evidenceId },\n z.object({ evidence: sessionEvidenceSchema })\n )\n ).evidence,\n retrySegment: async (segmentId) =>\n (\n await post(\n \"/api/v1/sessions/segments/retry\",\n { segmentId },\n segmentResponse\n )\n ).segment,\n update: async (body) =>\n (await post(\"/api/v1/sessions/update\", body, summaryResponse)).session,\n };\n}\n","import type { z } from \"zod\";\nimport type { SessionApiPath } from \"../protocol\";\nimport type { SessionTransport } from \"./session-api\";\n\nexport interface SessionRequests {\n get: <T>(\n path: SessionApiPath,\n schema: z.ZodType<T>,\n query?: Record<string, string>\n ) => Promise<T>;\n post: <T>(\n path: SessionApiPath,\n body: unknown,\n schema: z.ZodType<T>\n ) => Promise<T>;\n}\n\nexport function createSessionRequests(\n transport: SessionTransport\n): SessionRequests {\n return {\n get: (path, schema, query) =>\n transport.request({ method: \"GET\", path, query, schema }),\n post: (path, body, schema) =>\n transport.request({ body, method: \"POST\", path, schema }),\n };\n}\n","import type { z } from \"zod\";\nimport type {\n AnalysisStatus,\n ElementRef,\n EvidenceLink,\n EvidenceTrigger,\n Frame,\n HandoffFile,\n ProposalDecision,\n SessionApiPath,\n SessionDetail,\n SessionEvent,\n SessionEvidence,\n SessionGapReason,\n SessionHandoff,\n SessionIdentity,\n SessionLimitKind,\n SessionProposal,\n SessionSegment,\n SessionSummary,\n SessionSurface,\n} from \"../protocol\";\nimport { createProposalEndpoints } from \"./proposal-endpoints\";\nimport { createRecordingEndpoints } from \"./recording-endpoints\";\nimport { createReviewEndpoints } from \"./review-endpoints\";\nimport { createSessionRequests } from \"./session-requests\";\n\nexport interface SessionRequest<T> {\n body?: unknown;\n method: \"GET\" | \"POST\";\n path: SessionApiPath;\n query?: Record<string, string>;\n schema: z.ZodType<T>;\n}\n\nexport interface SessionTransport {\n request: <T>(options: SessionRequest<T>) => Promise<T>;\n}\n\nexport class SessionApiError extends Error {\n readonly limit: SessionLimitKind | null;\n readonly status: number;\n\n constructor(\n message: string,\n details: { limit: SessionLimitKind | null; status: number }\n ) {\n super(message);\n this.name = \"SessionApiError\";\n this.status = details.status;\n this.limit = details.limit;\n }\n}\n\nexport interface StartSessionBody {\n clientKey: string;\n page: { title: string; url: string };\n startedAt: number;\n surface: SessionSurface;\n title?: string;\n}\n\nexport interface CollectionBody {\n action: \"pause\" | \"resume\" | \"end\";\n atMs: number;\n reason?: SessionGapReason;\n sessionId: string;\n}\n\nexport interface EventsBody {\n clientKey: string;\n events: SessionEvent[];\n sessionId: string;\n}\n\nexport interface EventsResult {\n accepted: number;\n dropped: number;\n limitReached: boolean;\n}\n\nexport interface SegmentTiming {\n clientKey: string;\n endMs: number;\n sessionId: string;\n startMs: number;\n}\n\nexport interface AddEvidenceBody {\n atMs: number;\n clientKey: string;\n element?: ElementRef;\n frame?: Frame;\n image?: { height: number; storageId: string; width: number };\n link?: EvidenceLink;\n missingReason?: string;\n note?: string;\n sessionId: string;\n trigger: EvidenceTrigger;\n}\n\nexport interface CreateProposalBody {\n clientKey: string;\n evidenceIds?: string[];\n need: string;\n observed?: string;\n segmentIds?: string[];\n sessionId: string;\n}\n\nexport interface EditProposalBody {\n expectedRevision: number;\n need?: string;\n observed?: string;\n proposalId: string;\n response?: string | null;\n setAside?: string[];\n unknowns?: string[];\n}\n\nexport interface CreateHandoffBody {\n clientKey: string;\n evidenceIds: string[];\n proposalIds: string[];\n sessionId: string;\n}\n\nexport interface SessionApi {\n addEvidence: (body: AddEvidenceBody) => Promise<SessionEvidence>;\n addTypedSegment: (\n body: SegmentTiming & { text: string }\n ) => Promise<SessionSegment>;\n addVoiceSegment: (\n body: SegmentTiming & { audioStorageId: string }\n ) => Promise<SessionSegment>;\n analyze: (sessionId: string) => Promise<AnalysisStatus>;\n clarifyProposal: (body: {\n expectedRevision: number;\n proposalId: string;\n text: string;\n }) => Promise<SessionProposal>;\n collection: (body: CollectionBody) => Promise<SessionSummary>;\n correctSegment: (body: {\n expectedRevision: number;\n segmentId: string;\n text: string;\n }) => Promise<SessionSegment>;\n createFeedback: (\n proposalId: string\n ) => Promise<{ created: boolean; feedbackId: string }>;\n createHandoff: (\n body: CreateHandoffBody\n ) => Promise<{ files: HandoffFile[]; handoff: SessionHandoff }>;\n createProposal: (body: CreateProposalBody) => Promise<SessionProposal>;\n decideProposal: (body: {\n decision: ProposalDecision;\n proposalId: string;\n }) => Promise<SessionProposal>;\n deleteSession: (sessionId: string) => Promise<void>;\n detail: (sessionId: string) => Promise<SessionDetail>;\n editProposal: (body: EditProposalBody) => Promise<SessionProposal>;\n events: (body: EventsBody) => Promise<EventsResult>;\n identity: () => Promise<SessionIdentity>;\n list: () => Promise<SessionSummary[]>;\n markHandoffDelivered: (body: {\n handoffId: string;\n kind: \"copied\" | \"exported\";\n }) => Promise<SessionHandoff>;\n mergeProposals: (body: {\n sourceIds: string[];\n targetId: string;\n }) => Promise<SessionProposal>;\n removeEvidence: (evidenceId: string) => Promise<SessionEvidence>;\n retrySegment: (segmentId: string) => Promise<SessionSegment>;\n separateProposal: (proposalId: string) => Promise<SessionProposal>;\n start: (body: StartSessionBody) => Promise<SessionSummary>;\n update: (body: {\n sessionId: string;\n title?: string;\n visibility?: \"private\" | \"team\";\n }) => Promise<SessionSummary>;\n uploadUrl: (body: {\n kind: \"audio\" | \"image\";\n sessionId: string;\n }) => Promise<string>;\n verifyProposal: (body: {\n note?: string;\n proposalId: string;\n status: \"works\" | \"needs_work\";\n }) => Promise<SessionProposal>;\n}\n\nexport function createSessionApi(transport: SessionTransport): SessionApi {\n const requests = createSessionRequests(transport);\n return {\n ...createRecordingEndpoints(requests),\n ...createReviewEndpoints(requests),\n ...createProposalEndpoints(requests),\n };\n}\n","/** Executor form: the SDK targets ES2022, before `Promise.withResolvers`. */\nexport function settle<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nexport function committed(transaction: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onerror = () => reject(transaction.error);\n transaction.onabort = () => reject(transaction.error);\n });\n}\n\nexport function openDatabase(options: {\n name: string;\n upgrade: (database: IDBDatabase) => void;\n version: number;\n}): Promise<IDBDatabase> {\n if (typeof indexedDB === \"undefined\") {\n return Promise.reject(\n new Error(\"IndexedDB is unavailable in this browser.\")\n );\n }\n const request = indexedDB.open(options.name, options.version);\n request.onupgradeneeded = () => options.upgrade(request.result);\n return settle(request);\n}\n\nconst FAILURE_COPY_BY_NAME: Record<string, string> = {\n QuotaExceededError:\n \"This device is out of storage space. Free some up, then try again.\",\n SecurityError:\n \"This browser blocks storage on this page, often in a private window or by site settings.\",\n};\n\nexport function describeStorageFailure(error: unknown): string {\n if (typeof error !== \"object\" || error === null) {\n return \"The browser cancelled the save without giving a reason.\";\n }\n const name =\n \"name\" in error && typeof error.name === \"string\" ? error.name : \"\";\n const message =\n \"message\" in error && typeof error.message === \"string\"\n ? error.message\n : \"\";\n return FAILURE_COPY_BY_NAME[name] ?? (message || name || \"Saving failed.\");\n}\n","import type { OutboxPayload, StoredOperation } from \"./session-store\";\n\n/** WebKit private windows refuse Blobs in IndexedDB, so recordings are stored as raw bytes. */\ninterface StoredBytes {\n bytes: ArrayBuffer;\n type: string;\n}\n\ntype VoicePayload = Extract<OutboxPayload, { kind: \"voice\" }>;\ntype EvidencePayload = Extract<OutboxPayload, { kind: \"evidence\" }>;\ntype EvidenceImage = NonNullable<EvidencePayload[\"image\"]>;\n\ntype StoredPayload =\n | Exclude<OutboxPayload, { kind: \"voice\" | \"evidence\" }>\n | (Omit<VoicePayload, \"audio\"> & { audio: StoredBytes | null })\n | (Omit<EvidencePayload, \"image\"> & {\n image:\n | (Omit<EvidenceImage, \"blob\"> & { blob: StoredBytes | null })\n | null;\n });\n\nexport type StoredRow<Operation> = Omit<Operation, \"payload\"> & {\n payload: StoredPayload;\n};\n\nasync function toBytes(blob: Blob | null): Promise<StoredBytes | null> {\n return blob ? { bytes: await blob.arrayBuffer(), type: blob.type } : null;\n}\n\nfunction toBlob(stored: StoredBytes | null): Blob | null {\n return stored ? new Blob([stored.bytes], { type: stored.type }) : null;\n}\n\nasync function packPayload(payload: OutboxPayload): Promise<StoredPayload> {\n if (payload.kind === \"voice\") {\n return { ...payload, audio: await toBytes(payload.audio) };\n }\n if (payload.kind === \"evidence\" && payload.image) {\n const blob = await toBytes(payload.image.blob);\n return { ...payload, image: { ...payload.image, blob } };\n }\n if (payload.kind === \"evidence\") {\n return { ...payload, image: null };\n }\n return payload;\n}\n\nfunction unpackPayload(payload: StoredPayload): OutboxPayload {\n if (payload.kind === \"voice\") {\n return { ...payload, audio: toBlob(payload.audio) };\n }\n if (payload.kind === \"evidence\" && payload.image) {\n const blob = toBlob(payload.image.blob);\n return { ...payload, image: { ...payload.image, blob } };\n }\n if (payload.kind === \"evidence\") {\n return { ...payload, image: null };\n }\n return payload;\n}\n\nexport async function packOperation<\n Operation extends Omit<StoredOperation, \"id\">,\n>(operation: Operation): Promise<StoredRow<Operation>> {\n return { ...operation, payload: await packPayload(operation.payload) };\n}\n\nexport function unpackOperation(\n row: StoredRow<StoredOperation>\n): StoredOperation {\n return { ...row, payload: unpackPayload(row.payload) };\n}\n","import { committed, openDatabase, settle } from \"../../storage/indexed-db\";\nimport type {\n SessionLocalStore,\n StoredDraft,\n StoredOperation,\n} from \"./session-store\";\nimport {\n packOperation,\n type StoredRow,\n unpackOperation,\n} from \"./stored-payload\";\n\nconst DATABASE_NAME = \"reflet-sessions\";\nconst DATABASE_VERSION = 1;\nconst DRAFTS = \"drafts\";\nconst OPERATIONS = \"operations\";\nconst BY_ACCOUNT = \"by_account\";\n\ninterface SessionDatabase {\n readAccount: <T>(storeName: string, accountKey: string) => Promise<T[]>;\n transaction: (storeNames: string[]) => Promise<IDBTransaction>;\n write: (\n storeNames: string[],\n run: (transaction: IDBTransaction) => void\n ) => Promise<void>;\n}\n\nfunction createSessionsSchema(database: IDBDatabase): void {\n database\n .createObjectStore(DRAFTS, { keyPath: \"sessionKey\" })\n .createIndex(BY_ACCOUNT, \"accountKey\");\n database\n .createObjectStore(OPERATIONS, { autoIncrement: true, keyPath: \"id\" })\n .createIndex(BY_ACCOUNT, \"accountKey\");\n}\n\nfunction connectSessionDatabase(): SessionDatabase {\n let database: Promise<IDBDatabase> | null = null;\n const connect = () => {\n database ??= openDatabase({\n name: DATABASE_NAME,\n upgrade: createSessionsSchema,\n version: DATABASE_VERSION,\n }).catch((error: unknown) => {\n database = null;\n throw error;\n });\n return database;\n };\n const transaction = async (storeNames: string[]) =>\n (await connect()).transaction(storeNames, \"readwrite\");\n\n return {\n readAccount: async (storeName, accountKey) =>\n await settle(\n (await connect())\n .transaction(storeName, \"readonly\")\n .objectStore(storeName)\n .index(BY_ACCOUNT)\n .getAll(accountKey)\n ),\n transaction,\n write: async (storeNames, run) => {\n const opened = await transaction(storeNames);\n run(opened);\n await committed(opened);\n },\n };\n}\n\nfunction deleteAccountRows(\n transaction: IDBTransaction,\n storeName: string,\n accountKey: string\n): void {\n const store = transaction.objectStore(storeName);\n const request = store.index(BY_ACCOUNT).getAllKeys(accountKey);\n request.onsuccess = () => {\n for (const key of request.result) {\n store.delete(key);\n }\n };\n}\n\nfunction draftMethods(database: SessionDatabase) {\n return {\n deleteDraft: (sessionKey: string) =>\n database.write([DRAFTS], (transaction) => {\n transaction.objectStore(DRAFTS).delete(sessionKey);\n }),\n patchDraft: (sessionKey: string, patch: Partial<StoredDraft>) =>\n database.write([DRAFTS], (transaction) => {\n const drafts = transaction.objectStore(DRAFTS);\n const request = drafts.get(sessionKey);\n request.onsuccess = () => {\n const current: StoredDraft | undefined = request.result;\n if (current) {\n drafts.put({ ...current, ...patch });\n }\n };\n }),\n purgeAccount: (accountKey: string) =>\n database.write([DRAFTS, OPERATIONS], (transaction) => {\n deleteAccountRows(transaction, DRAFTS, accountKey);\n deleteAccountRows(transaction, OPERATIONS, accountKey);\n }),\n readDrafts: (accountKey: string) =>\n database.readAccount<StoredDraft>(DRAFTS, accountKey),\n writeDraft: (draft: StoredDraft) =>\n database.write([DRAFTS], (transaction) => {\n transaction.objectStore(DRAFTS).put(draft);\n }),\n } satisfies Partial<SessionLocalStore>;\n}\n\nfunction operationMethods(database: SessionDatabase) {\n return {\n addOperation: async (operation: Omit<StoredOperation, \"id\">) => {\n const row = await packOperation(operation);\n const transaction = await database.transaction([OPERATIONS]);\n const request = transaction.objectStore(OPERATIONS).add(row);\n await committed(transaction);\n if (typeof request.result !== \"number\") {\n throw new Error(\"IndexedDB returned no operation id.\");\n }\n return { ...operation, id: request.result };\n },\n deleteOperations: (ids: number[]) =>\n database.write([OPERATIONS], (transaction) => {\n for (const id of ids) {\n transaction.objectStore(OPERATIONS).delete(id);\n }\n }),\n readOperations: async (accountKey: string) =>\n (\n await database.readAccount<StoredRow<StoredOperation>>(\n OPERATIONS,\n accountKey\n )\n )\n .map(unpackOperation)\n .sort((a, b) => a.id - b.id),\n replaceOperation: async (operation: StoredOperation) => {\n const row = await packOperation(operation);\n await database.write([OPERATIONS], (transaction) => {\n const operations = transaction.objectStore(OPERATIONS);\n const request = operations.getKey(operation.id);\n request.onsuccess = () => {\n if (request.result !== undefined) {\n operations.put(row);\n }\n };\n });\n },\n } satisfies Partial<SessionLocalStore>;\n}\n\nexport function createIndexedSessionStore(): SessionLocalStore {\n const database = connectSessionDatabase();\n return { ...draftMethods(database), ...operationMethods(database) };\n}\n","import type { FeedbackContext, FeedbackItem } from \"../../../types\";\nimport {\n type BoardAccess,\n type CodeSearchResult,\n type ConnectStartResponse,\n DEVTOOLS_ENDPOINTS,\n DEVTOOLS_REQUEST_HEADER,\n DEVTOOLS_ROUTE_BASE,\n DEVTOOLS_STATUS_MARKER,\n type DevtoolsStatus,\n type DisconnectResponse,\n EDITORS,\n type PROXIED_API_PATHS,\n type SourceFile,\n} from \"../../protocol\";\n\nexport interface BoardFeedback extends FeedbackItem {\n context?: FeedbackContext;\n isInternal?: boolean;\n}\n\nexport interface BoardFeedbackPage {\n hasMore: boolean;\n items: BoardFeedback[];\n total: number;\n}\n\nexport interface SourceRequest {\n column: number | null;\n fileName: string;\n line: number | null;\n}\n\ntype ProxiedApiPath = (typeof PROXIED_API_PATHS)[number];\n\nconst INBOX_PAGE_SIZE = 50;\n\nexport class DevRouteError extends Error {\n readonly body: unknown;\n readonly status: number;\n\n constructor(message: string, details: { body: unknown; status: number }) {\n super(message);\n this.name = \"DevRouteError\";\n this.status = details.status;\n this.body = details.body;\n }\n}\n\nfunction isBoardAccess(value: unknown): value is BoardAccess {\n if (typeof value !== \"object\" || value === null || !(\"kind\" in value)) {\n return false;\n }\n switch (value.kind) {\n case \"secretKey\":\n return true;\n case \"connected\":\n return (\n \"organizationName\" in value &&\n typeof value.organizationName === \"string\"\n );\n case \"disconnected\":\n return \"canConnect\" in value && typeof value.canConnect === \"boolean\";\n default:\n return false;\n }\n}\n\nfunction isDevtoolsStatus(value: unknown): value is DevtoolsStatus {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"marker\" in value &&\n value.marker === DEVTOOLS_STATUS_MARKER &&\n \"board\" in value &&\n isBoardAccess(value.board) &&\n \"editor\" in value &&\n EDITORS.some((known) => known === value.editor)\n );\n}\n\nasync function callDevRoute<T>(\n endpoint: string,\n init: {\n body?: unknown;\n method?: \"GET\" | \"POST\";\n query?: Record<string, string>;\n } = {}\n): Promise<T> {\n const search = init.query ? `?${new URLSearchParams(init.query)}` : \"\";\n const response = await fetch(`${DEVTOOLS_ROUTE_BASE}${endpoint}${search}`, {\n body: init.body === undefined ? undefined : JSON.stringify(init.body),\n headers: {\n \"Content-Type\": \"application/json\",\n [DEVTOOLS_REQUEST_HEADER]: \"1\",\n },\n method: init.method ?? \"GET\",\n });\n\n if (!response.ok) {\n const body: unknown = await response.json().catch(() => null);\n const routeError =\n typeof body === \"object\" && body !== null && \"error\" in body\n ? body.error\n : null;\n throw new DevRouteError(\n typeof routeError === \"string\"\n ? routeError\n : `The Reflet dev route answered ${response.status}.`,\n { body, status: response.status }\n );\n }\n // Shapes owned by protocol.ts and the Reflet public API, same trust as client.ts.\n return await response.json();\n}\n\nexport async function probeDevRoute(): Promise<DevtoolsStatus | null> {\n try {\n const status = await callDevRoute<unknown>(DEVTOOLS_ENDPOINTS.status);\n return isDevtoolsStatus(status) ? status : null;\n } catch {\n return null;\n }\n}\n\nexport function startBoardConnect(\n publicKey: string\n): Promise<ConnectStartResponse> {\n return callDevRoute<ConnectStartResponse>(DEVTOOLS_ENDPOINTS.connectStart, {\n body: { publicKey },\n method: \"POST\",\n });\n}\n\nexport function disconnectBoard(): Promise<DisconnectResponse> {\n return callDevRoute<DisconnectResponse>(DEVTOOLS_ENDPOINTS.disconnect, {\n body: {},\n method: \"POST\",\n });\n}\n\nexport function fetchSourceFile(request: SourceRequest): Promise<SourceFile> {\n const query: Record<string, string> = { file: request.fileName };\n if (request.line !== null) {\n query.line = String(request.line);\n }\n if (request.column !== null) {\n query.column = String(request.column);\n }\n return callDevRoute<SourceFile>(DEVTOOLS_ENDPOINTS.source, { query });\n}\n\nexport function searchCode(text: string): Promise<CodeSearchResult> {\n return callDevRoute<CodeSearchResult>(DEVTOOLS_ENDPOINTS.search, {\n query: { q: text },\n });\n}\n\nexport function callReflet<T>(\n apiPath: ProxiedApiPath,\n init: { body?: unknown; query?: Record<string, string> } = {}\n): Promise<T> {\n return callDevRoute<T>(`${DEVTOOLS_ENDPOINTS.proxy}${apiPath}`, {\n body: init.body,\n method: init.body === undefined ? \"GET\" : \"POST\",\n query: init.query,\n });\n}\n\nexport function fetchBoardFeedback(\n pagePath: string | null\n): Promise<BoardFeedbackPage> {\n const query: Record<string, string> = {\n limit: String(INBOX_PAGE_SIZE),\n sortBy: \"newest\",\n };\n if (pagePath !== null) {\n query.pagePath = pagePath;\n }\n return callReflet<BoardFeedbackPage>(\"/api/v1/feedback/list\", { query });\n}\n","import {\n callReflet,\n DevRouteError,\n} from \"../../devtools/client/route/dev-route\";\nimport { uploadBlob } from \"../../feedback/core/submit\";\nimport { sessionApiErrorSchema } from \"../protocol\";\nimport {\n SessionApiError,\n type SessionRequest,\n type SessionTransport,\n} from \"./session-api\";\n\nconst TRAILING_SLASHES = /\\/+$/;\n\nfunction toSessionApiError(body: unknown, status: number): SessionApiError {\n const parsed = sessionApiErrorSchema.safeParse(body);\n const message = parsed.success\n ? parsed.data.error\n : `Reflet answered ${status}.`;\n return new SessionApiError(message, {\n limit: parsed.success ? (parsed.data.limit ?? null) : null,\n status,\n });\n}\n\nexport function devtoolsTransport(): SessionTransport {\n return {\n async request<T>({ body, method, path, query, schema }: SessionRequest<T>) {\n try {\n const response = await callReflet<unknown>(path, {\n body: method === \"POST\" ? (body ?? {}) : undefined,\n query,\n });\n return schema.parse(response);\n } catch (error) {\n if (error instanceof DevRouteError) {\n throw toSessionApiError(error.body, error.status);\n }\n throw error;\n }\n },\n };\n}\n\nexport function teamTransport(options: {\n apiUrl: string;\n token: string;\n}): SessionTransport {\n const base = options.apiUrl.replace(TRAILING_SLASHES, \"\");\n return {\n async request<T>({ body, method, path, query, schema }: SessionRequest<T>) {\n const search = query ? `?${new URLSearchParams(query)}` : \"\";\n const response = await fetch(`${base}${path}${search}`, {\n body: method === \"POST\" ? JSON.stringify(body ?? {}) : undefined,\n headers: {\n Authorization: `Bearer ${options.token}`,\n \"Content-Type\": \"application/json\",\n },\n method,\n });\n if (!response.ok) {\n const failure: unknown = await response.json().catch(() => null);\n throw toSessionApiError(failure, response.status);\n }\n return schema.parse(await response.json().catch(() => null));\n },\n };\n}\n\nexport function uploadSessionBlob(\n uploadUrl: string,\n blob: Blob\n): Promise<string> {\n return uploadBlob(uploadUrl, { blob, mimeType: blob.type });\n}\n","import { z } from \"zod\";\nimport { type SessionApi, SessionApiError } from \"../api/session-api\";\nimport { uploadSessionBlob } from \"../api/session-transports\";\nimport type { SessionLimitKind } from \"../protocol\";\nimport type {\n OutboxPayload,\n SessionLocalStore,\n StoredOperation,\n} from \"./session-store\";\n\nconst RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 504]);\nconst SMALL_OPERATION_BYTES = 256;\n\nexport type OperationOutcome =\n | { kind: \"auth\" }\n | { kind: \"done\" }\n | { kind: \"drop\"; message: string }\n | { kind: \"limit\"; limit: SessionLimitKind }\n | { kind: \"retry\"; message: string }\n | { kind: \"sessionGone\" }\n | { kind: \"started\"; sessionId: string };\n\ninterface OperationContext {\n api: SessionApi;\n operation: StoredOperation;\n sessionId: string;\n store: SessionLocalStore;\n}\n\nexport function operationBytes(payload: OutboxPayload): number {\n switch (payload.kind) {\n case \"voice\":\n return payload.audio?.size ?? SMALL_OPERATION_BYTES;\n case \"evidence\":\n return (payload.image?.blob?.size ?? 0) + SMALL_OPERATION_BYTES;\n case \"events\":\n return JSON.stringify(payload.events).length;\n default:\n return SMALL_OPERATION_BYTES;\n }\n}\n\nexport function classifyFailure(error: unknown): OperationOutcome {\n const message = error instanceof Error ? error.message : String(error);\n if (error instanceof z.ZodError) {\n return { kind: \"drop\", message: \"Reflet sent an unexpected answer.\" };\n }\n if (!(error instanceof SessionApiError)) {\n return { kind: \"retry\", message };\n }\n if (error.status === 401) {\n return { kind: \"auth\" };\n }\n if (error.status === 404) {\n return { kind: \"sessionGone\" };\n }\n if (error.status === 413) {\n return { kind: \"limit\", limit: error.limit ?? \"bytes\" };\n }\n return RETRYABLE_STATUSES.has(error.status)\n ? { kind: \"retry\", message }\n : { kind: \"drop\", message };\n}\n\n/** Uploads once: the storage id is saved before the record that uses it, so a retry never re-uploads. */\nasync function uploadOnce(\n context: OperationContext,\n upload: {\n blob: Blob | null;\n kind: \"audio\" | \"image\";\n storageId: string | null;\n },\n remember: (storageId: string) => OutboxPayload\n): Promise<string> {\n if (upload.storageId !== null) {\n return upload.storageId;\n }\n if (!upload.blob) {\n throw new Error(\"The recorded file is missing from this browser.\");\n }\n const uploadUrl = await context.api.uploadUrl({\n kind: upload.kind,\n sessionId: context.sessionId,\n });\n const storageId = await uploadSessionBlob(uploadUrl, upload.blob);\n await context.store.replaceOperation({\n ...context.operation,\n bytes: SMALL_OPERATION_BYTES,\n payload: remember(storageId),\n });\n return storageId;\n}\n\nasync function sendVoice(\n context: OperationContext,\n payload: Extract<OutboxPayload, { kind: \"voice\" }>\n): Promise<void> {\n const audioStorageId = await uploadOnce(\n context,\n { blob: payload.audio, kind: \"audio\", storageId: payload.storageId },\n (storageId) => ({ ...payload, audio: null, storageId })\n );\n await context.api.addVoiceSegment({\n audioStorageId,\n clientKey: payload.clientKey,\n endMs: payload.endMs,\n sessionId: context.sessionId,\n startMs: payload.startMs,\n });\n}\n\nasync function sendEvidence(\n context: OperationContext,\n payload: Extract<OutboxPayload, { kind: \"evidence\" }>\n): Promise<void> {\n const { image } = payload;\n const storageId = image\n ? await uploadOnce(\n context,\n { blob: image.blob, kind: \"image\", storageId: image.storageId },\n (uploaded) => ({\n ...payload,\n image: { ...image, blob: null, storageId: uploaded },\n })\n )\n : null;\n await context.api.addEvidence({\n ...payload.evidence,\n image:\n image && storageId\n ? { height: image.height, storageId, width: image.width }\n : undefined,\n sessionId: context.sessionId,\n });\n}\n\nasync function sendSessionOperation(\n context: OperationContext,\n payload: Exclude<OutboxPayload, { kind: \"start\" }>\n): Promise<OperationOutcome> {\n const { api, sessionId } = context;\n switch (payload.kind) {\n case \"collection\":\n await api.collection({\n action: payload.action,\n atMs: payload.atMs,\n reason: payload.reason,\n sessionId,\n });\n return { kind: \"done\" };\n case \"events\": {\n const result = await api.events({\n clientKey: payload.clientKey,\n events: payload.events,\n sessionId,\n });\n return result.limitReached\n ? { kind: \"limit\", limit: \"events\" }\n : { kind: \"done\" };\n }\n case \"voice\":\n await sendVoice(context, payload);\n return { kind: \"done\" };\n case \"evidence\":\n await sendEvidence(context, payload);\n return { kind: \"done\" };\n default:\n await api.analyze(sessionId);\n return { kind: \"done\" };\n }\n}\n\nexport async function sendOperation(\n context: Omit<OperationContext, \"sessionId\"> & { sessionId: string | null }\n): Promise<OperationOutcome> {\n const { payload } = context.operation;\n if (payload.kind === \"start\") {\n const session = await context.api.start(payload.body);\n return { kind: \"started\", sessionId: session.id };\n }\n if (context.sessionId === null) {\n return {\n kind: \"drop\",\n message: \"This session was never created on Reflet.\",\n };\n }\n return await sendSessionOperation(\n { ...context, sessionId: context.sessionId },\n payload\n );\n}\n","import { describeStorageFailure } from \"../../storage/indexed-db\";\nimport type { SessionApi } from \"../api/session-api\";\nimport type { SessionLimitKind } from \"../protocol\";\nimport {\n classifyFailure,\n type OperationOutcome,\n operationBytes,\n sendOperation,\n} from \"./outbox-operations\";\nimport type {\n OutboxPayload,\n SessionLocalStore,\n StoredDraft,\n StoredOperation,\n SyncSnapshot,\n} from \"./session-store\";\n\nconst FIRST_RETRY_DELAY_MS = 1000;\nconst MAX_RETRY_DELAY_MS = 60_000;\nconst BUFFER_FULL = \"This device's upload buffer is full.\";\n\nexport type OutboxIssue =\n | { kind: \"auth\" }\n | { kind: \"limit\"; limit: SessionLimitKind; sessionKey: string }\n | { kind: \"sessionGone\"; sessionKey: string };\n\nexport interface Outbox {\n drain: () => void;\n enqueue: (sessionKey: string, payload: OutboxPayload) => Promise<void>;\n getSnapshot: () => SyncSnapshot;\n stop: () => void;\n subscribe: (listener: () => void) => () => void;\n subscribeIssues: (listener: (issue: OutboxIssue) => void) => () => void;\n}\n\nexport interface OutboxOptions {\n accountKey: string;\n api: SessionApi;\n maxLocalBufferBytes: number;\n onDraftsChanged: () => void;\n store: SessionLocalStore;\n}\n\nexport class OutboxStorageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OutboxStorageError\";\n }\n}\n\ninterface DrainPass {\n outcomes: Map<string, OperationOutcome>;\n sessionIds: Map<string, string>;\n}\n\nfunction sessionIdsOf(drafts: StoredDraft[]): Map<string, string> {\n const ids = new Map<string, string>();\n for (const draft of drafts) {\n if (draft.sessionId !== null) {\n ids.set(draft.sessionKey, draft.sessionId);\n }\n }\n return ids;\n}\n\nclass SessionOutbox implements Outbox {\n private readonly controller = new AbortController();\n private draining = false;\n private drainAgain = false;\n private failedPasses = 0;\n private readonly issueListeners = new Set<(issue: OutboxIssue) => void>();\n private readonly listeners = new Set<() => void>();\n private readonly options: OutboxOptions;\n private retryTimer: number | undefined;\n private snapshot: SyncSnapshot = {\n blockedBy: null,\n isOnline: navigator.onLine,\n lastError: null,\n pendingBytes: 0,\n pendingOperations: 0,\n };\n\n constructor(options: OutboxOptions) {\n this.options = options;\n const listen = { signal: this.controller.signal };\n window.addEventListener(\"online\", this.reconnected, listen);\n window.addEventListener(\"offline\", this.disconnected, listen);\n window.addEventListener(\"focus\", this.drain, listen);\n }\n\n readonly drain = (): void => {\n if (this.isHalted()) {\n return;\n }\n if (this.draining) {\n this.drainAgain = true;\n return;\n }\n this.draining = true;\n this.drainPass()\n .catch((error: unknown) =>\n this.publish({\n blockedBy: \"storage\",\n lastError: describeStorageFailure(error),\n })\n )\n .finally(() => {\n this.draining = false;\n if (this.drainAgain) {\n this.drainAgain = false;\n this.drain();\n }\n });\n };\n\n async enqueue(sessionKey: string, payload: OutboxPayload): Promise<void> {\n const bytes = operationBytes(payload);\n if (this.snapshot.pendingBytes + bytes > this.options.maxLocalBufferBytes) {\n this.failStorage(BUFFER_FULL);\n }\n try {\n await this.options.store.addOperation({\n accountKey: this.options.accountKey,\n bytes,\n payload,\n sessionKey,\n });\n } catch (error) {\n this.failStorage(describeStorageFailure(error));\n }\n this.publish({\n blockedBy: this.snapshot.blockedBy === \"auth\" ? \"auth\" : null,\n pendingBytes: this.snapshot.pendingBytes + bytes,\n pendingOperations: this.snapshot.pendingOperations + 1,\n });\n this.drain();\n }\n\n getSnapshot = (): SyncSnapshot => this.snapshot;\n\n stop(): void {\n this.controller.abort();\n window.clearTimeout(this.retryTimer);\n }\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n subscribeIssues(listener: (issue: OutboxIssue) => void): () => void {\n this.issueListeners.add(listener);\n return () => this.issueListeners.delete(listener);\n }\n\n private readonly disconnected = () => this.publish({ isOnline: false });\n\n private readonly reconnected = () => {\n this.publish({ isOnline: true });\n this.drain();\n };\n\n private isHalted(): boolean {\n return this.snapshot.blockedBy === \"auth\" || this.controller.signal.aborted;\n }\n\n private failStorage(message: string): never {\n this.publish({ blockedBy: \"storage\", lastError: message });\n throw new OutboxStorageError(message);\n }\n\n private publish(next: Partial<SyncSnapshot>): void {\n this.snapshot = { ...this.snapshot, ...next };\n for (const listener of this.listeners) {\n listener();\n }\n }\n\n private report(issue: OutboxIssue): void {\n for (const listener of this.issueListeners) {\n listener(issue);\n }\n }\n\n private async drainPass(): Promise<void> {\n const { accountKey, store } = this.options;\n const pass: DrainPass = {\n outcomes: new Map(),\n sessionIds: sessionIdsOf(await store.readDrafts(accountKey)),\n };\n for (const operation of await store.readOperations(accountKey)) {\n if (this.isHalted()) {\n return;\n }\n if (pass.outcomes.get(operation.sessionKey)?.kind !== \"retry\") {\n await this.runOperation(operation, pass);\n }\n }\n const remaining = await store.readOperations(accountKey);\n this.publish({\n pendingBytes: remaining.reduce((sum, item) => sum + item.bytes, 0),\n pendingOperations: remaining.length,\n });\n await this.forgetFinishedDrafts(remaining);\n this.afterPass(pass);\n }\n\n private afterPass(pass: DrainPass): void {\n const stalled = [...pass.outcomes.values()].some(\n (outcome) => outcome.kind === \"retry\"\n );\n if (!stalled) {\n this.failedPasses = 0;\n this.publish({ lastError: null });\n return;\n }\n this.failedPasses += 1;\n const delay = Math.min(\n MAX_RETRY_DELAY_MS,\n FIRST_RETRY_DELAY_MS * 2 ** (this.failedPasses - 1)\n );\n window.clearTimeout(this.retryTimer);\n this.retryTimer = window.setTimeout(this.drain, delay);\n }\n\n private async runOperation(\n operation: StoredOperation,\n pass: DrainPass\n ): Promise<void> {\n const outcome = await sendOperation({\n api: this.options.api,\n operation,\n sessionId: pass.sessionIds.get(operation.sessionKey) ?? null,\n store: this.options.store,\n }).catch(classifyFailure);\n pass.outcomes.set(operation.sessionKey, outcome);\n const settled = await this.settle(operation, outcome, pass);\n if (settled) {\n await this.options.store.deleteOperations([operation.id]);\n }\n }\n\n private async settle(\n operation: StoredOperation,\n outcome: OperationOutcome,\n pass: DrainPass\n ): Promise<boolean> {\n const { sessionKey } = operation;\n switch (outcome.kind) {\n case \"retry\":\n this.publish({ lastError: outcome.message });\n return false;\n case \"auth\":\n this.publish({ blockedBy: \"auth\", lastError: null });\n this.report({ kind: \"auth\" });\n return false;\n case \"sessionGone\":\n await this.dropSession(sessionKey);\n this.report({ kind: \"sessionGone\", sessionKey });\n return false;\n case \"started\":\n pass.sessionIds.set(sessionKey, outcome.sessionId);\n await this.options.store.patchDraft(sessionKey, {\n sessionId: outcome.sessionId,\n });\n this.options.onDraftsChanged();\n return true;\n case \"limit\":\n this.report({ kind: \"limit\", limit: outcome.limit, sessionKey });\n return true;\n case \"drop\":\n this.publish({ lastError: outcome.message });\n return true;\n default:\n return true;\n }\n }\n\n private async dropSession(sessionKey: string): Promise<void> {\n const { accountKey, store } = this.options;\n const operations = await store.readOperations(accountKey);\n await store.deleteOperations(\n operations\n .filter((operation) => operation.sessionKey === sessionKey)\n .map((operation) => operation.id)\n );\n await store.deleteDraft(sessionKey);\n this.options.onDraftsChanged();\n }\n\n private async forgetFinishedDrafts(\n operations: StoredOperation[]\n ): Promise<void> {\n const { accountKey, store } = this.options;\n const waiting = new Set(\n operations.map((operation) => operation.sessionKey)\n );\n const finished = (await store.readDrafts(accountKey)).filter(\n (draft) => draft.state === \"ended\" && !waiting.has(draft.sessionKey)\n );\n await Promise.all(\n finished.map((draft) => store.deleteDraft(draft.sessionKey))\n );\n if (finished.length > 0) {\n this.options.onDraftsChanged();\n }\n }\n}\n\nexport function createOutbox(options: OutboxOptions): Outbox {\n return new SessionOutbox(options);\n}\n","import { useSyncExternalStore } from \"react\";\nimport type { SessionApi } from \"../api/session-api\";\nimport { createIndexedSessionStore } from \"./indexed-session-store\";\nimport { createOutbox, type Outbox } from \"./outbox\";\nimport type {\n LocalDraft,\n SessionLocalStore,\n StoredDraft,\n SyncSnapshot,\n} from \"./session-store\";\n\nconst CHANGE_CHANNEL = \"reflet-sessions\";\nconst ACCESS_ENDED =\n \"Your Reflet access ended, so recording stopped. Sign in again to record.\";\nconst NO_DRAFTS: LocalDraft[] = [];\nconst IDLE_SYNC: SyncSnapshot = {\n blockedBy: null,\n isOnline: true,\n lastError: null,\n pendingBytes: 0,\n pendingOperations: 0,\n};\n\nexport interface LiveRecording {\n halt: (failure: { kind: \"auth\"; message: string }) => void;\n sessionKey: string;\n}\n\nexport interface AccountSessions {\n claim: (recording: LiveRecording) => () => void;\n outbox: Outbox;\n refreshDrafts: () => void;\n store: SessionLocalStore;\n}\n\nexport interface LocalSessions {\n connect: (options: {\n accountKey: string;\n api: SessionApi;\n maxLocalBufferBytes: number | null;\n }) => AccountSessions;\n discardDraft: (options: {\n accountKey: string;\n api: SessionApi;\n sessionKey: string;\n }) => Promise<void>;\n getDrafts: (accountKey: string) => LocalDraft[];\n getSyncSnapshot: (accountKey: string) => SyncSnapshot;\n purgeAccount: (accountKey: string) => Promise<void>;\n refreshDrafts: (accountKey: string) => void;\n subscribe: (listener: () => void) => () => void;\n subscribeDrafts: (accountKey: string, listener: () => void) => () => void;\n}\n\ninterface ConnectedAccount {\n api: SessionApi;\n maxLocalBufferBytes: number;\n outbox: Outbox;\n stopped: boolean;\n}\n\nfunction visibleDraft(stored: StoredDraft, isLive: boolean): LocalDraft {\n const leftOpen = stored.state === \"recording\" || stored.state === \"paused\";\n return {\n lastActiveAt: stored.lastActiveAt,\n sessionId: stored.sessionId,\n sessionKey: stored.sessionKey,\n startedAt: stored.startedAt,\n state: leftOpen && !isLive ? \"interrupted\" : stored.state,\n title: stored.title,\n };\n}\n\nclass LocalSessionsRegistry implements LocalSessions {\n private readonly accounts = new Map<string, ConnectedAccount>();\n private readonly channel =\n typeof window === \"undefined\" || typeof BroadcastChannel === \"undefined\"\n ? null\n : new BroadcastChannel(CHANGE_CHANNEL);\n private readonly drafts = new Map<string, LocalDraft[]>();\n private readonly listeners = new Set<() => void>();\n private readonly live = new Map<\n string,\n LiveRecording & { accountKey: string }\n >();\n private readonly store: SessionLocalStore;\n\n constructor(store: SessionLocalStore) {\n this.store = store;\n this.channel?.addEventListener(\"message\", () => {\n for (const accountKey of this.drafts.keys()) {\n this.refreshDrafts(accountKey);\n }\n });\n }\n\n connect(options: {\n accountKey: string;\n api: SessionApi;\n maxLocalBufferBytes: number | null;\n }): AccountSessions {\n const { accountKey } = options;\n const connected = this.ensureOutbox(options);\n return {\n claim: (recording) => {\n this.live.set(recording.sessionKey, { ...recording, accountKey });\n this.refreshDrafts(accountKey);\n return () => {\n this.live.delete(recording.sessionKey);\n this.refreshDrafts(accountKey);\n };\n },\n outbox: connected.outbox,\n refreshDrafts: () => this.draftsChanged(accountKey),\n store: this.store,\n };\n }\n\n async discardDraft(options: {\n accountKey: string;\n api: SessionApi;\n sessionKey: string;\n }): Promise<void> {\n const { accountKey, sessionKey } = options;\n const stored = (await this.store.readDrafts(accountKey)).find(\n (candidate) => candidate.sessionKey === sessionKey\n );\n if (!stored || this.live.has(sessionKey) || stored.state === \"ended\") {\n return;\n }\n const { outbox } = this.ensureOutbox({\n ...options,\n maxLocalBufferBytes: null,\n });\n const atMs = Math.max(0, stored.lastActiveAt - stored.startedAt);\n await outbox.enqueue(sessionKey, {\n action: \"end\",\n atMs,\n kind: \"collection\",\n reason: \"interrupted\",\n });\n await outbox.enqueue(sessionKey, { kind: \"analyze\" });\n await this.store.patchDraft(sessionKey, { state: \"ended\" });\n this.draftsChanged(accountKey);\n }\n\n getDrafts = (accountKey: string): LocalDraft[] =>\n this.drafts.get(accountKey) ?? NO_DRAFTS;\n\n getSyncSnapshot = (accountKey: string): SyncSnapshot =>\n this.accounts.get(accountKey)?.outbox.getSnapshot() ?? IDLE_SYNC;\n\n async purgeAccount(accountKey: string): Promise<void> {\n for (const [sessionKey, recording] of this.live) {\n if (recording.accountKey === accountKey) {\n this.live.delete(sessionKey);\n recording.halt({ kind: \"auth\", message: ACCESS_ENDED });\n }\n }\n const connected = this.accounts.get(accountKey);\n if (connected) {\n connected.outbox.stop();\n connected.stopped = true;\n }\n await this.store.purgeAccount(accountKey);\n this.draftsChanged(accountKey);\n }\n\n refreshDrafts(accountKey: string): void {\n this.store\n .readDrafts(accountKey)\n .then((stored) => {\n const visible = stored\n .map((item) => visibleDraft(item, this.live.has(item.sessionKey)))\n .sort((a, b) => b.startedAt - a.startedAt);\n this.drafts.set(accountKey, visible);\n this.notify();\n })\n .catch(() => {\n this.drafts.set(accountKey, NO_DRAFTS);\n this.notify();\n });\n }\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n subscribeDrafts(accountKey: string, listener: () => void): () => void {\n const unsubscribe = this.subscribe(listener);\n if (!this.drafts.has(accountKey)) {\n this.drafts.set(accountKey, NO_DRAFTS);\n this.refreshDrafts(accountKey);\n }\n return unsubscribe;\n }\n\n private draftsChanged(accountKey: string): void {\n this.refreshDrafts(accountKey);\n this.channel?.postMessage(\"changed\");\n }\n\n private ensureOutbox(options: {\n accountKey: string;\n api: SessionApi;\n maxLocalBufferBytes: number | null;\n }): ConnectedAccount {\n const { accountKey, api } = options;\n const existing = this.accounts.get(accountKey);\n const reusable =\n existing &&\n !existing.stopped &&\n existing.api === api &&\n existing.outbox.getSnapshot().blockedBy !== \"auth\";\n if (reusable) {\n return existing;\n }\n existing?.outbox.stop();\n const maxLocalBufferBytes =\n options.maxLocalBufferBytes ??\n existing?.maxLocalBufferBytes ??\n Number.POSITIVE_INFINITY;\n const outbox = createOutbox({\n accountKey,\n api,\n maxLocalBufferBytes,\n onDraftsChanged: () => this.draftsChanged(accountKey),\n store: this.store,\n });\n outbox.subscribe(() => this.notify());\n outbox.subscribeIssues((issue) => {\n if (issue.kind === \"auth\") {\n this.purgeAccount(accountKey).catch(() => undefined);\n }\n });\n const connected = { api, maxLocalBufferBytes, outbox, stopped: false };\n this.accounts.set(accountKey, connected);\n outbox.drain();\n return connected;\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n\nexport function createLocalSessions(store: SessionLocalStore): LocalSessions {\n return new LocalSessionsRegistry(store);\n}\n\nexport const localSessions = createLocalSessions(createIndexedSessionStore());\n\nexport function useSyncStatus(accountKey: string): SyncSnapshot {\n return useSyncExternalStore(\n localSessions.subscribe,\n () => localSessions.getSyncSnapshot(accountKey),\n () => IDLE_SYNC\n );\n}\n\nexport function useLocalDrafts(accountKey: string): LocalDraft[] {\n return useSyncExternalStore(\n (listener) => localSessions.subscribeDrafts(accountKey, listener),\n () => localSessions.getDrafts(accountKey),\n () => NO_DRAFTS\n );\n}\n\nexport function discardLocalDraft(options: {\n accountKey: string;\n api: SessionApi;\n sessionKey: string;\n}): Promise<void> {\n return localSessions.discardDraft(options);\n}\n\nexport function purgeAccount(accountKey: string): Promise<void> {\n return localSessions.purgeAccount(accountKey);\n}\n","import type { SessionGap, SessionGapReason } from \"../protocol\";\n\nexport interface SessionClock {\n activeMs: () => number;\n atMs: () => number;\n gaps: () => SessionGap[];\n isPaused: () => boolean;\n pause: (reason: SessionGapReason) => number;\n resume: () => number;\n}\n\nfunction readMonotonicTime(): number {\n return performance.timeOrigin + performance.now();\n}\n\nexport function createSessionClock(options: {\n gaps?: SessionGap[];\n readTime?: () => number;\n startedAt: number;\n}): SessionClock {\n const readTime = options.readTime ?? readMonotonicTime;\n let gaps = [...(options.gaps ?? [])];\n let latestMs = 0;\n\n const atMs = () => {\n latestMs = Math.max(latestMs, Math.round(readTime() - options.startedAt));\n return latestMs;\n };\n const openGap = () => gaps.find((gap) => gap.endMs === null);\n\n return {\n activeMs: () => {\n const nowMs = atMs();\n const pausedMs = gaps.reduce(\n (sum, gap) => sum + (gap.endMs ?? nowMs) - gap.startMs,\n 0\n );\n return Math.max(0, nowMs - pausedMs);\n },\n atMs,\n gaps: () => gaps.map((gap) => ({ ...gap })),\n isPaused: () => openGap() !== undefined,\n pause: (reason) => {\n const startMs = atMs();\n if (!openGap()) {\n gaps = [...gaps, { endMs: null, reason, startMs }];\n }\n return startMs;\n },\n resume: () => {\n const endMs = atMs();\n gaps = gaps.map((gap) => (gap.endMs === null ? { ...gap, endMs } : gap));\n return endMs;\n },\n };\n}\n","export type MicrophoneFailureKind =\n | \"insecure_context\"\n | \"mic_blocked_by_site\"\n | \"mic_denied\"\n | \"mic_unavailable\";\n\nconst FAILURE_MESSAGES: Record<MicrophoneFailureKind, string> = {\n insecure_context:\n \"The microphone only works on a secure page (https or localhost).\",\n mic_blocked_by_site:\n \"This site's Permissions-Policy header turns the microphone off. Allow microphone=(self) in it to record sessions here.\",\n mic_denied:\n \"The microphone is blocked for this site. Allow it from the address bar, then try again.\",\n mic_unavailable:\n \"No microphone is available. Plug one in or close the app using it, then try again.\",\n};\n\nconst PROCESSOR_NAME = \"reflet-session-capture\";\nconst FALLBACK_FRAME_SIZE = 4096;\nconst WORKLET_SOURCE = `\nconst FRAME_SIZE = 2048;\nclass RefletSessionCapture extends AudioWorkletProcessor {\n constructor() {\n super();\n this.frame = new Float32Array(FRAME_SIZE);\n this.filled = 0;\n }\n process(inputs) {\n const channel = inputs[0] && inputs[0][0];\n if (!channel) return true;\n for (let index = 0; index < channel.length; index += 1) {\n this.frame[this.filled] = channel[index];\n this.filled += 1;\n if (this.filled === FRAME_SIZE) {\n this.port.postMessage(this.frame, [this.frame.buffer]);\n this.frame = new Float32Array(FRAME_SIZE);\n this.filled = 0;\n }\n }\n return true;\n }\n}\nregisterProcessor(\"${PROCESSOR_NAME}\", RefletSessionCapture);\n`;\n\nexport class MicrophoneError extends Error {\n readonly kind: MicrophoneFailureKind;\n\n constructor(kind: MicrophoneFailureKind) {\n super(FAILURE_MESSAGES[kind]);\n this.name = \"MicrophoneError\";\n this.kind = kind;\n }\n}\n\nexport interface Microphone {\n readonly sampleRate: number;\n stop: () => void;\n}\n\nfunction isMicrophoneDisallowedBySite(): boolean {\n const policy =\n Reflect.get(document, \"permissionsPolicy\") ??\n Reflect.get(document, \"featurePolicy\");\n if (typeof policy !== \"object\" || policy === null) {\n return false;\n }\n const allowsFeature: unknown = Reflect.get(policy, \"allowsFeature\");\n return (\n typeof allowsFeature === \"function\" &&\n allowsFeature.call(policy, \"microphone\") === false\n );\n}\n\nfunction failureKind(error: unknown): MicrophoneFailureKind {\n const name =\n typeof error === \"object\" && error !== null && \"name\" in error\n ? error.name\n : null;\n if (name !== \"NotAllowedError\" && name !== \"SecurityError\") {\n return \"mic_unavailable\";\n }\n return isMicrophoneDisallowedBySite() ? \"mic_blocked_by_site\" : \"mic_denied\";\n}\n\nasync function requestVoiceStream(): Promise<MediaStream> {\n if (!(globalThis.isSecureContext && navigator.mediaDevices?.getUserMedia)) {\n throw new MicrophoneError(\"insecure_context\");\n }\n try {\n return await navigator.mediaDevices.getUserMedia({\n audio: {\n autoGainControl: true,\n channelCount: 1,\n echoCancellation: true,\n noiseSuppression: true,\n },\n });\n } catch (error) {\n throw new MicrophoneError(failureKind(error));\n }\n}\n\nasync function connectWorklet(options: {\n context: AudioContext;\n moduleUrl: string;\n onFrame: (frame: Float32Array) => void;\n}): Promise<AudioNode> {\n await options.context.audioWorklet.addModule(options.moduleUrl);\n const node = new AudioWorkletNode(options.context, PROCESSOR_NAME);\n node.port.onmessage = (event: MessageEvent<unknown>) => {\n if (event.data instanceof Float32Array) {\n options.onFrame(event.data);\n }\n };\n return node;\n}\n\nfunction connectScriptProcessor(\n context: AudioContext,\n onFrame: (frame: Float32Array) => void\n): AudioNode {\n const processor = context.createScriptProcessor(FALLBACK_FRAME_SIZE, 1, 1);\n processor.onaudioprocess = (event) => {\n onFrame(event.inputBuffer.getChannelData(0).slice());\n };\n return processor;\n}\n\nexport async function openMicrophone(options: {\n onFrame: (frame: Float32Array) => void;\n}): Promise<Microphone> {\n const stream = await requestVoiceStream();\n let active = true;\n const onFrame = (frame: Float32Array) => {\n if (active) {\n options.onFrame(frame);\n }\n };\n const moduleUrl = URL.createObjectURL(\n new Blob([WORKLET_SOURCE], { type: \"text/javascript\" })\n );\n const stopTracks = () => {\n for (const track of stream.getTracks()) {\n track.stop();\n }\n };\n try {\n const context = new AudioContext();\n const source = context.createMediaStreamSource(stream);\n const silentSink = context.createGain();\n silentSink.gain.value = 0;\n silentSink.connect(context.destination);\n const capture = await connectWorklet({ context, moduleUrl, onFrame }).catch(\n () => connectScriptProcessor(context, onFrame)\n );\n source.connect(capture);\n capture.connect(silentSink);\n await context.resume();\n return {\n sampleRate: context.sampleRate,\n stop: () => {\n active = false;\n stopTracks();\n source.disconnect();\n capture.disconnect();\n silentSink.disconnect();\n context.close().catch(() => undefined);\n URL.revokeObjectURL(moduleUrl);\n },\n };\n } catch {\n stopTracks();\n URL.revokeObjectURL(moduleUrl);\n throw new MicrophoneError(\"mic_unavailable\");\n }\n}\n","export const SPEECH_SAMPLE_RATE = 16_000;\n\nconst SAMPLES_PER_MS = SPEECH_SAMPLE_RATE / 1000;\nconst WINDOW_MS = 30;\nconst WINDOW_SAMPLES = WINDOW_MS * SAMPLES_PER_MS;\nconst PRE_ROLL_WINDOWS = 300 / WINDOW_MS;\nconst POST_ROLL_WINDOWS = 300 / WINDOW_MS;\nconst END_SILENCE_MS = 800;\nconst MIN_CHUNK_MS_BEFORE_SILENCE_END = 1500;\nconst MIN_SPEECH_MS = 400;\nconst MIN_SPEECH_LEVEL = 0.015;\nconst SPEECH_OVER_NOISE_RATIO = 3;\nconst INITIAL_NOISE_FLOOR = 0.005;\nconst NOISE_ADAPTATION_IN_SILENCE = 0.05;\nconst NOISE_ADAPTATION_IN_SPEECH = 0.0002;\nconst METER_GAIN = 5;\n\nexport interface SpeechChunk {\n endMs: number;\n samples: Float32Array;\n startMs: number;\n}\n\nexport interface SpeechChunker {\n flush: () => void;\n push: (samples: Float32Array) => void;\n}\n\ninterface OpenChunk {\n lastSpeechWindow: number;\n silentWindows: number;\n speechWindows: number;\n startSample: number;\n windows: Float32Array[];\n}\n\nfunction rootMeanSquare(samples: Float32Array): number {\n let sum = 0;\n for (const sample of samples) {\n sum += sample * sample;\n }\n return samples.length === 0 ? 0 : Math.sqrt(sum / samples.length);\n}\n\nexport function meterLevel(samples: Float32Array): number {\n return Math.min(1, rootMeanSquare(samples) * METER_GAIN);\n}\n\nfunction concatenate(windows: Float32Array[]): Float32Array {\n const joined = new Float32Array(\n windows.reduce((total, window) => total + window.length, 0)\n );\n let offset = 0;\n for (const window of windows) {\n joined.set(window, offset);\n offset += window.length;\n }\n return joined;\n}\n\nfunction createNoiseGate() {\n let noiseFloor = INITIAL_NOISE_FLOOR;\n return (level: number): boolean => {\n const isSpeech =\n level >= Math.max(MIN_SPEECH_LEVEL, noiseFloor * SPEECH_OVER_NOISE_RATIO);\n const adaptation = isSpeech\n ? NOISE_ADAPTATION_IN_SPEECH\n : NOISE_ADAPTATION_IN_SILENCE;\n noiseFloor =\n level < noiseFloor\n ? level\n : noiseFloor + (level - noiseFloor) * adaptation;\n return isSpeech;\n };\n}\n\ninterface SpeechChunkerOptions {\n maxSegmentMs: number;\n onChunk: (chunk: SpeechChunk) => void;\n startMs: number;\n}\n\nclass UtteranceChunker implements SpeechChunker {\n private chunk: OpenChunk | null = null;\n private consumedSamples = 0;\n private readonly isSpeech = createNoiseGate();\n private readonly maxWindows: number;\n private readonly options: SpeechChunkerOptions;\n private pending = new Float32Array(0);\n private preRoll: Float32Array[] = [];\n\n constructor(options: SpeechChunkerOptions) {\n this.options = options;\n this.maxWindows = Math.floor(options.maxSegmentMs / WINDOW_MS);\n }\n\n flush = (): void => {\n if (this.pending.length > 0) {\n this.processWindow(this.pending);\n this.pending = new Float32Array(0);\n }\n if (this.chunk) {\n this.emit(\n this.chunk,\n this.chunk.lastSpeechWindow + 1 + POST_ROLL_WINDOWS\n );\n }\n };\n\n push = (samples: Float32Array): void => {\n let buffer = concatenate([this.pending, samples]);\n while (buffer.length >= WINDOW_SAMPLES) {\n this.processWindow(buffer.slice(0, WINDOW_SAMPLES));\n buffer = buffer.subarray(WINDOW_SAMPLES);\n }\n this.pending = buffer.slice();\n };\n\n private emit(open: OpenChunk, keptWindows: number): void {\n this.chunk = null;\n this.preRoll = [];\n if (open.speechWindows * WINDOW_MS < MIN_SPEECH_MS) {\n return;\n }\n const samples = concatenate(open.windows.slice(0, keptWindows));\n const startMs =\n this.options.startMs + Math.round(open.startSample / SAMPLES_PER_MS);\n this.options.onChunk({\n endMs: startMs + Math.round(samples.length / SAMPLES_PER_MS),\n samples,\n startMs,\n });\n }\n\n private extend(open: OpenChunk, window: Float32Array, speech: boolean): void {\n open.windows.push(window);\n if (speech) {\n open.speechWindows += 1;\n open.silentWindows = 0;\n open.lastSpeechWindow = open.windows.length - 1;\n return;\n }\n open.silentWindows += 1;\n const ended =\n open.silentWindows * WINDOW_MS >= END_SILENCE_MS &&\n open.windows.length * WINDOW_MS >= MIN_CHUNK_MS_BEFORE_SILENCE_END;\n if (ended) {\n this.emit(open, open.lastSpeechWindow + 1 + POST_ROLL_WINDOWS);\n }\n }\n\n private open(window: Float32Array, windowStart: number): OpenChunk {\n const preRollSamples = this.preRoll.reduce(\n (total, part) => total + part.length,\n 0\n );\n return {\n lastSpeechWindow: this.preRoll.length,\n silentWindows: 0,\n speechWindows: 1,\n startSample: windowStart - preRollSamples,\n windows: [...this.preRoll, window],\n };\n }\n\n private processWindow(window: Float32Array): void {\n const windowStart = this.consumedSamples;\n this.consumedSamples += window.length;\n const speech = this.isSpeech(rootMeanSquare(window));\n if (this.chunk) {\n this.extend(this.chunk, window, speech);\n } else if (speech) {\n this.chunk = this.open(window, windowStart);\n } else {\n this.preRoll = [...this.preRoll, window].slice(-PRE_ROLL_WINDOWS);\n }\n if (this.chunk && this.chunk.windows.length + 1 > this.maxWindows) {\n this.emit(this.chunk, this.chunk.windows.length);\n }\n }\n}\n\n// Input is 16 kHz mono; timestamps are on the session clock.\nexport function createSpeechChunker(\n options: SpeechChunkerOptions\n): SpeechChunker {\n return new UtteranceChunker(options);\n}\n","import { SPEECH_SAMPLE_RATE } from \"./speech-chunker\";\n\nconst WAV_HEADER_BYTES = 44;\nconst BYTES_PER_SAMPLE = 2;\nconst MAX_POSITIVE_SAMPLE = 0x7f_ff;\nconst MAX_NEGATIVE_SAMPLE = 0x80_00;\n\nfunction writeText(view: DataView, offset: number, text: string): void {\n for (let index = 0; index < text.length; index += 1) {\n view.setUint8(offset + index, text.charCodeAt(index));\n }\n}\n\n/** 16-bit mono PCM WAV, the format the transcription endpoint expects. */\nexport function encodeWav(\n samples: Float32Array,\n sampleRate: number\n): ArrayBuffer {\n const dataBytes = samples.length * BYTES_PER_SAMPLE;\n const buffer = new ArrayBuffer(WAV_HEADER_BYTES + dataBytes);\n const view = new DataView(buffer);\n writeText(view, 0, \"RIFF\");\n view.setUint32(4, 36 + dataBytes, true);\n writeText(view, 8, \"WAVEfmt \");\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, 1, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, sampleRate * BYTES_PER_SAMPLE, true);\n view.setUint16(32, BYTES_PER_SAMPLE, true);\n view.setUint16(34, 16, true);\n writeText(view, 36, \"data\");\n view.setUint32(40, dataBytes, true);\n samples.forEach((sample, index) => {\n const clamped = Math.max(-1, Math.min(1, sample));\n const scale = clamped < 0 ? MAX_NEGATIVE_SAMPLE : MAX_POSITIVE_SAMPLE;\n view.setInt16(\n WAV_HEADER_BYTES + index * BYTES_PER_SAMPLE,\n Math.round(clamped * scale),\n true\n );\n });\n return buffer;\n}\n\nexport function maxWavDurationMs(maxBytes: number): number {\n const bytesPerMs = (SPEECH_SAMPLE_RATE / 1000) * BYTES_PER_SAMPLE;\n return Math.floor((maxBytes - WAV_HEADER_BYTES) / bytesPerMs);\n}\n\nexport function createDownsampler(\n inputRate: number\n): (frame: Float32Array) => Float32Array {\n if (inputRate < SPEECH_SAMPLE_RATE) {\n throw new Error(`Cannot record speech from a ${inputRate} Hz microphone.`);\n }\n const ratio = inputRate / SPEECH_SAMPLE_RATE;\n let carry = new Float32Array(0);\n let offset = 0;\n\n return (frame) => {\n const input = new Float32Array(carry.length + frame.length);\n input.set(carry);\n input.set(frame, carry.length);\n const count = Math.floor((input.length - offset) / ratio);\n const output = new Float32Array(count);\n for (let index = 0; index < count; index += 1) {\n const from = Math.floor(offset + index * ratio);\n const to = Math.max(from + 1, Math.floor(offset + (index + 1) * ratio));\n let sum = 0;\n for (let position = from; position < to; position += 1) {\n sum += input[position] ?? 0;\n }\n output[index] = sum / (to - from);\n }\n const consumed = offset + count * ratio;\n const kept = Math.floor(consumed);\n carry = input.slice(kept);\n offset = consumed - kept;\n return output;\n };\n}\n","import {\n buildSelector,\n describeElement,\n getElementRect,\n} from \"../../feedback/core/element-selector\";\nimport { clip } from \"../../feedback/core/page-context\";\nimport { inspectReactElement } from \"../../feedback/core/react-source\";\nimport { REDACT_ATTRIBUTE, redactUrl } from \"../../feedback/core/redact\";\nimport type { ElementRef, Frame } from \"../protocol\";\n\nexport const SESSION_MASK_SELECTORS = [\n `[${REDACT_ATTRIBUTE}]`,\n \"input[type=password]\",\n \"[autocomplete^=cc-]\",\n];\n\nexport const MAX_LABEL_CHARS = 160;\nconst MAX_SELECTOR_CHARS = 600;\nconst MAX_URL_CHARS = 2000;\nconst MAX_PAGE_TITLE_CHARS = 300;\nconst NAMING_ATTRIBUTES = [\"aria-label\", \"placeholder\", \"title\", \"name\"];\n\nconst INTERACTIVE_SELECTOR = [\n \"a[href]\",\n \"button\",\n \"input\",\n \"select\",\n \"textarea\",\n \"summary\",\n \"label\",\n \"[contenteditable]:not([contenteditable=false])\",\n \"[role=button]\",\n \"[role=checkbox]\",\n \"[role=combobox]\",\n \"[role=link]\",\n \"[role=menuitem]\",\n \"[role=option]\",\n \"[role=radio]\",\n \"[role=switch]\",\n \"[role=tab]\",\n \"[tabindex]:not([tabindex='-1'])\",\n].join(\", \");\n\nconst VALUE_HOLDER_SELECTOR =\n \"input, textarea, select, [contenteditable]:not([contenteditable=false])\";\n\nconst IMPLICIT_ROLES: Record<string, string> = {\n article: \"article\",\n aside: \"complementary\",\n button: \"button\",\n dialog: \"dialog\",\n footer: \"contentinfo\",\n form: \"form\",\n h1: \"heading\",\n h2: \"heading\",\n h3: \"heading\",\n h4: \"heading\",\n h5: \"heading\",\n h6: \"heading\",\n header: \"banner\",\n img: \"img\",\n li: \"listitem\",\n main: \"main\",\n nav: \"navigation\",\n ol: \"list\",\n option: \"option\",\n select: \"combobox\",\n summary: \"button\",\n table: \"table\",\n textarea: \"textbox\",\n ul: \"list\",\n};\n\nconst INPUT_ROLES: Record<string, string> = {\n button: \"button\",\n checkbox: \"checkbox\",\n radio: \"radio\",\n range: \"slider\",\n reset: \"button\",\n search: \"searchbox\",\n submit: \"button\",\n};\n\nexport function interactiveTarget(target: Element): Element {\n return target.closest(INTERACTIVE_SELECTOR) ?? target;\n}\n\nfunction elementRole(element: Element): string | null {\n const explicit = element.getAttribute(\"role\");\n if (explicit) {\n return explicit;\n }\n if (element instanceof HTMLInputElement) {\n return INPUT_ROLES[element.type] ?? \"textbox\";\n }\n if (element instanceof HTMLAnchorElement) {\n return element.hasAttribute(\"href\") ? \"link\" : null;\n }\n return IMPLICIT_ROLES[element.localName] ?? null;\n}\n\n/** Fields are named by their attributes only: their text is what the user typed. */\nfunction elementLabel(element: Element): string {\n if (!element.matches(VALUE_HOLDER_SELECTOR)) {\n return clip(describeElement(element), MAX_LABEL_CHARS);\n }\n const name = NAMING_ATTRIBUTES.map((attribute) =>\n element.getAttribute(attribute)?.trim()\n ).find(Boolean);\n return clip(\n name ? `${element.localName} \"${name}\"` : element.localName,\n MAX_LABEL_CHARS\n );\n}\n\nexport function describeElementRef(\n element: Element,\n options: { includeSource: boolean }\n): ElementRef {\n const { componentStack, sourceLocation } = inspectReactElement(element);\n return {\n component: componentStack[0] ?? null,\n label: elementLabel(element),\n rect: getElementRect(element),\n role: elementRole(element),\n selector: clip(buildSelector(element), MAX_SELECTOR_CHARS),\n source: options.includeSource ? (sourceLocation ?? null) : null,\n };\n}\n\nexport function captureFrame(): Frame {\n return {\n devicePixelRatio: window.devicePixelRatio,\n scrollX: Math.round(window.scrollX),\n scrollY: Math.round(window.scrollY),\n title: document.title ? clip(document.title, MAX_PAGE_TITLE_CHARS) : null,\n url: clip(redactUrl(window.location.href), MAX_URL_CHARS),\n viewportHeight: window.innerHeight,\n viewportWidth: window.innerWidth,\n };\n}\n","import { startsInWidget } from \"../../../feedback/ui/widget-events\";\nimport type { SessionEvent } from \"../../protocol\";\nimport {\n captureFrame,\n describeElementRef,\n interactiveTarget,\n} from \"../element-ref\";\n\nconst MIN_DWELL_MS = 700;\nconst POINTER_SAMPLE_INTERVAL_MS = 100;\nconst SETTLE_DEBOUNCE_MS = 400;\n\nexport interface InteractionRecorderOptions {\n atMs: () => number;\n includeSource: boolean;\n onEvent: (event: SessionEvent) => void;\n}\n\nexport interface InteractionRecorder {\n stop: () => void;\n}\n\nfunction eventElement(event: Event): Element | null {\n if (startsInWidget(event)) {\n return null;\n }\n const [origin] = event.composedPath();\n if (!(origin instanceof Element)) {\n return null;\n }\n const element = interactiveTarget(origin);\n const isPageRoot =\n element === document.body || element === document.documentElement;\n return isPageRoot ? null : element;\n}\n\ntype DwellEvent = Extract<SessionEvent, { kind: \"dwell\" }>;\n\nfunction pointerOf(event: MouseEvent): { x: number; y: number } {\n return { x: Math.round(event.clientX), y: Math.round(event.clientY) };\n}\n\nfunction isPhysicalPointerClick(event: Event): event is MouseEvent {\n return event instanceof MouseEvent && event.detail > 0;\n}\n\nfunction debounced(signal: AbortSignal, run: () => void): () => void {\n let settleTimer: number | undefined;\n signal.addEventListener(\"abort\", () => window.clearTimeout(settleTimer));\n return () => {\n window.clearTimeout(settleTimer);\n settleTimer = window.setTimeout(run, SETTLE_DEBOUNCE_MS);\n };\n}\n\nfunction recordClick(options: InteractionRecorderOptions) {\n return (event: Event) => {\n const element = eventElement(event);\n if (element) {\n options.onEvent({\n atMs: options.atMs(),\n element: describeElementRef(element, options),\n frame: captureFrame(),\n kind: \"click\",\n pointer: isPhysicalPointerClick(event) ? pointerOf(event) : null,\n });\n }\n };\n}\n\nfunction watchDwell(options: InteractionRecorderOptions, signal: AbortSignal) {\n let hovered: Element | null = null;\n let lastSampleAt = Number.NEGATIVE_INFINITY;\n let entered: Omit<DwellEvent, \"durationMs\"> | null = null;\n\n const settle = () => {\n if (!entered) {\n return;\n }\n const durationMs = options.atMs() - entered.atMs;\n if (durationMs >= MIN_DWELL_MS) {\n options.onEvent({ ...entered, durationMs });\n }\n entered = null;\n };\n signal.addEventListener(\"abort\", settle);\n\n const onPointerMove = (event: Event) => {\n if (!(event instanceof MouseEvent)) {\n return;\n }\n const now = Date.now();\n if (now - lastSampleAt < POINTER_SAMPLE_INTERVAL_MS) {\n return;\n }\n lastSampleAt = now;\n const element = eventElement(event);\n if (element === hovered) {\n return;\n }\n settle();\n hovered = element;\n if (element) {\n entered = {\n atMs: options.atMs(),\n element: describeElementRef(element, options),\n frame: captureFrame(),\n kind: \"dwell\",\n pointer: pointerOf(event),\n };\n }\n };\n\n const onPointerLeaveWindow = (event: Event) => {\n if (event instanceof MouseEvent && event.relatedTarget === null) {\n settle();\n hovered = null;\n }\n };\n\n return { onPointerLeaveWindow, onPointerMove };\n}\n\nexport function startInteractionRecorder(\n options: InteractionRecorderOptions\n): InteractionRecorder {\n const controller = new AbortController();\n const { signal } = controller;\n const listen = { capture: true, passive: true, signal };\n const recordScroll = debounced(signal, () =>\n options.onEvent({\n atMs: options.atMs(),\n kind: \"scroll\",\n scrollX: Math.round(window.scrollX),\n scrollY: Math.round(window.scrollY),\n })\n );\n const recordViewport = debounced(signal, () =>\n options.onEvent({\n atMs: options.atMs(),\n devicePixelRatio: window.devicePixelRatio,\n kind: \"viewport\",\n viewportHeight: window.innerHeight,\n viewportWidth: window.innerWidth,\n })\n );\n\n const dwell = watchDwell(options, signal);\n document.addEventListener(\"click\", recordClick(options), listen);\n document.addEventListener(\"pointermove\", dwell.onPointerMove, listen);\n document.addEventListener(\"pointerout\", dwell.onPointerLeaveWindow, listen);\n window.addEventListener(\"scroll\", recordScroll, listen);\n window.addEventListener(\"resize\", recordViewport, listen);\n return { stop: () => controller.abort() };\n}\n","import type { Frame } from \"../../protocol\";\nimport { captureFrame } from \"../element-ref\";\n\nconst URL_POLL_INTERVAL_MS = 500;\n\nexport interface NavigationWatch {\n stop: () => void;\n}\n\n/** SPA routers change the URL without an event, so the URL is also polled. */\nexport function startNavigationWatch(options: {\n onNavigate: (frame: Frame) => void;\n}): NavigationWatch {\n const controller = new AbortController();\n let knownHref = window.location.href;\n const check = () => {\n if (window.location.href === knownHref) {\n return;\n }\n knownHref = window.location.href;\n options.onNavigate(captureFrame());\n };\n const poll = window.setInterval(check, URL_POLL_INTERVAL_MS);\n window.addEventListener(\"popstate\", check, { signal: controller.signal });\n window.addEventListener(\"hashchange\", check, { signal: controller.signal });\n return {\n stop: () => {\n window.clearInterval(poll);\n controller.abort();\n },\n };\n}\n","import {\n MicrophoneError,\n type MicrophoneFailureKind,\n openMicrophone,\n} from \"../../capture/audio/microphone\";\nimport {\n createSpeechChunker,\n meterLevel,\n type SpeechChunk,\n type SpeechChunker,\n} from \"../../capture/audio/speech-chunker\";\nimport { createDownsampler } from \"../../capture/audio/wav\";\nimport {\n type InteractionRecorder,\n startInteractionRecorder,\n} from \"../../capture/page/interaction-recorder\";\nimport {\n type NavigationWatch,\n startNavigationWatch,\n} from \"../../capture/page/navigation-watch\";\nimport type { Frame, SessionEvent } from \"../../protocol\";\n\nexport interface VoiceCapture {\n attach: (options: {\n maxSegmentMs: number;\n onChunk: (chunk: SpeechChunk) => void;\n onLevel: (level: number) => void;\n startMs: number;\n }) => void;\n stop: () => void;\n}\n\nasync function openVoiceCapture(): Promise<VoiceCapture> {\n let receive: ((frame: Float32Array) => void) | null = null;\n let chunker: SpeechChunker | null = null;\n const microphone = await openMicrophone({\n onFrame: (frame) => receive?.(frame),\n });\n let downsample: (frame: Float32Array) => Float32Array;\n try {\n downsample = createDownsampler(microphone.sampleRate);\n } catch {\n microphone.stop();\n throw new MicrophoneError(\"mic_unavailable\");\n }\n return {\n attach: (options) => {\n const speech = createSpeechChunker(options);\n chunker = speech;\n receive = (frame) => {\n const samples = downsample(frame);\n options.onLevel(meterLevel(samples));\n speech.push(samples);\n };\n },\n stop: () => {\n receive = null;\n microphone.stop();\n chunker?.flush();\n chunker = null;\n },\n };\n}\n\nexport type VoiceOpening =\n | { failure: { kind: MicrophoneFailureKind; message: string }; voice: null }\n | { failure: null; voice: VoiceCapture };\n\nexport async function openVoice(): Promise<VoiceOpening> {\n try {\n return { failure: null, voice: await openVoiceCapture() };\n } catch (error) {\n const refusal =\n error instanceof MicrophoneError\n ? error\n : new MicrophoneError(\"mic_unavailable\");\n return {\n failure: { kind: refusal.kind, message: refusal.message },\n voice: null,\n };\n }\n}\n\nexport interface CollectionRun {\n stop: () => void;\n stopEvents: () => void;\n stopVoice: () => void;\n}\n\nexport interface CollectionRunOptions {\n atMs: () => number;\n collectEvents: boolean;\n includeSource: boolean;\n maxSegmentMs: number;\n onChunk: (chunk: SpeechChunk) => void;\n onEvent: (event: SessionEvent) => void;\n onLevel: (level: number) => void;\n onNavigate: (frame: Frame) => void;\n voice: VoiceCapture | null;\n}\n\nexport function startCollectionRun(\n options: CollectionRunOptions\n): CollectionRun {\n let { voice } = options;\n voice?.attach({\n maxSegmentMs: options.maxSegmentMs,\n onChunk: options.onChunk,\n onLevel: options.onLevel,\n startMs: options.atMs(),\n });\n let interactions: InteractionRecorder | null = options.collectEvents\n ? startInteractionRecorder(options)\n : null;\n const navigation: NavigationWatch = startNavigationWatch(options);\n const stopVoice = () => {\n const stopping = voice;\n voice = null;\n stopping?.stop();\n options.onLevel(0);\n };\n const stopEvents = () => {\n interactions?.stop();\n interactions = null;\n };\n return {\n stop: () => {\n stopVoice();\n stopEvents();\n navigation.stop();\n },\n stopEvents,\n stopVoice,\n };\n}\n","const VALUE_IS_PAGE_CONTENT: Record<string, boolean> = {\n button: true,\n checkbox: true,\n color: true,\n file: true,\n hidden: true,\n image: true,\n radio: true,\n range: true,\n reset: true,\n submit: true,\n};\n\nexport function blankFieldValues(root: Element): void {\n for (const input of root.querySelectorAll(\"input\")) {\n if (!VALUE_IS_PAGE_CONTENT[input.type]) {\n input.value = \"\";\n input.removeAttribute(\"value\");\n }\n }\n for (const textarea of root.querySelectorAll(\"textarea\")) {\n textarea.value = \"\";\n textarea.textContent = \"\";\n }\n for (const select of root.querySelectorAll(\"select\")) {\n select.replaceChildren();\n }\n}\n","import {\n captureViewport,\n releaseCapture,\n} from \"../../../feedback/core/capture\";\nimport type {\n ElementRef,\n EvidenceTrigger,\n Frame,\n SessionLimits,\n} from \"../../protocol\";\nimport { blankFieldValues } from \"../blank-fields\";\nimport {\n captureFrame,\n describeElementRef,\n SESSION_MASK_SELECTORS,\n} from \"../element-ref\";\n\nconst NAVIGATION_SETTLE_MS = 1500;\nconst CAPTURE_FAILED = \"The page could not be captured.\";\nconst CAPTURE_TOO_LARGE = \"The screenshot was larger than the upload limit.\";\nconst STOPPED_BEFORE_CAPTURE =\n \"Recording stopped before the screenshot was taken.\";\n\nexport interface CapturedEvidence {\n atMs: number;\n clientKey: string;\n element: ElementRef | null;\n frame: Frame;\n image: { blob: Blob; height: number; width: number } | null;\n missingReason: string | null;\n note: string | null;\n trigger: EvidenceTrigger;\n}\n\nexport interface EvidenceRequest {\n element?: Element | null;\n note?: string | null;\n trigger: \"mark\" | \"select\" | \"start\";\n}\n\nexport interface EvidenceScheduler {\n cancelPending: () => void;\n capture: (request: EvidenceRequest) => string | null;\n navigated: () => void;\n}\n\nexport interface EvidenceSchedulerOptions {\n atMs: () => number;\n includeSource: boolean;\n limits: Pick<\n SessionLimits,\n \"maxEvidence\" | \"maxImageBytes\" | \"minAutoCaptureIntervalMs\"\n >;\n onEvidence: (evidence: CapturedEvidence) => void;\n}\n\ntype EvidenceBase = Omit<CapturedEvidence, \"image\" | \"missingReason\">;\n\nconst stoppedBeforeCapture = (base: EvidenceBase): CapturedEvidence => ({\n ...base,\n image: null,\n missingReason: STOPPED_BEFORE_CAPTURE,\n});\n\nasync function shoot(\n base: EvidenceBase,\n maxImageBytes: number\n): Promise<CapturedEvidence> {\n const image = await captureViewport({\n excludeSelectors: SESSION_MASK_SELECTORS,\n prepareClone: blankFieldValues,\n });\n releaseCapture(image);\n if (!image) {\n return { ...base, image: null, missingReason: CAPTURE_FAILED };\n }\n if (image.blob.size > maxImageBytes) {\n return { ...base, image: null, missingReason: CAPTURE_TOO_LARGE };\n }\n const { blob, height, width } = image;\n return { ...base, image: { blob, height, width }, missingReason: null };\n}\n\nexport function createEvidenceScheduler(\n options: EvidenceSchedulerOptions\n): EvidenceScheduler {\n const { limits } = options;\n let captured = 0;\n let lastCaptureAtMs = Number.NEGATIVE_INFINITY;\n let navigationTimer: number | undefined;\n let previousCapture = Promise.resolve();\n let collectionRun = 0;\n\n const take = (\n trigger: EvidenceTrigger,\n request: Omit<EvidenceRequest, \"trigger\">\n ) => {\n if (captured >= limits.maxEvidence) {\n return null;\n }\n captured += 1;\n const atMs = options.atMs();\n lastCaptureAtMs = atMs;\n const clientKey = crypto.randomUUID();\n const base = {\n atMs,\n clientKey,\n element: request.element\n ? describeElementRef(request.element, options)\n : null,\n frame: captureFrame(),\n note: request.note ?? null,\n trigger,\n };\n const takenInRun = collectionRun;\n const captureUnlessStopped = async () => {\n if (takenInRun !== collectionRun) {\n return stoppedBeforeCapture(base);\n }\n const evidence = await shoot(base, limits.maxImageBytes);\n return takenInRun === collectionRun\n ? evidence\n : stoppedBeforeCapture(base);\n };\n previousCapture = previousCapture\n .then(captureUnlessStopped)\n .then(options.onEvidence);\n return clientKey;\n };\n\n return {\n cancelPending: () => {\n window.clearTimeout(navigationTimer);\n collectionRun += 1;\n },\n capture: (request) => take(request.trigger, request),\n navigated: () => {\n window.clearTimeout(navigationTimer);\n navigationTimer = window.setTimeout(() => {\n const sinceLastMs = options.atMs() - lastCaptureAtMs;\n if (sinceLastMs >= limits.minAutoCaptureIntervalMs) {\n take(\"navigation\", {});\n }\n }, NAVIGATION_SETTLE_MS);\n },\n };\n}\n","import type { SessionEvent } from \"../../protocol\";\n\nconst FLUSH_INTERVAL_MS = 5000;\nconst NOTE_WAIT_MS = 60_000;\n\ntype MarkEvent = Extract<SessionEvent, { kind: \"mark\" }>;\n\nexport interface EventBatcher {\n add: (event: SessionEvent) => void;\n annotate: (key: string, note: string | null) => void;\n flush: () => void;\n flushAll: () => void;\n hold: (key: string, event: MarkEvent) => void;\n stop: () => void;\n}\n\ninterface EventBatcherOptions {\n maxBatchEvents: number;\n onBatch: (events: SessionEvent[]) => void;\n}\n\n/** A mark waits for its note so it is sent once, complete. */\nclass TimedEventBatcher implements EventBatcher {\n private buffered: SessionEvent[] = [];\n private readonly held = new Map<\n string,\n { event: MarkEvent; timer: number }\n >();\n private readonly interval: number;\n private readonly options: EventBatcherOptions;\n\n constructor(options: EventBatcherOptions) {\n this.options = options;\n this.interval = window.setInterval(this.flush, FLUSH_INTERVAL_MS);\n }\n\n add = (event: SessionEvent): void => {\n this.buffered.push(event);\n if (this.buffered.length >= this.options.maxBatchEvents) {\n this.flush();\n }\n };\n\n annotate = (key: string, note: string | null): void => {\n const entry = this.held.get(key);\n if (!entry) {\n return;\n }\n this.held.delete(key);\n window.clearTimeout(entry.timer);\n this.add({ ...entry.event, note });\n };\n\n flush = (): void => {\n if (this.buffered.length === 0) {\n return;\n }\n const batch = this.buffered;\n this.buffered = [];\n this.options.onBatch(batch);\n };\n\n flushAll = (): void => {\n this.releaseAll();\n this.flush();\n };\n\n hold = (key: string, event: MarkEvent): void => {\n this.releaseAll();\n const timer = window.setTimeout(\n () => this.annotate(key, null),\n NOTE_WAIT_MS\n );\n this.held.set(key, { event, timer });\n };\n\n stop = (): void => {\n window.clearInterval(this.interval);\n for (const entry of this.held.values()) {\n window.clearTimeout(entry.timer);\n }\n this.held.clear();\n };\n\n private releaseAll(): void {\n for (const key of [...this.held.keys()]) {\n this.annotate(key, null);\n }\n }\n}\n\nexport function createEventBatcher(options: EventBatcherOptions): EventBatcher {\n return new TimedEventBatcher(options);\n}\n","import {\n SPEECH_SAMPLE_RATE,\n type SpeechChunk,\n} from \"../../capture/audio/speech-chunker\";\nimport { encodeWav } from \"../../capture/audio/wav\";\nimport { captureFrame } from \"../../capture/element-ref\";\nimport type { CapturedEvidence } from \"../../capture/page/evidence-scheduler\";\nimport type { OutboxPayload, StoredDraft } from \"../../local/session-store\";\nimport type { SessionGap, SessionSurface } from \"../../protocol\";\n\nexport function newSessionDraft(options: {\n accountKey: string;\n surface: SessionSurface;\n title: string;\n}): StoredDraft {\n const startedAt = Date.now();\n return {\n ...options,\n gaps: [],\n lastActiveAt: startedAt,\n sessionId: null,\n sessionKey: crypto.randomUUID(),\n startedAt,\n state: \"recording\",\n };\n}\n\n/** A draft left open by a reload stopped at its last save, not when it is resumed. */\nexport function interruptedGap(draft: StoredDraft): SessionGap | null {\n if (draft.gaps.some((gap) => gap.endMs === null)) {\n return null;\n }\n const startMs = Math.max(0, draft.lastActiveAt - draft.startedAt);\n return { endMs: null, reason: \"interrupted\", startMs };\n}\n\nexport function startPayload(draft: StoredDraft): OutboxPayload {\n const page = captureFrame();\n return {\n body: {\n clientKey: draft.sessionKey,\n page: { title: page.title ?? \"\", url: page.url },\n startedAt: draft.startedAt,\n surface: draft.surface,\n ...(draft.title ? { title: draft.title } : {}),\n },\n kind: \"start\",\n };\n}\n\nexport function evidencePayload(captured: CapturedEvidence): OutboxPayload {\n const { element, image, missingReason, note } = captured;\n return {\n evidence: {\n atMs: captured.atMs,\n clientKey: captured.clientKey,\n element: element ?? undefined,\n frame: captured.frame,\n missingReason: missingReason ?? undefined,\n note: note ?? undefined,\n trigger: captured.trigger,\n },\n image: image ? { ...image, storageId: null } : null,\n kind: \"evidence\",\n };\n}\n\nexport function voicePayload(chunk: SpeechChunk): OutboxPayload {\n return {\n audio: new Blob([encodeWav(chunk.samples, SPEECH_SAMPLE_RATE)], {\n type: \"audio/wav\",\n }),\n clientKey: crypto.randomUUID(),\n endMs: chunk.endMs,\n kind: \"voice\",\n startMs: chunk.startMs,\n storageId: null,\n };\n}\n","import type {\n SessionEvent,\n SessionLimitKind,\n SessionLimits,\n} from \"../../protocol\";\n\nexport class SessionQuota {\n private eventCount = 0;\n private readonly limits: SessionLimits;\n private segmentCount = 0;\n readonly stopped = new Set<SessionLimitKind>();\n\n constructor(limits: SessionLimits) {\n this.limits = limits;\n }\n\n acceptEvents(batch: SessionEvent[]): SessionEvent[] {\n const room = Math.max(0, this.limits.maxEvents - this.eventCount);\n const accepted = batch.slice(0, room);\n this.eventCount += accepted.length;\n return accepted;\n }\n\n acceptSegment(): boolean {\n if (this.segmentCount >= this.limits.maxSegments) {\n return false;\n }\n this.segmentCount += 1;\n return true;\n }\n\n eventsFull(): boolean {\n return this.eventCount >= this.limits.maxEvents;\n }\n\n segmentsFull(): boolean {\n return this.segmentCount >= this.limits.maxSegments;\n }\n}\n","import type { SpeechChunk } from \"../../capture/audio/speech-chunker\";\nimport { maxWavDurationMs } from \"../../capture/audio/wav\";\nimport { captureFrame, describeElementRef } from \"../../capture/element-ref\";\nimport {\n createEvidenceScheduler,\n type EvidenceRequest,\n type EvidenceScheduler,\n} from \"../../capture/page/evidence-scheduler\";\nimport type { SessionClock } from \"../../capture/session-clock\";\nimport type { AccountSessions } from \"../../local/local-sessions\";\nimport type { OutboxPayload, StoredDraft } from \"../../local/session-store\";\nimport type {\n SessionEvent,\n SessionGapReason,\n SessionLimitKind,\n SessionLimits,\n} from \"../../protocol\";\nimport {\n type CollectionRun,\n startCollectionRun,\n type VoiceCapture,\n} from \"./collection-run\";\nimport { createEventBatcher, type EventBatcher } from \"./event-batcher\";\nimport { evidencePayload, voicePayload } from \"./session-payloads\";\nimport { SessionQuota } from \"./session-quota\";\n\nconst LARGEST_EVENT_BATCH = 100;\nconst TICK_MS = 1000;\nconst DRAFT_SAVE_INTERVAL_MS = 5000;\n\nexport interface LiveSessionHooks {\n onHidden: () => void;\n onLevel: (level: number) => void;\n onPageHide: () => void;\n onStorageFailure: (error: unknown) => void;\n onTick: () => void;\n reachLimit: (limit: SessionLimitKind) => void;\n}\n\nexport interface LiveSessionOptions {\n account: Pick<AccountSessions, \"outbox\" | \"store\">;\n clock: SessionClock;\n hooks: LiveSessionHooks;\n includeSource: boolean;\n limits: SessionLimits;\n sessionKey: string;\n}\n\nexport class LiveSession {\n readonly clock: SessionClock;\n readonly sessionKey: string;\n private readonly events: EventBatcher;\n private readonly evidence: EvidenceScheduler;\n private readonly hooks: LiveSessionHooks;\n private lastSavedAt = Date.now();\n private readonly options: LiveSessionOptions;\n private readonly quota: SessionQuota;\n private run: CollectionRun | null = null;\n private stopListening: AbortController | null = null;\n private tick: number | undefined;\n\n constructor(options: LiveSessionOptions) {\n this.options = options;\n this.clock = options.clock;\n this.hooks = options.hooks;\n this.sessionKey = options.sessionKey;\n this.quota = new SessionQuota(options.limits);\n this.events = createEventBatcher({\n maxBatchEvents: Math.min(\n LARGEST_EVENT_BATCH,\n options.limits.maxEventsPerBatch\n ),\n onBatch: this.sendBatch,\n });\n this.evidence = createEvidenceScheduler({\n atMs: options.clock.atMs,\n includeSource: options.includeSource,\n limits: options.limits,\n onEvidence: (captured) => this.persist(evidencePayload(captured)),\n });\n }\n\n annotate(key: string, note: string | null): void {\n this.events.annotate(key, note);\n }\n\n captureEvidence(request: EvidenceRequest): string | null {\n const clientKey = this.quota.stopped.has(\"evidence\")\n ? null\n : this.evidence.capture(request);\n if (clientKey === null) {\n this.hooks.reachLimit(\"evidence\");\n }\n return clientKey;\n }\n\n checkpoint(): void {\n if (Date.now() - this.lastSavedAt >= DRAFT_SAVE_INTERVAL_MS) {\n this.saveDraft();\n }\n }\n\n async end(): Promise<void> {\n this.stop();\n const { outbox, store } = this.options.account;\n const atMs = this.clock.atMs();\n await outbox.enqueue(this.sessionKey, {\n action: \"end\",\n atMs,\n kind: \"collection\",\n });\n await outbox.enqueue(this.sessionKey, { kind: \"analyze\" });\n await store.patchDraft(this.sessionKey, this.draftPatch(\"ended\"));\n }\n\n hasVoiceRoom(): boolean {\n return !this.quota.stopped.has(\"segments\");\n }\n\n mark(): { atMs: number; key: string } {\n const key = crypto.randomUUID();\n const atMs = this.clock.atMs();\n this.events.hold(key, {\n atMs,\n element: null,\n evidenceClientKey: this.captureEvidence({ trigger: \"mark\" }),\n frame: captureFrame(),\n kind: \"mark\",\n note: null,\n });\n return { atMs, key };\n }\n\n pause(reason: SessionGapReason): void {\n this.stopCollecting();\n if (!this.clock.isPaused()) {\n const atMs = this.clock.pause(reason);\n this.persist({ action: \"pause\", atMs, kind: \"collection\", reason });\n }\n this.saveDraft(reason === \"interrupted\" ? \"interrupted\" : \"paused\");\n }\n\n persist(payload: OutboxPayload): void {\n this.options.account.outbox\n .enqueue(this.sessionKey, payload)\n .catch(this.hooks.onStorageFailure);\n }\n\n resume(voice: VoiceCapture): void {\n const atMs = this.clock.resume();\n this.persist({ action: \"resume\", atMs, kind: \"collection\" });\n this.saveDraft(\"recording\");\n this.startCollecting(voice);\n }\n\n select(element: Element, note: string | null): void {\n this.events.add({\n atMs: this.clock.atMs(),\n element: describeElementRef(element, {\n includeSource: this.options.includeSource,\n }),\n evidenceClientKey: this.captureEvidence({\n element,\n note,\n trigger: \"select\",\n }),\n frame: captureFrame(),\n kind: \"select\",\n note,\n });\n }\n\n startCollecting(voice: VoiceCapture): void {\n const { limits } = this.options;\n const hasVoiceRoom = this.hasVoiceRoom();\n if (!hasVoiceRoom) {\n voice.stop();\n }\n this.run = startCollectionRun({\n atMs: this.clock.atMs,\n collectEvents: !this.quota.stopped.has(\"events\"),\n includeSource: this.options.includeSource,\n maxSegmentMs: Math.min(\n limits.maxSegmentMs,\n maxWavDurationMs(limits.maxSegmentBytes)\n ),\n onChunk: this.recordChunk,\n onEvent: (event) => this.events.add(event),\n onLevel: this.hooks.onLevel,\n onNavigate: (frame) => {\n this.events.add({ atMs: this.clock.atMs(), frame, kind: \"navigation\" });\n this.evidence.navigated();\n },\n voice: hasVoiceRoom ? voice : null,\n });\n this.listen();\n this.tick = window.setInterval(this.hooks.onTick, TICK_MS);\n }\n\n stop(): void {\n this.stopCollecting();\n this.events.stop();\n }\n\n stopCollecting(): void {\n this.run?.stop();\n this.run = null;\n this.stopListening?.abort();\n this.stopListening = null;\n this.evidence.cancelPending();\n window.clearInterval(this.tick);\n this.events.flushAll();\n }\n\n stopKind(limit: SessionLimitKind): void {\n this.quota.stopped.add(limit);\n if (limit === \"segments\") {\n this.run?.stopVoice();\n }\n if (limit === \"events\") {\n this.run?.stopEvents();\n }\n }\n\n private draftPatch(state?: StoredDraft[\"state\"]) {\n this.lastSavedAt = Date.now();\n return {\n ...(state ? { state } : {}),\n gaps: this.clock.gaps(),\n lastActiveAt: this.lastSavedAt,\n };\n }\n\n private listen(): void {\n this.stopListening = new AbortController();\n const listen = { signal: this.stopListening.signal };\n const onVisibility = () => {\n if (document.visibilityState === \"hidden\") {\n this.hooks.onHidden();\n }\n };\n document.addEventListener(\"visibilitychange\", onVisibility, listen);\n window.addEventListener(\"pagehide\", this.hooks.onPageHide, listen);\n }\n\n private readonly recordChunk = (chunk: SpeechChunk): void => {\n if (!this.quota.acceptSegment()) {\n return;\n }\n this.persist(voicePayload(chunk));\n if (this.quota.segmentsFull()) {\n this.hooks.reachLimit(\"segments\");\n }\n };\n\n private saveDraft(state?: StoredDraft[\"state\"]): void {\n this.options.account.store\n .patchDraft(this.sessionKey, this.draftPatch(state))\n .catch(this.hooks.onStorageFailure);\n }\n\n private readonly sendBatch = (batch: SessionEvent[]): void => {\n const accepted = this.quota.acceptEvents(batch);\n if (accepted.length > 0) {\n const clientKey = crypto.randomUUID();\n this.persist({ clientKey, events: accepted, kind: \"events\" });\n }\n if (this.quota.eventsFull()) {\n this.hooks.reachLimit(\"events\");\n }\n };\n}\n","import { clip } from \"../../feedback/core/page-context\";\nimport { describeStorageFailure } from \"../../storage/indexed-db\";\nimport { createSessionClock } from \"../capture/session-clock\";\nimport { type AccountSessions, localSessions } from \"../local/local-sessions\";\nimport type { OutboxIssue } from \"../local/outbox\";\nimport type { StoredDraft } from \"../local/session-store\";\nimport type { SessionGap, SessionLimitKind } from \"../protocol\";\nimport { openVoice, type VoiceCapture } from \"./live/collection-run\";\nimport { LiveSession } from \"./live/live-session\";\nimport {\n interruptedGap,\n newSessionDraft,\n startPayload,\n} from \"./live/session-payloads\";\nimport type {\n RecorderFailure,\n RecorderSnapshot,\n SessionRecorder,\n SessionRecorderOptions,\n} from \"./session-recorder\";\n\nconst MAX_NOTE_CHARS = 1000;\nconst MAX_TITLE_CHARS = 120;\nconst SESSION_GONE = \"This session no longer exists on Reflet.\";\n\nconst IDLE: RecorderSnapshot = {\n activeMs: 0,\n failure: null,\n lastMark: null,\n limitsReached: [],\n markCount: 0,\n nearLimit: false,\n pauseReason: null,\n phase: \"idle\",\n sessionId: null,\n sessionKey: null,\n startedAt: null,\n};\n\nfunction cleanText(text: string | undefined, maxChars: number): string | null {\n const trimmed = text?.trim() ?? \"\";\n return trimmed ? clip(trimmed, maxChars) : null;\n}\n\nexport class RecordingController implements SessionRecorder {\n private readonly account: AccountSessions;\n private readonly levelListeners = new Set<(level: number) => void>();\n private readonly listeners = new Set<() => void>();\n private live: LiveSession | null = null;\n private readonly options: SessionRecorderOptions;\n private releaseClaim: () => void = () => undefined;\n private snapshot: RecorderSnapshot = IDLE;\n private readonly stopIssues: () => void;\n private readonly stopSessionIds: () => void;\n\n constructor(options: SessionRecorderOptions) {\n this.options = options;\n this.account = localSessions.connect({\n accountKey: options.account.key,\n api: options.api,\n maxLocalBufferBytes: options.limits.maxLocalBufferBytes,\n });\n this.stopIssues = this.account.outbox.subscribeIssues(this.handleIssue);\n this.stopSessionIds = localSessions.subscribe(this.syncSessionId);\n }\n\n annotateMark(key: string, note: string): void {\n this.live?.annotate(key, cleanText(note, MAX_NOTE_CHARS));\n }\n\n dispose(): void {\n this.interrupt();\n this.stopIssues();\n this.stopSessionIds();\n }\n\n async finish(): Promise<{ sessionKey: string }> {\n const live = this.live;\n if (!live) {\n throw new Error(\"No session is being recorded.\");\n }\n const ending = live.end();\n this.publish({ phase: \"finishing\" });\n try {\n await ending;\n } catch {\n // The sync status reports the storage failure; the server closes sessions left open.\n }\n this.close(live, IDLE);\n return { sessionKey: live.sessionKey };\n }\n\n getSnapshot = (): RecorderSnapshot => this.snapshot;\n\n mark(): string {\n const lastMark = this.requireRecording().mark();\n this.publish({ lastMark, markCount: this.snapshot.markCount + 1 });\n return lastMark.key;\n }\n\n pause(reason: \"paused\" | \"hidden\" = \"paused\"): void {\n this.pauseFor(reason);\n }\n\n async resume(): Promise<void> {\n const live = this.live;\n const { pauseReason, phase } = this.snapshot;\n if (!live || phase !== \"paused\" || pauseReason === \"limit\") {\n return;\n }\n this.publish({ failure: null, phase: \"requesting\" });\n const opening = await openVoice();\n if (this.live !== live) {\n opening.voice?.stop();\n return;\n }\n if (opening.failure) {\n this.publish({ failure: opening.failure, phase: \"paused\" });\n return;\n }\n live.resume(opening.voice);\n this.publish({ pauseReason: null, phase: \"recording\" });\n }\n\n async resumeDraft(sessionKey: string): Promise<void> {\n const drafts = await this.account.store.readDrafts(\n this.options.account.key\n );\n const draft = drafts.find(\n (candidate) =>\n candidate.sessionKey === sessionKey && candidate.state !== \"ended\"\n );\n if (!draft || this.isBusy()) {\n return;\n }\n const voice = await this.requestVoice();\n if (!voice) {\n return;\n }\n const gap = interruptedGap(draft);\n const live = this.adopt(draft, gap ? [...draft.gaps, gap] : draft.gaps);\n if (gap) {\n const { reason, startMs: atMs } = gap;\n live.persist({ action: \"pause\", atMs, kind: \"collection\", reason });\n }\n live.resume(voice);\n this.publish({ phase: \"recording\" });\n }\n\n select(element: Element, note?: string): void {\n this.requireRecording().select(element, cleanText(note, MAX_NOTE_CHARS));\n }\n\n async start(options: { title?: string }): Promise<void> {\n if (this.isBusy()) {\n return;\n }\n const voice = await this.requestVoice();\n if (!voice) {\n return;\n }\n const draft = newSessionDraft({\n accountKey: this.options.account.key,\n surface: this.options.surface,\n title: cleanText(options.title, MAX_TITLE_CHARS) ?? \"\",\n });\n try {\n await this.account.store.writeDraft(draft);\n await this.account.outbox.enqueue(draft.sessionKey, startPayload(draft));\n } catch (error) {\n voice.stop();\n this.account.store.deleteDraft(draft.sessionKey).catch(() => undefined);\n const message = describeStorageFailure(error);\n this.publish({\n ...IDLE,\n failure: { kind: \"storage\", message },\n phase: \"failed\",\n });\n return;\n }\n const live = this.adopt(draft, []);\n live.startCollecting(voice);\n this.publish({ phase: \"recording\" });\n live.captureEvidence({ trigger: \"start\" });\n }\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n subscribeLevel(listener: (level: number) => void): () => void {\n this.levelListeners.add(listener);\n return () => this.levelListeners.delete(listener);\n }\n\n private adopt(draft: StoredDraft, gaps: SessionGap[]): LiveSession {\n const { sessionKey, startedAt } = draft;\n const clock = createSessionClock({ gaps, startedAt });\n const live = new LiveSession({\n account: this.account,\n clock,\n hooks: {\n onHidden: () => this.pauseFor(\"hidden\"),\n onLevel: (level) => this.emitLevel(level),\n onPageHide: () => this.interrupt(),\n onStorageFailure: (error) => this.failStorage(live, error),\n onTick: () => this.onTick(live),\n reachLimit: (limit) => this.reachLimit(live, limit),\n },\n includeSource: this.options.surface === \"devtools\",\n limits: this.options.limits,\n sessionKey,\n });\n this.live = live;\n this.releaseClaim = this.account.claim({\n halt: (failure) => this.halt(failure),\n sessionKey,\n });\n this.publish({\n ...IDLE,\n activeMs: clock.activeMs(),\n sessionId: draft.sessionId,\n sessionKey,\n startedAt,\n });\n return live;\n }\n\n private close(live: LiveSession, next: RecorderSnapshot): void {\n live.stop();\n if (this.live === live) {\n this.live = null;\n this.releaseClaim();\n }\n this.emitLevel(0);\n this.publish(next);\n this.account.refreshDrafts();\n }\n\n private emitLevel(level: number): void {\n for (const listener of this.levelListeners) {\n listener(level);\n }\n }\n\n private failStorage(live: LiveSession, error: unknown): void {\n if (this.live !== live || this.snapshot.phase === \"failed\") {\n return;\n }\n live.stopCollecting();\n const message = describeStorageFailure(error);\n this.publish({ failure: { kind: \"storage\", message }, phase: \"failed\" });\n }\n\n private halt(failure: RecorderFailure): void {\n if (this.live) {\n this.close(this.live, { ...IDLE, failure, phase: \"failed\" });\n }\n }\n\n private readonly handleIssue = (issue: OutboxIssue): void => {\n const live = this.live;\n if (issue.kind === \"auth\" || issue.sessionKey !== live?.sessionKey) {\n return;\n }\n if (issue.kind === \"sessionGone\") {\n this.halt({ kind: \"network\", message: SESSION_GONE });\n return;\n }\n this.reachLimit(live, issue.limit);\n };\n\n private interrupt(): void {\n const live = this.live;\n if (!live) {\n this.publish(IDLE);\n return;\n }\n live.pause(\"interrupted\");\n this.close(live, IDLE);\n }\n\n private isBusy(): boolean {\n return this.live !== null || this.snapshot.phase === \"requesting\";\n }\n\n private onTick(live: LiveSession): void {\n const { maxDurationMs, warnBeforeLimitMs } = this.options.limits;\n const activeMs = live.clock.activeMs();\n const nearLimit = activeMs >= maxDurationMs - warnBeforeLimitMs;\n this.publish({ activeMs, nearLimit });\n if (activeMs >= maxDurationMs) {\n this.reachLimit(live, \"duration\");\n return;\n }\n live.checkpoint();\n }\n\n private pauseFor(reason: \"paused\" | \"hidden\" | \"limit\"): void {\n const live = this.live;\n if (!live || this.snapshot.phase !== \"recording\") {\n return;\n }\n live.pause(reason);\n this.emitLevel(0);\n const activeMs = live.clock.activeMs();\n this.publish({ activeMs, pauseReason: reason, phase: \"paused\" });\n }\n\n private publish(next: Partial<RecorderSnapshot>): void {\n this.snapshot = { ...this.snapshot, ...next };\n for (const listener of this.listeners) {\n listener();\n }\n }\n\n private reachLimit(live: LiveSession, limit: SessionLimitKind): void {\n if (this.live !== live) {\n return;\n }\n const { limitsReached } = this.snapshot;\n if (!limitsReached.includes(limit)) {\n this.publish({ limitsReached: [...limitsReached, limit] });\n }\n live.stopKind(limit);\n if (limit === \"duration\") {\n this.pauseFor(\"limit\");\n }\n }\n\n private async requestVoice(): Promise<VoiceCapture | null> {\n this.publish({ ...IDLE, phase: \"requesting\" });\n const opening = await openVoice();\n if (opening.failure) {\n this.publish({ ...IDLE, failure: opening.failure, phase: \"failed\" });\n }\n return opening.voice;\n }\n\n private requireRecording(): LiveSession {\n if (!this.live || this.snapshot.phase !== \"recording\") {\n throw new Error(\"Nothing is being recorded right now.\");\n }\n return this.live;\n }\n\n private readonly syncSessionId = (): void => {\n const sessionKey = this.live?.sessionKey;\n if (!sessionKey || this.snapshot.sessionId !== null) {\n return;\n }\n const draft = localSessions\n .getDrafts(this.options.account.key)\n .find((candidate) => candidate.sessionKey === sessionKey);\n if (draft?.sessionId) {\n this.publish({ sessionId: draft.sessionId });\n }\n };\n}\n","import type { SessionApi } from \"../api/session-api\";\nimport type { MicrophoneFailureKind } from \"../capture/audio/microphone\";\nimport type { SessionAccount } from \"../local/session-store\";\nimport type {\n SessionLimitKind,\n SessionLimits,\n SessionSurface,\n} from \"../protocol\";\nimport { RecordingController } from \"./recording-controller\";\n\nexport type RecorderPhase =\n | \"idle\"\n | \"requesting\"\n | \"recording\"\n | \"paused\"\n | \"finishing\"\n | \"failed\";\n\nexport interface RecorderFailure {\n kind: MicrophoneFailureKind | \"storage\" | \"limit\" | \"auth\" | \"network\";\n message: string;\n}\n\nexport interface RecorderSnapshot {\n activeMs: number;\n failure: RecorderFailure | null;\n lastMark: { atMs: number; key: string } | null;\n limitsReached: SessionLimitKind[];\n markCount: number;\n nearLimit: boolean;\n pauseReason: \"paused\" | \"hidden\" | \"limit\" | null;\n phase: RecorderPhase;\n sessionId: string | null;\n sessionKey: string | null;\n /** Epoch ms the session clock counts from. */\n startedAt: number | null;\n}\n\nexport interface SessionRecorder {\n annotateMark: (key: string, note: string) => void;\n /** Stops collecting without ending the server session; the draft shows as interrupted. */\n dispose: () => void;\n finish: () => Promise<{ sessionKey: string }>;\n getSnapshot: () => RecorderSnapshot;\n mark: () => string;\n pause: (reason?: \"paused\" | \"hidden\") => void;\n resume: () => Promise<void>;\n resumeDraft: (sessionKey: string) => Promise<void>;\n select: (element: Element, note?: string) => void;\n /** Asks for the microphone before anything is stored, sent or shown as recording. */\n start: (options: { title?: string }) => Promise<void>;\n subscribe: (listener: () => void) => () => void;\n subscribeLevel: (listener: (level: number) => void) => () => void;\n}\n\nexport interface SessionRecorderOptions {\n account: SessionAccount;\n api: SessionApi;\n limits: SessionLimits;\n surface: SessionSurface;\n}\n\nexport function createSessionRecorder(\n options: SessionRecorderOptions\n): SessionRecorder {\n return new RecordingController(options);\n}\n","import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { reportFailure } from \"../../devtools/client/notices\";\nimport {\n createSessionApi,\n type SessionApi,\n SessionApiError,\n type SessionTransport,\n} from \"../api/session-api\";\nimport { purgeAccount, useSyncStatus } from \"../local/local-sessions\";\nimport type { SessionAccount } from \"../local/session-store\";\nimport type { SessionIdentity, SessionSurface } from \"../protocol\";\nimport {\n createSessionRecorder,\n type SessionRecorder,\n} from \"../recorder/session-recorder\";\nimport { useRecorderSnapshot } from \"../recorder/use-recorder-snapshot\";\n\nexport interface SessionWorkspace {\n account: SessionAccount;\n api: SessionApi;\n identity: SessionIdentity;\n onUnauthorized: () => void;\n recorder: SessionRecorder;\n surface: SessionSurface;\n}\n\nexport type WorkspaceState =\n | { kind: \"idle\" }\n | { kind: \"loading\" }\n | { kind: \"failed\"; message: string; retry: () => void }\n | { kind: \"ready\"; workspace: SessionWorkspace };\n\nexport const UNAUTHORIZED_MESSAGE =\n \"Reflet no longer accepts this connection, so recording stopped and this device's unsent session data was removed.\";\n\nexport function isUnauthorized(error: unknown): boolean {\n return error instanceof SessionApiError && error.status === 401;\n}\n\nexport function failureMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"Unknown error.\";\n}\n\nfunction accountFor(identity: SessionIdentity): SessionAccount {\n return {\n key: `${identity.organizationId}:${identity.user.id}`,\n organizationName: identity.organizationName,\n userEmail: identity.user.email,\n userName: identity.user.name,\n };\n}\n\nasync function openWorkspace(options: {\n onRefused: (account: SessionAccount) => void;\n surface: SessionSurface;\n transport: SessionTransport;\n}): Promise<SessionWorkspace> {\n const { surface } = options;\n const api = createSessionApi(options.transport);\n const identity = await api.identity();\n const account = accountFor(identity);\n const recorder = createSessionRecorder({\n account,\n api,\n limits: identity.limits,\n surface,\n });\n return {\n account,\n api,\n identity,\n onUnauthorized: () => options.onRefused(account),\n recorder,\n surface,\n };\n}\n\nfunction loadWorkspace(options: {\n onUnauthorized: () => void;\n setState: (state: WorkspaceState) => void;\n surface: SessionSurface;\n transport: SessionTransport;\n}): () => void {\n const { setState, surface, transport } = options;\n let isCurrent = true;\n let opened: SessionWorkspace | null = null;\n const showFailure = (message: string) => {\n if (isCurrent) {\n setState({ kind: \"failed\", message, retry: load });\n }\n };\n const refuse = (account: SessionAccount | null) => {\n opened?.recorder.dispose();\n if (account) {\n purgeAccount(account.key).catch((error: unknown) =>\n reportFailure(\"This device's session data was not removed\", error)\n );\n }\n showFailure(UNAUTHORIZED_MESSAGE);\n options.onUnauthorized();\n };\n const load = () => {\n setState({ kind: \"loading\" });\n openWorkspace({ onRefused: refuse, surface, transport }).then(\n (workspace) => {\n opened = workspace;\n if (isCurrent) {\n setState({ kind: \"ready\", workspace });\n } else {\n workspace.recorder.dispose();\n }\n },\n (error: unknown) => {\n if (isUnauthorized(error)) {\n refuse(null);\n } else {\n showFailure(failureMessage(error));\n }\n }\n );\n };\n load();\n return () => {\n isCurrent = false;\n opened?.recorder.dispose();\n };\n}\n\nexport function useWorkspaceLoader(options: {\n onUnauthorized: () => void;\n surface: SessionSurface;\n transport: SessionTransport | null;\n}): WorkspaceState {\n const { surface, transport } = options;\n const [state, setState] = useState<WorkspaceState>({ kind: \"idle\" });\n const onUnauthorizedRef = useRef(options.onUnauthorized);\n useLayoutEffect(() => {\n onUnauthorizedRef.current = options.onUnauthorized;\n });\n\n useEffect(() => {\n if (!transport) {\n setState({ kind: \"idle\" });\n return;\n }\n return loadWorkspace({\n onUnauthorized: () => onUnauthorizedRef.current(),\n setState,\n surface,\n transport,\n });\n }, [surface, transport]);\n\n return state;\n}\n\nconst WorkspaceContext = createContext<SessionWorkspace | null>(null);\n\nfunction RefusedCredentialWatch({\n workspace,\n}: {\n workspace: SessionWorkspace;\n}) {\n const snapshot = useRecorderSnapshot(workspace.recorder);\n const sync = useSyncStatus(workspace.account.key);\n const isRefused =\n snapshot.failure?.kind === \"auth\" || sync.blockedBy === \"auth\";\n const { onUnauthorized } = workspace;\n useEffect(() => {\n if (isRefused) {\n onUnauthorized();\n }\n }, [isRefused, onUnauthorized]);\n return null;\n}\n\nexport function SessionWorkspaceProvider({\n children,\n workspace,\n}: {\n children: ReactNode;\n workspace: SessionWorkspace | null;\n}) {\n return (\n <WorkspaceContext.Provider value={workspace}>\n {workspace && <RefusedCredentialWatch workspace={workspace} />}\n {children}\n </WorkspaceContext.Provider>\n );\n}\n\nexport function useSessionWorkspace(): SessionWorkspace {\n const workspace = useContext(WorkspaceContext);\n if (!workspace) {\n throw new Error(\"Session views render inside SessionWorkspaceProvider.\");\n }\n return workspace;\n}\n\nexport function useSessionAction() {\n const { onUnauthorized } = useSessionWorkspace();\n return async <T,>(\n failureLabel: string,\n action: () => Promise<T>\n ): Promise<T | null> => {\n try {\n return await action();\n } catch (error) {\n if (isUnauthorized(error)) {\n onUnauthorized();\n } else {\n reportFailure(failureLabel, error);\n }\n return null;\n }\n };\n}\n","import type { SessionDetail, SessionSummary } from \"../protocol\";\n\nconst SECOND_MS = 1000;\nconst MINUTE_MS = 60 * SECOND_MS;\n\nexport function formatClock(ms: number): string {\n const totalSeconds = Math.max(0, Math.floor(ms / SECOND_MS));\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`;\n}\n\nexport function countLabel(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? \"\" : \"s\"}`;\n}\n\nexport function spokenDuration(ms: number): string {\n const totalSeconds = Math.max(0, Math.floor(ms / SECOND_MS));\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = countLabel(totalSeconds % 60, \"second\");\n return minutes > 0 ? `${countLabel(minutes, \"minute\")} ${seconds}` : seconds;\n}\n\nexport function shortDuration(ms: number): string {\n const totalSeconds = Math.max(0, Math.round(ms / SECOND_MS));\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes === 0) {\n return `${seconds} s`;\n }\n return seconds === 0 ? `${minutes} min` : `${minutes} min ${seconds} s`;\n}\n\nexport function minutesLeft(remainingMs: number): number {\n return Math.max(1, Math.ceil(remainingMs / MINUTE_MS));\n}\n\nexport function formatDate(epochMs: number): string {\n return new Date(epochMs).toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n });\n}\n\nexport function isAnalysisBusy(summary: SessionSummary): boolean {\n return (\n summary.analysis.state === \"waiting\" || summary.analysis.state === \"running\"\n );\n}\n\nexport function isAnalysisOutdated(summary: SessionSummary): boolean {\n const { analyzedRevision, transcriptRevision } = summary.analysis;\n return analyzedRevision !== null && analyzedRevision < transcriptRevision;\n}\n\nexport function sessionStatusLine(summary: SessionSummary): string {\n const { analysis, collection, counts } = summary;\n if (collection !== \"ended\") {\n return \"Recording\";\n }\n if (counts.pendingSegments > 0) {\n return \"Transcribing\";\n }\n if (isAnalysisBusy(summary)) {\n return \"Reading\";\n }\n if (analysis.state === \"failed\") {\n return \"Analysis failed\";\n }\n if (analysis.state === \"idle\") {\n return \"Not analyzed yet\";\n }\n return `${countLabel(counts.proposals, \"proposal\")} · ${counts.kept} kept`;\n}\n\nexport function isDetailProcessing(detail: SessionDetail): boolean {\n const transcribing = detail.segments.some(\n (segment) =>\n segment.transcription.state === \"pending\" ||\n segment.transcription.state === \"running\"\n );\n const refining = detail.proposals.some(\n (proposal) => proposal.refinement?.state === \"running\"\n );\n return (\n transcribing ||\n refining ||\n isAnalysisBusy(detail.session) ||\n detail.session.collection !== \"ended\"\n );\n}\n","import { Svg } from \"../../feedback/ui/icons\";\n\nexport function MicIcon() {\n return (\n <Svg>\n <rect height=\"11\" rx=\"3\" width=\"6\" x=\"9\" y=\"3\" />\n <path d=\"M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21\" />\n </Svg>\n );\n}\n\nexport function MarkIcon() {\n return (\n <Svg>\n <path d=\"M6 21V4h11l-2 4 2 4H6\" />\n </Svg>\n );\n}\n\nexport function PauseIcon() {\n return (\n <Svg>\n <path d=\"M9 5v14M15 5v14\" />\n </Svg>\n );\n}\n\nexport function PlayIcon() {\n return (\n <Svg>\n <path d=\"m8 5 11 7-11 7z\" />\n </Svg>\n );\n}\n\nexport function PersonIcon() {\n return (\n <Svg>\n <circle cx=\"12\" cy=\"8\" r=\"4\" />\n <path d=\"M4.5 20a7.5 7.5 0 0 1 15 0\" />\n </Svg>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport type { SessionRecorder } from \"../../recorder/session-recorder\";\n\nconst REDUCED_MOTION_QUERY = \"(prefers-reduced-motion: reduce)\";\n\n/** The level changes many times a second: it goes straight to a CSS variable, never through React state. */\nexport function LevelMeter({ recorder }: { recorder: SessionRecorder }) {\n const meterRef = useRef<HTMLSpanElement>(null);\n\n useEffect(() => {\n const prefersStill =\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(REDUCED_MOTION_QUERY).matches;\n if (prefersStill) {\n return;\n }\n return recorder.subscribeLevel((level) => {\n meterRef.current?.style.setProperty(\"--dt-level\", level.toFixed(2));\n });\n }, [recorder]);\n\n return (\n <span aria-hidden=\"true\" className=\"dt-rec-meter\" ref={meterRef}>\n <span />\n <span />\n <span />\n </span>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { isSubmitEnter } from \"../../../feedback/ui/keyboard\";\n\nconst UNTOUCHED_NOTE_MS = 6000;\n\nexport function MarkNote({\n focusOnOpen,\n onClose,\n}: {\n focusOnOpen: boolean;\n onClose: (note: string) => void;\n}) {\n const [note, setNote] = useState(\"\");\n const inputRef = useRef<HTMLInputElement>(null);\n const isTouched = note !== \"\";\n\n useEffect(() => {\n if (focusOnOpen) {\n inputRef.current?.focus({ preventScroll: true });\n }\n }, [focusOnOpen]);\n\n useEffect(() => {\n if (isTouched) {\n return;\n }\n const timer = setTimeout(() => onClose(\"\"), UNTOUCHED_NOTE_MS);\n return () => clearTimeout(timer);\n }, [isTouched, onClose]);\n\n return (\n <div className=\"dt-rec-note\">\n <span aria-hidden=\"true\">Moment marked ·</span>\n <input\n aria-label=\"Moment marked · Add a note\"\n className=\"dt-field\"\n maxLength={1000}\n onChange={(event) => setNote(event.target.value)}\n onKeyDown={(event) => {\n if (isSubmitEnter(event.nativeEvent)) {\n event.preventDefault();\n onClose(note.trim());\n } else if (event.key === \"Escape\") {\n onClose(\"\");\n }\n }}\n placeholder=\"Add a note\"\n ref={inputRef}\n value={note}\n />\n </div>\n );\n}\n","import { type RefObject, useEffect, useRef, useState } from \"react\";\nimport { matchesHotkey } from \"../../../feedback/ui/keyboard\";\nimport { listenToKeydown } from \"../../../feedback/ui/widget-events\";\nimport { useSyncStatus } from \"../../local/local-sessions\";\nimport type {\n RecorderSnapshot,\n SessionRecorder,\n} from \"../../recorder/session-recorder\";\nimport { formatClock, minutesLeft, spokenDuration } from \"../session-format\";\nimport { MarkIcon, PauseIcon, PlayIcon } from \"../session-icons\";\nimport { useSessionWorkspace } from \"../session-workspace\";\nimport { LevelMeter } from \"./level-meter\";\nimport { MarkNote } from \"./mark-note\";\n\nconst MARK_HOTKEY = \"alt+shift+m\";\n\nfunction SyncChip() {\n const { account } = useSessionWorkspace();\n const sync = useSyncStatus(account.key);\n let label = \"Saved\";\n if (sync.blockedBy === \"storage\") {\n label = \"Not saved on this device\";\n } else if (!sync.isOnline) {\n label = \"Offline — kept on this device\";\n } else if (sync.pendingOperations > 0) {\n label = `${sync.pendingOperations} waiting to upload`;\n }\n return <span className=\"dt-chip\">{label}</span>;\n}\n\nfunction statusText(snapshot: RecorderSnapshot, maxDurationMs: number) {\n if (snapshot.phase === \"failed\") {\n return snapshot.failure?.message ?? \"Recording stopped.\";\n }\n if (snapshot.phase === \"finishing\") {\n return \"Finishing…\";\n }\n if (snapshot.pauseReason === \"limit\") {\n return \"Time limit reached · Finish to review the session\";\n }\n if (snapshot.pauseReason === \"hidden\") {\n return \"Paused because the tab was hidden\";\n }\n if (snapshot.phase === \"paused\") {\n return \"Paused · nothing is recorded\";\n }\n if (snapshot.limitsReached.length > 0) {\n return `Limit reached for ${snapshot.limitsReached.join(\", \")}`;\n }\n return snapshot.nearLimit\n ? `${minutesLeft(maxDurationMs - snapshot.activeMs)} min left`\n : \"\";\n}\n\ninterface OpenMark {\n closeNote: (note: string) => void;\n focus: boolean;\n key: string;\n}\n\n// closeNote is created with the mark so MarkNote's untouched-timer effect keeps a stable onClose.\nfunction markMoment(\n recorder: SessionRecorder,\n focus: boolean,\n setOpenMark: (mark: OpenMark | null) => void\n) {\n const key = recorder.mark();\n setOpenMark({\n closeNote: (note: string) => {\n recorder.annotateMark(key, note);\n setOpenMark(null);\n },\n focus,\n key,\n });\n}\n\nfunction useMarkMoment(\n snapshot: RecorderSnapshot,\n barRef: RefObject<HTMLDivElement | null>\n) {\n const { recorder } = useSessionWorkspace();\n const [openMark, setOpenMark] = useState<OpenMark | null>(null);\n const canMark = snapshot.phase === \"recording\";\n\n useEffect(\n () =>\n listenToKeydown(barRef.current, (event) => {\n if (canMark && matchesHotkey(event, MARK_HOTKEY)) {\n event.preventDefault();\n markMoment(recorder, false, setOpenMark);\n }\n }),\n [barRef, canMark, recorder]\n );\n return {\n markWithNote: () => markMoment(recorder, true, setOpenMark),\n openMark,\n };\n}\n\nfunction CaptureButtons({\n canCapture,\n onMark,\n onPointAt,\n}: {\n canCapture: boolean;\n onMark: () => void;\n onPointAt: () => void;\n}) {\n return (\n <>\n <button\n aria-keyshortcuts=\"Alt+Shift+M\"\n className=\"dt-btn\"\n disabled={!canCapture}\n onClick={onMark}\n title=\"Mark moment (Alt+Shift+M)\"\n type=\"button\"\n >\n <MarkIcon />\n Mark moment\n </button>\n <button\n className=\"dt-btn\"\n disabled={!canCapture}\n onClick={onPointAt}\n type=\"button\"\n >\n Point at element\n </button>\n </>\n );\n}\n\nfunction PauseToggle({ snapshot }: { snapshot: RecorderSnapshot }) {\n const { recorder } = useSessionWorkspace();\n if (snapshot.phase === \"recording\") {\n return (\n <button\n className=\"dt-btn\"\n onClick={() => recorder.pause(\"paused\")}\n type=\"button\"\n >\n <PauseIcon />\n Pause\n </button>\n );\n }\n if (snapshot.phase === \"paused\" && snapshot.pauseReason !== \"limit\") {\n return (\n <button\n className=\"dt-btn\"\n onClick={() => recorder.resume()}\n type=\"button\"\n >\n <PlayIcon />\n Resume\n </button>\n );\n }\n return null;\n}\n\nfunction RecordingControls({\n onFinish,\n onMark,\n onPointAt,\n snapshot,\n}: {\n onFinish: () => void;\n onMark: () => void;\n onPointAt: () => void;\n snapshot: RecorderSnapshot;\n}) {\n const { phase } = snapshot;\n const isActive = phase === \"recording\" || phase === \"paused\";\n return (\n <>\n {isActive && (\n <CaptureButtons\n canCapture={phase === \"recording\"}\n onMark={onMark}\n onPointAt={onPointAt}\n />\n )}\n <PauseToggle snapshot={snapshot} />\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={phase === \"finishing\"}\n onClick={onFinish}\n type=\"button\"\n >\n Finish\n </button>\n </>\n );\n}\n\nfunction RecordingClock({ activeMs }: { activeMs: number }) {\n return (\n <span\n aria-label={`Recording, ${spokenDuration(activeMs)}`}\n aria-live=\"off\"\n className=\"dt-rec-time\"\n role=\"timer\"\n >\n {formatClock(activeMs)}\n </span>\n );\n}\n\nexport function RecordingBar({\n onFinish,\n onPointAt,\n snapshot,\n}: {\n onFinish: () => void;\n onPointAt: () => void;\n snapshot: RecorderSnapshot;\n}) {\n const { identity, recorder } = useSessionWorkspace();\n const barRef = useRef<HTMLDivElement>(null);\n const { markWithNote, openMark } = useMarkMoment(snapshot, barRef);\n\n return (\n <div\n aria-label=\"Session recording\"\n className=\"dt-rec glass\"\n data-phase={snapshot.phase}\n ref={barRef}\n role=\"toolbar\"\n >\n <span aria-hidden=\"true\" className=\"dt-rec-dot\" />\n {snapshot.phase === \"recording\" && <LevelMeter recorder={recorder} />}\n <RecordingClock activeMs={snapshot.activeMs} />\n <span aria-live=\"polite\" className=\"dt-rec-status\">\n {statusText(snapshot, identity.limits.maxDurationMs)}\n </span>\n <RecordingControls\n onFinish={onFinish}\n onMark={markWithNote}\n onPointAt={onPointAt}\n snapshot={snapshot}\n />\n <SyncChip />\n {openMark && (\n <MarkNote\n focusOnOpen={openMark.focus}\n key={openMark.key}\n onClose={openMark.closeNote}\n />\n )}\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { reportFailure } from \"../../../devtools/client/notices\";\nimport {\n DEFAULT_WIDGET_LABELS,\n type FeedbackWidgetLabels,\n} from \"../../../feedback/types\";\nimport { ElementPicker } from \"../../../feedback/ui/picker\";\nimport type { RecorderSnapshot } from \"../../recorder/session-recorder\";\nimport { useRecorderSnapshot } from \"../../recorder/use-recorder-snapshot\";\nimport { useSessionWorkspace } from \"../session-workspace\";\nimport type { SessionTarget } from \"../start/session-list\";\nimport { RecordingBar } from \"./recording-bar\";\n\nconst SESSION_PICKER_LABELS: FeedbackWidgetLabels = {\n ...DEFAULT_WIDGET_LABELS,\n attachElement: \"Add to session\",\n elementNote: \"Note for this element (optional)\",\n elementNotePlaceholder: \"What about it?\",\n pickElementHint: \"Point at the element you are talking about\",\n};\n\nfunction showsBar(snapshot: RecorderSnapshot): boolean {\n if (snapshot.sessionKey === null) {\n return false;\n }\n return (\n snapshot.phase === \"recording\" ||\n snapshot.phase === \"paused\" ||\n snapshot.phase === \"finishing\" ||\n snapshot.phase === \"failed\"\n );\n}\n\n/** Lives outside the sheet: recording goes on while every panel is closed. */\nexport function RecordingLayer({\n onFinished,\n}: {\n onFinished: (target: SessionTarget) => void;\n}) {\n const { recorder } = useSessionWorkspace();\n const snapshot = useRecorderSnapshot(recorder);\n const [isPointing, setIsPointing] = useState(false);\n\n if (!showsBar(snapshot)) {\n return null;\n }\n const finish = async () => {\n setIsPointing(false);\n const { sessionId } = recorder.getSnapshot();\n try {\n const { sessionKey } = await recorder.finish();\n onFinished({ sessionId, sessionKey });\n } catch (error) {\n reportFailure(\"The session did not finish\", error, finish);\n }\n };\n\n return (\n <>\n <RecordingBar\n onFinish={finish}\n onPointAt={() => setIsPointing(true)}\n snapshot={snapshot}\n />\n {isPointing && snapshot.phase === \"recording\" && (\n <ElementPicker\n labels={SESSION_PICKER_LABELS}\n onCancel={() => setIsPointing(false)}\n onPick={(element, note) => {\n setIsPointing(false);\n recorder.select(element, note.trim() || undefined);\n }}\n />\n )}\n </>\n );\n}\n","import { REFLET_Z_INDEX } from \"../../z-index\";\n\nconst MONO_FONT = \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\";\n\nconst RECORDING_STYLES = `\n.dt-rec {\n position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; left: 50%; translate: -50% 0;\n bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + 16px);\n display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px;\n max-width: calc(100vw - 24px); padding: 6px 6px 6px 12px; border-radius: 18px;\n animation: dt-rec-in 240ms var(--rf-ease);\n}\n@keyframes dt-rec-in { from { transform: translateY(8px); opacity: 0; } }\n.dt-rec-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--rf-danger); }\n.dt-rec[data-phase=\"recording\"] .dt-rec-dot { animation: dt-rec-pulse 1.6s ease-in-out infinite; }\n.dt-rec[data-phase=\"paused\"] .dt-rec-dot, .dt-rec[data-phase=\"finishing\"] .dt-rec-dot { background: var(--rf-text-muted); }\n@keyframes dt-rec-pulse { 50% { opacity: .35; } }\n.dt-rec-meter { display: inline-flex; align-items: center; gap: 2px; height: 16px; }\n.dt-rec-meter span {\n width: 3px; height: 100%; border-radius: 2px; background: var(--rf-text-muted);\n scale: 1 calc(.2 + var(--dt-level, 0) * .8); transition: scale 90ms linear;\n}\n.dt-rec-meter span:nth-child(2) { scale: 1 calc(.2 + var(--dt-level, 0)); }\n.dt-rec-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 5ch; }\n.dt-rec-status { color: var(--rf-text-muted); font-size: 12px; overflow-wrap: anywhere; }\n.dt-rec-status:empty { display: none; }\n.dt-rec-note { display: flex; align-items: center; gap: 6px; flex: 1 1 100%; font-size: 12px; color: var(--rf-text-muted); }\n.dt-rec-note .dt-field { flex: 1; min-width: 0; padding: 4px 8px; }\n`;\n\nconst LIST_STYLES = `\n.dt-ses-subhead, .dt-ses-label { margin: 0 0 4px; font-size: 12px; font-weight: 600; color: var(--rf-text); }\n.dt-ses-label { font-size: 11px; color: var(--rf-text-muted); }\n.dt-ses-list { margin: 0; padding-left: 18px; overflow-wrap: anywhere; }\n.dt-ses-list li + li { margin-top: 3px; }\n.dt-ses-link { align-self: flex-start; padding: 0; color: var(--rf-accent); font-size: 12px; text-align: left; }\n.dt-ses-link:hover { text-decoration: underline; }\n.dt-ses-problem, .dt-ses-banner, .dt-ses-form, .dt-ses-head, .dt-ses-strip, .dt-ses-handoff { display: flex; flex-direction: column; gap: 6px; }\n.dt-ses-banner { padding: 8px 10px; border-radius: 10px; background: color-mix(in srgb, var(--rf-accent) 10%, transparent); }\n.dt-ses-banner p { margin: 0; overflow-wrap: anywhere; }\n.dt-ses-strip:empty { display: none; }\n.dt-ses-rows { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; }\n.dt-ses-row {\n display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;\n padding: 8px 10px; border-radius: 10px; background: var(--rf-bg-subtle); text-align: left;\n}\nbutton.dt-ses-row:hover { background: var(--rf-bg-hover); }\n.dt-ses-row .dt-card-title { max-width: 100%; }\n`;\n\nconst REVIEW_STYLES = `\n.dt-ses-title { flex: 1; min-width: 0; margin: 0; font-size: 15px; font-weight: 650; overflow-wrap: anywhere; }\n.dt-ses-tabs { flex-wrap: wrap; margin: 0; }\n.dt-ses-field { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--rf-text-muted); }\n.dt-ses-need {\n margin: 0; font-weight: 600; overflow-wrap: anywhere;\n display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;\n}\n.dt-ses-need[data-expanded=\"true\"] { display: block; }\n.dt-card[data-decision=\"dismissed\"] .dt-ses-need { color: var(--rf-text-muted); text-decoration: line-through; }\n.dt-ses-chips { display: flex; flex-wrap: wrap; gap: 4px; }\n.dt-ses-chips:empty { display: none; }\n.dt-ses-details { display: flex; flex-direction: column; gap: 8px; }\n.dt-ses-details[hidden] { display: none; }\n.dt-ses-details section { display: flex; flex-direction: column; gap: 2px; }\n.dt-ses-quote { padding: 2px 0; font-size: 12px; text-align: left; overflow-wrap: anywhere; }\n.dt-ses-quote:hover { color: var(--rf-accent); }\n.dt-ses-time { flex: none; color: var(--rf-text-muted); font: 11.5px ${MONO_FONT}; font-variant-numeric: tabular-nums; }\n.dt-ses-verify { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 8px 0 0; border: 0; border-top: 1px solid var(--rf-border); }\n.dt-ses-timeline { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }\n.dt-ses-seg { display: flex; gap: 8px; padding: 6px 8px; border-radius: 8px; }\n.dt-ses-seg:focus { outline: 2px solid var(--rf-accent); outline-offset: -2px; }\n.dt-ses-seg[data-kind=\"note\"] { padding-block: 2px; }\n.dt-ses-seg-body { display: flex; flex: 1; flex-direction: column; gap: 4px; min-width: 0; }\n`;\n\nconst EVIDENCE_STYLES = `\n.dt-ses-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }\n.dt-ses-shot { position: relative; display: inline-block; max-width: 100%; line-height: 0; }\n.dt-ses-shot img { display: block; max-width: 100%; height: auto; max-height: 132px; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }\n.dt-ses-shot[data-large=\"true\"] img { max-height: none; }\n.dt-ses-shot-mark { position: absolute; border: 2px solid var(--rf-accent); border-radius: 4px; pointer-events: none; }\n.dt-ses-shot-btn { align-self: flex-start; padding: 0; border-radius: 8px; }\n.dt-ses-check { display: flex; align-items: flex-start; gap: 6px; overflow-wrap: anywhere; }\n.dt-ses-check input { flex: none; margin-top: 3px; accent-color: var(--rf-accent); }\n.dt-ses-choices { margin: 0; padding: 0; border: 0; }\n.dt-ses-choices .dt-ses-list { padding-left: 0; list-style: none; }\n.dt-ses-brief {\n max-height: 50vh; overflow: auto; margin: 0; padding: 10px; border-radius: 10px;\n background: var(--rf-bg-subtle); font: 11.5px/1.55 ${MONO_FONT}; white-space: pre-wrap; overflow-wrap: anywhere;\n}\n`;\n\nconst TEAM_STYLES = `\n.dt-team-anchor {\n --dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);\n position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar}; width: min(300px, calc(100vw - 24px));\n}\n.dt-team-anchor[data-side=\"left\"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }\n.dt-team-anchor[data-side=\"right\"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }\n.dt-team-anchor[data-edge=\"bottom\"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }\n.dt-team-anchor[data-edge=\"top\"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }\n.dt-team-card { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: 14px; animation: dt-popover-in 200ms var(--rf-ease); }\n.dt-bar > .dt-btn { margin-inline: 2px 4px; }\n`;\n\nexport const SESSIONS_STYLES = `${RECORDING_STYLES}${LIST_STYLES}${REVIEW_STYLES}${EVIDENCE_STYLES}${TEAM_STYLES}`;\n","/**\n * Safari only lets a page write the clipboard inside the key press or click\n * itself, while the text waits on a source-map lookup: the write starts now\n * and the text follows.\n */\nexport async function copyToClipboard(text: Promise<string>): Promise<void> {\n if (!window.isSecureContext) {\n throw new Error(\"The clipboard needs HTTPS or localhost.\");\n }\n const blob = text.then((value) => new Blob([value], { type: \"text/plain\" }));\n await navigator.clipboard.write([new ClipboardItem({ \"text/plain\": blob })]);\n}\n","import { Svg } from \"../../feedback/ui/icons\";\n\nexport function NotesIcon() {\n return (\n <Svg>\n <path d=\"M8 6h13M8 12h13M8 18h13M3.5 6h.01M3.5 12h.01M3.5 18h.01\" />\n </Svg>\n );\n}\n\nexport function InboxIcon() {\n return (\n <Svg>\n <path d=\"M22 12h-6l-2 3h-4l-2-3H2\" />\n <path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\" />\n </Svg>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { useFloatingPosition } from \"../../feedback/ui/floating/use-floating-position\";\nimport { GripIcon, TargetIcon } from \"../../feedback/ui/icons\";\nimport { MicIcon } from \"../../sessions/ui/session-icons\";\nimport { InboxIcon, NotesIcon } from \"./devtools-icons\";\n\nconst BAR_POSITION_KEY = \"reflet-devtools-bar-position\";\nexport const PICK_BUTTON_LABEL =\n \"Pick an element: note it, copy it, or Shift+click to open its code\";\n\nexport type SheetTab = \"code\" | \"inbox\" | \"notes\" | \"sessions\";\n\nexport function BarButton({\n children,\n label,\n onClick,\n pressed,\n}: {\n children: ReactNode;\n label: string;\n onClick: () => void;\n pressed: boolean;\n}) {\n return (\n <button\n aria-label={label}\n aria-pressed={pressed}\n className=\"icon-btn\"\n onClick={onClick}\n title={label}\n type=\"button\"\n >\n {children}\n </button>\n );\n}\n\nexport function DevtoolsBar({\n children,\n edge,\n label = \"Reflet devtools\",\n side,\n}: {\n children: ReactNode;\n edge: \"bottom\" | \"top\";\n label?: string;\n side: \"left\" | \"right\";\n}) {\n const floating = useFloatingPosition(`${edge}-${side}`, false, {\n anchorSelector: \".dt-bar\",\n persistKey: BAR_POSITION_KEY,\n });\n\n return (\n <div\n aria-label={label}\n className=\"dt-bar glass\"\n data-edge={edge}\n data-moved={floating.position !== null}\n data-side={side}\n ref={floating.rootRef}\n role=\"toolbar\"\n >\n <style>{floating.styles}</style>\n <button\n aria-label={`Move ${label} (double-click to reset)`}\n className=\"icon-btn drag-handle dt-grip\"\n onDoubleClick={floating.resetPosition}\n title=\"Drag to move · double-click to reset\"\n type=\"button\"\n {...floating.handleProps}\n >\n <GripIcon />\n </button>\n {children}\n </div>\n );\n}\n\nexport function SessionsBarButton({\n isOpen,\n onToggle,\n}: {\n isOpen: boolean;\n onToggle: () => void;\n}) {\n return (\n <BarButton label=\"Sessions\" onClick={onToggle} pressed={isOpen}>\n <MicIcon />\n </BarButton>\n );\n}\n\nexport function DevtoolsBarButtons({\n noteCount,\n onPick,\n onToggleSheet,\n openTab,\n}: {\n noteCount: number;\n onPick: () => void;\n onToggleSheet: (tab: SheetTab) => void;\n openTab: SheetTab | null;\n}) {\n return (\n <>\n <BarButton label={PICK_BUTTON_LABEL} onClick={onPick} pressed={false}>\n <TargetIcon />\n </BarButton>\n <BarButton\n label=\"Dev notes\"\n onClick={() => onToggleSheet(\"notes\")}\n pressed={openTab === \"notes\"}\n >\n <NotesIcon />\n {noteCount > 0 && <span className=\"dt-count\">{noteCount}</span>}\n </BarButton>\n <SessionsBarButton\n isOpen={openTab === \"sessions\"}\n onToggle={() => onToggleSheet(\"sessions\")}\n />\n <BarButton\n label=\"Board feedback\"\n onClick={() => onToggleSheet(\"inbox\")}\n pressed={openTab === \"inbox\"}\n >\n <InboxIcon />\n </BarButton>\n </>\n );\n}\n","import {\n type KeyboardEvent,\n type PointerEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n onViewportChange,\n type VisibleViewport,\n visibleViewport,\n} from \"../../feedback/ui/visible-viewport\";\n\nexport type ResizeAxis = \"both\" | \"height\" | \"width\";\n\ninterface SheetSize {\n /** Null keeps the sheet full height. */\n height: number | null;\n width: number;\n}\n\nconst SIZE_KEY = \"reflet-devtools-sheet-size\";\nconst DEFAULT_WIDTH = 440;\nconst MIN_WIDTH = 320;\nconst MIN_HEIGHT = 240;\nconst EDGE_GAP = 12;\nconst KEYBOARD_STEP = 24;\nconst ARROW_DELTAS: Record<string, { dx: number; dy: number }> = {\n ArrowDown: { dx: 0, dy: KEYBOARD_STEP },\n ArrowLeft: { dx: -KEYBOARD_STEP, dy: 0 },\n ArrowRight: { dx: KEYBOARD_STEP, dy: 0 },\n ArrowUp: { dx: 0, dy: -KEYBOARD_STEP },\n};\n\nfunction readStoredSize(): SheetSize {\n const fallback = { height: null, width: DEFAULT_WIDTH };\n try {\n const stored: unknown = JSON.parse(\n localStorage.getItem(SIZE_KEY) ?? \"null\"\n );\n if (\n typeof stored === \"object\" &&\n stored !== null &&\n \"width\" in stored &&\n typeof stored.width === \"number\" &&\n \"height\" in stored &&\n (stored.height === null || typeof stored.height === \"number\")\n ) {\n return { height: stored.height, width: stored.width };\n }\n } catch {\n return fallback;\n }\n return fallback;\n}\n\n/**\n * The stored size is the preference; what renders is that preference fitted\n * to today's window, so shrinking the window never loses the chosen size.\n */\nfunction fitted(size: SheetSize, viewport: VisibleViewport): SheetSize {\n const maxWidth = viewport.width - EDGE_GAP * 2;\n const maxHeight = viewport.height - EDGE_GAP * 2;\n return {\n height:\n size.height === null || size.height >= maxHeight\n ? null\n : Math.max(Math.min(MIN_HEIGHT, maxHeight), size.height),\n width: Math.min(maxWidth, Math.max(MIN_WIDTH, size.width)),\n };\n}\n\n/**\n * Width grows away from the docked side, height grows downward from the top;\n * a height reaching the bottom of the window snaps back to full height.\n */\nexport function useSheetSize(side: \"left\" | \"right\") {\n const [preference, setPreference] = useState(readStoredSize);\n const [viewport, setViewport] = useState(visibleViewport);\n const drag = useRef<{\n axis: ResizeAxis;\n size: SheetSize;\n x: number;\n y: number;\n } | null>(null);\n const widthDirection = side === \"right\" ? -1 : 1;\n const size = fitted(preference, viewport);\n\n useEffect(() => onViewportChange(() => setViewport(visibleViewport())), []);\n\n useEffect(() => {\n try {\n localStorage.setItem(SIZE_KEY, JSON.stringify(preference));\n } catch {\n // Blocked storage only costs the size on the next reload.\n }\n }, [preference]);\n\n const resize = (\n axis: ResizeAxis,\n from: SheetSize,\n dx: number,\n dy: number\n ) => {\n const fullHeight = viewport.height - EDGE_GAP * 2;\n setPreference(\n fitted(\n {\n height:\n axis === \"width\" ? from.height : (from.height ?? fullHeight) + dy,\n width:\n axis === \"height\" ? from.width : from.width + dx * widthDirection,\n },\n viewport\n )\n );\n };\n\n const handleProps = (axis: ResizeAxis) => ({\n onDoubleClick: () =>\n setPreference((current) => ({\n height: axis === \"width\" ? current.height : null,\n width: axis === \"height\" ? current.width : DEFAULT_WIDTH,\n })),\n onKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => {\n const delta = ARROW_DELTAS[event.key];\n if (!delta) {\n return;\n }\n event.preventDefault();\n const sheetHeight =\n event.currentTarget.parentElement?.getBoundingClientRect().height ??\n null;\n resize(\n axis,\n { height: size.height ?? sheetHeight, width: size.width },\n delta.dx,\n delta.dy\n );\n },\n onLostPointerCapture: () => {\n drag.current = null;\n },\n onPointerDown: (event: PointerEvent<HTMLButtonElement>) => {\n if (event.button !== 0) {\n return;\n }\n const sheet = event.currentTarget.parentElement?.getBoundingClientRect();\n event.currentTarget.setPointerCapture(event.pointerId);\n drag.current = {\n axis,\n size: { height: sheet?.height ?? size.height, width: size.width },\n x: event.clientX,\n y: event.clientY,\n };\n },\n onPointerMove: (event: PointerEvent<HTMLButtonElement>) => {\n const start = drag.current;\n if (start && event.currentTarget.hasPointerCapture(event.pointerId)) {\n resize(\n start.axis,\n start.size,\n event.clientX - start.x,\n event.clientY - start.y\n );\n }\n },\n });\n\n return { handleProps, size };\n}\n","import {\n type ReactNode,\n type RefObject,\n useEffect,\n useLayoutEffect,\n} from \"react\";\nimport { useFloatingPosition } from \"../../feedback/ui/floating/use-floating-position\";\nimport { CloseIcon, TargetIcon } from \"../../feedback/ui/icons\";\nimport { listenToKeydown } from \"../../feedback/ui/widget-events\";\nimport { PICK_BUTTON_LABEL, type SheetTab } from \"./devtools-bar\";\nimport { useSheetSize } from \"./use-sheet-size\";\n\nconst FULL_HEIGHT = \"calc(100dvh - 24px)\";\n\nconst TAB_LABELS: Record<SheetTab, string> = {\n code: \"Code\",\n inbox: \"Board\",\n notes: \"Notes\",\n sessions: \"Sessions\",\n};\n\nconst SHEET_POSITION_KEY = \"reflet-devtools-sheet-position\";\n\nfunction useSheetFocus(rootRef: RefObject<HTMLElement | null>) {\n useLayoutEffect(() => {\n const root = rootRef.current;\n const scope = root?.getRootNode();\n const opener =\n scope instanceof ShadowRoot || scope instanceof Document\n ? scope.activeElement\n : null;\n const isOpenerHidden =\n opener instanceof HTMLElement &&\n typeof opener.checkVisibility === \"function\" &&\n !opener.checkVisibility({ visibilityProperty: true });\n if (isOpenerHidden) {\n root\n ?.querySelector<HTMLElement>('[role=\"tab\"][aria-selected=\"true\"]')\n ?.focus({ preventScroll: true });\n }\n return () => {\n if (opener instanceof HTMLElement && opener.isConnected) {\n opener.focus({ preventScroll: true });\n }\n };\n }, [rootRef]);\n}\n\nexport function DevtoolsSheet({\n children,\n label = \"Reflet devtools\",\n onClose,\n onPick,\n onSelectTab,\n side,\n tab,\n tabs,\n}: {\n children: ReactNode;\n label?: string;\n onClose: () => void;\n onPick?: () => void;\n onSelectTab: (tab: SheetTab) => void;\n side: \"left\" | \"right\";\n tab: SheetTab;\n tabs: SheetTab[];\n}) {\n const { handleProps, size } = useSheetSize(side);\n const floating = useFloatingPosition<HTMLElement>(`top-${side}`, false, {\n anchorSelector: \".dt-sheet\",\n persistKey: SHEET_POSITION_KEY,\n });\n const isMoved = floating.position !== null;\n const { rootRef } = floating;\n useSheetFocus(rootRef);\n\n useEffect(\n () =>\n listenToKeydown(rootRef.current, (event) => {\n if (event.key === \"Escape\" && !event.isComposing) {\n onClose();\n }\n }),\n [onClose, rootRef]\n );\n\n return (\n <aside\n aria-label={label}\n className=\"dt-sheet glass\"\n data-moved={isMoved}\n data-side={side}\n ref={rootRef}\n style={{\n height: size.height ?? (isMoved ? FULL_HEIGHT : undefined),\n width: size.width,\n }}\n >\n <style>\n {floating.styles}\n {isMoved\n ? \"\"\n : `.dt-bar[data-moved=\"false\"][data-side=\"${side}\"] { ${side}: ${size.width + 24}px; }`}\n </style>\n <button\n aria-label=\"Resize panel width (double-click to reset)\"\n className=\"dt-resize\"\n data-axis=\"width\"\n type=\"button\"\n {...handleProps(\"width\")}\n />\n <button\n aria-label=\"Resize panel height (double-click for full height)\"\n className=\"dt-resize\"\n data-axis=\"height\"\n type=\"button\"\n {...handleProps(\"height\")}\n />\n <button\n aria-label=\"Resize panel (double-click to reset)\"\n className=\"dt-resize\"\n data-axis=\"both\"\n type=\"button\"\n {...handleProps(\"both\")}\n />\n <div className=\"dt-sheet-head\">\n <button\n aria-label=\"Move panel (double-click to dock it back)\"\n className=\"dt-sheet-drag\"\n onDoubleClick={floating.resetPosition}\n title=\"Drag to move · double-click to dock\"\n type=\"button\"\n {...floating.handleProps}\n />\n {onPick && (\n <button\n aria-label={PICK_BUTTON_LABEL}\n className=\"icon-btn\"\n onClick={onPick}\n title=\"Pick an element\"\n type=\"button\"\n >\n <TargetIcon />\n </button>\n )}\n <div className=\"dt-tabs\" role=\"tablist\">\n {tabs.map((option) => (\n <button\n aria-selected={option === tab}\n className=\"dt-tab\"\n key={option}\n onClick={() => onSelectTab(option)}\n role=\"tab\"\n type=\"button\"\n >\n {TAB_LABELS[option]}\n </button>\n ))}\n </div>\n <button\n aria-label={`Close ${label} panel`}\n className=\"icon-btn\"\n onClick={onClose}\n title=\"Close\"\n type=\"button\"\n >\n <CloseIcon />\n </button>\n </div>\n <div className=\"dt-sheet-body\" key={tab} role=\"tabpanel\">\n {children}\n </div>\n </aside>\n );\n}\n","import { REFLET_Z_INDEX } from \"../../z-index\";\n\nconst MONO_FONT = \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\";\n\nexport const DEVTOOLS_STYLES = `\n.dt { font: 13px/1.45 var(--rf-font, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif); color: var(--rf-text); }\n.dt[data-recessed=\"true\"] .dt-bar, .dt[data-recessed=\"true\"] .dt-sheet { visibility: hidden; pointer-events: none; }\n@media (max-width: 600px) { .dt[data-sheet-open=\"true\"] .dt-bar { visibility: hidden; pointer-events: none; } }\n.dt-pin {\n position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; top: 0; left: 0;\n display: flex; align-items: center; justify-content: center;\n min-width: 24px; height: 24px; padding: 0 7px;\n border-radius: 12px 12px 12px 3px; background: var(--rf-accent); color: var(--rf-accent-text);\n font-size: 11.5px; font-weight: 650; box-shadow: 0 0 0 2px var(--rf-bg), var(--rf-shadow-low);\n animation: dt-pin-in 260ms var(--rf-ease);\n transition: scale 140ms var(--rf-ease), opacity 160ms var(--rf-ease);\n}\n.dt-pin:hover, .dt-pin[aria-expanded=\"true\"] { scale: 1.12; }\n.dt-pin[data-sent=\"true\"] { background: var(--rf-text-muted); }\n.dt-pin-badge { display: inline-flex; flex: none; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px 10px 10px 3px; background: var(--rf-accent); color: var(--rf-accent-text); font-size: 10.5px; font-weight: 650; }\n.dt-card[data-sent=\"true\"] .dt-pin-badge { background: var(--rf-text-muted); }\n.dt-pin[data-locating=\"true\"] { animation: dt-pin-in 260ms var(--rf-ease), dt-pin-pulse 1.2s ease-in-out infinite; }\n@keyframes dt-pin-in { from { scale: .4; opacity: 0; } }\n@keyframes dt-pin-pulse { 50% { box-shadow: 0 0 0 2px var(--rf-bg), 0 0 0 6px color-mix(in srgb, var(--rf-accent) 30%, transparent); } }\n.dt-popover {\n position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; width: 320px; max-height: calc(100dvh - 24px); overflow: auto;\n inset-inline-end: auto; margin: 0; padding: 6px; border-radius: 14px; background: transparent; color: inherit;\n animation: dt-popover-in 200ms var(--rf-ease);\n}\n.dt-popover.glass::before { animation: rf-fade 180ms var(--rf-ease); }\n.dt-popover .dt-card { background: transparent; }\n@keyframes dt-popover-in { from { transform: translateY(4px); } }\n@keyframes dt-notice-in { from { transform: translateY(-6px); } }\n.dt-notices {\n position: fixed; z-index: ${REFLET_Z_INDEX.annotatorOverlay}; left: 50%; top: 16px; translate: -50% 0;\n display: flex; flex-direction: column; gap: 6px; width: min(460px, calc(100vw - 24px));\n}\n.dt-notice {\n display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 14px; border-radius: 12px;\n color: var(--rf-danger); font-size: 12.5px; animation: dt-notice-in 220ms var(--rf-ease);\n}\n.dt-notice[data-kind=\"status\"] { color: var(--rf-text); }\n.dt-notice p { flex: 1; margin: 0; overflow-wrap: anywhere; }\n.dt-notice .icon-btn { width: 30px; height: 30px; }\n.dt-bar {\n --dt-edge-gap: calc(max(var(--rf-offset), 12px) + 48px);\n position: fixed; z-index: ${REFLET_Z_INDEX.devtoolsBar};\n display: flex; align-items: center; gap: 2px; padding: 3px;\n border-radius: var(--rf-pill);\n}\n.dt-bar[data-moved=\"false\"] { transition: left 260ms var(--rf-ease), right 260ms var(--rf-ease); }\n.dt-bar[data-side=\"left\"] { left: calc(var(--rf-viewport-left, 0px) + max(12px, var(--rf-offset))); }\n.dt-bar[data-side=\"right\"] { right: calc(var(--rf-viewport-right, 0px) + max(12px, var(--rf-offset))); }\n.dt-bar[data-edge=\"bottom\"] { bottom: calc(var(--rf-viewport-bottom, 0px) + env(safe-area-inset-bottom) + var(--dt-edge-gap)); }\n.dt-bar[data-edge=\"top\"] { top: calc(var(--rf-viewport-top, 0px) + env(safe-area-inset-top) + var(--dt-edge-gap)); }\n.dt-bar .icon-btn { position: relative; width: 34px; height: 34px; }\n.dt-bar .icon-btn.dt-grip { width: 22px; color: var(--rf-text-muted); opacity: .6; }\n.dt-bar .icon-btn.dt-grip:hover { opacity: 1; }\n.dt-bar .icon-btn[aria-pressed=\"true\"] { background: var(--rf-bg-hover); color: var(--rf-text); }\n.dt-count {\n position: absolute; top: 1px; right: 1px; display: flex; align-items: center; justify-content: center;\n min-width: 15px; height: 15px; padding: 0 4px; border-radius: var(--rf-pill);\n background: var(--rf-accent); color: var(--rf-accent-text); font-size: 9.5px; font-weight: 600;\n}\n.dt-sheet {\n --dt-enter-x: 20px;\n position: fixed; z-index: ${REFLET_Z_INDEX.widgetRoot}; top: 12px; bottom: 12px;\n display: flex; flex-direction: column; max-width: calc(100vw - 24px); max-height: calc(100dvh - 24px);\n border-radius: 16px; overflow: hidden;\n animation: dt-sheet-slide 320ms var(--rf-ease);\n}\n.dt-sheet[data-side=\"left\"] { --dt-enter-x: -20px; left: 12px; }\n.dt-sheet[data-side=\"right\"] { right: 12px; }\n.dt-sheet.glass::before { animation: rf-fade 220ms var(--rf-ease); }\n.dt-sheet-head, .dt-sheet-body { animation: rf-fade 260ms 60ms var(--rf-ease) both; }\n@keyframes dt-sheet-slide { from { transform: translateX(var(--dt-enter-x)); box-shadow: none; } }\n.dt-resize { position: absolute; z-index: 2; padding: 0; touch-action: none; }\n.dt-resize:active:not(:disabled) { scale: 1; }\n.dt-resize:focus-visible { outline: none; }\n.dt-resize[data-axis=\"width\"] { top: 16px; bottom: 16px; width: 10px; cursor: ew-resize; }\n.dt-sheet[data-side=\"right\"] .dt-resize[data-axis=\"width\"] { left: 0; }\n.dt-sheet[data-side=\"left\"] .dt-resize[data-axis=\"width\"] { right: 0; }\n.dt-resize[data-axis=\"height\"] { left: 16px; right: 16px; bottom: 0; height: 10px; cursor: ns-resize; }\n.dt-resize[data-axis=\"both\"] { bottom: 0; width: 16px; height: 16px; }\n.dt-sheet[data-side=\"right\"] .dt-resize[data-axis=\"both\"] { left: 0; cursor: nesw-resize; }\n.dt-sheet[data-side=\"left\"] .dt-resize[data-axis=\"both\"] { right: 0; cursor: nwse-resize; }\n.dt-resize[data-axis=\"width\"]::after, .dt-resize[data-axis=\"height\"]::after {\n content: \"\"; position: absolute; border-radius: var(--rf-pill); background: var(--rf-text-muted);\n opacity: 0; transition: opacity 160ms var(--rf-ease);\n}\n.dt-resize[data-axis=\"width\"]::after { top: 50%; left: 3px; width: 4px; height: 36px; translate: 0 -50%; }\n.dt-resize[data-axis=\"height\"]::after { left: 50%; top: 3px; width: 36px; height: 4px; translate: -50% 0; }\n.dt-resize:hover::after, .dt-resize:focus-visible::after, .dt-resize:active::after { opacity: .5; }\n.dt-sheet-head { position: relative; display: flex; align-items: center; gap: 4px; padding: 8px 8px 8px 6px; border-bottom: 1px solid var(--rf-border); }\n.dt-sheet-head > :not(.dt-sheet-drag) { position: relative; z-index: 1; }\n.dt-sheet-head .icon-btn { width: 32px; height: 32px; }\n.dt-sheet .dt-sheet-drag { position: absolute; inset: 0; z-index: 0; padding: 0; border-radius: 0; cursor: grab; touch-action: none; }\n.dt-sheet .dt-sheet-drag::before { content: \"\"; position: absolute; top: 4px; left: 50%; width: 36px; height: 4px; translate: -50% 0; border-radius: var(--rf-pill); background: var(--rf-text-muted); opacity: .3; transition: opacity 160ms var(--rf-ease); }\n.dt-sheet .dt-sheet-drag:hover::before, .dt-sheet .dt-sheet-drag:active::before { opacity: .7; }\n.dt-sheet .dt-sheet-drag:active:not(:disabled) { cursor: grabbing; scale: 1; }\n.dt-sheet .dt-sheet-drag:focus-visible { outline-offset: -2px; }\n.dt-tabs { display: flex; gap: 2px; margin-right: auto; }\n.dt-tab { height: 30px; padding: 0 11px; border-radius: var(--rf-pill); color: var(--rf-text-muted); font-weight: 500; }\n.dt-tab:hover { color: var(--rf-text); }\n.dt-tab[aria-selected=\"true\"], .dt-tab[aria-pressed=\"true\"] { background: var(--rf-bg-hover); color: var(--rf-text); }\n.dt-sheet-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; padding: 10px; }\n.dt-sheet-foot {\n position: sticky; bottom: -10px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px;\n margin: auto -10px -10px; padding: 10px; border-top: 1px solid var(--rf-border); background: var(--rf-bg);\n}\n.dt-archived { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 10px; border: 1px dashed var(--rf-border); border-radius: 12px; }\n.dt-archived .dt-meta { flex: 1 1 100%; }\n.dt-group { margin: 6px 2px 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--rf-text-muted); }\n.dt-card { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border-radius: 12px; background: var(--rf-bg-subtle); }\n.dt-card[data-sent=\"true\"] { opacity: .7; }\n.dt-card-head { display: flex; align-items: center; gap: 6px; min-width: 0; }\n.dt-card-title { min-width: 0; margin: 0; overflow: hidden; font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }\n.dt-meta { margin: 0; font-size: 11.5px; color: var(--rf-text-muted); overflow-wrap: anywhere; }\n.dt-note-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }\n.dt-chip { flex: none; padding: 1px 7px; border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text-muted); font-size: 10.5px; font-weight: 600; }\n.dt-chip[data-tone=\"accent\"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); color: var(--rf-accent); }\n.dt-source { padding: 0; font: 11.5px/1.4 ${MONO_FONT}; color: var(--rf-accent); text-align: left; overflow-wrap: anywhere; }\n.dt-source:hover { text-decoration: underline; }\n.dt-thumb { display: block; align-self: flex-start; max-width: 100%; height: auto; max-height: 132px; object-fit: contain; border-radius: 8px; box-shadow: var(--rf-shadow-inset); }\n.dt-actions { display: flex; flex-wrap: wrap; gap: 4px; }\n.dt-btn {\n display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;\n border-radius: var(--rf-pill); background: var(--rf-bg-hover); color: var(--rf-text);\n font-size: 12px; font-weight: 500; text-decoration: none;\n}\n.dt-btn:hover { background: color-mix(in srgb, var(--rf-text) 12%, transparent); }\n.dt-btn[data-variant=\"primary\"] { background: var(--rf-primary); color: var(--rf-primary-text); }\n.dt-btn[data-variant=\"danger\"] { color: var(--rf-danger); }\n.dt-empty { margin: auto; padding: 24px 16px; color: var(--rf-text-muted); font-size: 12.5px; text-align: center; }\n.dt-empty p { margin: 0 0 8px; }\n.dt-empty code, .dt-hint code { padding: 1px 4px; border-radius: 4px; background: var(--rf-bg-hover); font: 11.5px ${MONO_FONT}; overflow-wrap: anywhere; }\n.dt-hint { margin: 0; padding: 8px 10px; border-radius: 10px; background: var(--rf-bg-subtle); color: var(--rf-text-muted); font-size: 12px; }\n.dt-error { margin: 0; color: var(--rf-danger); font-size: 12px; }\n.dt-status { margin: 0 auto 0 0; color: var(--rf-text-muted); font-size: 12px; }\n.dt-field {\n width: 100%; padding: 7px 9px; border: 1px solid var(--rf-border); border-radius: 8px;\n background: var(--rf-bg); color: var(--rf-text); font: inherit; resize: vertical;\n}\n.dt-field:focus { outline: 2px solid var(--rf-accent); outline-offset: 0; }\n.dt-search { display: flex; gap: 6px; }\n.dt-matches { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }\n.dt-match { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 6px 8px; border-radius: 8px; text-align: left; }\n.dt-match:hover { background: var(--rf-bg-hover); }\n.dt-match code { font: 11.5px ${MONO_FONT}; color: var(--rf-accent); }\n.dt-match span { font: 11.5px ${MONO_FONT}; color: var(--rf-text-muted); white-space: pre; overflow: hidden; text-overflow: ellipsis; }\n.dt-code-head { display: flex; flex-direction: column; gap: 6px; }\n.dt-code-path { margin: 0; font: 12px/1.4 ${MONO_FONT}; overflow-wrap: anywhere; }\n.dt-code { flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 8px 0; border-radius: 10px; background: var(--rf-bg-subtle); font: 12px/1.6 ${MONO_FONT}; }\n.dt-code-lines { display: table; min-width: 100%; }\n.dt-line { display: table-row; white-space: pre; }\n.dt-line > span { display: table-cell; padding-right: 14px; }\n.dt-line > .dt-line-number { width: 1%; padding: 0 12px 0 10px; color: var(--rf-text-muted); text-align: right; user-select: none; }\n.dt-line[data-marked=\"true\"] { background: color-mix(in srgb, var(--rf-accent) 16%, transparent); }\n.dt-line[data-marked=\"true\"] > .dt-line-number { color: var(--rf-accent); }\n`;\n","export interface ZipEntry {\n data: Uint8Array<ArrayBuffer>;\n name: string;\n}\n\nconst LOCAL_HEADER_SIGNATURE = 0x04_03_4b_50;\nconst CENTRAL_HEADER_SIGNATURE = 0x02_01_4b_50;\nconst END_SIGNATURE = 0x06_05_4b_50;\nconst LOCAL_HEADER_SIZE = 30;\nconst CENTRAL_HEADER_SIZE = 46;\nconst END_RECORD_SIZE = 22;\nconst ZIP_VERSION = 20;\nconst UTF8_NAMES_FLAG = 0x08_00;\nconst DEFLATE_METHOD = 8;\nconst GZIP_HEADER_SIZE = 10;\nconst GZIP_FLAGS_OFFSET = 3;\nconst GZIP_TRAILER_SIZE = 8;\nconst DOS_EPOCH_YEAR = 1980;\n\ninterface DosStamp {\n date: number;\n time: number;\n}\n\ninterface EntryRecord {\n checksum: number;\n compressed: Uint8Array<ArrayBuffer>;\n name: Uint8Array<ArrayBuffer>;\n offset: number;\n size: number;\n}\n\nfunction dosStamp(date: Date): DosStamp {\n return {\n date:\n (date.getFullYear() - DOS_EPOCH_YEAR) * 512 +\n (date.getMonth() + 1) * 32 +\n date.getDate(),\n time:\n date.getHours() * 2048 +\n date.getMinutes() * 32 +\n Math.floor(date.getSeconds() / 2),\n };\n}\n\n/** gzip wraps raw deflate data and ends with the CRC-32 zip needs, so the browser computes both natively. */\nasync function deflateEntry(data: Uint8Array<ArrayBuffer>) {\n const stream = new Response(data).body?.pipeThrough(\n new CompressionStream(\"gzip\")\n );\n const gzip = new Uint8Array(await new Response(stream).arrayBuffer());\n if (gzip[GZIP_FLAGS_OFFSET] !== 0) {\n throw new Error(\"The browser wrote an unexpected gzip header.\");\n }\n const trailer = new DataView(gzip.buffer, gzip.length - GZIP_TRAILER_SIZE);\n return {\n checksum: trailer.getUint32(0, true),\n compressed: gzip.slice(GZIP_HEADER_SIZE, gzip.length - GZIP_TRAILER_SIZE),\n };\n}\n\nfunction writeCommonFields(\n view: DataView,\n start: number,\n options: { record: EntryRecord; stamp: DosStamp }\n) {\n const { record, stamp } = options;\n view.setUint16(start, ZIP_VERSION, true);\n view.setUint16(start + 2, UTF8_NAMES_FLAG, true);\n view.setUint16(start + 4, DEFLATE_METHOD, true);\n view.setUint16(start + 6, stamp.time, true);\n view.setUint16(start + 8, stamp.date, true);\n view.setUint32(start + 10, record.checksum, true);\n view.setUint32(start + 14, record.compressed.length, true);\n view.setUint32(start + 18, record.size, true);\n view.setUint16(start + 22, record.name.length, true);\n view.setUint16(start + 24, 0, true);\n}\n\nfunction localHeader(record: EntryRecord, stamp: DosStamp) {\n const bytes = new Uint8Array(LOCAL_HEADER_SIZE + record.name.length);\n const view = new DataView(bytes.buffer);\n view.setUint32(0, LOCAL_HEADER_SIGNATURE, true);\n writeCommonFields(view, 4, { record, stamp });\n bytes.set(record.name, LOCAL_HEADER_SIZE);\n return bytes;\n}\n\nfunction centralHeader(record: EntryRecord, stamp: DosStamp) {\n const bytes = new Uint8Array(CENTRAL_HEADER_SIZE + record.name.length);\n const view = new DataView(bytes.buffer);\n view.setUint32(0, CENTRAL_HEADER_SIGNATURE, true);\n view.setUint16(4, ZIP_VERSION, true);\n writeCommonFields(view, 6, { record, stamp });\n view.setUint32(42, record.offset, true);\n bytes.set(record.name, CENTRAL_HEADER_SIZE);\n return bytes;\n}\n\nfunction endRecord(options: {\n count: number;\n directoryOffset: number;\n directorySize: number;\n}) {\n const bytes = new Uint8Array(END_RECORD_SIZE);\n const view = new DataView(bytes.buffer);\n view.setUint32(0, END_SIGNATURE, true);\n view.setUint16(8, options.count, true);\n view.setUint16(10, options.count, true);\n view.setUint32(12, options.directorySize, true);\n view.setUint32(16, options.directoryOffset, true);\n return bytes;\n}\n\nexport async function createZipArchive(\n entries: ZipEntry[],\n modifiedAt: Date = new Date()\n): Promise<Blob> {\n const stamp = dosStamp(modifiedAt);\n const encoder = new TextEncoder();\n const deflated = await Promise.all(\n entries.map(async (entry) => ({\n ...(await deflateEntry(entry.data)),\n name: encoder.encode(entry.name),\n size: entry.data.length,\n }))\n );\n const records: EntryRecord[] = [];\n const parts: Uint8Array<ArrayBuffer>[] = [];\n let offset = 0;\n for (const entry of deflated) {\n const record = { ...entry, offset };\n const header = localHeader(record, stamp);\n parts.push(header, record.compressed);\n records.push(record);\n offset += header.length + record.compressed.length;\n }\n const directory = records.map((record) => centralHeader(record, stamp));\n const directorySize = directory.reduce((size, part) => size + part.length, 0);\n const end = endRecord({\n count: records.length,\n directoryOffset: offset,\n directorySize,\n });\n return new Blob([...parts, ...directory, end], { type: \"application/zip\" });\n}\n","import type { HandoffFile } from \"../../protocol\";\nimport { createZipArchive, type ZipEntry } from \"./zip-archive\";\n\nconst BRIEF_FILE_NAME = \"brief.md\";\nconst UNSAFE_FILE_CHARACTERS = /[^a-z0-9]+/g;\nconst EDGE_DASHES = /^-|-$/g;\n\nasync function downloadFile(file: HandoffFile): Promise<ZipEntry> {\n const response = await fetch(file.url);\n if (!response.ok) {\n throw new Error(\n `${file.name} could not be downloaded (${response.status}).`\n );\n }\n return {\n data: new Uint8Array(await response.arrayBuffer()),\n name: file.name,\n };\n}\n\nexport function zipFileName(sessionTitle: string): string {\n const slug = sessionTitle\n .toLowerCase()\n .replace(UNSAFE_FILE_CHARACTERS, \"-\")\n .replace(EDGE_DASHES, \"\");\n return `reflet-session-${slug || \"brief\"}.zip`;\n}\n\n/** File URLs are short-lived, so they are fetched right when the export is asked for. */\nexport async function buildBriefZip(options: {\n brief: string;\n files: HandoffFile[];\n}): Promise<Blob> {\n const evidence = await Promise.all(options.files.map(downloadFile));\n return await createZipArchive([\n { data: new TextEncoder().encode(options.brief), name: BRIEF_FILE_NAME },\n ...evidence,\n ]);\n}\n\nexport function saveBlob(options: { blob: Blob; fileName: string }) {\n const url = URL.createObjectURL(options.blob);\n const link = document.createElement(\"a\");\n link.download = options.fileName;\n link.href = url;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n","import type { SessionEvidence } from \"../../../protocol\";\n\nconst TRIGGER_LABELS: Record<SessionEvidence[\"trigger\"], string> = {\n manual: \"Added by hand\",\n mark: \"Marked moment\",\n navigation: \"Page change\",\n select: \"Pointed element\",\n start: \"Session start\",\n};\n\nexport function evidenceCaption(evidence: SessionEvidence): string {\n const element = evidence.element ? ` · ${evidence.element.label}` : \"\";\n return `${TRIGGER_LABELS[evidence.trigger]}${element}`;\n}\n\nfunction highlightStyle(evidence: SessionEvidence) {\n const { element, frame } = evidence;\n if (\n !(element && frame) ||\n frame.viewportWidth === 0 ||\n frame.viewportHeight === 0\n ) {\n return null;\n }\n const percent = (value: number, total: number) => `${(value / total) * 100}%`;\n return {\n height: percent(element.rect.height, frame.viewportHeight),\n left: percent(element.rect.x, frame.viewportWidth),\n top: percent(element.rect.y, frame.viewportHeight),\n width: percent(element.rect.width, frame.viewportWidth),\n };\n}\n\nexport function EvidenceThumb({\n evidence,\n isLarge = false,\n}: {\n evidence: SessionEvidence;\n isLarge?: boolean;\n}) {\n const { image } = evidence;\n if (!image?.url) {\n return null;\n }\n const highlight = highlightStyle(evidence);\n return (\n <span className=\"dt-ses-shot\" data-large={isLarge}>\n <img\n alt={evidenceCaption(evidence)}\n height={image.height}\n src={image.url}\n width={image.width}\n />\n {highlight && (\n <span\n aria-hidden=\"true\"\n className=\"dt-ses-shot-mark\"\n style={highlight}\n />\n )}\n </span>\n );\n}\n","import type { ReactNode } from \"react\";\nimport type {\n SessionDetail,\n SessionEvidence,\n SessionProposal,\n} from \"../../protocol\";\nimport { evidenceCaption } from \"../review/transcript/evidence-thumb\";\nimport { formatClock } from \"../session-format\";\n\nexport interface HandoffSelection {\n evidenceIds: string[];\n proposalIds: string[];\n}\n\nexport function keptProposals(detail: SessionDetail): SessionProposal[] {\n return detail.proposals.filter(\n (proposal) => proposal.decision === \"kept\" && proposal.mergedIntoId === null\n );\n}\n\nexport function evidenceOf(\n detail: SessionDetail,\n proposals: SessionProposal[]\n): SessionEvidence[] {\n const cited = new Set(proposals.flatMap((proposal) => proposal.evidenceIds));\n return detail.evidence.filter(\n (item) => cited.has(item.id) && item.status === \"available\"\n );\n}\n\nexport function initialSelection(detail: SessionDetail): HandoffSelection {\n const proposals = keptProposals(detail);\n return {\n evidenceIds: evidenceOf(detail, proposals).map((item) => item.id),\n proposalIds: proposals.map((proposal) => proposal.id),\n };\n}\n\nfunction toggled(ids: string[], id: string): string[] {\n return ids.includes(id) ? ids.filter((other) => other !== id) : [...ids, id];\n}\n\nfunction CheckRow({\n isChecked,\n label,\n onToggle,\n}: {\n isChecked: boolean;\n label: string;\n onToggle: () => void;\n}) {\n return (\n <li>\n <label className=\"dt-ses-check\">\n <input checked={isChecked} onChange={onToggle} type=\"checkbox\" />\n <span>{label}</span>\n </label>\n </li>\n );\n}\n\nfunction ChoiceGroup({\n children,\n legend,\n}: {\n children: ReactNode;\n legend: string;\n}) {\n return (\n <fieldset className=\"dt-ses-choices\">\n <legend className=\"dt-ses-label\">{legend}</legend>\n <ul className=\"dt-ses-list\">{children}</ul>\n </fieldset>\n );\n}\n\nexport function HandoffChoices({\n detail,\n onChange,\n selection,\n}: {\n detail: SessionDetail;\n onChange: (selection: HandoffSelection) => void;\n selection: HandoffSelection;\n}) {\n const proposals = keptProposals(detail);\n const evidence = evidenceOf(detail, proposals);\n const toggleProposal = (id: string) =>\n onChange({ ...selection, proposalIds: toggled(selection.proposalIds, id) });\n const toggleEvidence = (id: string) =>\n onChange({ ...selection, evidenceIds: toggled(selection.evidenceIds, id) });\n const chosenProposalIds = new Set(selection.proposalIds);\n const chosenEvidenceIds = new Set(selection.evidenceIds);\n return (\n <>\n <ChoiceGroup legend=\"Proposals\">\n {proposals.map((proposal) => (\n <CheckRow\n isChecked={chosenProposalIds.has(proposal.id)}\n key={proposal.id}\n label={proposal.need}\n onToggle={() => toggleProposal(proposal.id)}\n />\n ))}\n </ChoiceGroup>\n {evidence.length > 0 && (\n <ChoiceGroup legend=\"Evidence\">\n {evidence.map((item) => (\n <CheckRow\n isChecked={chosenEvidenceIds.has(item.id)}\n key={item.id}\n label={`${formatClock(item.atMs)} · ${evidenceCaption(item)}`}\n onToggle={() => toggleEvidence(item.id)}\n />\n ))}\n </ChoiceGroup>\n )}\n </>\n );\n}\n","import { useState } from \"react\";\nimport { copyToClipboard } from \"../../../devtools/client/clipboard\";\nimport { announce, reportFailure } from \"../../../devtools/client/notices\";\nimport type {\n HandoffFile,\n SessionDetail,\n SessionHandoff,\n} from \"../../protocol\";\nimport type { ReviewHandle } from \"../review/use-session-detail\";\nimport { useSessionAction, useSessionWorkspace } from \"../session-workspace\";\nimport { buildBriefZip, saveBlob, zipFileName } from \"./brief-export\";\nimport {\n HandoffChoices,\n type HandoffSelection,\n initialSelection,\n} from \"./handoff-selection\";\n\ninterface PreparedHandoff {\n files: HandoffFile[];\n handoff: SessionHandoff;\n}\n\nfunction useDelivery(options: { prepared: PreparedHandoff; title: string }) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const { files, handoff } = options.prepared;\n\n const deliver = async (\n kind: \"copied\" | \"exported\",\n send: () => Promise<void>\n ) => {\n try {\n await send();\n } catch (error) {\n reportFailure(`The brief was not ${kind}`, error);\n return;\n }\n announce(kind === \"copied\" ? \"Brief copied\" : \"Brief exported\");\n await run(\"The delivery was not recorded\", () =>\n api.markHandoffDelivered({ handoffId: handoff.id, kind })\n );\n };\n\n return {\n copy: () =>\n deliver(\"copied\", () => copyToClipboard(Promise.resolve(handoff.brief))),\n exportZip: () =>\n deliver(\"exported\", async () => {\n const blob = await buildBriefZip({ brief: handoff.brief, files });\n saveBlob({ blob, fileName: zipFileName(options.title) });\n }),\n };\n}\n\nfunction PreparedBrief({\n onChangeSelection,\n prepared,\n title,\n}: {\n onChangeSelection: () => void;\n prepared: PreparedHandoff;\n title: string;\n}) {\n const { copy, exportZip } = useDelivery({ prepared, title });\n return (\n <>\n <textarea\n aria-label=\"Brief\"\n className=\"dt-field dt-ses-brief\"\n readOnly\n rows={12}\n value={prepared.handoff.brief}\n />\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n onClick={copy}\n type=\"button\"\n >\n Copy brief\n </button>\n <button className=\"dt-btn\" onClick={exportZip} type=\"button\">\n Export .zip\n </button>\n <button className=\"dt-btn\" onClick={onChangeSelection} type=\"button\">\n Change selection\n </button>\n </div>\n </>\n );\n}\n\nfunction useInternalFeedback(proposalIds: string[]) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n return async () => {\n const results = await Promise.all(\n proposalIds.map((proposalId) =>\n run(\"The feedback was not created\", () =>\n api.createFeedback(proposalId)\n )\n )\n );\n if (results.every((result) => result !== null)) {\n announce(\n \"Internal feedback created — agents don't pick it up from the queue; hand off the brief instead.\"\n );\n }\n };\n}\n\ninterface PrepareHandoff {\n clear: () => void;\n isPreparing: boolean;\n prepare: () => Promise<void>;\n prepared: PreparedHandoff | null;\n select: (selection: HandoffSelection) => void;\n selection: HandoffSelection;\n}\n\nfunction usePrepareHandoff(options: {\n detail: SessionDetail;\n review: ReviewHandle;\n}): PrepareHandoff {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const [request, setRequest] = useState(() => ({\n clientKey: crypto.randomUUID(),\n selection: initialSelection(options.detail),\n }));\n const [prepared, setPrepared] = useState<PreparedHandoff | null>(null);\n const [isPreparing, setIsPreparing] = useState(false);\n\n const prepare = async () => {\n setIsPreparing(true);\n const result = await run(\"The brief was not prepared\", () =>\n api.createHandoff({\n clientKey: request.clientKey,\n sessionId: options.detail.session.id,\n ...request.selection,\n })\n );\n setIsPreparing(false);\n if (result) {\n setPrepared(result);\n options.review.reload();\n }\n };\n return {\n clear: () => setPrepared(null),\n isPreparing,\n prepare,\n prepared,\n select: (selection: HandoffSelection) =>\n setRequest({ clientKey: crypto.randomUUID(), selection }),\n selection: request.selection,\n };\n}\n\nfunction SelectionStep({\n detail,\n handoff,\n}: {\n detail: SessionDetail;\n handoff: PrepareHandoff;\n}) {\n const createFeedback = useInternalFeedback(handoff.selection.proposalIds);\n const hasProposals = handoff.selection.proposalIds.length > 0;\n return (\n <>\n <p className=\"dt-hint\">\n Coding agents get exactly the brief and files you pick here.\n </p>\n <HandoffChoices\n detail={detail}\n onChange={handoff.select}\n selection={handoff.selection}\n />\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={!hasProposals || handoff.isPreparing}\n onClick={handoff.prepare}\n type=\"button\"\n >\n Prepare brief\n </button>\n <button\n className=\"dt-btn\"\n disabled={!hasProposals}\n onClick={createFeedback}\n type=\"button\"\n >\n Create internal feedback\n </button>\n </div>\n </>\n );\n}\n\nexport function HandoffView({\n detail,\n onClose,\n review,\n}: {\n detail: SessionDetail;\n onClose: () => void;\n review: ReviewHandle;\n}) {\n const handoff = usePrepareHandoff({ detail, review });\n return (\n <section aria-labelledby=\"rf-handoff-title\" className=\"dt-ses-handoff\">\n <button className=\"dt-ses-link\" onClick={onClose} type=\"button\">\n ← Back to review\n </button>\n <h2 className=\"dt-ses-title\" id=\"rf-handoff-title\">\n Hand off\n </h2>\n {handoff.prepared ? (\n <PreparedBrief\n onChangeSelection={handoff.clear}\n prepared={handoff.prepared}\n title={detail.session.title}\n />\n ) : (\n <SelectionStep detail={detail} handoff={handoff} />\n )}\n <p className=\"dt-meta\">Copied or exported briefs can't be recalled.</p>\n </section>\n );\n}\n","import { useState } from \"react\";\nimport type { SessionDetail, SessionProposal } from \"../../../protocol\";\nimport { formatClock } from \"../../session-format\";\nimport { EvidenceThumb } from \"../transcript/evidence-thumb\";\nimport type { ReviewHandle } from \"../use-session-detail\";\nimport type { ProposalActions } from \"./use-proposal-actions\";\n\nexport interface ProposalContext {\n actions: ProposalActions;\n canEdit: boolean;\n detail: SessionDetail;\n onShowSegment: (segmentId: string) => void;\n review: ReviewHandle;\n}\n\nfunction ListSection({ items, title }: { items: string[]; title: string }) {\n if (items.length === 0) {\n return null;\n }\n return (\n <section>\n <h4 className=\"dt-ses-label\">{title}</h4>\n <ul className=\"dt-ses-list\">\n {items.map((item) => (\n <li key={item}>{item}</li>\n ))}\n </ul>\n </section>\n );\n}\n\nfunction RefinementState({\n onRetry,\n proposal,\n}: {\n onRetry: () => void;\n proposal: SessionProposal;\n}) {\n const { refinement } = proposal;\n if (refinement?.state === \"running\") {\n return <p className=\"dt-status\">Refining…</p>;\n }\n if (refinement?.state === \"outdated\") {\n return (\n <p className=\"dt-meta\">\n The proposal changed while it was being refined. Add your precision\n again.\n </p>\n );\n }\n if (refinement?.state !== \"failed\") {\n return null;\n }\n return (\n <div className=\"dt-actions\">\n <p className=\"dt-error\">\n Refining failed: {refinement.error ?? \"Unknown error.\"}\n </p>\n <button className=\"dt-btn\" onClick={onRetry} type=\"button\">\n Retry\n </button>\n </div>\n );\n}\n\nfunction ClarifyBox({\n context,\n proposal,\n}: {\n context: ProposalContext;\n proposal: SessionProposal;\n}) {\n const [text, setText] = useState(\"\");\n const isRefining = proposal.refinement?.state === \"running\";\n const lastClarification = proposal.clarifications.at(-1)?.text;\n const send = async (value: string) => {\n const sent = await context.actions.clarify(proposal, value);\n if (sent) {\n setText(\"\");\n }\n };\n\n return (\n <div className=\"dt-ses-form\">\n {proposal.question && <p className=\"dt-note-text\">{proposal.question}</p>}\n <textarea\n aria-label={proposal.question ? \"Your answer\" : \"Add a precision…\"}\n className=\"dt-field\"\n disabled={isRefining}\n maxLength={1000}\n onChange={(event) => setText(event.target.value)}\n placeholder=\"Add a precision…\"\n rows={2}\n value={text}\n />\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n disabled={isRefining || text.trim() === \"\"}\n onClick={() => send(text.trim())}\n type=\"button\"\n >\n Update proposal\n </button>\n </div>\n <RefinementState\n onRetry={() => lastClarification && send(lastClarification)}\n proposal={proposal}\n />\n </div>\n );\n}\n\nfunction Sources({\n context,\n proposal,\n}: {\n context: ProposalContext;\n proposal: SessionProposal;\n}) {\n const segmentIds = new Set(proposal.segmentIds);\n const evidenceIds = new Set(proposal.evidenceIds);\n const segments = context.detail.segments.filter((segment) =>\n segmentIds.has(segment.id)\n );\n const evidence = context.detail.evidence.filter((item) =>\n evidenceIds.has(item.id)\n );\n if (segments.length + evidence.length === 0) {\n return null;\n }\n return (\n <section>\n <h4 className=\"dt-ses-label\">Sources</h4>\n {segments.map((segment) => (\n <button\n className=\"dt-ses-quote\"\n key={segment.id}\n onClick={() => context.onShowSegment(segment.id)}\n type=\"button\"\n >\n <span className=\"dt-ses-time\">{formatClock(segment.startMs)}</span>\n {` “${segment.text}”`}\n </button>\n ))}\n <div className=\"dt-ses-thumbs\">\n {evidence.map((item) => (\n <EvidenceThumb evidence={item} key={item.id} />\n ))}\n </div>\n </section>\n );\n}\n\nexport function ProposalDetails({\n context,\n proposal,\n}: {\n context: ProposalContext;\n proposal: SessionProposal;\n}) {\n return (\n <>\n <section>\n <h4 className=\"dt-ses-label\">What you said or showed — not verified</h4>\n <p className=\"dt-note-text\">{proposal.observed}</p>\n </section>\n {proposal.response && (\n <section>\n <h4 className=\"dt-ses-label\">Considered response</h4>\n <p className=\"dt-note-text\">{proposal.response}</p>\n </section>\n )}\n <ListSection items={proposal.setAside} title=\"Set aside\" />\n <ListSection items={proposal.unknowns} title=\"Unknowns\" />\n {context.canEdit && <ClarifyBox context={context} proposal={proposal} />}\n <Sources context={context} proposal={proposal} />\n </>\n );\n}\n","import { useState } from \"react\";\nimport { SessionApiError } from \"../../api/session-api\";\nimport {\n failureMessage,\n isUnauthorized,\n useSessionWorkspace,\n} from \"../session-workspace\";\n\nexport type SaveProblem =\n | { kind: \"stale\" }\n | { kind: \"failed\"; message: string };\n\nexport function useGuardedSave() {\n const { onUnauthorized } = useSessionWorkspace();\n const [problem, setProblem] = useState<SaveProblem | null>(null);\n const [isSaving, setIsSaving] = useState(false);\n\n const save = async (write: () => Promise<void>) => {\n setIsSaving(true);\n setProblem(null);\n try {\n await write();\n } catch (error) {\n if (isUnauthorized(error)) {\n onUnauthorized();\n } else if (error instanceof SessionApiError && error.status === 409) {\n setProblem({ kind: \"stale\" });\n } else {\n setProblem({ kind: \"failed\", message: failureMessage(error) });\n }\n }\n setIsSaving(false);\n };\n return { isSaving, problem, save };\n}\n\nexport function SaveProblemMessage({\n onReload,\n problem,\n}: {\n onReload: () => void;\n problem: SaveProblem;\n}) {\n return (\n <div className=\"dt-actions\" role=\"alert\">\n <p className=\"dt-error\">\n {problem.kind === \"stale\"\n ? \"Someone changed this since you opened it. Reload it, then edit again.\"\n : `Not saved: ${problem.message}`}\n </p>\n {problem.kind === \"stale\" && (\n <button className=\"dt-btn\" onClick={onReload} type=\"button\">\n Reload\n </button>\n )}\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { reportFailure } from \"../../../devtools/client/notices\";\nimport { SessionApiError } from \"../../api/session-api\";\nimport type {\n SessionDetail,\n SessionEvidence,\n SessionProposal,\n SessionSegment,\n} from \"../../protocol\";\nimport { isDetailProcessing } from \"../session-format\";\nimport {\n failureMessage,\n isUnauthorized,\n useSessionWorkspace,\n} from \"../session-workspace\";\n\nconst POLL_INTERVAL_MS = 2000;\n\nexport type DetailState =\n | { kind: \"loading\" }\n | { kind: \"missing\" }\n | { kind: \"failed\"; message: string }\n | { detail: SessionDetail; kind: \"ready\" };\n\nexport interface SessionDetailHandle {\n patch: (update: (detail: SessionDetail) => SessionDetail) => void;\n reload: () => void;\n state: DetailState;\n}\n\nexport type ReviewHandle = Pick<SessionDetailHandle, \"patch\" | \"reload\">;\n\ninterface DetailRequest {\n count: number;\n sessionId: string;\n}\n\nfunction nextRequest(current: DetailRequest): DetailRequest {\n return { ...current, count: current.count + 1 };\n}\n\nexport function withProposal(\n detail: SessionDetail,\n proposal: SessionProposal\n): SessionDetail {\n const isKnown = detail.proposals.some((item) => item.id === proposal.id);\n return {\n ...detail,\n proposals: isKnown\n ? detail.proposals.map((item) =>\n item.id === proposal.id ? proposal : item\n )\n : [...detail.proposals, proposal],\n };\n}\n\nexport function withSegment(\n detail: SessionDetail,\n segment: SessionSegment\n): SessionDetail {\n const others = detail.segments.filter((item) => item.id !== segment.id);\n return {\n ...detail,\n segments: [...others, segment].sort((a, b) => a.startMs - b.startMs),\n };\n}\n\nexport function withEvidence(\n detail: SessionDetail,\n evidence: SessionEvidence\n): SessionDetail {\n return {\n ...detail,\n evidence: detail.evidence.map((item) =>\n item.id === evidence.id ? evidence : item\n ),\n };\n}\n\nfunction isHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\nfunction usePollTick(lastAnswer: DetailState): number {\n const [tick, setTick] = useState(0);\n useEffect(() => {\n if (lastAnswer.kind !== \"ready\" || !isDetailProcessing(lastAnswer.detail)) {\n return;\n }\n let timer = 0;\n const schedule = () => {\n window.clearTimeout(timer);\n if (!isHidden()) {\n timer = window.setTimeout(\n () => setTick((current) => current + 1),\n POLL_INTERVAL_MS\n );\n }\n };\n schedule();\n document.addEventListener(\"visibilitychange\", schedule);\n return () => {\n window.clearTimeout(timer);\n document.removeEventListener(\"visibilitychange\", schedule);\n };\n }, [lastAnswer]);\n return tick;\n}\n\nfunction failedState(error: unknown, current: DetailState): DetailState {\n if (error instanceof SessionApiError && error.status === 404) {\n return { kind: \"missing\" };\n }\n if (current.kind === \"ready\") {\n return current;\n }\n return { kind: \"failed\", message: failureMessage(error) };\n}\n\nexport function useSessionDetail(sessionId: string): SessionDetailHandle {\n const { api, onUnauthorized } = useSessionWorkspace();\n const [state, setState] = useState<DetailState>({ kind: \"loading\" });\n const [request, setRequest] = useState<DetailRequest>({\n count: 0,\n sessionId,\n });\n const pollTick = usePollTick(state);\n\n useEffect(() => {\n let isCurrent = true;\n api.detail(request.sessionId).then(\n (detail) => isCurrent && setState({ detail, kind: \"ready\" }),\n (error: unknown) => {\n if (isUnauthorized(error)) {\n onUnauthorized();\n return;\n }\n if (isCurrent) {\n setState((current) => failedState(error, current));\n }\n if (isCurrent && request.count + pollTick > 0) {\n reportFailure(\"The session did not refresh\", error);\n }\n }\n );\n return () => {\n isCurrent = false;\n };\n }, [api, onUnauthorized, request, pollTick]);\n\n return {\n patch: (update) =>\n setState((current) =>\n current.kind === \"ready\"\n ? { detail: update(current.detail), kind: \"ready\" }\n : current\n ),\n reload: () => setRequest(nextRequest),\n state,\n };\n}\n","import { useState } from \"react\";\nimport type { EditProposalBody } from \"../../../api/session-api\";\nimport type { SessionProposal } from \"../../../protocol\";\nimport { useSessionWorkspace } from \"../../session-workspace\";\nimport { SaveProblemMessage, useGuardedSave } from \"../guarded-save\";\nimport { type ReviewHandle, withProposal } from \"../use-session-detail\";\n\nconst MAX_LIST_ITEMS = 8;\n\ninterface ProposalDraft {\n need: string;\n observed: string;\n response: string;\n setAside: string;\n unknowns: string;\n}\n\nfunction lines(text: string): string[] {\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line !== \"\")\n .slice(0, MAX_LIST_ITEMS);\n}\n\nfunction editBody(\n proposal: SessionProposal,\n draft: ProposalDraft\n): EditProposalBody {\n return {\n expectedRevision: proposal.revision,\n need: draft.need.trim(),\n observed: draft.observed.trim(),\n proposalId: proposal.id,\n response: draft.response.trim() || null,\n setAside: lines(draft.setAside),\n unknowns: lines(draft.unknowns),\n };\n}\n\nexport function TextField({\n label,\n maxLength,\n onChange,\n rows,\n value,\n}: {\n label: string;\n maxLength: number;\n onChange: (value: string) => void;\n rows: number;\n value: string;\n}) {\n return (\n <label className=\"dt-ses-field\">\n <span>{label}</span>\n <textarea\n className=\"dt-field\"\n maxLength={maxLength}\n onChange={(event) => onChange(event.target.value)}\n rows={rows}\n value={value}\n />\n </label>\n );\n}\n\nexport function FormActions({\n isSubmitDisabled,\n onCancel,\n submitLabel,\n}: {\n isSubmitDisabled: boolean;\n onCancel: () => void;\n submitLabel: string;\n}) {\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={isSubmitDisabled}\n type=\"submit\"\n >\n {submitLabel}\n </button>\n <button className=\"dt-btn\" onClick={onCancel} type=\"button\">\n Cancel\n </button>\n </div>\n );\n}\n\ninterface DraftFieldProps {\n onChange: (value: string) => void;\n value: string;\n}\n\ntype DraftField = (key: keyof ProposalDraft) => DraftFieldProps;\n\nfunction useProposalDraft(proposal: SessionProposal) {\n const [draft, setDraft] = useState<ProposalDraft>({\n need: proposal.need,\n observed: proposal.observed,\n response: proposal.response ?? \"\",\n setAside: proposal.setAside.join(\"\\n\"),\n unknowns: proposal.unknowns.join(\"\\n\"),\n });\n const field: DraftField = (key) => ({\n onChange: (value: string) =>\n setDraft((current) => ({ ...current, [key]: value })),\n value: draft[key],\n });\n return { draft, field };\n}\n\nfunction ProposalDraftFields({ field }: { field: DraftField }) {\n return (\n <>\n <TextField label=\"Need\" maxLength={300} rows={2} {...field(\"need\")} />\n <TextField\n label=\"Observed\"\n maxLength={2000}\n rows={3}\n {...field(\"observed\")}\n />\n <TextField\n label=\"Considered response\"\n maxLength={1000}\n rows={2}\n {...field(\"response\")}\n />\n <TextField\n label=\"Unknowns (one per line)\"\n maxLength={2400}\n rows={2}\n {...field(\"unknowns\")}\n />\n <TextField\n label=\"Set aside (one per line)\"\n maxLength={2400}\n rows={2}\n {...field(\"setAside\")}\n />\n </>\n );\n}\n\nexport function ProposalEditor({\n onDone,\n proposal,\n review,\n}: {\n onDone: () => void;\n proposal: SessionProposal;\n review: ReviewHandle;\n}) {\n const { api } = useSessionWorkspace();\n const { isSaving, problem, save } = useGuardedSave();\n const { draft, field } = useProposalDraft(proposal);\n const submit = () =>\n save(async () => {\n const saved = await api.editProposal(editBody(proposal, draft));\n review.patch((detail) => withProposal(detail, saved));\n onDone();\n });\n\n return (\n <form\n className=\"dt-ses-form\"\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n >\n <ProposalDraftFields field={field} />\n {problem && (\n <SaveProblemMessage onReload={review.reload} problem={problem} />\n )}\n <FormActions\n isSubmitDisabled={isSaving || draft.need.trim() === \"\"}\n onCancel={onDone}\n submitLabel=\"Save\"\n />\n </form>\n );\n}\n","import { announce } from \"../../../../devtools/client/notices\";\nimport type { SessionApi } from \"../../../api/session-api\";\nimport type { ProposalDecision, SessionProposal } from \"../../../protocol\";\nimport { useSessionAction, useSessionWorkspace } from \"../../session-workspace\";\nimport { type ReviewHandle, withProposal } from \"../use-session-detail\";\n\nconst NOTICE_NEED_LENGTH = 60;\n\nconst DECISION_NOTICE: Record<ProposalDecision, string> = {\n dismissed: \"Dismissed\",\n kept: \"Kept\",\n later: \"Saved for later\",\n pending: \"Back to undecided\",\n};\n\nexport interface ProposalActions {\n clarify: (proposal: SessionProposal, text: string) => Promise<unknown>;\n decide: (proposal: SessionProposal, decision: ProposalDecision) => void;\n merge: (targetId: string, sourceIds: string[]) => void;\n save: (\n failureLabel: string,\n request: (api: SessionApi) => Promise<SessionProposal>\n ) => Promise<SessionProposal | null>;\n separate: (proposalId: string) => void;\n verify: (\n proposalId: string,\n outcome: { note: string; status: \"works\" | \"needs_work\" }\n ) => void;\n}\n\nexport function quotedNeed(need: string): string {\n const short =\n need.length > NOTICE_NEED_LENGTH\n ? `${need.slice(0, NOTICE_NEED_LENGTH - 1)}…`\n : need;\n return `“${short}”`;\n}\n\nfunction useProposalSave(review: ReviewHandle): ProposalActions[\"save\"] {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n return async (failureLabel, request) => {\n const proposal = await run(failureLabel, () => request(api));\n if (proposal) {\n review.patch((detail) => withProposal(detail, proposal));\n }\n return proposal;\n };\n}\n\nfunction decideWithUndo(\n save: ProposalActions[\"save\"]\n): ProposalActions[\"decide\"] {\n const restore = async (proposalId: string, decision: ProposalDecision) => {\n const restored = await save(\"The decision was not undone\", (client) =>\n client.decideProposal({ decision, proposalId })\n );\n if (restored) {\n announce(\"Decision undone\");\n }\n };\n\n return async (proposal, decision) => {\n const previous = proposal.decision;\n const updated = await save(\"The decision was not saved\", (client) =>\n client.decideProposal({ decision, proposalId: proposal.id })\n );\n if (updated) {\n announce(`${DECISION_NOTICE[decision]} ${quotedNeed(proposal.need)}`, {\n label: \"Undo\",\n run: () => restore(proposal.id, previous),\n });\n }\n };\n}\n\nexport function useProposalActions(review: ReviewHandle): ProposalActions {\n const save = useProposalSave(review);\n\n return {\n clarify: (proposal, text) =>\n save(\"The precision was not sent\", (client) =>\n client.clarifyProposal({\n expectedRevision: proposal.revision,\n proposalId: proposal.id,\n text,\n })\n ),\n decide: decideWithUndo(save),\n merge: async (targetId, sourceIds) => {\n const merged = await save(\"The proposals were not merged\", (client) =>\n client.mergeProposals({ sourceIds, targetId })\n );\n if (merged) {\n review.reload();\n }\n },\n save,\n separate: (proposalId) =>\n save(\"The suggestion was not cleared\", (client) =>\n client.separateProposal(proposalId)\n ),\n verify: (proposalId, { note, status }) =>\n save(\"The check was not saved\", (client) =>\n client.verifyProposal({ note: note || undefined, proposalId, status })\n ),\n };\n}\n","import { useState } from \"react\";\nimport type { SessionProposal } from \"../../../protocol\";\nimport type { ProposalContext } from \"./proposal-details\";\n\nconst OUTCOME_LABELS = {\n needs_work: \"Needs more work\",\n works: \"Works\",\n} as const;\n\nexport function Verification({\n context,\n proposal,\n}: {\n context: ProposalContext;\n proposal: SessionProposal;\n}) {\n const [note, setNote] = useState(proposal.verification?.note ?? \"\");\n if (proposal.handedOffRevision === null) {\n return null;\n }\n const { verification } = proposal;\n return (\n <fieldset className=\"dt-ses-verify\">\n <legend className=\"dt-ses-label\">Did the change work?</legend>\n {verification && (\n <p className=\"dt-meta\">\n Checked: {OUTCOME_LABELS[verification.status]}\n {verification.note ? ` · ${verification.note}` : \"\"}\n </p>\n )}\n <input\n aria-label=\"Note about the change (optional)\"\n className=\"dt-field\"\n maxLength={1000}\n onChange={(event) => setNote(event.target.value)}\n placeholder=\"Note (optional)\"\n value={note}\n />\n <div className=\"dt-actions\">\n {([\"works\", \"needs_work\"] as const).map((status) => (\n <button\n aria-pressed={verification?.status === status}\n className=\"dt-btn\"\n key={status}\n onClick={() =>\n context.actions.verify(proposal.id, { note: note.trim(), status })\n }\n type=\"button\"\n >\n {OUTCOME_LABELS[status]}\n </button>\n ))}\n </div>\n </fieldset>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { ProposalDecision, SessionProposal } from \"../../../protocol\";\nimport { type ProposalContext, ProposalDetails } from \"./proposal-details\";\nimport { ProposalEditor } from \"./proposal-editor\";\nimport { quotedNeed } from \"./use-proposal-actions\";\nimport { Verification } from \"./verification\";\n\nconst DECISION_CHIPS: Partial<Record<ProposalDecision, string>> = {\n dismissed: \"Dismissed\",\n kept: \"Kept\",\n later: \"Later\",\n};\n\nconst DECISION_BUTTONS: { decision: ProposalDecision; label: string }[] = [\n { decision: \"kept\", label: \"Keep\" },\n { decision: \"later\", label: \"Later\" },\n { decision: \"dismissed\", label: \"Dismiss\" },\n];\n\nfunction ProposalChips({ proposal }: { proposal: SessionProposal }) {\n const decisionChip = DECISION_CHIPS[proposal.decision];\n const { handedOffRevision } = proposal;\n let handoffChip: string | null = null;\n if (handedOffRevision !== null) {\n handoffChip =\n proposal.revision > handedOffRevision\n ? \"Changed since handoff\"\n : `Handed off rev ${handedOffRevision}`;\n }\n return (\n <div className=\"dt-ses-chips\">\n {proposal.certainty === \"uncertain\" && (\n <span className=\"dt-chip\">Unclear</span>\n )}\n {proposal.needsReview && (\n <span className=\"dt-chip\" data-tone=\"accent\">\n Needs review\n </span>\n )}\n {decisionChip && <span className=\"dt-chip\">{decisionChip}</span>}\n {handoffChip && <span className=\"dt-chip\">{handoffChip}</span>}\n </div>\n );\n}\n\nfunction MergeSuggestion({\n context,\n proposal,\n}: {\n context: ProposalContext;\n proposal: SessionProposal;\n}) {\n const suggestion = proposal.mergeSuggestion;\n if (!suggestion) {\n return null;\n }\n const suggestedIds = new Set(suggestion.withIds);\n const others = context.detail.proposals.filter(\n (other) => suggestedIds.has(other.id) && other.mergedIntoId === null\n );\n if (others.length === 0) {\n return null;\n }\n const names = others.map((other) => quotedNeed(other.need)).join(\", \");\n return (\n <div className=\"dt-ses-banner\">\n <p>Looks like the same need as {names}.</p>\n <p className=\"dt-meta\">{suggestion.reason}</p>\n {context.canEdit && (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n onClick={() =>\n context.actions.merge(\n proposal.id,\n others.map((other) => other.id)\n )\n }\n type=\"button\"\n >\n Merge\n </button>\n <button\n className=\"dt-btn\"\n onClick={() => context.actions.separate(proposal.id)}\n type=\"button\"\n >\n Keep separate\n </button>\n </div>\n )}\n </div>\n );\n}\n\nfunction DecisionButtons({\n context,\n onEdit,\n proposal,\n}: {\n context: ProposalContext;\n onEdit: () => void;\n proposal: SessionProposal;\n}) {\n return (\n <div className=\"dt-actions\">\n {DECISION_BUTTONS.map(({ decision, label }) => (\n <button\n aria-pressed={proposal.decision === decision}\n className=\"dt-btn\"\n data-variant={decision === \"kept\" ? \"primary\" : undefined}\n disabled={proposal.decision === decision}\n key={decision}\n onClick={() => context.actions.decide(proposal, decision)}\n type=\"button\"\n >\n {label}\n </button>\n ))}\n <button className=\"dt-btn\" onClick={onEdit} type=\"button\">\n Edit\n </button>\n </div>\n );\n}\n\ninterface Disclosure {\n detailsId: string;\n isExpanded: boolean;\n toggle: () => void;\n}\n\nfunction useDisclosure(): Disclosure {\n const [isExpanded, setIsExpanded] = useState(false);\n const detailsId = useId();\n return { detailsId, isExpanded, toggle: () => setIsExpanded(!isExpanded) };\n}\n\nfunction DetailsDisclosure({\n context,\n disclosure,\n proposal,\n}: {\n context: ProposalContext;\n disclosure: Disclosure;\n proposal: SessionProposal;\n}) {\n const { detailsId, isExpanded, toggle } = disclosure;\n return (\n <>\n <button\n aria-controls={detailsId}\n aria-expanded={isExpanded}\n className=\"dt-ses-link\"\n onClick={toggle}\n type=\"button\"\n >\n {isExpanded ? \"Hide details\" : \"Show details\"}\n </button>\n <div className=\"dt-ses-details\" hidden={!isExpanded} id={detailsId}>\n {isExpanded && (\n <ProposalDetails context={context} proposal={proposal} />\n )}\n </div>\n </>\n );\n}\n\nexport function ProposalCard({\n context,\n proposal,\n}: {\n context: ProposalContext;\n proposal: SessionProposal;\n}) {\n const disclosure = useDisclosure();\n const [isEditing, setIsEditing] = useState(false);\n\n if (isEditing) {\n return (\n <article className=\"dt-card\">\n <ProposalEditor\n key={proposal.revision}\n onDone={() => setIsEditing(false)}\n proposal={proposal}\n review={context.review}\n />\n </article>\n );\n }\n return (\n <article className=\"dt-card\" data-decision={proposal.decision}>\n <p className=\"dt-ses-need\" data-expanded={disclosure.isExpanded}>\n {proposal.need}\n </p>\n <ProposalChips proposal={proposal} />\n <MergeSuggestion context={context} proposal={proposal} />\n {context.canEdit && (\n <DecisionButtons\n context={context}\n onEdit={() => setIsEditing(true)}\n proposal={proposal}\n />\n )}\n <DetailsDisclosure\n context={context}\n disclosure={disclosure}\n proposal={proposal}\n />\n {context.canEdit && (\n <Verification context={context} proposal={proposal} />\n )}\n </article>\n );\n}\n","import { useState } from \"react\";\nimport type { SessionDetail } from \"../../../protocol\";\nimport { isAnalysisBusy } from \"../../session-format\";\nimport { ProposalCard } from \"./proposal-card\";\nimport type { ProposalContext } from \"./proposal-details\";\nimport { FormActions, TextField } from \"./proposal-editor\";\n\nfunction emptyCopy(detail: SessionDetail): string {\n const { session } = detail;\n if (session.collection !== \"ended\") {\n return \"Proposals appear here once the recording has uploaded and Reflet has read it.\";\n }\n if (detail.segments.length === 0 && detail.marks.length === 0) {\n return \"Nothing was said or marked in this session.\";\n }\n if (isAnalysisBusy(session)) {\n return \"Proposals appear here once Reflet has read the session.\";\n }\n if (session.analysis.state === \"failed\") {\n return \"The transcript is kept. Read it, or write the proposal yourself.\";\n }\n if (session.analysis.state === \"succeeded\") {\n return \"No request stood out in this session. Read the transcript or write the proposal yourself.\";\n }\n return \"Proposals appear here once the session is analyzed.\";\n}\n\nfunction useAddProposal(context: ProposalContext, onDone: () => void) {\n const [need, setNeed] = useState(\"\");\n const [observed, setObserved] = useState(\"\");\n const [clientKey] = useState(() => crypto.randomUUID());\n const [isSaving, setIsSaving] = useState(false);\n const sessionId = context.detail.session.id;\n\n const add = async () => {\n setIsSaving(true);\n try {\n const created = await context.actions.save(\n \"The proposal was not added\",\n (api) =>\n api.createProposal({\n clientKey,\n need: need.trim(),\n observed: observed.trim() || undefined,\n sessionId,\n })\n );\n if (created) {\n onDone();\n }\n } finally {\n setIsSaving(false);\n }\n };\n\n return { add, isSaving, need, observed, setNeed, setObserved };\n}\n\nfunction AddProposalForm({\n context,\n onDone,\n}: {\n context: ProposalContext;\n onDone: () => void;\n}) {\n const { add, isSaving, need, observed, setNeed, setObserved } =\n useAddProposal(context, onDone);\n\n return (\n <form\n className=\"dt-card dt-ses-form\"\n onSubmit={(event) => {\n event.preventDefault();\n add();\n }}\n >\n <TextField\n label=\"Need\"\n maxLength={300}\n onChange={setNeed}\n rows={2}\n value={need}\n />\n <TextField\n label=\"What you observed (optional)\"\n maxLength={2000}\n onChange={setObserved}\n rows={3}\n value={observed}\n />\n <FormActions\n isSubmitDisabled={isSaving || need.trim() === \"\"}\n onCancel={onDone}\n submitLabel=\"Add proposal\"\n />\n </form>\n );\n}\n\nexport function ProposalsTab({ context }: { context: ProposalContext }) {\n const [isAdding, setIsAdding] = useState(false);\n const proposals = context.detail.proposals.filter(\n (proposal) => proposal.mergedIntoId === null\n );\n return (\n <>\n {proposals.length === 0 && (\n <p className=\"dt-empty\">{emptyCopy(context.detail)}</p>\n )}\n {proposals.map((proposal) => (\n <ProposalCard context={context} key={proposal.id} proposal={proposal} />\n ))}\n {context.canEdit &&\n (isAdding ? (\n <AddProposalForm\n context={context}\n onDone={() => setIsAdding(false)}\n />\n ) : (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n onClick={() => setIsAdding(true)}\n type=\"button\"\n >\n Add a proposal\n </button>\n </div>\n ))}\n </>\n );\n}\n","import { useState } from \"react\";\nimport { announce } from \"../../../devtools/client/notices\";\nimport { MoreIcon } from \"../../../feedback/ui/icons\";\nimport type { SessionDetail, SessionSummary } from \"../../protocol\";\nimport { formatDate, shortDuration } from \"../session-format\";\nimport { useSessionAction, useSessionWorkspace } from \"../session-workspace\";\nimport type { ReviewHandle } from \"./use-session-detail\";\n\nconst DELETE_COPY =\n \"Delete this session? Its recordings, transcript and proposals are removed. Briefs you already copied or exported can't be recalled.\";\n\ntype ReviewSession = SessionDetail[\"session\"];\n\nfunction useSessionUpdate(review: ReviewHandle, sessionId: string) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n return async (\n failureLabel: string,\n change: { title?: string; visibility?: SessionSummary[\"visibility\"] }\n ) => {\n const updated = await run(failureLabel, () =>\n api.update({ sessionId, ...change })\n );\n if (updated) {\n review.patch((detail) => ({\n ...detail,\n session: { ...detail.session, ...updated },\n }));\n }\n return updated !== null;\n };\n}\n\nfunction TitleEditor({\n onDone,\n review,\n session,\n}: {\n onDone: () => void;\n review: ReviewHandle;\n session: ReviewSession;\n}) {\n const [title, setTitle] = useState(session.title);\n const update = useSessionUpdate(review, session.id);\n return (\n <form\n className=\"dt-search\"\n onSubmit={async (event) => {\n event.preventDefault();\n if (await update(\"The title was not saved\", { title: title.trim() })) {\n onDone();\n }\n }}\n >\n <input\n aria-label=\"Session title\"\n className=\"dt-field\"\n maxLength={120}\n onChange={(event) => setTitle(event.target.value)}\n value={title}\n />\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={title.trim() === \"\"}\n type=\"submit\"\n >\n Save\n </button>\n <button className=\"dt-btn\" onClick={onDone} type=\"button\">\n Cancel\n </button>\n </form>\n );\n}\n\nfunction DeleteConfirmation({\n onCancel,\n onDeleted,\n sessionId,\n}: {\n onCancel: () => void;\n onDeleted: () => void;\n sessionId: string;\n}) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const deleteSession = async () => {\n const deleted = await run(\"The session was not deleted\", () =>\n api.deleteSession(sessionId)\n );\n if (deleted !== null) {\n announce(\"Session deleted\");\n onDeleted();\n }\n };\n return (\n <div className=\"dt-ses-banner\">\n <p>{DELETE_COPY}</p>\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"danger\"\n onClick={deleteSession}\n type=\"button\"\n >\n Delete\n </button>\n <button className=\"dt-btn\" onClick={onCancel} type=\"button\">\n Cancel\n </button>\n </div>\n </div>\n );\n}\n\nfunction SessionMenu({\n onDeleted,\n review,\n session,\n}: {\n onDeleted: () => void;\n review: ReviewHandle;\n session: ReviewSession;\n}) {\n const update = useSessionUpdate(review, session.id);\n const [isConfirming, setIsConfirming] = useState(false);\n const isShared = session.visibility === \"team\";\n\n if (isConfirming) {\n return (\n <DeleteConfirmation\n onCancel={() => setIsConfirming(false)}\n onDeleted={onDeleted}\n sessionId={session.id}\n />\n );\n }\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n onClick={() =>\n update(\"The sharing was not changed\", {\n visibility: isShared ? \"private\" : \"team\",\n })\n }\n type=\"button\"\n >\n {isShared ? \"Make private\" : \"Share with team\"}\n </button>\n <button\n className=\"dt-btn\"\n data-variant=\"danger\"\n onClick={() => setIsConfirming(true)}\n type=\"button\"\n >\n Delete session\n </button>\n </div>\n );\n}\n\nfunction HeaderTitle({\n isMenuOpen,\n onRename,\n onToggleMenu,\n session,\n}: {\n isMenuOpen: boolean;\n onRename: () => void;\n onToggleMenu: () => void;\n session: ReviewSession;\n}) {\n return (\n <div className=\"dt-card-head\">\n <h2 className=\"dt-ses-title\">{session.title}</h2>\n {session.canEdit && (\n <>\n <button className=\"dt-btn\" onClick={onRename} type=\"button\">\n Rename\n </button>\n <button\n aria-expanded={isMenuOpen}\n aria-label=\"Session options\"\n className=\"icon-btn\"\n onClick={onToggleMenu}\n type=\"button\"\n >\n <MoreIcon />\n </button>\n </>\n )}\n </div>\n );\n}\n\nexport function ReviewHeader({\n onBack,\n review,\n session,\n}: {\n onBack: () => void;\n review: ReviewHandle;\n session: ReviewSession;\n}) {\n const [isRenaming, setIsRenaming] = useState(false);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const visibility =\n session.visibility === \"team\" ? \"Shared with team\" : \"Private\";\n return (\n <header className=\"dt-ses-head\">\n <button className=\"dt-ses-link\" onClick={onBack} type=\"button\">\n ← All sessions\n </button>\n {isRenaming ? (\n <TitleEditor\n onDone={() => setIsRenaming(false)}\n review={review}\n session={session}\n />\n ) : (\n <HeaderTitle\n isMenuOpen={isMenuOpen}\n onRename={() => setIsRenaming(true)}\n onToggleMenu={() => setIsMenuOpen(!isMenuOpen)}\n session={session}\n />\n )}\n <p className=\"dt-meta\">\n {formatDate(session.startedAt)} · {shortDuration(session.durationMs)} ·{\" \"}\n {visibility}\n {session.isMine ? \"\" : ` · ${session.authorName ?? \"A teammate\"}`}\n </p>\n {isMenuOpen && session.canEdit && (\n <SessionMenu onDeleted={onBack} review={review} session={session} />\n )}\n </header>\n );\n}\n","import { useSyncStatus } from \"../../local/local-sessions\";\nimport type { SessionDetail } from \"../../protocol\";\nimport { isAnalysisBusy, isAnalysisOutdated } from \"../session-format\";\nimport { useSessionAction, useSessionWorkspace } from \"../session-workspace\";\nimport type { ReviewHandle } from \"./use-session-detail\";\n\nfunction transcribingLine(detail: SessionDetail): string | null {\n const voice = detail.segments.filter((segment) => segment.source === \"voice\");\n const busy = voice.filter(\n (segment) =>\n segment.transcription.state === \"pending\" ||\n segment.transcription.state === \"running\"\n );\n if (busy.length === 0) {\n return null;\n }\n return `Transcribing ${voice.length - busy.length} of ${voice.length}`;\n}\n\nfunction analysisLine(detail: SessionDetail): {\n action: string | null;\n text: string;\n} | null {\n const { session } = detail;\n if (isAnalysisBusy(session)) {\n return { action: null, text: \"Reading the session…\" };\n }\n if (session.analysis.state === \"failed\") {\n const reason = session.analysis.error ?? \"Unknown error.\";\n return { action: \"Try again\", text: `Analysis failed: ${reason}` };\n }\n if (isAnalysisOutdated(session)) {\n return {\n action: \"Analyze again\",\n text: \"The transcript changed since the analysis.\",\n };\n }\n const canAnalyze =\n session.analysis.state === \"idle\" &&\n session.collection === \"ended\" &&\n detail.segments.length > 0;\n return canAnalyze ? { action: \"Analyze\", text: \"Not analyzed yet.\" } : null;\n}\n\nfunction AnalysisNotice({\n detail,\n review,\n}: {\n detail: SessionDetail;\n review: ReviewHandle;\n}) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const analysis = analysisLine(detail);\n if (!analysis) {\n return null;\n }\n const { session } = detail;\n\n const analyze = async () => {\n const status = await run(\"The analysis did not start\", () =>\n api.analyze(session.id)\n );\n if (status) {\n review.patch((current) => ({\n ...current,\n session: { ...current.session, analysis: status },\n }));\n }\n };\n\n return (\n <div className=\"dt-actions\">\n <p className={analysis.action === \"Try again\" ? \"dt-error\" : \"dt-status\"}>\n {analysis.text}\n </p>\n {analysis.action && session.canEdit && (\n <button className=\"dt-btn\" onClick={analyze} type=\"button\">\n {analysis.action}\n </button>\n )}\n </div>\n );\n}\n\nexport function StatusStrip({\n detail,\n review,\n}: {\n detail: SessionDetail;\n review: ReviewHandle;\n}) {\n const { account } = useSessionWorkspace();\n const sync = useSyncStatus(account.key);\n const uploading =\n detail.session.isMine && sync.pendingOperations > 0\n ? `${sync.pendingOperations} waiting to upload`\n : null;\n const transcribing = transcribingLine(detail);\n\n return (\n <div aria-live=\"polite\" className=\"dt-ses-strip\">\n {uploading && <p className=\"dt-status\">{uploading}</p>}\n {transcribing && <p className=\"dt-status\">{transcribing}</p>}\n <AnalysisNotice detail={detail} review={review} />\n </div>\n );\n}\n","import { type Dispatch, type SetStateAction, useState } from \"react\";\nimport type { SessionDetail } from \"../../../protocol\";\nimport { useSessionAction, useSessionWorkspace } from \"../../session-workspace\";\nimport type { ReviewHandle } from \"../use-session-detail\";\n\nconst WEB_PROTOCOLS = [\"http:\", \"https:\"];\n\ninterface LinkDraft {\n access: string;\n label: string;\n url: string;\n}\n\nconst EMPTY_LINK: LinkDraft = { access: \"\", label: \"\", url: \"\" };\n\ninterface AttachLinkProps {\n detail: SessionDetail;\n onDone: () => void;\n review: ReviewHandle;\n}\n\nfunction isWebUrl(value: string): boolean {\n try {\n return WEB_PROTOCOLS.includes(new URL(value).protocol);\n } catch {\n return false;\n }\n}\n\nfunction useLinkAttachment({ detail, onDone, review }: AttachLinkProps) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const [clientKey] = useState(() => crypto.randomUUID());\n return async (link: LinkDraft) => {\n const evidence = await run(\"The link was not attached\", () =>\n api.addEvidence({\n atMs: detail.session.durationMs,\n clientKey,\n link: {\n access: link.access.trim(),\n label: link.label.trim(),\n url: link.url.trim(),\n },\n sessionId: detail.session.id,\n trigger: \"manual\",\n })\n );\n if (evidence) {\n review.patch((current) => ({\n ...current,\n evidence: [...current.evidence, evidence],\n }));\n onDone();\n }\n };\n}\n\nfunction LinkFields({\n link,\n setLink,\n}: {\n link: LinkDraft;\n setLink: Dispatch<SetStateAction<LinkDraft>>;\n}) {\n const field = (key: keyof LinkDraft) => ({\n className: \"dt-field\",\n onChange: (event: { target: { value: string } }) =>\n setLink((current) => ({ ...current, [key]: event.target.value })),\n value: link[key],\n });\n return (\n <>\n <label className=\"dt-ses-field\">\n <span>URL</span>\n <input maxLength={2000} type=\"url\" {...field(\"url\")} />\n </label>\n <label className=\"dt-ses-field\">\n <span>Label</span>\n <input maxLength={120} {...field(\"label\")} />\n </label>\n <label className=\"dt-ses-field\">\n <span>Who can open it</span>\n <input\n maxLength={200}\n placeholder=\"For example: the design team\"\n {...field(\"access\")}\n />\n </label>\n </>\n );\n}\n\nexport function AttachLink({ detail, onDone, review }: AttachLinkProps) {\n const attachLink = useLinkAttachment({ detail, onDone, review });\n const [link, setLink] = useState(EMPTY_LINK);\n const isValid = isWebUrl(link.url.trim()) && link.label.trim() !== \"\";\n\n return (\n <form\n className=\"dt-card dt-ses-form\"\n onSubmit={(event) => {\n event.preventDefault();\n attachLink(link);\n }}\n >\n <LinkFields link={link} setLink={setLink} />\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={!isValid}\n type=\"submit\"\n >\n Attach link\n </button>\n <button className=\"dt-btn\" onClick={onDone} type=\"button\">\n Cancel\n </button>\n </div>\n </form>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { announce } from \"../../../../devtools/client/notices\";\nimport type { SessionEvidence } from \"../../../protocol\";\nimport { formatClock } from \"../../session-format\";\nimport { useSessionAction, useSessionWorkspace } from \"../../session-workspace\";\nimport { type ReviewHandle, withEvidence } from \"../use-session-detail\";\n\nconst REMOVE_COPY =\n \"Remove this screenshot? The image is deleted for good. Briefs you already copied or exported can't be recalled.\";\n\nexport interface EvidenceRemoval {\n canRemove: boolean;\n onRemoved: (evidenceId: string) => void;\n removedId: string | null;\n review: ReviewHandle;\n}\n\nexport function useFocusWhen<T extends HTMLElement>(shouldFocus: boolean) {\n const ref = useRef<T>(null);\n useEffect(() => {\n if (shouldFocus) {\n ref.current?.focus();\n }\n }, [shouldFocus]);\n return ref;\n}\n\nfunction RemoveConfirmation({\n evidence,\n onCancel,\n removal,\n}: {\n evidence: SessionEvidence;\n onCancel: () => void;\n removal: EvidenceRemoval;\n}) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const cancelRef = useFocusWhen<HTMLButtonElement>(true);\n\n const remove = async () => {\n const removed = await run(\"The screenshot was not removed\", () =>\n api.removeEvidence(evidence.id)\n );\n if (removed !== null) {\n removal.review.patch((detail) => withEvidence(detail, removed));\n removal.onRemoved(removed.id);\n announce(\"Screenshot removed\");\n }\n };\n return (\n <div className=\"dt-ses-banner\">\n <p>{REMOVE_COPY}</p>\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"danger\"\n onClick={remove}\n type=\"button\"\n >\n Remove\n </button>\n <button\n className=\"dt-btn\"\n onClick={onCancel}\n ref={cancelRef}\n type=\"button\"\n >\n Cancel\n </button>\n </div>\n </div>\n );\n}\n\nexport function RemoveEvidence({\n evidence,\n removal,\n}: {\n evidence: SessionEvidence;\n removal: EvidenceRemoval;\n}) {\n const [isConfirming, setIsConfirming] = useState(false);\n const [hasCancelled, setHasCancelled] = useState(false);\n const triggerRef = useFocusWhen<HTMLButtonElement>(hasCancelled);\n if (isConfirming) {\n return (\n <RemoveConfirmation\n evidence={evidence}\n onCancel={() => {\n setIsConfirming(false);\n setHasCancelled(true);\n }}\n removal={removal}\n />\n );\n }\n return (\n <button\n aria-label={`Remove screenshot at ${formatClock(evidence.atMs)}`}\n className=\"dt-ses-link\"\n onClick={() => {\n setIsConfirming(true);\n setHasCancelled(false);\n }}\n ref={triggerRef}\n type=\"button\"\n >\n Remove\n </button>\n );\n}\n","import { useState } from \"react\";\nimport type { SessionDetail, SessionEvidence } from \"../../../protocol\";\nimport { formatClock } from \"../../session-format\";\nimport type { ReviewHandle } from \"../use-session-detail\";\nimport { AttachLink } from \"./attach-link\";\nimport { EvidenceThumb, evidenceCaption } from \"./evidence-thumb\";\nimport {\n type EvidenceRemoval,\n RemoveEvidence,\n useFocusWhen,\n} from \"./remove-evidence\";\n\nconst isViewable = (evidence: SessionEvidence): boolean =>\n evidence.status === \"available\" && Boolean(evidence.image?.url);\n\nfunction MissingEvidenceItem({\n caption,\n evidence,\n isJustRemoved,\n}: {\n caption: string;\n evidence: SessionEvidence;\n isJustRemoved: boolean;\n}) {\n const cardRef = useFocusWhen<HTMLLIElement>(isJustRemoved);\n return (\n <li\n className=\"dt-card\"\n ref={cardRef}\n tabIndex={isJustRemoved ? -1 : undefined}\n >\n <p className=\"dt-meta\">{caption}</p>\n <p className=\"dt-meta\">\n Screenshot missing: {evidence.missingReason ?? \"not captured.\"}\n </p>\n </li>\n );\n}\n\nfunction LinkEvidenceItem({\n link,\n}: {\n link: NonNullable<SessionEvidence[\"link\"]>;\n}) {\n return (\n <li className=\"dt-card\">\n <a\n className=\"dt-source\"\n href={link.url}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {link.label}\n </a>\n <p className=\"dt-meta\">{link.url}</p>\n {link.access && <p className=\"dt-meta\">Who can open it: {link.access}</p>}\n </li>\n );\n}\n\nfunction EvidenceItem({\n evidence,\n onEnlarge,\n removal,\n}: {\n evidence: SessionEvidence;\n onEnlarge: () => void;\n removal: EvidenceRemoval;\n}) {\n const caption = `${formatClock(evidence.atMs)} · ${evidenceCaption(evidence)}`;\n if (evidence.link) {\n return <LinkEvidenceItem link={evidence.link} />;\n }\n if (!isViewable(evidence)) {\n return (\n <MissingEvidenceItem\n caption={caption}\n evidence={evidence}\n isJustRemoved={evidence.id === removal.removedId}\n />\n );\n }\n return (\n <li className=\"dt-card\">\n <button\n aria-label={`Enlarge: ${caption}`}\n className=\"dt-ses-shot-btn\"\n onClick={onEnlarge}\n type=\"button\"\n >\n <EvidenceThumb evidence={evidence} />\n </button>\n <p className=\"dt-meta\">{caption}</p>\n {evidence.note && <p className=\"dt-note-text\">{evidence.note}</p>}\n {removal.canRemove && (\n <RemoveEvidence evidence={evidence} removal={removal} />\n )}\n </li>\n );\n}\n\nfunction EnlargedEvidence({\n evidence,\n onBack,\n removal,\n}: {\n evidence: SessionEvidence;\n onBack: () => void;\n removal: EvidenceRemoval;\n}) {\n return (\n <>\n <button className=\"dt-ses-link\" onClick={onBack} type=\"button\">\n ← All evidence\n </button>\n <EvidenceThumb evidence={evidence} isLarge />\n <p className=\"dt-meta\">\n {formatClock(evidence.atMs)} · {evidenceCaption(evidence)}\n </p>\n {removal.canRemove && (\n <RemoveEvidence evidence={evidence} removal={removal} />\n )}\n </>\n );\n}\n\nfunction EvidenceList({\n evidence,\n onEnlarge,\n removal,\n}: {\n evidence: SessionEvidence[];\n onEnlarge: (evidenceId: string) => void;\n removal: EvidenceRemoval;\n}) {\n return (\n <>\n {evidence.length === 0 && (\n <p className=\"dt-empty\">No screenshots or links in this session.</p>\n )}\n <ul className=\"dt-ses-rows\">\n {evidence.map((item) => (\n <EvidenceItem\n evidence={item}\n key={item.id}\n onEnlarge={() => onEnlarge(item.id)}\n removal={removal}\n />\n ))}\n </ul>\n </>\n );\n}\n\nfunction AttachLinkAction({\n detail,\n review,\n}: {\n detail: SessionDetail;\n review: ReviewHandle;\n}) {\n const [isAttaching, setIsAttaching] = useState(false);\n if (isAttaching) {\n return (\n <AttachLink\n detail={detail}\n onDone={() => setIsAttaching(false)}\n review={review}\n />\n );\n }\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n onClick={() => setIsAttaching(true)}\n type=\"button\"\n >\n Attach a link\n </button>\n </div>\n );\n}\n\nexport function EvidenceTab({\n detail,\n review,\n}: {\n detail: SessionDetail;\n review: ReviewHandle;\n}) {\n const [enlargedId, setEnlargedId] = useState<string | null>(null);\n const [removedId, setRemovedId] = useState<string | null>(null);\n const enlarged = detail.evidence.find(\n (item) => item.id === enlargedId && isViewable(item)\n );\n const removal: EvidenceRemoval = {\n canRemove: detail.session.canEdit,\n onRemoved: (evidenceId) => {\n setEnlargedId(null);\n setRemovedId(evidenceId);\n },\n removedId,\n review,\n };\n\n if (enlarged) {\n return (\n <EnlargedEvidence\n evidence={enlarged}\n onBack={() => setEnlargedId(null)}\n removal={removal}\n />\n );\n }\n return (\n <>\n <EvidenceList\n evidence={detail.evidence}\n onEnlarge={setEnlargedId}\n removal={removal}\n />\n {detail.session.canEdit && (\n <AttachLinkAction detail={detail} review={review} />\n )}\n </>\n );\n}\n","import { useState } from \"react\";\nimport type { SessionSegment } from \"../../../protocol\";\nimport { formatClock } from \"../../session-format\";\nimport { useSessionAction, useSessionWorkspace } from \"../../session-workspace\";\nimport { SaveProblemMessage, useGuardedSave } from \"../guarded-save\";\nimport { type ReviewHandle, withSegment } from \"../use-session-detail\";\n\nfunction SaveCancelActions({\n isSaveDisabled,\n onCancel,\n onSave,\n}: {\n isSaveDisabled: boolean;\n onCancel: () => void;\n onSave: () => void;\n}) {\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={isSaveDisabled}\n onClick={onSave}\n type=\"button\"\n >\n Save\n </button>\n <button className=\"dt-btn\" onClick={onCancel} type=\"button\">\n Cancel\n </button>\n </div>\n );\n}\n\nfunction SegmentEditor({\n onDone,\n review,\n segment,\n}: {\n onDone: () => void;\n review: ReviewHandle;\n segment: SessionSegment;\n}) {\n const { api } = useSessionWorkspace();\n const { isSaving, problem, save } = useGuardedSave();\n const [text, setText] = useState(segment.text);\n const submit = () =>\n save(async () => {\n const saved = await api.correctSegment({\n expectedRevision: segment.revision,\n segmentId: segment.id,\n text: text.trim(),\n });\n review.patch((detail) => withSegment(detail, saved));\n review.reload();\n onDone();\n });\n\n return (\n <div className=\"dt-ses-form\">\n <textarea\n aria-label={`Passage at ${formatClock(segment.startMs)}`}\n className=\"dt-field\"\n maxLength={5000}\n onChange={(event) => setText(event.target.value)}\n rows={3}\n value={text}\n />\n {problem && (\n <SaveProblemMessage onReload={review.reload} problem={problem} />\n )}\n <SaveCancelActions\n isSaveDisabled={isSaving || text.trim() === \"\"}\n onCancel={onDone}\n onSave={submit}\n />\n </div>\n );\n}\n\nfunction SegmentBody({\n onType,\n review,\n segment,\n}: {\n onType?: () => void;\n review: ReviewHandle;\n segment: SessionSegment;\n}) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const { state } = segment.transcription;\n const retry = async () => {\n const pending = await run(\"The transcription did not restart\", () =>\n api.retrySegment(segment.id)\n );\n if (pending) {\n review.patch((detail) => withSegment(detail, pending));\n }\n };\n\n if (state === \"pending\" || state === \"running\") {\n return <p className=\"dt-status\">Transcribing…</p>;\n }\n if (state === \"failed\" || state === \"expired\") {\n return (\n <div className=\"dt-actions\">\n <p className=\"dt-error\">\n {state === \"failed\"\n ? \"Couldn't transcribe\"\n : \"Audio expired — type what you said\"}\n </p>\n {onType && state === \"failed\" && segment.hasAudio && (\n <button className=\"dt-btn\" onClick={retry} type=\"button\">\n Retry\n </button>\n )}\n {onType && (\n <button className=\"dt-btn\" onClick={onType} type=\"button\">\n Type it\n </button>\n )}\n </div>\n );\n }\n if (state === \"empty\" && segment.text === \"\") {\n return <p className=\"dt-meta\">No speech was heard here.</p>;\n }\n return <p className=\"dt-note-text\">{segment.text}</p>;\n}\n\nfunction ContextChips({ segment }: { segment: SessionSegment }) {\n if (segment.context.length === 0) {\n return null;\n }\n return (\n <div className=\"dt-ses-chips\">\n {segment.contextAmbiguous && (\n <span className=\"dt-chip\">Unclear which element</span>\n )}\n {segment.context.map((item) => (\n <span\n className=\"dt-chip\"\n key={`${item.kind}:${item.atMs}:${item.label}`}\n >\n {item.label}\n </span>\n ))}\n </div>\n );\n}\n\nfunction EditPassageLink({\n onEdit,\n time,\n}: {\n onEdit: () => void;\n time: string;\n}) {\n return (\n <button\n aria-label={`Edit passage at ${time}`}\n className=\"dt-ses-link\"\n onClick={onEdit}\n type=\"button\"\n >\n Edit\n </button>\n );\n}\n\nexport function SegmentRow({\n canEdit,\n isFocused,\n review,\n segment,\n}: {\n canEdit: boolean;\n isFocused: boolean;\n review: ReviewHandle;\n segment: SessionSegment;\n}) {\n const [isEditing, setIsEditing] = useState(false);\n const time = formatClock(segment.startMs);\n const isSettled = [\"done\", \"empty\"].includes(segment.transcription.state);\n const canStartEditing = canEdit && isSettled && !isEditing;\n\n return (\n <li\n className=\"dt-ses-seg\"\n ref={\n isFocused ? (node) => node?.focus({ preventScroll: false }) : undefined\n }\n tabIndex={-1}\n >\n <span className=\"dt-ses-time\">{time}</span>\n <div className=\"dt-ses-seg-body\">\n {isEditing ? (\n <SegmentEditor\n onDone={() => setIsEditing(false)}\n review={review}\n segment={segment}\n />\n ) : (\n <SegmentBody\n onType={canEdit ? () => setIsEditing(true) : undefined}\n review={review}\n segment={segment}\n />\n )}\n <ContextChips segment={segment} />\n {canStartEditing && (\n <EditPassageLink onEdit={() => setIsEditing(true)} time={time} />\n )}\n </div>\n </li>\n );\n}\n","import { type ReactNode, useState } from \"react\";\nimport type {\n SessionDetail,\n SessionGap,\n SessionMark,\n SessionSegment,\n} from \"../../../protocol\";\nimport { formatClock, shortDuration } from \"../../session-format\";\nimport { useSessionAction, useSessionWorkspace } from \"../../session-workspace\";\nimport { type ReviewHandle, withSegment } from \"../use-session-detail\";\nimport { SegmentRow } from \"./segment-row\";\n\nconst GAP_LABELS: Record<SessionGap[\"reason\"], string> = {\n hidden: \"Tab hidden\",\n interrupted: \"Interrupted\",\n limit: \"Time limit reached\",\n paused: \"Paused\",\n};\n\nfunction gapLabel(gap: SessionGap): string {\n const label = GAP_LABELS[gap.reason];\n return gap.endMs === null\n ? label\n : `${label} · ${shortDuration(gap.endMs - gap.startMs)}`;\n}\n\nfunction markLabel(mark: SessionMark): string {\n const note = mark.note ? ` — ${mark.note}` : \"\";\n if (mark.kind === \"navigation\") {\n return `Went to ${mark.url ?? mark.label}`;\n }\n const verb = mark.kind === \"select\" ? \"Pointed at\" : \"Marked a moment on\";\n return `${verb} ${mark.label}${note}`;\n}\n\nfunction TimelineNote({\n atMs,\n children,\n}: {\n atMs: number;\n children: ReactNode;\n}) {\n return (\n <li className=\"dt-ses-seg\" data-kind=\"note\">\n <span className=\"dt-ses-time\">{formatClock(atMs)}</span>\n <p className=\"dt-meta\">{children}</p>\n </li>\n );\n}\n\ntype TimelineItem =\n | { atMs: number; key: string; segment: SessionSegment }\n | { atMs: number; key: string; label: string };\n\ninterface TranscriptEditing {\n detail: SessionDetail;\n review: ReviewHandle;\n}\n\nfunction buildTimeline(detail: SessionDetail): TimelineItem[] {\n return [\n ...detail.segments.map((segment) => ({\n atMs: segment.startMs,\n key: `s:${segment.id}`,\n segment,\n })),\n ...detail.session.gaps.map((gap) => ({\n atMs: gap.startMs,\n key: `g:${gap.startMs}`,\n label: gapLabel(gap),\n })),\n ...detail.marks.map((mark) => ({\n atMs: mark.atMs,\n key: `m:${mark.kind}:${mark.atMs}`,\n label: markLabel(mark),\n })),\n ].sort((earlier, later) => earlier.atMs - later.atMs);\n}\n\nfunction useTypedPassage({ detail, review }: TranscriptEditing) {\n const { api } = useSessionWorkspace();\n const run = useSessionAction();\n const [text, setText] = useState(\"\");\n const [clientKey, setClientKey] = useState(() => crypto.randomUUID());\n const atMs = detail.segments.at(-1)?.endMs ?? 0;\n\n const add = async () => {\n const segment = await run(\"The passage was not added\", () =>\n api.addTypedSegment({\n clientKey,\n endMs: atMs,\n sessionId: detail.session.id,\n startMs: atMs,\n text: text.trim(),\n })\n );\n if (segment) {\n review.patch((current) => withSegment(current, segment));\n setText(\"\");\n setClientKey(crypto.randomUUID());\n }\n };\n\n return { add, setText, text };\n}\n\nfunction AddTypedPassage({ detail, review }: TranscriptEditing) {\n const { add, setText, text } = useTypedPassage({ detail, review });\n return (\n <div className=\"dt-ses-form\">\n <textarea\n aria-label=\"Add a typed passage\"\n className=\"dt-field\"\n maxLength={5000}\n onChange={(event) => setText(event.target.value)}\n placeholder=\"Add a typed passage\"\n rows={2}\n value={text}\n />\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n disabled={text.trim() === \"\"}\n onClick={add}\n type=\"button\"\n >\n Add passage\n </button>\n </div>\n </div>\n );\n}\n\nexport function TranscriptTab({\n detail,\n focusSegmentId,\n review,\n}: {\n detail: SessionDetail;\n focusSegmentId: string | null;\n review: ReviewHandle;\n}) {\n const { canEdit } = detail.session;\n const timeline = buildTimeline(detail);\n\n return (\n <>\n <p className=\"dt-hint\">\n Audio is deleted once transcribed. You can still correct the text.\n </p>\n {timeline.length === 0 && (\n <p className=\"dt-empty\">Nothing was said in this session.</p>\n )}\n <ol className=\"dt-ses-timeline\">\n {timeline.map((item) =>\n \"segment\" in item ? (\n <SegmentRow\n canEdit={canEdit}\n isFocused={item.segment.id === focusSegmentId}\n key={item.key}\n review={review}\n segment={item.segment}\n />\n ) : (\n <TimelineNote atMs={item.atMs} key={item.key}>\n {item.label}\n </TimelineNote>\n )\n )}\n </ol>\n {canEdit && <AddTypedPassage detail={detail} review={review} />}\n </>\n );\n}\n","import { useState } from \"react\";\nimport type { SessionDetail } from \"../../protocol\";\nimport { HandoffView } from \"../handoff/handoff-view\";\nimport type { ProposalContext } from \"./proposals/proposal-details\";\nimport { ProposalsTab } from \"./proposals/proposals-tab\";\nimport { useProposalActions } from \"./proposals/use-proposal-actions\";\nimport { ReviewHeader } from \"./review-header\";\nimport { StatusStrip } from \"./status-strip\";\nimport { EvidenceTab } from \"./transcript/evidence-tab\";\nimport { TranscriptTab } from \"./transcript/transcript-tab\";\nimport { type ReviewHandle, useSessionDetail } from \"./use-session-detail\";\n\ntype ReviewTab = \"evidence\" | \"proposals\" | \"transcript\";\n\nfunction HandoffFooter({\n detail,\n onHandOff,\n}: {\n detail: SessionDetail;\n onHandOff: () => void;\n}) {\n const kept = detail.proposals.filter(\n (proposal) => proposal.decision === \"kept\" && proposal.mergedIntoId === null\n ).length;\n return (\n <div className=\"dt-sheet-foot\">\n <button\n aria-describedby={kept === 0 ? \"rf-handoff-hint\" : undefined}\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={kept === 0}\n onClick={onHandOff}\n type=\"button\"\n >\n {kept === 0 ? \"Hand off\" : `Hand off ${kept} kept`}\n </button>\n {kept === 0 && (\n <span className=\"dt-status\" id=\"rf-handoff-hint\">\n Keep a proposal to hand it off\n </span>\n )}\n </div>\n );\n}\n\nfunction ReviewTabs({\n detail,\n onSelect,\n tab,\n}: {\n detail: SessionDetail;\n onSelect: (tab: ReviewTab) => void;\n tab: ReviewTab;\n}) {\n const proposalCount = detail.proposals.filter(\n (proposal) => proposal.mergedIntoId === null\n ).length;\n const options: { label: string; value: ReviewTab }[] = [\n { label: `Proposals (${proposalCount})`, value: \"proposals\" },\n { label: \"Transcript\", value: \"transcript\" },\n { label: `Evidence (${detail.evidence.length})`, value: \"evidence\" },\n ];\n return (\n <div className=\"dt-tabs dt-ses-tabs\">\n {options.map((option) => (\n <button\n aria-pressed={option.value === tab}\n className=\"dt-tab\"\n key={option.value}\n onClick={() => onSelect(option.value)}\n type=\"button\"\n >\n {option.label}\n </button>\n ))}\n </div>\n );\n}\n\nfunction ReviewTabPanel({\n context,\n focusSegmentId,\n tab,\n}: {\n context: ProposalContext;\n focusSegmentId: string | null;\n tab: ReviewTab;\n}) {\n const { detail, review } = context;\n if (tab === \"proposals\") {\n return <ProposalsTab context={context} />;\n }\n if (tab === \"transcript\") {\n return (\n <TranscriptTab\n detail={detail}\n focusSegmentId={focusSegmentId}\n review={review}\n />\n );\n }\n return <EvidenceTab detail={detail} review={review} />;\n}\n\nfunction useReviewTab() {\n const [tab, setTab] = useState<ReviewTab>(\"proposals\");\n const [focusSegmentId, setFocusSegmentId] = useState<string | null>(null);\n const showSegment = (segmentId: string) => {\n setFocusSegmentId(segmentId);\n setTab(\"transcript\");\n };\n return { focusSegmentId, setTab, showSegment, tab };\n}\n\nfunction ReviewScreen({\n detail,\n onBack,\n review,\n}: {\n detail: SessionDetail;\n onBack: () => void;\n review: ReviewHandle;\n}) {\n const { focusSegmentId, setTab, showSegment, tab } = useReviewTab();\n const [isHandingOff, setIsHandingOff] = useState(false);\n const actions = useProposalActions(review);\n const { canEdit } = detail.session;\n const context: ProposalContext = {\n actions,\n canEdit,\n detail,\n onShowSegment: showSegment,\n review,\n };\n\n if (isHandingOff) {\n return (\n <HandoffView\n detail={detail}\n onClose={() => setIsHandingOff(false)}\n review={review}\n />\n );\n }\n return (\n <>\n <ReviewHeader onBack={onBack} review={review} session={detail.session} />\n <StatusStrip detail={detail} review={review} />\n <ReviewTabs detail={detail} onSelect={setTab} tab={tab} />\n <ReviewTabPanel\n context={context}\n focusSegmentId={focusSegmentId}\n tab={tab}\n />\n {canEdit && (\n <HandoffFooter\n detail={detail}\n onHandOff={() => setIsHandingOff(true)}\n />\n )}\n </>\n );\n}\n\nexport function SessionReview({\n onBack,\n sessionId,\n}: {\n onBack: () => void;\n sessionId: string;\n}) {\n const handle = useSessionDetail(sessionId);\n const { state } = handle;\n if (state.kind === \"loading\") {\n return <p className=\"dt-status\">Loading the session…</p>;\n }\n if (state.kind === \"ready\") {\n return (\n <ReviewScreen detail={state.detail} onBack={onBack} review={handle} />\n );\n }\n return (\n <div className=\"dt-empty\">\n <p>\n {state.kind === \"missing\"\n ? \"This session is gone: it was deleted or is no longer shared with you.\"\n : `The session did not load: ${state.message}`}\n </p>\n <div className=\"dt-actions\">\n {state.kind === \"failed\" && (\n <button className=\"dt-btn\" onClick={handle.reload} type=\"button\">\n Try again\n </button>\n )}\n <button className=\"dt-btn\" onClick={onBack} type=\"button\">\n All sessions\n </button>\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport type { LocalDraft } from \"../../local/session-store\";\nimport type { SessionSummary } from \"../../protocol\";\nimport {\n formatDate,\n sessionStatusLine,\n shortDuration,\n} from \"../session-format\";\nimport {\n failureMessage,\n isUnauthorized,\n useSessionWorkspace,\n} from \"../session-workspace\";\n\nexport interface SessionTarget {\n sessionId: string | null;\n sessionKey: string | null;\n}\n\ntype ListState =\n | { kind: \"loading\" }\n | { kind: \"failed\"; message: string; retry: () => void }\n | { kind: \"ready\"; sessions: SessionSummary[] };\n\nfunction useSessionList(): ListState {\n const { api, onUnauthorized } = useSessionWorkspace();\n const [state, setState] = useState<ListState>({ kind: \"loading\" });\n\n useEffect(() => {\n let isCurrent = true;\n const load = () => {\n setState({ kind: \"loading\" });\n api.list().then(\n (sessions) => isCurrent && setState({ kind: \"ready\", sessions }),\n (error: unknown) => {\n if (isUnauthorized(error)) {\n onUnauthorized();\n } else if (isCurrent) {\n const message = failureMessage(error);\n setState({ kind: \"failed\", message, retry: load });\n }\n }\n );\n };\n load();\n return () => {\n isCurrent = false;\n };\n }, [api, onUnauthorized]);\n\n return state;\n}\n\nfunction SessionRow({\n isInterrupted,\n onOpen,\n session,\n}: {\n isInterrupted: boolean;\n onOpen: () => void;\n session: SessionSummary;\n}) {\n const author = session.isMine\n ? \"\"\n : ` · ${session.authorName ?? \"A teammate\"}`;\n return (\n <li>\n <button className=\"dt-ses-row\" onClick={onOpen} type=\"button\">\n <span className=\"dt-card-title\">{session.title}</span>\n <span className=\"dt-meta\">\n {formatDate(session.startedAt)} · {shortDuration(session.durationMs)}\n {author}\n </span>\n <span className=\"dt-meta\">\n {isInterrupted\n ? \"Interrupted · microphone off\"\n : sessionStatusLine(session)}\n </span>\n </button>\n </li>\n );\n}\n\nfunction UploadingDrafts({ drafts }: { drafts: LocalDraft[] }) {\n const waiting = drafts.filter(\n (draft) => draft.sessionId === null && draft.state === \"ended\"\n );\n if (waiting.length === 0) {\n return null;\n }\n return (\n <ul className=\"dt-ses-rows\">\n {waiting.map((draft) => (\n <li className=\"dt-ses-row\" key={draft.sessionKey}>\n <span className=\"dt-card-title\">{draft.title}</span>\n <span className=\"dt-meta\">\n {formatDate(draft.startedAt)} · Waiting to upload\n </span>\n </li>\n ))}\n </ul>\n );\n}\n\nfunction SessionGroup({\n interruptedIds,\n onOpen,\n sessions,\n title,\n}: {\n interruptedIds: ReadonlySet<string>;\n onOpen: (target: SessionTarget) => void;\n sessions: SessionSummary[];\n title: string;\n}) {\n if (sessions.length === 0) {\n return null;\n }\n return (\n <>\n <h2 className=\"dt-group\">{title}</h2>\n <ul className=\"dt-ses-rows\">\n {sessions.map((session) => (\n <SessionRow\n isInterrupted={\n session.collection !== \"ended\" && interruptedIds.has(session.id)\n }\n key={session.id}\n onOpen={() => onOpen({ sessionId: session.id, sessionKey: null })}\n session={session}\n />\n ))}\n </ul>\n </>\n );\n}\n\nexport function SessionList({\n drafts,\n onOpen,\n}: {\n drafts: LocalDraft[];\n onOpen: (target: SessionTarget) => void;\n}) {\n const state = useSessionList();\n if (state.kind === \"loading\") {\n return <p className=\"dt-status\">Loading sessions…</p>;\n }\n if (state.kind === \"failed\") {\n return (\n <div className=\"dt-actions\">\n <p className=\"dt-error\">Sessions did not load: {state.message}</p>\n <button className=\"dt-btn\" onClick={state.retry} type=\"button\">\n Try again\n </button>\n </div>\n );\n }\n const mine = state.sessions.filter((session) => session.isMine);\n const shared = state.sessions.filter((session) => !session.isMine);\n const interruptedIds = new Set(\n drafts.flatMap((draft) =>\n draft.state === \"interrupted\" && draft.sessionId ? [draft.sessionId] : []\n )\n );\n return (\n <>\n <UploadingDrafts drafts={drafts} />\n {mine.length + shared.length === 0 && (\n <p className=\"dt-meta\">Your recorded sessions will be listed here.</p>\n )}\n <SessionGroup\n interruptedIds={interruptedIds}\n onOpen={onOpen}\n sessions={mine}\n title=\"Mine\"\n />\n <SessionGroup\n interruptedIds={interruptedIds}\n onOpen={onOpen}\n sessions={shared}\n title=\"Shared with the team\"\n />\n </>\n );\n}\n","import { useState } from \"react\";\n\nconst SEEN_KEY_PREFIX = \"reflet-sessions-disclosure:\";\n\nfunction hasSeenDisclosure(accountKey: string): boolean {\n try {\n return localStorage.getItem(`${SEEN_KEY_PREFIX}${accountKey}`) !== null;\n } catch {\n return false;\n }\n}\n\nexport function markDisclosureSeen(accountKey: string): void {\n try {\n localStorage.setItem(`${SEEN_KEY_PREFIX}${accountKey}`, \"1\");\n } catch {\n // Storage blocked: the explanation simply shows again next time.\n }\n}\n\nfunction DisclosureList() {\n return (\n <section aria-labelledby=\"rf-session-disclosure\" className=\"dt-hint\">\n <h3 className=\"dt-ses-subhead\" id=\"rf-session-disclosure\">\n What a session records\n </h3>\n <ul className=\"dt-ses-list\">\n <li>\n Your voice while recording. It is sent to Reflet and transcribed by\n Whisper through OpenRouter with zero data retention. The audio is\n deleted as soon as its transcript is saved, within 24 hours at most.\n </li>\n <li>\n The page: its address without sensitive parameters, its title, the\n scroll position and the window size.\n </li>\n <li>\n What you click, point at and mark: element names and positions, never\n your keystrokes.\n </li>\n <li>\n Screenshots of this tab at the start, when you mark a moment and when\n the page changes. Form fields appear empty; password fields and\n elements marked <code>data-reflet-redact</code> are hidden. Other text\n on screen, rich-text editors included, stays visible.\n </li>\n <li>Not recorded: keystrokes, other tabs or apps, network calls.</li>\n <li>Pausing stops everything.</li>\n <li>A session stays private to you until you share it.</li>\n </ul>\n </section>\n );\n}\n\nexport function SessionDisclosure({ accountKey }: { accountKey: string }) {\n const [isOpen, setIsOpen] = useState(() => !hasSeenDisclosure(accountKey));\n if (isOpen) {\n return <DisclosureList />;\n }\n return (\n <button\n aria-expanded={false}\n className=\"dt-ses-link\"\n onClick={() => setIsOpen(true)}\n type=\"button\"\n >\n What a session records\n </button>\n );\n}\n","import { useState } from \"react\";\nimport type { RecorderSnapshot } from \"../../recorder/session-recorder\";\nimport { useRecorderSnapshot } from \"../../recorder/use-recorder-snapshot\";\nimport { useSessionWorkspace } from \"../session-workspace\";\nimport { markDisclosureSeen, SessionDisclosure } from \"./session-disclosure\";\n\ntype StartFailure = NonNullable<RecorderSnapshot[\"failure\"]>;\n\nconst IS_MICROPHONE_FAILURE: Record<StartFailure[\"kind\"], boolean> = {\n auth: false,\n insecure_context: true,\n limit: false,\n mic_blocked_by_site: true,\n mic_denied: true,\n mic_unavailable: true,\n network: false,\n storage: false,\n};\n\nfunction StartProblem({\n failure,\n onRetry,\n onWriteNote,\n}: {\n failure: StartFailure;\n onRetry: () => void;\n onWriteNote?: () => void;\n}) {\n return (\n <div className=\"dt-ses-problem\" role=\"alert\">\n <p className=\"dt-error\">{failure.message}</p>\n <div className=\"dt-actions\">\n <button className=\"dt-btn\" onClick={onRetry} type=\"button\">\n Try again\n </button>\n {IS_MICROPHONE_FAILURE[failure.kind] && onWriteNote && (\n <button className=\"dt-btn\" onClick={onWriteNote} type=\"button\">\n Write a note instead\n </button>\n )}\n </div>\n </div>\n );\n}\n\nfunction StartActions({\n isBusy,\n onStart,\n onWriteNote,\n}: {\n isBusy: boolean;\n onStart: () => void;\n onWriteNote?: () => void;\n}) {\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={isBusy}\n onClick={onStart}\n type=\"button\"\n >\n Start session\n </button>\n {onWriteNote && (\n <button className=\"dt-btn\" onClick={onWriteNote} type=\"button\">\n Write a note instead\n </button>\n )}\n </div>\n );\n}\n\nexport function StartSession({\n onStarted,\n onWriteNote,\n}: {\n onStarted: () => void;\n onWriteNote?: () => void;\n}) {\n const { account, recorder } = useSessionWorkspace();\n const snapshot = useRecorderSnapshot(recorder);\n const [hasTried, setHasTried] = useState(false);\n\n const start = async () => {\n markDisclosureSeen(account.key);\n setHasTried(true);\n await recorder.start({});\n if (recorder.getSnapshot().phase === \"recording\") {\n onStarted();\n }\n };\n\n const isRequesting = snapshot.phase === \"requesting\";\n const startFailure =\n hasTried && snapshot.phase === \"failed\" && snapshot.sessionKey === null\n ? snapshot.failure\n : null;\n\n return (\n <>\n <SessionDisclosure accountKey={account.key} />\n <p aria-live=\"polite\" className=\"dt-meta\">\n {isRequesting ? \"Allow the microphone in your browser to start.\" : \"\"}\n </p>\n {startFailure ? (\n <StartProblem\n failure={startFailure}\n onRetry={start}\n onWriteNote={onWriteNote}\n />\n ) : (\n <StartActions\n isBusy={isRequesting || snapshot.phase === \"finishing\"}\n onStart={start}\n onWriteNote={onWriteNote}\n />\n )}\n </>\n );\n}\n","import { discardLocalDraft, useLocalDrafts } from \"../../local/local-sessions\";\nimport type { LocalDraft } from \"../../local/session-store\";\nimport { formatDate } from \"../session-format\";\nimport { useSessionAction, useSessionWorkspace } from \"../session-workspace\";\nimport { SessionList, type SessionTarget } from \"./session-list\";\nimport { StartSession } from \"./start-session\";\n\ninterface InterruptedDraftProps {\n draft: LocalDraft;\n onOpenSession: (target: SessionTarget) => void;\n onStarted: () => void;\n}\n\nfunction useDraftRecovery({\n draft,\n onOpenSession,\n onStarted,\n}: InterruptedDraftProps) {\n const { account, api, recorder } = useSessionWorkspace();\n const run = useSessionAction();\n\n const review = async () => {\n const closed = await run(\"The session was not closed\", () =>\n discardLocalDraft({\n accountKey: account.key,\n api,\n sessionKey: draft.sessionKey,\n })\n );\n if (closed !== null) {\n onOpenSession({\n sessionId: draft.sessionId,\n sessionKey: draft.sessionKey,\n });\n }\n };\n\n const resume = async () => {\n await recorder.resumeDraft(draft.sessionKey);\n if (recorder.getSnapshot().phase === \"recording\") {\n onStarted();\n }\n };\n\n return { resume, review };\n}\n\nfunction InterruptedDraft(props: InterruptedDraftProps) {\n const { resume, review } = useDraftRecovery(props);\n\n return (\n <div className=\"dt-ses-banner\" role=\"status\">\n <p>\n Your session from {formatDate(props.draft.startedAt)} stopped when the\n page reloaded. The microphone is off.\n </p>\n <div className=\"dt-actions\">\n <button className=\"dt-btn\" onClick={review} type=\"button\">\n Review\n </button>\n <button className=\"dt-btn\" onClick={resume} type=\"button\">\n Resume recording\n </button>\n </div>\n </div>\n );\n}\n\nexport function SessionsHome({\n onOpenSession,\n onStarted,\n onWriteNote,\n}: {\n onOpenSession: (target: SessionTarget) => void;\n onStarted: () => void;\n onWriteNote?: () => void;\n}) {\n const { account } = useSessionWorkspace();\n const drafts = useLocalDrafts(account.key);\n const interrupted = drafts.filter((draft) => draft.state === \"interrupted\");\n const name = account.userName ?? account.userEmail ?? \"you\";\n\n return (\n <>\n <p className=\"dt-meta\">\n Recording as {name} · {account.organizationName}\n </p>\n {interrupted.map((draft) => (\n <InterruptedDraft\n draft={draft}\n key={draft.sessionKey}\n onOpenSession={onOpenSession}\n onStarted={onStarted}\n />\n ))}\n <StartSession onStarted={onStarted} onWriteNote={onWriteNote} />\n <SessionList drafts={drafts} onOpen={onOpenSession} />\n </>\n );\n}\n","import { useLocalDrafts } from \"../local/local-sessions\";\nimport { SessionReview } from \"./review/session-review\";\nimport { useSessionWorkspace } from \"./session-workspace\";\nimport type { SessionTarget } from \"./start/session-list\";\nimport { SessionsHome } from \"./start/sessions-home\";\n\nexport interface SessionNavigation {\n onOpen: (target: SessionTarget | null) => void;\n open: SessionTarget | null;\n}\n\nfunction useResolvedSessionId(target: SessionTarget | null): string | null {\n const { account } = useSessionWorkspace();\n const drafts = useLocalDrafts(account.key);\n if (!target) {\n return null;\n }\n return (\n target.sessionId ??\n drafts.find((draft) => draft.sessionKey === target.sessionKey)?.sessionId ??\n null\n );\n}\n\n/** A just-finished session may not have reached Reflet yet: it opens once its id is known. */\nexport function SessionsPanel({\n navigation,\n onStarted,\n onWriteNote,\n}: {\n navigation: SessionNavigation;\n onStarted: () => void;\n onWriteNote?: () => void;\n}) {\n const sessionId = useResolvedSessionId(navigation.open);\n const back = () => navigation.onOpen(null);\n\n if (sessionId) {\n return (\n <SessionReview key={sessionId} onBack={back} sessionId={sessionId} />\n );\n }\n if (navigation.open) {\n return (\n <div className=\"dt-empty\" role=\"status\">\n <p>\n This session is still uploading. It opens here once it reaches Reflet.\n </p>\n <button className=\"dt-btn\" onClick={back} type=\"button\">\n All sessions\n </button>\n </div>\n );\n }\n return (\n <SessionsHome\n onOpenSession={navigation.onOpen}\n onStarted={onStarted}\n onWriteNote={onWriteNote}\n />\n );\n}\n"],"mappings":"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"}