@opengeni/react 0.20.0 → 0.25.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.
Files changed (60) hide show
  1. package/dist/{chunk-6BXBGJ3B.js → chunk-6XUS5VFM.js} +2 -2
  2. package/dist/{chunk-MRSECXRP.js → chunk-AVPU5PMC.js} +87 -57
  3. package/dist/chunk-AVPU5PMC.js.map +1 -0
  4. package/dist/{chunk-HHFA4AFX.js → chunk-I3BJZIG5.js} +15 -1
  5. package/dist/chunk-I3BJZIG5.js.map +1 -0
  6. package/dist/{chunk-LAZ2A743.js → chunk-RDPDU4TA.js} +8 -7
  7. package/dist/chunk-RDPDU4TA.js.map +1 -0
  8. package/dist/{chunk-6UT5OC3P.js → chunk-SHOFILHJ.js} +130 -16
  9. package/dist/chunk-SHOFILHJ.js.map +1 -0
  10. package/dist/{chunk-EBTT3MYN.js → chunk-YDNWMKXO.js} +11 -1
  11. package/dist/chunk-YDNWMKXO.js.map +1 -0
  12. package/dist/{composer-DvUaa5ki.d.ts → composer-BXb0Q1HF.d.ts} +19 -5
  13. package/dist/composer.d.ts +3 -3
  14. package/dist/composer.js +3 -3
  15. package/dist/fleet-decision-projection-SLNZMS42.js +241 -0
  16. package/dist/fleet-decision-projection-SLNZMS42.js.map +1 -0
  17. package/dist/fleet-decision-row-GGCAT4E4.js +351 -0
  18. package/dist/fleet-decision-row-GGCAT4E4.js.map +1 -0
  19. package/dist/index.d.ts +14 -11
  20. package/dist/index.js +466 -244
  21. package/dist/index.js.map +1 -1
  22. package/dist/machines.d.ts +1 -1
  23. package/dist/machines.js +2 -2
  24. package/dist/{queue-surface-implementation-NQMV2ML3.js → queue-surface-implementation-3UW3MIIR.js} +9 -9
  25. package/dist/queue-surface-implementation-3UW3MIIR.js.map +1 -0
  26. package/dist/{session-Gd4iVPYw.d.ts → session-BEvtFWhe.d.ts} +71 -24
  27. package/dist/{session-context-DIFFlXKc.d.ts → session-context-rgrfElMl.d.ts} +7 -1
  28. package/dist/session.d.ts +3 -3
  29. package/dist/session.js +7 -3
  30. package/dist/{use-composer-BCfm4mzX.d.ts → use-composer-BnEzheSk.d.ts} +13 -20
  31. package/package.json +2 -2
  32. package/src/client.ts +4 -0
  33. package/src/components/composer.tsx +7 -6
  34. package/src/components/message-timeline.tsx +197 -25
  35. package/src/components/queue-draft-policy.ts +18 -0
  36. package/src/components/queue-surface-implementation.tsx +6 -10
  37. package/src/components/queue-surface.tsx +1 -0
  38. package/src/hooks/use-composer.ts +143 -83
  39. package/src/hooks/use-file-attachments.ts +95 -2
  40. package/src/hooks/use-goal.ts +22 -4
  41. package/src/hooks/use-session-mcp-approval-policy.ts +161 -0
  42. package/src/hooks/use-workspace-sessions.ts +30 -5
  43. package/src/index.ts +9 -0
  44. package/src/session-context.ts +25 -0
  45. package/src/session.ts +10 -0
  46. package/src/timeline/activity-rail.tsx +17 -1
  47. package/src/timeline/fleet-decision-projection.ts +366 -0
  48. package/src/timeline/fleet-decision-row.tsx +412 -0
  49. package/src/timeline/index.ts +2 -0
  50. package/src/timeline/projection.ts +19 -8
  51. package/src/timeline/tool-display-name.ts +16 -0
  52. package/src/timeline/tool-renderers.tsx +1 -1
  53. package/src/timeline/types.ts +76 -16
  54. package/dist/chunk-6UT5OC3P.js.map +0 -1
  55. package/dist/chunk-EBTT3MYN.js.map +0 -1
  56. package/dist/chunk-HHFA4AFX.js.map +0 -1
  57. package/dist/chunk-LAZ2A743.js.map +0 -1
  58. package/dist/chunk-MRSECXRP.js.map +0 -1
  59. package/dist/queue-surface-implementation-NQMV2ML3.js.map +0 -1
  60. /package/dist/{chunk-6BXBGJ3B.js.map → chunk-6XUS5VFM.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/timeline/projection.ts","../src/hooks/use-session-events.ts","../src/hooks/use-turn-queue.ts","../src/hooks/use-session-control.ts","../src/approvals.ts","../src/human-input.ts","../src/hooks/use-human-input.ts"],"sourcesContent":["import type { SessionEvent, SessionStatus } from \"@opengeni/sdk\";\nimport {\n CREDIT_EXHAUSTION_MESSAGE,\n humanizeFailureReason,\n isCreditExhaustion,\n tryParseJson,\n} from \"../lib/format\";\nimport type {\n AgentMessageItem,\n ActivityItem,\n AuthNeededItem,\n GoalItem,\n MemoryItem,\n SandboxItem,\n SessionStatusItem,\n TimelineGroup,\n TimelineItem,\n TurnEndItem,\n ToolCallItem,\n WorkerItem,\n} from \"./types\";\n\n/* ----------------------------------------------------------------------------\n Timeline projection\n\n `buildTimeline` folds a session's raw event log (replayed + live, ordered by\n sequence) into renderable items: chat messages with accumulated streaming\n deltas, reasoning summaries, tool calls matched to their outputs, sandbox\n operations with command output, spawned-worker status (the manager's\n `session_create` / `session_send_message` orchestration calls), goal\n markers, status changes, and turn failures.\n\n It is a pure function — same events in, same items out — so it can be\n memoized, unit-tested, and re-run incrementally as new events stream in.\n -------------------------------------------------------------------------- */\n\n/** Tool names on the first-party OpenGeni MCP server that operate on sessions. */\nconst WORKER_SPAWN_TOOL = \"session_create\";\nconst WORKER_MESSAGE_TOOL = \"session_send_message\";\n\nexport function buildTimeline(events: SessionEvent[]): TimelineItem[] {\n const items: TimelineItem[] = [];\n const prescan = prescanTurnAnchors(events);\n const ordered = orderTimelineEvents(events, prescan);\n\n const last = (): TimelineItem | undefined => items[items.length - 1];\n\n /** A new item of a different kind ends whatever was streaming at the tail. */\n const closeStreamingTail = (): void => {\n const open = last();\n if ((open?.kind === \"agent-message\" || open?.kind === \"reasoning\") && open.streaming) {\n open.streaming = false;\n }\n };\n\n const finalizeOpen = (\n turnId?: string | null,\n disposition: \"complete\" | \"failed\" | \"cancelled\" = \"complete\",\n ): void => {\n for (const item of items) {\n if (\n turnId !== undefined &&\n \"turnId\" in item &&\n item.turnId &&\n turnId &&\n item.turnId !== turnId\n ) {\n continue;\n }\n if ((item.kind === \"agent-message\" || item.kind === \"reasoning\") && item.streaming) {\n item.streaming = false;\n }\n if ((item.kind === \"tool-call\" || item.kind === \"worker\") && item.status === \"running\") {\n item.status = disposition;\n }\n if (item.kind === \"sandbox\" && item.status === \"running\") {\n item.status = disposition;\n }\n }\n };\n\n for (const event of ordered) {\n const payload = asRecord(event.payload);\n const turnId = event.turnId ?? null;\n\n switch (event.type) {\n case \"user.message\": {\n // A steering message must not mark in-flight tools complete; it only\n // ends whatever text was streaming. Turn lifecycle events finalize.\n closeStreamingTail();\n const childCompletion = workerCompletionPayload(payload.childCompletion);\n if (childCompletion) {\n items.push({\n kind: \"worker-completion\",\n id: event.id,\n turnId,\n occurredAt: event.occurredAt,\n childSessionId: childCompletion.childSessionId,\n childStatus: childCompletion.childStatus,\n goalStatus: childCompletion.goalStatus,\n goalText: childCompletion.goalText,\n evidence: childCompletion.evidence,\n pausedReason: childCompletion.pausedReason,\n text: typeof payload.text === \"string\" ? payload.text : \"\",\n });\n break;\n }\n items.push({\n kind: \"user-message\",\n id: event.id,\n text: typeof payload.text === \"string\" ? payload.text : \"\",\n resources: resourceRefs(payload.resources),\n tools: toolRefs(payload.tools),\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.message.delta\": {\n const text = typeof payload.text === \"string\" ? payload.text : \"\";\n if (!text) {\n break;\n }\n const open = last();\n if (open?.kind === \"agent-message\" && open.streaming && open.turnId === turnId) {\n open.text += text;\n break;\n }\n closeStreamingTail();\n items.push({\n kind: \"agent-message\",\n id: event.id,\n turnId,\n text,\n streaming: true,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.message.completed\": {\n const text = typeof payload.text === \"string\" ? payload.text : \"\";\n // Reconcile the most recent same-turn agent message — even when\n // activity (tool calls, reasoning) landed after its deltas — so the\n // completed text never duplicates the streamed one.\n const open = [...items]\n .reverse()\n .find(\n (item): item is AgentMessageItem =>\n item.kind === \"agent-message\" && item.turnId === turnId,\n );\n if (\n open &&\n (open.streaming || !open.text || text === open.text || text.startsWith(open.text))\n ) {\n // The completed text is authoritative when it extends what streamed.\n if (!open.text || (text && text.startsWith(open.text))) {\n open.text = text || open.text;\n }\n open.streaming = false;\n break;\n }\n if (text) {\n items.push({\n kind: \"agent-message\",\n id: event.id,\n turnId,\n text,\n streaming: false,\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"agent.reasoning.delta\": {\n const text = reasoningText(event.payload);\n if (!text) {\n break;\n }\n const open = last();\n if (open?.kind === \"reasoning\" && open.streaming && open.turnId === turnId) {\n open.text += text;\n break;\n }\n closeStreamingTail();\n items.push({\n kind: \"reasoning\",\n id: event.id,\n turnId,\n text,\n streaming: true,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.toolCall.created\": {\n const name = typeof payload.name === \"string\" ? payload.name : \"tool\";\n const callId = typeof payload.id === \"string\" ? payload.id : null;\n const args = payload.arguments ?? null;\n closeStreamingTail();\n if (name === WORKER_SPAWN_TOOL || name === WORKER_MESSAGE_TOOL) {\n items.push({\n kind: \"worker\",\n id: event.id,\n turnId,\n callId,\n action: name === WORKER_SPAWN_TOOL ? \"spawn\" : \"message\",\n prompt: workerPrompt(args),\n workerSessionId: extractSessionRef(args),\n status: \"running\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n items.push({\n kind: \"tool-call\",\n id: event.id,\n turnId,\n callId,\n name,\n arguments: args,\n output: undefined,\n // The provider-native item drives the per-tool renderers (apply_patch\n // operation, computer_call action, web_search providerData, …).\n raw: payload.raw,\n status: \"running\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.toolCall.output\": {\n const callId = typeof payload.id === \"string\" ? payload.id : null;\n const target = findOpenCall(items, callId);\n if (!target) {\n break;\n }\n if (target.kind === \"worker\") {\n // A worker spawn/message that returns an error flag (or an MCP\n // isError result) settles to \"failed\" too, so WorkerRow surfaces it.\n target.status = isErrorOutput(payload) ? \"failed\" : \"complete\";\n target.workerSessionId = target.workerSessionId ?? extractSessionRef(payload.output);\n break;\n }\n // An output carrying an explicit error flag (or an MCP isError result)\n // settles the tool to \"failed\" so the renderer can surface it loudly.\n target.status = isErrorOutput(payload) ? \"failed\" : \"complete\";\n target.output = payload.output;\n break;\n }\n\n case \"sandbox.operation.started\":\n case \"sandbox.operation.completed\":\n case \"sandbox.operation.failed\": {\n const name = typeof payload.name === \"string\" ? payload.name : \"sandbox\";\n const status = event.type.endsWith(\".failed\")\n ? \"failed\"\n : event.type.endsWith(\".completed\")\n ? \"complete\"\n : \"running\";\n // Routine per-turn platform plumbing that runs before EVERY turn to\n // guarantee box contents survive a re-warm — NOT the agent redoing work:\n // - repository-clone: idempotent clone check + off-manifest token re-seed;\n // - file-resource-download: idempotent `if [ ! -f ] then curl` (skips\n // when the attached file is already on the box — see\n // sandboxFileDownloadCommand), so an uploaded image is not re-fetched;\n // the operation still emits every turn even when it does nothing.\n // Rendering either every turn reads as churn. Only FAILURES surface, and\n // they surface loudly — the failed event below creates its own item even\n // without a started row.\n if (\n (name === \"repository-clone\" || name === \"file-resource-download\") &&\n status !== \"failed\"\n ) {\n break;\n }\n const existing = findOpenSandbox(items, name);\n if (existing && status !== \"running\") {\n existing.status = status;\n if (\n payload.origin === \"created\" ||\n payload.origin === \"restored\" ||\n payload.origin === \"resumed\"\n ) {\n existing.origin = payload.origin;\n }\n const message = failureMessage(payload);\n if (message) {\n existing.output = existing.output ? `${existing.output}\\n${message}` : message;\n }\n break;\n }\n if (!existing) {\n closeStreamingTail();\n items.push({\n kind: \"sandbox\",\n id: event.id,\n turnId,\n name,\n command: typeof payload.command === \"string\" ? payload.command : null,\n output: failureMessage(payload) ?? \"\",\n origin:\n payload.origin === \"created\" ||\n payload.origin === \"restored\" ||\n payload.origin === \"resumed\"\n ? payload.origin\n : null,\n status,\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"sandbox.command.output.delta\": {\n // `chunk` is the canonical wire field; text/output are legacy shapes.\n const text =\n typeof payload.chunk === \"string\"\n ? payload.chunk\n : typeof payload.text === \"string\"\n ? payload.text\n : typeof payload.output === \"string\"\n ? payload.output\n : \"\";\n if (!text) {\n break;\n }\n // Attach to the named operation when the payload carries one;\n // otherwise the latest running operation is the best available owner.\n const open =\n (typeof payload.name === \"string\" ? findOpenSandbox(items, payload.name) : undefined) ??\n [...items]\n .reverse()\n .find(\n (item): item is SandboxItem => item.kind === \"sandbox\" && item.status === \"running\",\n );\n if (open) {\n open.output += text;\n }\n break;\n }\n\n case \"session.status.changed\": {\n const status = payload.status;\n if (!isSessionStatus(status)) {\n break;\n }\n // Only attention-worthy statuses earn a timeline divider. queued /\n // running / idle are machinery telemetry: the header pill carries the\n // live status, the shimmer says \"running\", and the turn chip's duration\n // facet says how long — a stale \"idle · 27s\" row is pure noise,\n // especially in historical traces.\n if (!ATTENTION_STATUSES.has(status)) {\n break;\n }\n const previous = [...items]\n .reverse()\n .find((item): item is SessionStatusItem => item.kind === \"session-status\");\n if (previous?.status === status) {\n break;\n }\n items.push({ kind: \"session-status\", id: event.id, status, occurredAt: event.occurredAt });\n break;\n }\n\n case \"session.requiresAction\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"waiting\",\n text: \"Approval needed — the turn is paused until someone decides.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"session.context.compacted\": {\n closeStreamingTail();\n const before =\n typeof payload.estimatedTokensBefore === \"number\"\n ? Math.round(payload.estimatedTokensBefore).toLocaleString(\"en-US\")\n : null;\n const after =\n typeof payload.estimatedTokensAfter === \"number\"\n ? Math.round(payload.estimatedTokensAfter).toLocaleString(\"en-US\")\n : null;\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"waiting\",\n text:\n before && after\n ? `Active conversation history compacted from approximately ${before} to ${after} tokens.`\n : \"Context compacted so the turn could continue.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"session.context.compaction.skipped\": {\n closeStreamingTail();\n const reason = typeof payload.reason === \"string\" ? payload.reason : null;\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: reason === \"summarization_failed\" ? \"failed\" : \"waiting\",\n text:\n reason === \"no_history\"\n ? \"Context compaction skipped because there is no active history to compact.\"\n : reason === \"replacement_not_smaller\"\n ? \"Context compaction skipped because the generated checkpoint would not reduce the context.\"\n : reason === \"replacement_unchanged\"\n ? \"Context compaction stopped because it reproduced the same checkpoint without making progress.\"\n : reason === \"summarization_failed\"\n ? \"Context compaction failed without replacing the active conversation history. Request it again to retry.\"\n : \"Context compaction was not needed.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"turn.recovery.requested\": {\n // Recovery requests are durable control-plane evidence, not a user\n // message or proof that recovery succeeded. Live state already exposes\n // a genuinely recovering session; keep the raw event in Debug/audit.\n break;\n }\n\n case \"turn.event.rejected_late\": {\n // Attempt-fence rejections prove stale callbacks did not alter current\n // truth. They are useful diagnostics but never actionable chat content,\n // regardless of the rejected event type. Debug/audit retains the event.\n break;\n }\n\n case \"tool.auth_needed\":\n case \"credential.auth_needed\": {\n // Keep the whole structured payload — the renderer turns it into a clean\n // inline reconnect card, and the app starts the recovery flow off the\n // connectionId/resource. Losing it to a plain-text notice was the ugly\n // \"linear.app needs to be reconnected.\" line users complained about.\n closeStreamingTail();\n items.push({\n kind: \"auth-needed\",\n id: event.id,\n turnId,\n providerDomain: typeof payload.providerDomain === \"string\" ? payload.providerDomain : \"\",\n connectionId: typeof payload.connectionId === \"string\" ? payload.connectionId : null,\n reason: authNeededReason(payload.reason),\n scopes: stringList(payload.scopes),\n resource: typeof payload.resource === \"string\" ? payload.resource : null,\n toolName: typeof payload.toolName === \"string\" ? payload.toolName : null,\n authorizationUrl:\n typeof payload.authorizationUrl === \"string\" ? payload.authorizationUrl : null,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"turn.completed\": {\n // A standalone manual compaction uses the turn ledger for fencing and\n // recovery, but it is maintenance rather than a conversational turn.\n // The dedicated session.context.compacted notice is the complete UI\n // truth; adding a generic turn chip would falsely make it look like an\n // extra agent response.\n if (payload.maintenance === \"context_compaction\") {\n finalizeOpen(turnId);\n break;\n }\n // Credit exhaustion arrives as a NOMINALLY completed turn (`detail:\n // \"insufficient OpenGeni credits\"`, `segmentLimit: \"budget_exhausted\"`)\n // — the engine ended the segment early, it did not finish the work.\n // Rendering it as a clean \"complete\" turn is a lie that leaves the\n // session looking healthy while every future turn silently dies, so it\n // projects exactly like a failed turn plus an explicit notice.\n if (isCreditExhaustionPayload(payload)) {\n finalizeOpen(turnId);\n items.push(turnEndItem(event, \"failed\", CREDIT_EXHAUSTION_MESSAGE));\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"failed\",\n text: CREDIT_EXHAUSTION_MESSAGE,\n occurredAt: event.occurredAt,\n });\n break;\n }\n finalizeOpen(turnId);\n items.push(turnEndItem(event, \"complete\", null));\n break;\n }\n\n case \"turn.failed\": {\n const hadActivity = hasTurnActivity(items, turnId);\n // Credit death can hide behind fields `failureMessage` doesn't read\n // (detail/segmentLimit), so classify the whole payload before falling\n // back to the generic error/message extraction.\n const failureText = isCreditExhaustionPayload(payload)\n ? CREDIT_EXHAUSTION_MESSAGE\n : failureMessage(payload);\n // The TURN failed — the in-flight items did not. Chip doctrine: red is\n // spent once, on the turn-level outcome. Items caught mid-flight read\n // as calm \"interrupted\" (same as turn.cancelled); an item that itself\n // failed keeps its own failed status from its output event.\n finalizeOpen(turnId, \"cancelled\");\n items.push(turnEndItem(event, \"failed\", failureText));\n if (!hadActivity) {\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"failed\",\n text: failureText ?? \"The turn failed.\",\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"turn.cancelled\": {\n // A retraction of a never-started queued turn is not a turn ending —\n // the message was withdrawn before any work happened; show nothing.\n // A null turnId proves nothing, so it keeps the legacy finalize path.\n if (turnId && !prescan.startedTurnIds.has(turnId)) {\n break;\n }\n const hadActivity = hasTurnActivity(items, turnId);\n finalizeOpen(turnId, \"cancelled\");\n items.push(turnEndItem(event, \"cancelled\", null));\n if (!hadActivity) {\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"cancelled\",\n text: \"Interrupted.\",\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"memory.saved\":\n case \"memory.corrected\": {\n // A first-party memory write is a discrete step, not streamed text, so it\n // ends whatever was streaming (mirrors tool/sandbox pushes). A payload\n // missing the memory id is malformed and dropped rather than shown blank.\n const memory = memoryItem(event.id, event.type, turnId, payload, event.occurredAt);\n if (memory) {\n closeStreamingTail();\n items.push(memory);\n }\n break;\n }\n\n case \"goal.set\":\n case \"goal.updated\":\n case \"goal.completed\":\n case \"goal.paused\":\n case \"goal.resumed\":\n case \"goal.cleared\":\n case \"goal.continuation\": {\n items.push({\n kind: \"goal\",\n id: event.id,\n action: event.type.slice(\"goal.\".length) as GoalItem[\"action\"],\n text: goalText(payload),\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n default:\n break;\n }\n }\n\n return items;\n}\n\n/** The turn-end payload shape, as `isCreditExhaustion` wants it. */\nfunction isCreditExhaustionPayload(payload: Record<string, unknown>): boolean {\n return isCreditExhaustion({\n error: typeof payload.error === \"string\" ? payload.error : null,\n detail: typeof payload.detail === \"string\" ? payload.detail : null,\n segmentLimit: typeof payload.segmentLimit === \"string\" ? payload.segmentLimit : null,\n });\n}\n\n/**\n * Whether the session's most recent turn ended in credit exhaustion — the\n * terminal credit state apps key their \"add credits\" affordances on. Derived\n * from the LAST turn-end event (completed/failed/cancelled): a later turn that\n * settles any other way (someone topped up and kept working) clears it.\n */\nexport function creditExhaustedFromEvents(events: SessionEvent[]): boolean {\n const ordered = [...events].sort((a, b) => a.sequence - b.sequence);\n for (let index = ordered.length - 1; index >= 0; index -= 1) {\n const event = ordered[index];\n if (\n event?.type !== \"turn.completed\" &&\n event?.type !== \"turn.failed\" &&\n event?.type !== \"turn.cancelled\"\n ) {\n continue;\n }\n return isCreditExhaustionPayload(asRecord(event.payload));\n }\n return false;\n}\n\n/** The latest session status carried in the event log, if any. */\nexport function sessionStatusFromEvents(events: SessionEvent[]): SessionStatus | null {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event?.type !== \"session.status.changed\") {\n continue;\n }\n const status = asRecord(event.payload).status;\n if (isSessionStatus(status)) {\n return status;\n }\n }\n return null;\n}\n\n/* ----------------------------------------------------------------------------\n Visual grouping: consecutive activity items (reasoning / tools / workers /\n sandbox) cluster into collapsible blocks. Once a turn settles, the full\n non-user span folds behind a turn group, with activity blocks nested inside.\n -------------------------------------------------------------------------- */\n\n/**\n * Whether an item clusters into an activity block. A `switch` (not a stringly-\n * typed set) so adding an {@link ActivityItem} kind is a compile-time prompt to\n * decide its grouping — and it narrows `item` to `ActivityItem` with no cast.\n */\nfunction isActivityItem(item: TimelineItem): item is ActivityItem {\n switch (item.kind) {\n case \"reasoning\":\n case \"tool-call\":\n case \"worker\":\n case \"sandbox\":\n case \"memory\":\n return true;\n default:\n return false;\n }\n}\n\nexport function groupTimeline(items: TimelineItem[]): TimelineGroup[] {\n const groups: TimelineGroup[] = [];\n for (const item of items) {\n if (isActivityItem(item)) {\n const open = groups[groups.length - 1];\n if (open?.kind === \"activity\" && open.outcome === undefined) {\n open.items.push(item);\n } else {\n groups.push({ kind: \"activity\", id: `activity-${item.id}`, items: [item] });\n }\n continue;\n }\n if (item.kind === \"turn-end\") {\n stampTurnOutcome(groups, item);\n foldSettledTurn(groups, item);\n continue;\n }\n groups.push({ kind: \"item\", item });\n }\n return groups;\n}\n\n/* --- helpers ---------------------------------------------------------------- */\n\ntype TurnAnchorPrescan = {\n queuedTurnByTrigger: Map<string, string>;\n startSeqByTrigger: Map<string, number>;\n cancelledBeforeStartTriggers: Set<string>;\n startedTurnIds: Set<string>;\n};\n\nfunction prescanTurnAnchors(events: SessionEvent[]): TurnAnchorPrescan {\n const ordered = [...events].sort((a, b) => a.sequence - b.sequence);\n const queuedTurnByTrigger = new Map<string, string>();\n const startSeqByTrigger = new Map<string, number>();\n const cancelledTurnIds = new Set<string>();\n const fallbackSeqByTurn = new Map<string, number>();\n const startedTurnIds = new Set<string>();\n\n for (const event of ordered) {\n const payload = asRecord(event.payload);\n const turnId = event.turnId ?? null;\n if (event.type === \"turn.queued\") {\n const triggerEventId =\n typeof payload.triggerEventId === \"string\" ? payload.triggerEventId : null;\n const queuedTurnId = typeof payload.turnId === \"string\" ? payload.turnId : turnId;\n if (triggerEventId && queuedTurnId) {\n queuedTurnByTrigger.set(triggerEventId, queuedTurnId);\n }\n continue;\n }\n if (event.type === \"turn.started\") {\n const triggerEventId =\n typeof payload.triggerEventId === \"string\" ? payload.triggerEventId : null;\n if (triggerEventId && !startSeqByTrigger.has(triggerEventId)) {\n startSeqByTrigger.set(triggerEventId, event.sequence);\n }\n if (turnId) {\n startedTurnIds.add(turnId);\n }\n } else if (event.type === \"turn.cancelled\" && turnId) {\n cancelledTurnIds.add(turnId);\n }\n\n if (turnId && isTurnExecutionEvidence(event.type)) {\n const previous = fallbackSeqByTurn.get(turnId);\n if (previous === undefined || event.sequence < previous) {\n fallbackSeqByTurn.set(turnId, event.sequence);\n }\n }\n if (turnId && isTurnExecutionEvidence(event.type)) {\n startedTurnIds.add(turnId);\n }\n }\n\n for (const [triggerEventId, turnId] of queuedTurnByTrigger) {\n if (!startSeqByTrigger.has(triggerEventId)) {\n const fallbackSeq = fallbackSeqByTurn.get(turnId);\n if (fallbackSeq !== undefined) {\n startSeqByTrigger.set(triggerEventId, fallbackSeq);\n }\n }\n }\n\n const cancelledBeforeStartTriggers = new Set<string>();\n for (const [triggerEventId, turnId] of queuedTurnByTrigger) {\n if (\n cancelledTurnIds.has(turnId) &&\n !startSeqByTrigger.has(triggerEventId) &&\n !fallbackSeqByTurn.has(turnId)\n ) {\n cancelledBeforeStartTriggers.add(triggerEventId);\n }\n }\n\n return { queuedTurnByTrigger, startSeqByTrigger, cancelledBeforeStartTriggers, startedTurnIds };\n}\n\nfunction orderTimelineEvents(events: SessionEvent[], prescan: TurnAnchorPrescan): SessionEvent[] {\n const ordered = [...events].sort((a, b) => a.sequence - b.sequence);\n const insertions = new Map<number, SessionEvent[]>();\n\n for (const event of ordered) {\n if (event.type !== \"user.message\") {\n continue;\n }\n const queuedTurnId = prescan.queuedTurnByTrigger.get(event.id);\n if (!queuedTurnId) {\n pushInsertion(insertions, event.sequence, event);\n continue;\n }\n if (prescan.cancelledBeforeStartTriggers.has(event.id)) {\n continue;\n }\n const startSeq = prescan.startSeqByTrigger.get(event.id);\n if (startSeq !== undefined) {\n pushInsertion(insertions, startSeq, event);\n continue;\n }\n // A waiting prompt belongs only in the prompt queue. It enters the\n // timeline at turn.started (or the first same-turn activity fallback),\n // never as a second queued representation.\n }\n\n const projected: SessionEvent[] = [];\n for (const event of ordered) {\n const before = insertions.get(event.sequence);\n if (before) {\n projected.push(...before);\n }\n if (event.type !== \"user.message\") {\n projected.push(event);\n }\n }\n return projected;\n}\n\nfunction pushInsertion(\n insertions: Map<number, SessionEvent[]>,\n sequence: number,\n event: SessionEvent,\n): void {\n const bucket = insertions.get(sequence);\n if (bucket) {\n bucket.push(event);\n } else {\n insertions.set(sequence, [event]);\n }\n}\n\nfunction isAgentActivityEvent(type: string): boolean {\n return type.startsWith(\"agent.\") || type.startsWith(\"sandbox.\");\n}\n\n/**\n * Evidence that a queued prompt crossed the execution boundary when an older\n * or partially recovered ledger is missing its canonical `turn.started`.\n * Queue/control bookkeeping intentionally does not qualify: moving, editing,\n * steering, or deleting a waiting row must never make its prompt appear in the\n * transcript as though inference had begun.\n */\nfunction isTurnExecutionEvidence(type: string): boolean {\n return (\n isAgentActivityEvent(type) ||\n type === \"turn.completed\" ||\n type === \"turn.failed\" ||\n type === \"turn.recovery.requested\" ||\n type === \"turn.capacity_waiting\" ||\n type === \"session.requiresAction\" ||\n type === \"tool.auth_needed\" ||\n type === \"credential.auth_needed\" ||\n type.startsWith(\"rig.setup.\") ||\n type === \"codex.capacity.waiting\" ||\n type === \"codex.capacity.resumed\"\n );\n}\n\nfunction turnEndItem(\n event: SessionEvent,\n outcome: TurnEndItem[\"outcome\"],\n failureText: string | null,\n): TurnEndItem {\n return {\n kind: \"turn-end\",\n id: `${event.id}-turn-end`,\n turnId: event.turnId ?? null,\n outcome,\n failureText,\n occurredAt: event.occurredAt,\n };\n}\n\nfunction hasTurnActivity(items: TimelineItem[], turnId: string | null): boolean {\n if (turnId) {\n return items.some((item) => isActivityItem(item) && item.turnId === turnId);\n }\n for (let index = items.length - 1; index >= 0; index -= 1) {\n const item = items[index];\n if (!item || item.kind === \"turn-end\" || item.kind === \"user-message\") {\n return false;\n }\n if (isActivityItem(item)) {\n return true;\n }\n }\n return false;\n}\n\nfunction stampTurnOutcome(groups: TimelineGroup[], turnEnd: TurnEndItem): void {\n if (turnEnd.turnId === null) {\n const trailing = groups[groups.length - 1];\n if (trailing?.kind === \"activity\" && trailing.outcome === undefined) {\n applyTurnOutcome(trailing, turnEnd);\n }\n return;\n }\n for (const group of groups) {\n if (group.kind !== \"activity\" || group.outcome !== undefined) {\n continue;\n }\n if (group.items.some((activity) => activity.turnId === turnEnd.turnId)) {\n applyTurnOutcome(group, turnEnd);\n }\n }\n}\n\nfunction applyTurnOutcome(\n group: Extract<TimelineGroup, { kind: \"activity\" }>,\n turnEnd: TurnEndItem,\n): void {\n // A sub-cluster reports ITS OWN outcome, not the turn's. When a turn fails\n // at step 7, clusters 1–6 completed — painting them all red says \"everything\n // broke\" when one thing did. The turn-level fold carries the turn outcome;\n // a cluster goes red only if an item inside it actually failed, and reads\n // \"cancelled\" (interrupted) only when it holds the items cut off mid-flight.\n if (turnEnd.outcome === \"complete\") {\n group.outcome = \"complete\";\n return;\n }\n const hasFailed = group.items.some((item) => \"status\" in item && item.status === \"failed\");\n const hasInterrupted = group.items.some(\n (item) => \"status\" in item && item.status === \"cancelled\",\n );\n group.outcome = hasFailed ? \"failed\" : hasInterrupted ? \"cancelled\" : \"complete\";\n if (turnEnd.failureText && hasFailed) {\n group.failureText = turnEnd.failureText;\n }\n}\n\nfunction foldSettledTurn(groups: TimelineGroup[], turnEnd: TurnEndItem): void {\n let startIndex = groups.length;\n let stoppedAtForeignTurn = false;\n while (startIndex > 0) {\n const previous = groups[startIndex - 1];\n if (isTurnBoundary(previous)) {\n break;\n }\n if (belongsToDifferentTurn(previous, turnEnd.turnId)) {\n stoppedAtForeignTurn = true;\n break;\n }\n startIndex -= 1;\n }\n if (stoppedAtForeignTurn) {\n while (startIndex < groups.length && isBetweenTurnDivider(groups[startIndex])) {\n startIndex += 1;\n }\n }\n\n const collected = groups.slice(startIndex);\n if (collected.length === 0) {\n return;\n }\n\n const finalMessage = extractFinalAgentMessage(collected, turnEnd);\n const body = finalMessage ? collected.slice(0, -1) : collected;\n if (body.length === 0) {\n return;\n }\n\n const firstOccurredAt = groupStartedAt(body[0]) ?? turnEnd.occurredAt;\n const turnGroup: TimelineGroup = {\n kind: \"turn\",\n id: `turn-${turnEnd.turnId ?? turnEnd.id}`,\n outcome: turnEnd.outcome,\n startedAt: firstOccurredAt,\n endedAt: turnEnd.occurredAt,\n groups: body,\n };\n if (turnEnd.failureText) {\n turnGroup.failureText = turnEnd.failureText;\n }\n\n groups.splice(\n startIndex,\n collected.length,\n ...(finalMessage ? [turnGroup, finalMessage] : [turnGroup]),\n );\n}\n\nfunction isTurnBoundary(group: TimelineGroup | undefined): boolean {\n return group?.kind === \"turn\" || (group?.kind === \"item\" && group.item.kind === \"user-message\");\n}\n\nfunction belongsToDifferentTurn(group: TimelineGroup | undefined, turnId: string | null): boolean {\n if (!group || !turnId) {\n return false;\n }\n if (group.kind === \"activity\") {\n return (\n group.items.length > 0 &&\n group.items.every((item) => item.turnId !== null && item.turnId !== turnId)\n );\n }\n return (\n group.kind === \"item\" &&\n group.item.kind === \"agent-message\" &&\n group.item.turnId !== null &&\n group.item.turnId !== turnId\n );\n}\n\nfunction isBetweenTurnDivider(group: TimelineGroup | undefined): boolean {\n return (\n group?.kind === \"item\" &&\n group.item.kind === \"session-status\" &&\n group.item.status !== \"running\"\n );\n}\n\nfunction extractFinalAgentMessage(\n groups: TimelineGroup[],\n turnEnd: TurnEndItem,\n): Extract<TimelineGroup, { kind: \"item\" }> | null {\n const tail = groups[groups.length - 1];\n if (tail?.kind !== \"item\" || tail.item.kind !== \"agent-message\" || tail.item.streaming) {\n return null;\n }\n if (tail.item.turnId && turnEnd.turnId && tail.item.turnId !== turnEnd.turnId) {\n return null;\n }\n return tail;\n}\n\nfunction groupStartedAt(group: TimelineGroup | undefined): string | undefined {\n if (!group) {\n return undefined;\n }\n switch (group.kind) {\n case \"item\":\n return group.item.occurredAt;\n case \"activity\":\n return group.items[0]?.occurredAt;\n case \"turn\":\n return group.startedAt;\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === \"object\" ? (value as Record<string, unknown>) : {};\n}\n\nconst SESSION_STATUSES: readonly SessionStatus[] = [\n \"queued\",\n \"running\",\n \"idle\",\n \"requires_action\",\n \"failed\",\n \"cancelled\",\n];\n\n/** Statuses that demand the reader's attention and so earn a timeline divider. */\nconst ATTENTION_STATUSES: ReadonlySet<SessionStatus> = new Set([\n \"requires_action\",\n \"failed\",\n \"cancelled\",\n]);\n\n/** Keep only entries that match the wire shapes; user payloads are untyped. */\nfunction resourceRefs(value: unknown): import(\"@opengeni/sdk\").ResourceRef[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is import(\"@opengeni/sdk\").ResourceRef => {\n const record = asRecord(entry);\n if (record.kind === \"repository\") {\n return typeof record.uri === \"string\" && typeof record.ref === \"string\";\n }\n return record.kind === \"file\" && typeof record.fileId === \"string\";\n });\n}\n\nfunction toolRefs(value: unknown): import(\"@opengeni/sdk\").ToolRef[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is import(\"@opengeni/sdk\").ToolRef => {\n const record = asRecord(entry);\n return record.kind === \"mcp\" && typeof record.id === \"string\";\n });\n}\n\nfunction workerCompletionPayload(value: unknown): {\n childSessionId: string;\n childStatus: string;\n goalStatus: string | null;\n goalText: string | null;\n evidence: string | null;\n pausedReason: string | null;\n} | null {\n const payload = asRecord(value);\n const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n if (\n typeof payload.childSessionId !== \"string\" ||\n !uuidPattern.test(payload.childSessionId) ||\n typeof payload.status !== \"string\" ||\n payload.status.trim() === \"\"\n ) {\n return null;\n }\n const goal = asRecord(payload.goal);\n return {\n childSessionId: payload.childSessionId,\n childStatus: payload.status,\n goalStatus: typeof goal.status === \"string\" ? goal.status : null,\n goalText: typeof goal.text === \"string\" ? goal.text : null,\n evidence: typeof goal.evidence === \"string\" ? goal.evidence : null,\n // Console pauses and several server paths put the human explanation on\n // `rationale`, not `pausedReason` — same fallback the goal pill uses, so a\n // paused worker card never shows \"Worker paused\" with the reason missing.\n pausedReason:\n typeof goal.pausedReason === \"string\"\n ? goal.pausedReason\n : typeof goal.rationale === \"string\"\n ? goal.rationale\n : null,\n };\n}\n\nfunction isSessionStatus(value: unknown): value is SessionStatus {\n return typeof value === \"string\" && (SESSION_STATUSES as readonly string[]).includes(value);\n}\n\n/** Does this tool output represent an error (explicit flag or MCP `isError`)? */\nfunction isErrorOutput(payload: Record<string, unknown>): boolean {\n if (payload.error === true || payload.failed === true) {\n return true;\n }\n const output = payload.output;\n return (\n !!output && typeof output === \"object\" && (output as { isError?: unknown }).isError === true\n );\n}\n\nfunction findOpenCall(\n items: TimelineItem[],\n callId: string | null,\n): ToolCallItem | WorkerItem | undefined {\n const reversed = [...items].reverse();\n const isCall = (item: TimelineItem): item is ToolCallItem | WorkerItem =>\n item.kind === \"tool-call\" || item.kind === \"worker\";\n if (callId) {\n const byId = reversed.find((item) => isCall(item) && item.callId === callId);\n if (byId) {\n return byId as ToolCallItem | WorkerItem;\n }\n }\n return reversed.find(\n (item): item is ToolCallItem | WorkerItem => isCall(item) && item.status === \"running\",\n );\n}\n\nfunction findOpenSandbox(items: TimelineItem[], name: string): SandboxItem | undefined {\n return [...items]\n .reverse()\n .find(\n (item): item is SandboxItem =>\n item.kind === \"sandbox\" && item.name === name && item.status === \"running\",\n );\n}\n\nfunction failureMessage(payload: Record<string, unknown>): string | null {\n for (const key of [\"error\", \"message\"] as const) {\n const value = payload[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n // Auth/quota provider errors are rewritten for the right audience\n // (raw text remains in the event payload for debug surfaces).\n return humanizeFailureReason(value);\n }\n }\n return null;\n}\n\nfunction goalText(payload: Record<string, unknown>): string | null {\n if (typeof payload.text === \"string\" && payload.text) {\n return payload.text;\n }\n const goal = asRecord(payload.goal);\n if (typeof goal.text === \"string\" && goal.text) {\n return goal.text;\n }\n if (typeof payload.prompt === \"string\" && payload.prompt) {\n return payload.prompt;\n }\n return null;\n}\n\n/**\n * Fold a `memory.saved` / `memory.corrected` event into a {@link MemoryItem}.\n * Reads DEFENSIVELY (the payload is untyped `unknown`, no Zod schema): a missing\n * memory id means a malformed event, so we return null and the case drops it.\n */\nfunction memoryItem(\n id: string,\n type: string,\n turnId: string | null,\n payload: Record<string, unknown>,\n occurredAt: string,\n): MemoryItem | null {\n const memoryId =\n typeof payload.memoryId === \"string\" && payload.memoryId ? payload.memoryId : null;\n if (!memoryId) {\n return null;\n }\n const replacementPreview =\n typeof payload.replacementPreview === \"string\" ? payload.replacementPreview : undefined;\n const replacementMemoryId =\n typeof payload.replacementMemoryId === \"string\" ? payload.replacementMemoryId : undefined;\n const action = typeof payload.action === \"string\" ? payload.action : undefined;\n return {\n kind: \"memory\",\n id,\n turnId,\n variant: type === \"memory.corrected\" ? \"corrected\" : \"saved\",\n memoryKind: typeof payload.kind === \"string\" ? payload.kind : \"\",\n preview: typeof payload.preview === \"string\" ? payload.preview : \"\",\n ...(payload.deduped === true ? { deduped: true } : {}),\n ...(replacementPreview ? { replacementPreview } : {}),\n ...(action ? { action } : {}),\n memoryId,\n ...(replacementMemoryId ? { replacementMemoryId } : {}),\n occurredAt,\n };\n}\n\nconst AUTH_NEEDED_REASONS: ReadonlySet<string> = new Set([\n \"missing_connection\",\n \"expired\",\n \"insufficient_scope\",\n \"refresh_failed\",\n \"unsupported_auth\",\n \"resource_scope_unavailable\",\n]);\n\nfunction authNeededReason(value: unknown): AuthNeededItem[\"reason\"] {\n return typeof value === \"string\" && AUTH_NEEDED_REASONS.has(value)\n ? (value as AuthNeededItem[\"reason\"])\n : null;\n}\n\nfunction stringList(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((entry): entry is string => typeof entry === \"string\" && entry.trim().length > 0)\n : [];\n}\n\nfunction reasoningText(payload: unknown): string {\n const record = asRecord(payload);\n if (typeof record.text === \"string\") {\n return record.text;\n }\n const content = asRecord(asRecord(record.item).rawItem).content;\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((part) => {\n const text = asRecord(part).text;\n return typeof text === \"string\" ? text : \"\";\n })\n .join(\"\");\n}\n\n/** The worker's initial/sent message from `session_create`/`session_send_message` args. */\nfunction workerPrompt(args: unknown): string | null {\n const record = asRecord(typeof args === \"string\" ? tryParseJson(args) : args);\n for (const key of [\"initialMessage\", \"message\", \"text\", \"prompt\"] as const) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return null;\n}\n\n/**\n * Find a session id in orchestration tool arguments or output. Handles raw\n * objects, JSON strings, and MCP tool results (`{ content: [{ type: \"text\",\n * text: \"{...}\" }], structuredContent? }`).\n */\nexport function extractSessionRef(value: unknown, depth = 0): string | null {\n if (depth > 6 || value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\") {\n return extractSessionRef(tryParseJson(value), depth + 1);\n }\n if (Array.isArray(value)) {\n for (const entry of value) {\n const found = extractSessionRef(entry, depth + 1);\n if (found) {\n return found;\n }\n }\n return null;\n }\n if (typeof value !== \"object\") {\n return null;\n }\n const record = value as Record<string, unknown>;\n if (typeof record.sessionId === \"string\" && looksLikeId(record.sessionId)) {\n return record.sessionId;\n }\n if (\n typeof record.id === \"string\" &&\n looksLikeId(record.id) &&\n (\"status\" in record || \"workspaceId\" in record || \"initialMessage\" in record)\n ) {\n return record.id;\n }\n for (const key of [\"structuredContent\", \"session\", \"result\", \"content\"] as const) {\n if (key in record) {\n const found = extractSessionRef(record[key], depth + 1);\n if (found) {\n return found;\n }\n }\n }\n if (typeof record.text === \"string\") {\n return extractSessionRef(tryParseJson(record.text), depth + 1);\n }\n return null;\n}\n\nfunction looksLikeId(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n\n/**\n * Readable label for a tool call (\"session_create\" -> \"session create\").\n *\n * MCP tools are namespaced `<serverId>__<toolName>` (see prefixedMcpToolName),\n * and for catalog-imported servers that serverId is an opaque slug+hash\n * (\"mcp-integrations-sh-supabase-com-34ed9dcf1390-0i6tcf8\"). De-slugging the\n * whole thing leaked that id into the timeline; strip the server prefix and show\n * just the tool (\"list organizations\"). Names without the `__` boundary (plain\n * built-ins like \"session_create\") are unaffected.\n */\nexport function toolDisplayName(name: string): string {\n // The prefix is a single LEFT boundary (`registryId__toolName`), so split on\n // the FIRST `__` — the tool name itself may contain `__` and must survive whole.\n const boundary = name.indexOf(\"__\");\n const toolPart = boundary >= 0 ? name.slice(boundary + 2) : name;\n return toolPart.replace(/[_-]+/g, \" \").trim();\n}\n","import type { SessionEvent, SessionStatus, StreamConnectionState } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport { buildTimeline, groupTimeline, sessionStatusFromEvents } from \"../timeline/projection\";\nimport type { TimelineItem } from \"../timeline/types\";\nimport type { EmbeddedSessionClientLike } from \"../client\";\n\nexport type SessionEventsConnectionState = StreamConnectionState | \"idle\" | \"ended\" | \"error\";\n\nexport type UseSessionEventsOptions = EmbeddedSessionClientOverride & {\n /** Resume after this sequence (exclusive). Nonzero keeps full replay/resume semantics. */\n after?: number | undefined;\n /** Load a bounded tail by default, or opt back into full replay from `after`. */\n replay?: \"windowed\" | \"full\" | undefined;\n /** Pause the stream without unmounting (e.g. hidden tab). Defaults to true. */\n enabled?: boolean | undefined;\n};\n\nexport type UseSessionEventsResult = {\n /** Replayed + live events, ordered by sequence, no gaps, no duplicates. */\n events: SessionEvent[];\n /** Projected, renderable timeline (memoized over `events`). */\n timeline: TimelineItem[];\n /** Latest session status observed in the event log, if any. */\n sessionStatus: SessionStatus | null;\n connectionState: SessionEventsConnectionState;\n /** Highest sequence seen so far (0 before the first event). */\n lastSequence: number;\n /** Exact serialized bytes retained in the current browser event window. */\n windowBytes: number;\n /** Whether older delivered events were evicted from the browser window. */\n windowTruncated: boolean;\n /** True until the initial tail window has been applied (windowed mode). */\n initialLoading: boolean;\n /** Whether older durable events are available before the current window. */\n hasOlder: boolean;\n /** True while an older window is being fetched. */\n loadingOlder: boolean;\n /** Prepend an older density-bounded window; resolves true when more remain. */\n loadOlder: () => Promise<boolean>;\n error: Error | null;\n};\n\nconst INITIAL_TAIL_PAGE_SIZE = 1000;\nconst OLDER_PAGE_SIZE = 5000;\nconst INITIAL_FETCH_CAP = 1;\nconst OLDER_GROUP_TARGET = 32;\nconst OLDER_FETCH_CAP = 2;\nconst BOUNDARY_PAGE_CAP = 4;\nconst EMPTY_EVENTS: SessionEvent[] = [];\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\nconst BROWSER_EVENT_TYPE_MAX_BYTES = 256;\nconst BROWSER_EVENT_ID_MAX_BYTES = 256;\nconst BROWSER_EVENT_CLIENT_ID_MAX_BYTES = 4 * 1024;\nconst BROWSER_EVENT_DUPLICATE_REASON_MAX_BYTES = 4 * 1024;\nconst BROWSER_EVENT_PAYLOAD_PREVIEW_MAX_BYTES = 48 * 1024;\nconst BROWSER_EVENT_PAYLOAD_IDENTITY_FIELDS = [\n \"id\",\n \"callId\",\n \"call_id\",\n \"name\",\n \"toolName\",\n \"status\",\n \"code\",\n \"isError\",\n \"stream\",\n \"commandId\",\n \"sequence\",\n \"coalescedUntil\",\n \"coalescedCount\",\n \"firstSequence\",\n \"lastSequence\",\n] as const;\n\nexport const SESSION_EVENT_BROWSER_MAX_BYTES = 8 * 1024 * 1024;\nexport const SESSION_EVENT_BROWSER_MAX_COUNT = 10_000;\nexport const SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES = 96 * 1024;\nexport const SESSION_EVENT_BROWSER_PENDING_MAX_BYTES = 1024 * 1024;\nexport const SESSION_EVENT_BROWSER_PENDING_MAX_COUNT = 256;\n\nexport type BrowserSessionEventWindow = {\n events: SessionEvent[];\n bytes: number;\n truncated: boolean;\n};\n\nconst EMPTY_EVENT_WINDOW: BrowserSessionEventWindow = {\n events: EMPTY_EVENTS,\n bytes: 2,\n truncated: false,\n};\n\n/**\n * Live-stream a session's event log with replay-by-sequence, reconnect, and\n * batched React updates. Fresh loads default to a bounded tail window; pass\n * `replay: \"full\"` or a nonzero `after` for the previous full replay path.\n */\nexport function useSessionEvents(\n sessionId: string | null | undefined,\n options: UseSessionEventsOptions = {},\n): UseSessionEventsResult {\n const { client, workspaceId, reconcileSession } = useEmbeddedSession(options);\n const enabled = options.enabled ?? true;\n const after = options.after ?? 0;\n const replay = options.replay ?? \"windowed\";\n const fullReplay = replay === \"full\" || after !== 0;\n const streamKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${after}\\u0000${fullReplay ? \"full\" : \"windowed\"}`;\n\n const [eventWindow, setEventWindow] = useState<BrowserSessionEventWindow>(EMPTY_EVENT_WINDOW);\n const [connectionState, setConnectionState] = useState<SessionEventsConnectionState>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const [hasOlder, setHasOlder] = useState(false);\n const [sessionStatusProjection, setSessionStatusProjection] = useState<SessionStatus | null>(\n null,\n );\n const [initialLoading, setInitialLoading] = useState(true);\n const [loadingOlder, setLoadingOlder] = useState(false);\n const [streamEpoch, setStreamEpoch] = useState(0);\n const lastSequenceRef = useRef(after);\n const streamResumeSequenceRef = useRef(after);\n const oldestSequenceRef = useRef<number | null>(null);\n const hasOlderRef = useRef(false);\n const loadingOlderRef = useRef(false);\n const initialWindowLoadedRef = useRef(false);\n const streamAbortRef = useRef<AbortController | null>(null);\n const streamKeyRef = useRef<string | null>(null);\n const generationRef = useRef(0);\n const eventWindowRef = useRef<BrowserSessionEventWindow>(EMPTY_EVENT_WINDOW);\n const sessionStatusRef = useRef<{\n sequence: number;\n status: SessionStatus | null;\n }>({\n sequence: after,\n status: null,\n });\n // Effects reset state after commit. Tag the state so the first render for a\n // new stream identity cannot expose the previous session's event log.\n const [stateStreamKey, setStateStreamKey] = useState(streamKey);\n\n useEffect(() => {\n // Reset the accumulated log only when the stream identity changes —\n // pausing via `enabled: false` keeps the timeline visible.\n if (streamKeyRef.current !== streamKey) {\n streamKeyRef.current = streamKey;\n setStateStreamKey(streamKey);\n eventWindowRef.current = EMPTY_EVENT_WINDOW;\n setEventWindow(EMPTY_EVENT_WINDOW);\n setError(null);\n setHasOlder(false);\n sessionStatusRef.current = { sequence: after, status: null };\n setSessionStatusProjection(null);\n setLoadingOlder(false);\n setInitialLoading(true);\n lastSequenceRef.current = after;\n streamResumeSequenceRef.current = after;\n oldestSequenceRef.current = null;\n hasOlderRef.current = false;\n loadingOlderRef.current = false;\n initialWindowLoadedRef.current = false;\n }\n // AbortController is advisory: custom SDK clients and async iterators may\n // ignore it and resolve/yield after cleanup. Fence every effect instance so\n // only the newest dependency generation can mutate refs or React state.\n const generation = generationRef.current + 1;\n generationRef.current = generation;\n if (loadingOlderRef.current) {\n loadingOlderRef.current = false;\n setLoadingOlder(false);\n }\n if (!sessionId || !enabled) {\n setConnectionState(\"idle\");\n return;\n }\n const controller = new AbortController();\n const isCurrent = () => generationRef.current === generation && !controller.signal.aborted;\n streamAbortRef.current = controller;\n // Batch yielded events into one React update per flush window so a long\n // replay (thousands of events) does not render per event. Project every\n // event before retaining it here and synchronously flush at independent\n // count+byte high-water marks: a synchronously yielding async iterator can\n // otherwise starve the 16 ms timer and grow this pre-React buffer without\n // bound even though the final browser window is bounded.\n let pending: SessionEvent[] = [];\n let pendingBytes = 2; // []\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n const flush = () => {\n // A synchronous count/byte high-water flush can run before the scheduled\n // callback gets a macrotask. Cancel that callback before clearing its\n // handle so a long synchronously yielding replay retains at most one\n // timer rather than one stale callback per flushed batch.\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n if (!isCurrent()) {\n pending = [];\n pendingBytes = 2;\n return;\n }\n if (pending.length === 0) {\n return;\n }\n const batch = pending;\n pending = [];\n pendingBytes = 2;\n // The resume cursor only advances with delivered batches: events still\n // sitting in `pending` when the stream is torn down are re-fetched on\n // the next connect instead of being skipped.\n const lastInBatch = batch[batch.length - 1];\n if (lastInBatch) {\n const batchResumeSequence = Math.max(...batch.map(eventResumeSequence));\n lastSequenceRef.current = Math.max(lastSequenceRef.current, batchResumeSequence);\n streamResumeSequenceRef.current = Math.max(\n streamResumeSequenceRef.current,\n batchResumeSequence,\n );\n }\n observeSessionStatus(batch, sessionStatusRef, setSessionStatusProjection);\n const current = eventWindowRef.current;\n const next = boundBrowserSessionEventWindow([...current.events, ...batch]);\n const retained = {\n ...next,\n truncated: current.truncated || next.truncated,\n };\n eventWindowRef.current = retained;\n setEventWindow(retained);\n oldestSequenceRef.current = retained.events[0]?.sequence ?? null;\n if (retained.truncated) {\n hasOlderRef.current = true;\n setHasOlder(true);\n }\n };\n const scheduleFlush = () => {\n if (!isCurrent()) return;\n flushTimer ??= setTimeout(flush, 16);\n };\n\n void (async () => {\n try {\n if (!fullReplay && !initialWindowLoadedRef.current) {\n setConnectionState(\"connecting\");\n // First paint is ONE compact fetch — the newest window, revealed at\n // the bottom in a few hundred ms. Deeper history loads only when the\n // reader actually scrolls up (the sentinel drives loadOlder).\n const window = await loadEventWindow(client, workspaceId, sessionId, {\n before: Number.MAX_SAFE_INTEGER,\n pageSize: INITIAL_TAIL_PAGE_SIZE,\n targetGroups: Number.POSITIVE_INFINITY,\n maxFetches: INITIAL_FETCH_CAP,\n signal: controller.signal,\n });\n if (!isCurrent()) {\n return;\n }\n observeSessionStatus(window.events, sessionStatusRef, setSessionStatusProjection);\n const retained = boundBrowserSessionEventWindow(window.events);\n eventWindowRef.current = retained;\n setEventWindow(retained);\n oldestSequenceRef.current = retained.events[0]?.sequence ?? window.oldestSequence;\n hasOlderRef.current = window.hasOlder || retained.truncated;\n lastSequenceRef.current = window.newestSequence;\n streamResumeSequenceRef.current = window.newestSequence;\n initialWindowLoadedRef.current = true;\n setHasOlder(window.hasOlder || retained.truncated);\n setInitialLoading(false);\n }\n if (fullReplay) {\n setInitialLoading(false);\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: streamResumeSequenceRef.current,\n signal: controller.signal,\n beforeLive: async () => await reconcileSession(sessionId),\n onStateChange: (state) => {\n if (isCurrent()) {\n setConnectionState(state);\n }\n },\n });\n for await (const event of stream) {\n if (!isCurrent()) break;\n const boundedEvent = boundBrowserLegacyEvent(event);\n const boundedEventBytes = browserJsonBytes(boundedEvent);\n const separatorBytes = pending.length === 0 ? 0 : 1;\n if (\n pending.length > 0 &&\n (pending.length >= SESSION_EVENT_BROWSER_PENDING_MAX_COUNT ||\n pendingBytes + separatorBytes + boundedEventBytes >\n SESSION_EVENT_BROWSER_PENDING_MAX_BYTES)\n ) {\n flush();\n }\n pending.push(boundedEvent);\n pendingBytes += (pending.length === 1 ? 0 : 1) + boundedEventBytes;\n if (\n pending.length >= SESSION_EVENT_BROWSER_PENDING_MAX_COUNT ||\n pendingBytes >= SESSION_EVENT_BROWSER_PENDING_MAX_BYTES\n ) {\n flush();\n } else {\n scheduleFlush();\n }\n }\n if (isCurrent()) {\n flush();\n setConnectionState(\"ended\");\n }\n } catch (cause) {\n if (isCurrent()) {\n flush();\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setConnectionState(\"error\");\n }\n }\n })();\n\n return () => {\n controller.abort();\n if (generationRef.current === generation) {\n generationRef.current = generation + 1;\n }\n if (streamAbortRef.current === controller) {\n streamAbortRef.current = null;\n }\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n }\n };\n }, [\n client,\n workspaceId,\n sessionId,\n after,\n enabled,\n fullReplay,\n streamKey,\n streamEpoch,\n reconcileSession,\n ]);\n\n const loadOlder = useCallback(async (): Promise<boolean> => {\n if (!sessionId || loadingOlderRef.current || !hasOlderRef.current) {\n return false;\n }\n const before = oldestSequenceRef.current;\n if (before === null) {\n hasOlderRef.current = false;\n setHasOlder(false);\n return false;\n }\n const generation = generationRef.current;\n loadingOlderRef.current = true;\n setLoadingOlder(true);\n try {\n const window = await loadEventWindow(client, workspaceId, sessionId, {\n before,\n pageSize: OLDER_PAGE_SIZE,\n targetGroups: OLDER_GROUP_TARGET,\n maxFetches: OLDER_FETCH_CAP,\n });\n if (generationRef.current !== generation) {\n return false;\n }\n if (window.events.length === 0) {\n oldestSequenceRef.current = null;\n hasOlderRef.current = false;\n setHasOlder(false);\n return false;\n }\n const current = eventWindowRef.current;\n assertPrependOrder(current.events, window.events);\n // Freeze the live iterator before replacing its in-memory window. Rows\n // pending in the aborted iterator were never cursor-committed and will\n // be replayed from the retained high-water mark below.\n streamAbortRef.current?.abort();\n observeSessionStatus(window.events, sessionStatusRef, setSessionStatusProjection);\n const next = boundBrowserSessionEventWindow([...window.events, ...current.events], {\n direction: \"oldest\",\n });\n const retained = {\n ...next,\n truncated: current.truncated || next.truncated,\n };\n const retainedOldest = retained.events[0]?.sequence ?? null;\n if (retainedOldest === null || retainedOldest >= before) {\n throw new Error(\"@opengeni/react: loadOlder made no durable sequence progress\");\n }\n eventWindowRef.current = retained;\n setEventWindow(retained);\n oldestSequenceRef.current = retainedOldest;\n streamResumeSequenceRef.current = maxResumeSequence(retained.events);\n // Oldest-directed eviction can discard newer in-memory rows. That fact\n // keeps windowTruncated true, but it does not imply older durable rows\n // exist; only the backward DB page can answer hasOlder truthfully.\n const olderStillAvailable = window.hasOlder;\n hasOlderRef.current = olderStillAvailable;\n setHasOlder(olderStillAvailable);\n setStreamEpoch((epoch) => epoch + 1);\n return olderStillAvailable;\n } finally {\n if (generationRef.current === generation) {\n loadingOlderRef.current = false;\n setLoadingOlder(false);\n }\n }\n }, [client, workspaceId, sessionId]);\n\n const identityMatches = stateStreamKey === streamKey;\n const visibleEvents = identityMatches ? eventWindow.events : EMPTY_EVENTS;\n const timeline = useMemo(() => buildTimeline(visibleEvents), [visibleEvents]);\n\n return {\n events: visibleEvents,\n timeline,\n sessionStatus: identityMatches ? sessionStatusProjection : null,\n connectionState: identityMatches ? connectionState : \"idle\",\n lastSequence: identityMatches ? lastSequenceRef.current : after,\n windowBytes: identityMatches ? eventWindow.bytes : 2,\n windowTruncated: identityMatches ? eventWindow.truncated : false,\n initialLoading: fullReplay ? false : identityMatches ? initialLoading : true,\n hasOlder: !identityMatches ? false : hasOlder,\n loadingOlder: !identityMatches ? false : loadingOlder,\n loadOlder,\n error: identityMatches ? error : null,\n };\n}\n\n/**\n * Keep one direction-aware count+byte-bounded browser window. Live/default\n * accumulation retains the newest suffix; backward paging retains the oldest\n * prefix so newly fetched history cannot be immediately evicted. This is\n * deliberately separate from durable history and transport paging: when a\n * backward page evicts the live tail, the hook reconnects from the retained\n * high-water mark while preserving the highest-ever-observed sequence\n * separately. The source event remains durable in PostgreSQL throughout.\n */\nexport function boundBrowserSessionEventWindow(\n events: readonly SessionEvent[],\n options: {\n maxBytes?: number;\n maxCount?: number;\n direction?: \"newest\" | \"oldest\";\n } = {},\n): BrowserSessionEventWindow {\n const maxBytes = Math.max(1024, options.maxBytes ?? SESSION_EVENT_BROWSER_MAX_BYTES);\n const maxCount = Math.max(1, Math.floor(options.maxCount ?? SESSION_EVENT_BROWSER_MAX_COUNT));\n const safe = events.map(boundBrowserLegacyEvent);\n const selected: SessionEvent[] = [];\n let bytes = 2; // []\n const direction = options.direction ?? \"newest\";\n const start = direction === \"newest\" ? safe.length - 1 : 0;\n const end = direction === \"newest\" ? Math.max(-1, safe.length - maxCount - 1) : safe.length;\n const step = direction === \"newest\" ? -1 : 1;\n for (let index = start; index !== end && selected.length < maxCount; index += step) {\n const event = safe[index]!;\n const eventBytes = browserJsonBytes(event);\n const separator = selected.length === 0 ? 0 : 1;\n if (bytes + separator + eventBytes > maxBytes) break;\n selected.push(event);\n bytes += separator + eventBytes;\n }\n if (direction === \"newest\") selected.reverse();\n return {\n events: selected,\n bytes,\n truncated: selected.length < safe.length,\n };\n}\n\nfunction boundBrowserLegacyEvent(event: SessionEvent): SessionEvent {\n // The server-side canonical projection lives in @opengeni/contracts. The\n // publishable React package may depend only on the zero-runtime-dependency\n // SDK, so this is intentionally a last-resort client guard rather than a\n // second durable representation. Reconstructing the SDK wire shape prevents\n // legacy/malformed extra properties from bypassing the browser byte cap.\n const serialized = browserSerialize(event);\n const originalBytes = serialized.serializable\n ? encoder.encode(serialized.value).byteLength\n : null;\n const typeIsSafe =\n browserUtf8Bytes(event.type) <= BROWSER_EVENT_TYPE_MAX_BYTES &&\n !event.type.includes(\"\\n\") &&\n !event.type.includes(\"\\r\");\n const clientEventId = boundBrowserOptionalText(\n event.clientEventId,\n BROWSER_EVENT_CLIENT_ID_MAX_BYTES,\n );\n const duplicateReason = boundBrowserOptionalText(\n event.duplicateReason,\n BROWSER_EVENT_DUPLICATE_REASON_MAX_BYTES,\n );\n\n if (\n serialized.serializable &&\n originalBytes !== null &&\n originalBytes <= SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES &&\n typeIsSafe &&\n clientEventId === event.clientEventId &&\n duplicateReason === event.duplicateReason\n ) {\n return event;\n }\n\n const envelopeProjection = [\n !typeIsSafe\n ? browserEnvelopeFieldProjection(\"type\", event.type, \"session.event.envelope_omitted\")\n : null,\n clientEventId !== event.clientEventId\n ? browserEnvelopeFieldProjection(\"clientEventId\", event.clientEventId, clientEventId)\n : null,\n duplicateReason !== event.duplicateReason\n ? browserEnvelopeFieldProjection(\"duplicateReason\", event.duplicateReason, duplicateReason)\n : null,\n ].filter((field) => field !== null);\n const payloadSerialization = browserSerialize(event.payload);\n const payloadBytes = payloadSerialization.serializable\n ? encoder.encode(payloadSerialization.value).byteLength\n : null;\n const preview = truncateBrowserUtf8Middle(\n payloadSerialization.value,\n BROWSER_EVENT_PAYLOAD_PREVIEW_MAX_BYTES,\n );\n const truncation = {\n truncated: true as const,\n surface: \"browser_legacy_guard\" as const,\n reason: serialized.serializable ? \"event_envelope_bytes_exceeded\" : \"event_not_serializable\",\n originalBytes,\n deliveredBytes: 0,\n omittedBytes: originalBytes,\n estimatedOriginalTokens: originalBytes === null ? null : Math.ceil(originalBytes / 4),\n estimatedDeliveredTokens: 0,\n fullEvidence: { available: false as const, reason: \"not_retained\" as const },\n details: [\n {\n path: \"$.payload\",\n kind: \"payload_preview\",\n originalBytes: payloadBytes,\n deliveredBytes: browserUtf8Bytes(preview),\n },\n ],\n };\n const payload: Record<string, unknown> = {\n ...browserPayloadIdentity(event.payload),\n preview,\n ...(envelopeProjection.length > 0\n ? {\n originalType: boundBrowserText(event.type, BROWSER_EVENT_TYPE_MAX_BYTES),\n envelopeProjection: {\n truncated: true,\n surface: \"browser_legacy_guard\",\n fields: envelopeProjection,\n },\n }\n : {}),\n truncation,\n };\n const bounded: SessionEvent = {\n id: boundBrowserText(event.id, BROWSER_EVENT_ID_MAX_BYTES),\n workspaceId: boundBrowserText(event.workspaceId, BROWSER_EVENT_ID_MAX_BYTES),\n sessionId: boundBrowserText(event.sessionId, BROWSER_EVENT_ID_MAX_BYTES),\n sequence: event.sequence,\n type: typeIsSafe ? event.type : \"session.event.envelope_omitted\",\n payload,\n occurredAt: boundBrowserText(event.occurredAt, BROWSER_EVENT_ID_MAX_BYTES),\n clientEventId,\n turnId: boundBrowserOptionalText(event.turnId, BROWSER_EVENT_ID_MAX_BYTES),\n turnGeneration: event.turnGeneration,\n turnAttemptId: boundBrowserOptionalText(event.turnAttemptId, BROWSER_EVENT_ID_MAX_BYTES),\n turnAssociation: event.turnAssociation,\n duplicateOfEventId: boundBrowserOptionalText(\n event.duplicateOfEventId,\n BROWSER_EVENT_ID_MAX_BYTES,\n ),\n duplicateReason,\n };\n\n settleBrowserEventTruncation(bounded, truncation);\n if (browserJsonBytes(bounded) > SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES) {\n payload.preview = truncateBrowserUtf8Middle(String(payload.preview), 4 * 1024);\n truncation.details = truncation.details.slice(0, 1);\n settleBrowserEventTruncation(bounded, truncation);\n }\n if (browserJsonBytes(bounded) > SESSION_EVENT_BROWSER_SINGLE_EVENT_MAX_BYTES) {\n bounded.clientEventId = null;\n bounded.duplicateReason = null;\n payload.preview = \"[legacy event omitted at the browser byte boundary]\";\n settleBrowserEventTruncation(bounded, truncation);\n }\n return bounded;\n}\n\nfunction browserJsonBytes(value: unknown): number {\n return encoder.encode(browserSerialize(value).value).byteLength;\n}\n\nfunction browserSerialize(value: unknown): { value: string; serializable: boolean } {\n try {\n const serialized = JSON.stringify(value);\n return { value: serialized === undefined ? \"null\" : serialized, serializable: true };\n } catch {\n return {\n value: '\"[unserializable event payload omitted at browser boundary]\"',\n serializable: false,\n };\n }\n}\n\nfunction browserPayloadIdentity(payload: unknown): Record<string, unknown> {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return {};\n const record = payload as Record<string, unknown>;\n const identity: Record<string, unknown> = {};\n for (const field of BROWSER_EVENT_PAYLOAD_IDENTITY_FIELDS) {\n const value = record[field];\n if (typeof value === \"string\") {\n identity[field] = boundBrowserText(value, BROWSER_EVENT_ID_MAX_BYTES);\n } else if (typeof value === \"number\" || typeof value === \"boolean\" || value === null) {\n identity[field] = value;\n }\n }\n return identity;\n}\n\nfunction browserEnvelopeFieldProjection(\n field: string,\n original: string | null | undefined,\n delivered: string | null | undefined,\n): { field: string; originalBytes: number; deliveredBytes: number } {\n return {\n field,\n originalBytes: typeof original === \"string\" ? browserUtf8Bytes(original) : 0,\n deliveredBytes: typeof delivered === \"string\" ? browserUtf8Bytes(delivered) : 0,\n };\n}\n\nfunction boundBrowserOptionalText<T extends string | null | undefined>(\n value: T,\n maxBytes: number,\n): T {\n return (typeof value === \"string\" ? boundBrowserText(value, maxBytes) : value) as T;\n}\n\nfunction boundBrowserText(value: string, maxBytes: number): string {\n const bytes = encoder.encode(value);\n if (bytes.byteLength <= maxBytes) return value;\n const marker = \"…[truncated]\";\n const prefixBudget = Math.max(0, maxBytes - browserUtf8Bytes(marker));\n let prefixEnd = Math.min(prefixBudget, bytes.byteLength);\n while (\n prefixEnd > 0 &&\n prefixEnd < bytes.byteLength &&\n isBrowserUtf8Continuation(bytes[prefixEnd]!)\n ) {\n prefixEnd -= 1;\n }\n return `${decoder.decode(bytes.subarray(0, prefixEnd))}${marker}`;\n}\n\nfunction truncateBrowserUtf8Middle(value: string, maxBytes: number): string {\n const bytes = encoder.encode(value);\n if (bytes.byteLength <= maxBytes) return value;\n const marker = `…[${bytes.byteLength - maxBytes} bytes omitted]…`;\n const contentBudget = Math.max(0, maxBytes - browserUtf8Bytes(marker));\n const leftBudget = Math.floor(contentBudget / 2);\n const rightBudget = contentBudget - leftBudget;\n let leftEnd = Math.min(leftBudget, bytes.byteLength);\n while (leftEnd > 0 && leftEnd < bytes.byteLength && isBrowserUtf8Continuation(bytes[leftEnd]!)) {\n leftEnd -= 1;\n }\n let rightStart = Math.max(0, bytes.byteLength - rightBudget);\n while (rightStart < bytes.byteLength && isBrowserUtf8Continuation(bytes[rightStart]!)) {\n rightStart += 1;\n }\n return `${decoder.decode(bytes.subarray(0, leftEnd))}${marker}${decoder.decode(bytes.subarray(rightStart))}`;\n}\n\nfunction settleBrowserEventTruncation(\n event: SessionEvent,\n truncation: {\n originalBytes: number | null;\n deliveredBytes: number;\n omittedBytes: number | null;\n estimatedDeliveredTokens: number;\n },\n): void {\n for (let attempt = 0; attempt < 16; attempt += 1) {\n const deliveredBytes = browserJsonBytes(event);\n const omittedBytes =\n truncation.originalBytes === null\n ? null\n : Math.max(0, truncation.originalBytes - deliveredBytes);\n const estimatedDeliveredTokens = Math.ceil(deliveredBytes / 4);\n if (\n truncation.deliveredBytes === deliveredBytes &&\n truncation.omittedBytes === omittedBytes &&\n truncation.estimatedDeliveredTokens === estimatedDeliveredTokens\n ) {\n return;\n }\n truncation.deliveredBytes = deliveredBytes;\n truncation.omittedBytes = omittedBytes;\n truncation.estimatedDeliveredTokens = estimatedDeliveredTokens;\n }\n throw new RangeError(\"Browser event byte accounting did not converge\");\n}\n\nfunction browserUtf8Bytes(value: string): number {\n return encoder.encode(value).byteLength;\n}\n\nfunction isBrowserUtf8Continuation(value: number): boolean {\n return (value & 0xc0) === 0x80;\n}\n\nfunction observeSessionStatus(\n events: readonly SessionEvent[],\n ref: { current: { sequence: number; status: SessionStatus | null } },\n setStatus: (status: SessionStatus | null) => void,\n): void {\n let latest: { sequence: number; status: SessionStatus } | null = null;\n for (const event of events) {\n const status = sessionStatusFromEvents([event]);\n if (status && (!latest || event.sequence >= latest.sequence)) {\n latest = { sequence: event.sequence, status };\n }\n }\n if (!latest || latest.sequence < ref.current.sequence) return;\n ref.current = latest;\n setStatus(latest.status);\n}\n\ntype LoadedEventWindow = {\n events: SessionEvent[];\n oldestSequence: number | null;\n newestSequence: number;\n hasOlder: boolean;\n};\n\nasync function loadEventWindow(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n options: {\n before: number;\n pageSize: number;\n targetGroups: number;\n maxFetches: number;\n signal?: AbortSignal;\n },\n): Promise<LoadedEventWindow> {\n let cursor = options.before;\n let buffer: SessionEvent[] = [];\n let reachedStart = false;\n let fetches = 0;\n\n while (fetches < options.maxFetches) {\n if (buffer.length > 0 && groupCount(buffer) >= options.targetGroups) {\n break;\n }\n const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {\n pageSize: options.pageSize,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n fetches += 1;\n if (page.length === 0) {\n reachedStart = true;\n break;\n }\n assertAscending(page);\n buffer = [...page, ...buffer];\n cursor = page[0]!.sequence;\n if (isLogStart(page[0]!)) {\n reachedStart = true;\n break;\n }\n }\n\n // Boundary snap: a window that starts mid-turn TRIMS its head to the oldest\n // turn boundary already in the buffer — the dropped fragment is refetched by\n // the next loadOlder (everything below the new oldest sequence), whose own\n // window snaps the same way, so every seam lands on a turn start. Extra\n // pages are fetched only when the buffer holds no boundary at all (one\n // monster turn); past the cap a mid-turn top is accepted.\n let snapPages = 0;\n while (\n !reachedStart &&\n findBoundaryIndex(buffer) === -1 &&\n snapPages < BOUNDARY_PAGE_CAP &&\n fetches < options.maxFetches\n ) {\n const page = await loadPreviousPage(client, workspaceId, sessionId, cursor, {\n pageSize: options.pageSize,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n fetches += 1;\n snapPages += 1;\n if (page.length === 0) {\n reachedStart = true;\n break;\n }\n assertAscending(page);\n buffer = [...page, ...buffer];\n cursor = page[0]!.sequence;\n if (isLogStart(page[0]!)) {\n reachedStart = true;\n break;\n }\n }\n if (!reachedStart) {\n const boundary = findBoundaryIndex(buffer);\n if (boundary > 0) {\n buffer = buffer.slice(boundary);\n }\n }\n\n const oldest = buffer[0] ?? null;\n const newest = buffer[buffer.length - 1] ?? null;\n return {\n events: buffer,\n oldestSequence: oldest?.sequence ?? null,\n newestSequence: newest ? maxResumeSequence(buffer) : 0,\n hasOlder: buffer.length > 0 && !reachedStart && oldest?.type !== \"session.created\",\n };\n}\n\n/** Index of the oldest clean turn start in the buffer, or -1. */\nfunction findBoundaryIndex(events: SessionEvent[]): number {\n for (let index = 0; index < events.length; index += 1) {\n const type = events[index]!.type;\n if (type === \"session.created\" || type === \"user.message\") {\n return index;\n }\n }\n return -1;\n}\n\ntype PreviousPage = SessionEvent[] & { requested: number };\n\nasync function loadPreviousPage(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string,\n before: number,\n options: {\n pageSize: number;\n signal?: AbortSignal;\n },\n): Promise<PreviousPage> {\n if (options.signal?.aborted) {\n throw abortError();\n }\n const requested = options.pageSize;\n if (requested === 0) {\n return Object.assign([], { requested });\n }\n const page = await client.listEvents(workspaceId, sessionId, {\n before,\n limit: requested,\n compact: true,\n });\n if (options.signal?.aborted) {\n throw abortError();\n }\n return Object.assign(page, { requested });\n}\n\nfunction groupCount(events: SessionEvent[]): number {\n if (events.length === 0) {\n return 0;\n }\n return groupTimeline(buildTimeline(events)).length;\n}\n\nfunction isLogStart(event: SessionEvent): boolean {\n return event.type === \"session.created\" || event.sequence <= 1;\n}\n\nfunction maxResumeSequence(events: SessionEvent[]): number {\n return events.reduce((max, event) => Math.max(max, eventResumeSequence(event)), 0);\n}\n\nfunction eventResumeSequence(event: SessionEvent): number {\n const payload = asRecord(event.payload);\n const coalescedUntil = Number(payload.coalescedUntil);\n return Math.max(event.sequence, Number.isFinite(coalescedUntil) ? Math.floor(coalescedUntil) : 0);\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" ? (value as Record<string, unknown>) : {};\n}\n\nfunction assertAscending(events: SessionEvent[]): void {\n for (let index = 1; index < events.length; index += 1) {\n if (events[index - 1]!.sequence >= events[index]!.sequence) {\n throw new Error(\"@opengeni/react: session events must be ordered by ascending sequence\");\n }\n }\n}\n\nfunction assertPrependOrder(existing: SessionEvent[], older: SessionEvent[]): void {\n if (!shouldAssertDevelopment() || existing.length === 0 || older.length === 0) {\n return;\n }\n if (older[older.length - 1]!.sequence >= existing[0]!.sequence) {\n throw new Error(\"@opengeni/react: loadOlder returned overlapping session events\");\n }\n}\n\nfunction shouldAssertDevelopment(): boolean {\n const processEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env;\n return processEnv !== undefined && processEnv.NODE_ENV !== \"production\";\n}\n\nfunction abortError(): Error {\n const error = new Error(\"The operation was aborted.\");\n error.name = \"AbortError\";\n return error;\n}\n","import type {\n ComposerDraft,\n EffectiveSessionControl,\n SessionEvent,\n SessionQueueMutationResponse,\n SessionQueueSnapshot,\n SessionTurn,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport {\n useDebouncedCallback,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\n/** Events that can change the authoritative prompt queue or effective control. */\nexport function isTurnQueueEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return (\n event.type.startsWith(\"turn.\") ||\n event.type.startsWith(\"session.queue.\") ||\n event.type.startsWith(\"session.control.\") ||\n event.type.startsWith(\"workspace.inference.\")\n );\n}\n\nfunction queueSnapshotCovers(\n candidate: SessionQueueSnapshot | null,\n observed: SessionQueueSnapshot,\n): boolean {\n return Boolean(\n candidate &&\n candidate.version >= observed.version &&\n candidate.effectiveControl.controlVersion >= observed.effectiveControl.controlVersion,\n );\n}\n\nexport type QueueMutationKind = \"move\" | \"edit\" | \"steer\" | \"delete\";\nconst EMPTY_PENDING_BY_TURN: Readonly<Record<string, QueueMutationKind>> = {};\n\nexport type UseTurnQueueOptions = EmbeddedSessionClientOverride &\n SessionEventFeedOptions & {\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseTurnQueueResult = {\n snapshot: SessionQueueSnapshot | null;\n /** Human/API prompts exactly in server execution order. Never client-sorted. */\n queue: SessionTurn[];\n effectiveControl: EffectiveSessionControl | null;\n /** The latest interrupted attempt has not yet durably proved physical quiescence. */\n stoppingPreviousAttempt: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n moveTurn: (turnId: string, beforeTurnId: string | null) => Promise<boolean>;\n /** Atomically withdraw a waiting prompt into the private durable composer draft. */\n editTurn: (\n turnId: string,\n options: { expectedDraftRevision: number; replaceDraft: boolean },\n ) => Promise<ComposerDraft | null>;\n /** Advance the same durable waiting prompt; no duplicate prompt is created. */\n steerTurn: (turnId: string) => Promise<boolean>;\n removeTurn: (turnId: string) => Promise<boolean>;\n pendingByTurn: Readonly<Record<string, QueueMutationKind>>;\n mutationFor: (turnId: string) => QueueMutationKind | null;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The one authoritative human prompt queue. Every mutation carries the exact\n * server versions the operator saw and accepts only monotonic snapshots. A\n * conflict immediately reloads server truth; the client never invents order.\n */\nexport function useTurnQueue(\n sessionId: string | null | undefined,\n options: UseTurnQueueOptions = {},\n): UseTurnQueueResult {\n const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } =\n useEmbeddedSession(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n const [snapshot, setSnapshot] = useState<SessionQueueSnapshot | null>(null);\n const [stateTargetKey, setStateTargetKey] = useState(targetKey);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const [pendingByTurn, setPendingByTurn] = useState<Record<string, QueueMutationKind>>({});\n const pendingRef = useRef<Record<string, QueueMutationKind>>({});\n const readGeneration = useRef(0);\n const targetKeyRef = useRef(targetKey);\n const snapshotRef = useRef<SessionQueueSnapshot | null>(null);\n\n // Revoke the old target only when the new one commits. A concurrent render\n // may suspend while the previous target remains visible and interactive.\n useLayoutEffect(() => {\n if (targetKeyRef.current === targetKey) return;\n targetKeyRef.current = targetKey;\n readGeneration.current += 1;\n snapshotRef.current = null;\n pendingRef.current = {};\n setStateTargetKey(targetKey);\n setSnapshot(null);\n setLoading(enabled);\n setError(null);\n setMutationError(null);\n setPendingByTurn({});\n }, [enabled, targetKey]);\n\n const acceptSnapshot = useCallback(\n (ownedTargetKey: string, next: SessionQueueSnapshot | null): boolean => {\n if (targetKeyRef.current !== ownedTargetKey) return false;\n const current = snapshotRef.current;\n if (\n next &&\n current &&\n (next.version < current.version ||\n next.effectiveControl.controlVersion < current.effectiveControl.controlVersion)\n ) {\n return false;\n }\n snapshotRef.current = next;\n setStateTargetKey(ownedTargetKey);\n setSnapshot(next);\n return true;\n },\n [],\n );\n\n const load = useCallback(\n async (rejectOnFailure = false): Promise<void> => {\n if (!sessionId) return;\n const ownedTargetKey = `${workspaceId}\\u0000${sessionId}`;\n const ticket = ++readGeneration.current;\n try {\n const fetched = await client.getQueue(workspaceId, sessionId);\n if (targetKeyRef.current !== ownedTargetKey) return;\n const ownsLatestRead = ticket === readGeneration.current;\n if (rejectOnFailure) {\n const committed = acceptSnapshot(ownedTargetKey, fetched);\n if (!committed && !queueSnapshotCovers(snapshotRef.current, fetched)) {\n throw new TypeError(\"Queue reconciliation did not commit authoritative state\");\n }\n setError(null);\n if (ownsLatestRead) setLoading(false);\n } else if (ownsLatestRead) {\n acceptSnapshot(ownedTargetKey, fetched);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n (ticket === readGeneration.current || rejectOnFailure)\n ) {\n setError(asError(cause));\n if (ticket === readGeneration.current) setLoading(false);\n }\n if (rejectOnFailure) throw cause;\n }\n },\n [client, workspaceId, sessionId, acceptSnapshot],\n );\n\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void load();\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n readGeneration.current += 1;\n };\n }\n const timer = setInterval(() => void load(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n readGeneration.current += 1;\n };\n }, [load, enabled, options.pollIntervalMs]);\n\n useEffect(() => {\n if (enabled && workspaceControlEvent) void load();\n }, [enabled, load, workspaceControlEvent]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"queue\", load);\n }, [enabled, load, registerSessionReconciler, sessionId]);\n\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isTurnQueueEvent,\n scheduleRefresh,\n {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n },\n async () => await load(true),\n );\n\n const mutate = useCallback(\n async (\n turnId: string,\n kind: QueueMutationKind,\n command: (\n current: SessionQueueSnapshot,\n turn: SessionTurn,\n ) => Promise<SessionQueueMutationResponse>,\n ): Promise<SessionQueueMutationResponse | null> => {\n const ownedTargetKey = targetKey;\n if (!sessionId || targetKeyRef.current !== ownedTargetKey || pendingRef.current[turnId]) {\n return null;\n }\n const current = snapshotRef.current;\n const turn = current?.items.find((candidate) => candidate.id === turnId);\n if (!current || !turn) return null;\n pendingRef.current = { ...pendingRef.current, [turnId]: kind };\n setStateTargetKey(ownedTargetKey);\n setPendingByTurn(pendingRef.current);\n setMutationError(null);\n try {\n const result = await command(current, turn);\n if (targetKeyRef.current !== ownedTargetKey) return null;\n acceptSnapshot(ownedTargetKey, result.snapshot);\n return result;\n } catch (cause) {\n if (targetKeyRef.current === ownedTargetKey) {\n setMutationError(asError(cause));\n await load();\n }\n return null;\n } finally {\n if (targetKeyRef.current === ownedTargetKey && turnId in pendingRef.current) {\n const next = { ...pendingRef.current };\n delete next[turnId];\n pendingRef.current = next;\n setPendingByTurn(next);\n }\n }\n },\n [acceptSnapshot, load, sessionId, targetKey],\n );\n\n const moveTurn = useCallback(\n async (turnId: string, beforeTurnId: string | null): Promise<boolean> => {\n const result = await mutate(turnId, \"move\", (current) =>\n client.moveQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId: operationKey(),\n expectedQueueVersion: current.version,\n beforeTurnId,\n }),\n );\n return result !== null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const editTurn = useCallback(\n async (\n turnId: string,\n edit: { expectedDraftRevision: number; replaceDraft: boolean },\n ): Promise<ComposerDraft | null> => {\n const result = await mutate(turnId, \"edit\", (_current, turn) =>\n client.editQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId: operationKey(),\n expectedTurnVersion: turn.version,\n expectedDraftRevision: edit.expectedDraftRevision,\n replaceDraft: edit.replaceDraft,\n }),\n );\n return result?.draft ?? null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const steerTurn = useCallback(\n async (turnId: string): Promise<boolean> => {\n const result = await mutate(turnId, \"steer\", (current, turn) =>\n client.steerQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId: operationKey(),\n expectedTurnVersion: turn.version,\n controlEtag: current.effectiveControl.controlEtag,\n }),\n );\n return result !== null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const removeTurn = useCallback(\n async (turnId: string): Promise<boolean> => {\n const result = await mutate(turnId, \"delete\", (_current, turn) =>\n client.deleteQueueItem(workspaceId, sessionId!, turnId, {\n clientEventId: operationKey(),\n expectedTurnVersion: turn.version,\n reason: \"Deleted from the prompt queue\",\n }),\n );\n return result !== null;\n },\n [client, mutate, sessionId, workspaceId],\n );\n\n const identityMatches = stateTargetKey === targetKey;\n const visibleSnapshot = identityMatches ? snapshot : null;\n const visiblePendingByTurn = identityMatches ? pendingByTurn : EMPTY_PENDING_BY_TURN;\n const mutating = useMemo(\n () => Object.keys(visiblePendingByTurn).length > 0,\n [visiblePendingByTurn],\n );\n const mutationFor = useCallback(\n (turnId: string): QueueMutationKind | null => visiblePendingByTurn[turnId] ?? null,\n [visiblePendingByTurn],\n );\n\n return {\n snapshot: visibleSnapshot,\n queue: visibleSnapshot?.items ?? [],\n effectiveControl: visibleSnapshot?.effectiveControl ?? null,\n stoppingPreviousAttempt: visibleSnapshot?.stoppingPreviousAttempt ?? false,\n loading: identityMatches ? loading : enabled,\n error: identityMatches ? error : null,\n refresh: load,\n moveTurn,\n editTurn,\n steerTurn,\n removeTurn,\n pendingByTurn: visiblePendingByTurn,\n mutationFor,\n mutating,\n mutationError: identityMatches ? mutationError : null,\n clearMutationError: useCallback(() => {\n if (targetKeyRef.current === targetKey) setMutationError(null);\n }, [targetKey]),\n };\n}\n\nfunction operationKey(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction asError(cause: unknown): Error {\n return cause instanceof Error ? cause : new Error(String(cause));\n}\n","import type { SessionControlResponse, SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport { useMutationRunner } from \"./internal\";\n\nexport type UseSessionControlOptions = EmbeddedSessionClientOverride;\n\nexport type UseSessionControlResult = {\n pause: (reason?: string) => Promise<SessionControlResponse | null>;\n resume: (reason?: string) => Promise<SessionControlResponse | null>;\n controlling: boolean;\n /** Approve a pending `requires_action` approval. */\n approve: (approvalId: string, message?: string) => Promise<SessionEvent | null>;\n /** Reject a pending `requires_action` approval. */\n reject: (approvalId: string, message?: string) => Promise<SessionEvent | null>;\n /** True while an approval decision is in flight. */\n responding: boolean;\n error: Error | null;\n clearError: () => void;\n};\n\n/**\n * Session pause/resume and approval decisions. Pair with\n * `useSessionEvents` (for `session.requiresAction` payloads carrying the\n * `approvalId`) to render an approval bar.\n */\nexport function useSessionControl(\n sessionId: string | null | undefined,\n options: UseSessionControlOptions = {},\n): UseSessionControlResult {\n const { client, workspaceId } = useEmbeddedSession(options);\n const approvalTargetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n const pendingApproval = useRef<{\n targetKey: string;\n decisionKey: string;\n clientEventId: string;\n } | null>(null);\n useLayoutEffect(() => {\n if (pendingApproval.current?.targetKey !== approvalTargetKey) {\n pendingApproval.current = null;\n }\n }, [approvalTargetKey]);\n const {\n run: runControl,\n mutating: controlling,\n mutationError: controlError,\n clearMutationError: clearControlError,\n } = useMutationRunner(approvalTargetKey);\n const {\n run: runApproval,\n mutating: responding,\n mutationError: approvalError,\n clearMutationError: clearApprovalError,\n } = useMutationRunner(approvalTargetKey);\n\n const pause = useCallback(\n async (reason?: string): Promise<SessionControlResponse | null> => {\n if (!sessionId) {\n return null;\n }\n return await runControl(() =>\n client.pauseSession(workspaceId, sessionId, reason !== undefined ? { reason } : {}),\n );\n },\n [client, workspaceId, sessionId, runControl],\n );\n\n const resume = useCallback(\n async (reason?: string): Promise<SessionControlResponse | null> => {\n if (!sessionId) return null;\n return await runControl(() =>\n client.resumeSession(workspaceId, sessionId, reason !== undefined ? { reason } : {}),\n );\n },\n [client, workspaceId, sessionId, runControl],\n );\n\n const decide = useCallback(\n async (\n approvalId: string,\n decision: \"approve\" | \"reject\",\n message?: string,\n ): Promise<SessionEvent | null> => {\n if (!sessionId) {\n return null;\n }\n const decisionKey = JSON.stringify([approvalId, decision, message ?? null]);\n if (pendingApproval.current?.decisionKey !== decisionKey) {\n pendingApproval.current = {\n targetKey: approvalTargetKey,\n decisionKey,\n clientEventId: crypto.randomUUID(),\n };\n }\n const clientEventId = pendingApproval.current.clientEventId;\n const accepted = await runApproval(() =>\n client.sendApprovalDecision(workspaceId, sessionId, {\n approvalId,\n decision,\n ...(message !== undefined ? { message } : {}),\n clientEventId,\n }),\n );\n if (\n accepted !== null &&\n pendingApproval.current?.targetKey === approvalTargetKey &&\n pendingApproval.current.clientEventId === clientEventId\n ) {\n pendingApproval.current = null;\n }\n return accepted;\n },\n [approvalTargetKey, client, workspaceId, sessionId, runApproval],\n );\n\n const approve = useCallback(\n async (approvalId: string, message?: string) => await decide(approvalId, \"approve\", message),\n [decide],\n );\n const reject = useCallback(\n async (approvalId: string, message?: string) => await decide(approvalId, \"reject\", message),\n [decide],\n );\n\n const error = approvalError ?? controlError;\n const clearError = useCallback(() => {\n clearControlError();\n clearApprovalError();\n }, [clearControlError, clearApprovalError]);\n\n return {\n pause,\n resume,\n controlling,\n approve,\n reject,\n responding,\n error,\n clearError,\n };\n}\n","import type { SessionEvent } from \"@opengeni/sdk\";\n\n/* ----------------------------------------------------------------------------\n Pending-approvals projection\n\n `session.requiresAction` events live forever in the durable log, so a\n console that replays the log from sequence 0 must not render every\n historical approval as actionable. `projectPendingApprovals` folds the\n ordered event log into the approvals that are still undecided *now*:\n\n - `session.requiresAction` replaces the pending set with the payload's\n approvals (the producer always emits the full currently-pending set, so\n re-emission after a worker re-dispatch cannot duplicate cards);\n - `user.approvalDecision` subtracts the decided approval;\n - the owning turn finishing (`turn.completed`/`turn.failed`/\n `turn.cancelled`) clears the set — whatever was pending died with the\n turn. A `turn.cancelled` for a *different* turn (deleting a queued turn\n while the session waits on an approval) leaves the set alone.\n\n Pure function — same events in, same approvals out — so approve-then-reload\n projects to an empty set instead of a zombie Approve button.\n -------------------------------------------------------------------------- */\n\nexport type PendingApproval = {\n /** The id to send back via `user.approvalDecision` (`approvalId`). */\n id: string;\n /** Tool/function name awaiting the decision. */\n name: string;\n arguments?: unknown;\n /** The raw approval entry from the `session.requiresAction` payload. */\n raw?: unknown;\n};\n\n/** The approvals carried by one `session.requiresAction` payload. */\nexport function approvalsFromRequiresAction(payload: unknown): PendingApproval[] {\n const approvals =\n payload && typeof payload === \"object\"\n ? (payload as { approvals?: unknown }).approvals\n : undefined;\n if (!Array.isArray(approvals)) {\n return [];\n }\n return approvals.map((approval, index) => {\n const raw = (approval && typeof approval === \"object\" ? approval : {}) as Record<\n string,\n unknown\n >;\n const rawItem =\n raw.rawItem && typeof raw.rawItem === \"object\"\n ? (raw.rawItem as Record<string, unknown>)\n : {};\n return {\n // Mirror the runtime's canonical interruption identity before retaining\n // the legacy top-level callId fallback for already-normalized payloads.\n id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),\n name: String(raw.name ?? raw.toolName ?? rawItem.name ?? \"approval\"),\n arguments: raw.arguments ?? rawItem.arguments,\n raw: approval,\n };\n });\n}\n\n/** The approvals still awaiting a decision after replaying `events` in order. */\nexport function projectPendingApprovals(events: SessionEvent[]): PendingApproval[] {\n let pending: PendingApproval[] = [];\n let owningTurnId: string | null = null;\n for (const event of events) {\n switch (event.type) {\n case \"session.requiresAction\": {\n pending = approvalsFromRequiresAction(event.payload);\n owningTurnId = event.turnId ?? null;\n break;\n }\n case \"user.approvalDecision\": {\n const payload =\n event.payload && typeof event.payload === \"object\"\n ? (event.payload as { approvalId?: unknown })\n : {};\n if (typeof payload.approvalId === \"string\") {\n pending = pending.filter((approval) => approval.id !== payload.approvalId);\n }\n break;\n }\n case \"turn.completed\":\n case \"turn.failed\":\n case \"turn.cancelled\": {\n // Scope clearing to the turn that raised the approvals when both\n // sides carry a turn id; clear conservatively when either is unknown.\n if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {\n pending = [];\n owningTurnId = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return pending;\n}\n","import type { HumanInputQuestion, SessionEvent } from \"@opengeni/sdk\";\n\n/** Minimal actionable request shape available from the durable event log. */\nexport type PendingHumanInputRequest = {\n id: string;\n turnId: string | null;\n questions: HumanInputQuestion[];\n allowSkip: boolean;\n expiresAt: string | null;\n};\n\n/** Parse one generic `session.humanInput.requested` event defensively. */\nexport function humanInputRequestFromEvent(\n event: Pick<SessionEvent, \"type\" | \"payload\" | \"turnId\">,\n): PendingHumanInputRequest | null {\n if (event.type !== \"session.humanInput.requested\" || !isRecord(event.payload)) return null;\n const request = event.payload.request;\n if (!isRecord(request) || typeof request.id !== \"string\" || !Array.isArray(request.questions)) {\n return null;\n }\n return {\n id: request.id,\n turnId: event.turnId ?? null,\n questions: request.questions as HumanInputQuestion[],\n allowSkip: request.allowSkip === true,\n expiresAt: typeof request.expiresAt === \"string\" ? request.expiresAt : null,\n };\n}\n\n/**\n * Fold a durable event log into the structured requests that are actionable\n * now. Responses remove one request; a terminal owning turn clears any\n * unresolved requests that died with it. Replaying history cannot resurrect a\n * previously answered card.\n */\nexport function projectPendingHumanInputRequests(\n events: SessionEvent[],\n): PendingHumanInputRequest[] {\n const pending = new Map<string, PendingHumanInputRequest>();\n for (const event of events) {\n const requested = humanInputRequestFromEvent(event);\n if (requested) {\n pending.set(requested.id, requested);\n continue;\n }\n if (event.type === \"user.humanInputResponse\" && isRecord(event.payload)) {\n if (typeof event.payload.requestId === \"string\") pending.delete(event.payload.requestId);\n continue;\n }\n if (\n event.type === \"turn.completed\" ||\n event.type === \"turn.failed\" ||\n event.type === \"turn.cancelled\"\n ) {\n for (const [id, request] of pending) {\n if (\n request.turnId === null ||\n event.turnId === null ||\n event.turnId === undefined ||\n request.turnId === event.turnId\n ) {\n pending.delete(id);\n }\n }\n }\n }\n return [...pending.values()];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n","import type {\n SessionEvent,\n SessionHumanInputRequest,\n SubmitHumanInputResponseRequest,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n useEmbeddedHumanInputSession,\n type EmbeddedHumanInputClientOverride,\n} from \"../session-context\";\nimport {\n useDebouncedCallback,\n useMutationRunner,\n usePolledValue,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\n/** Events that can create, settle, or invalidate an actionable request. */\nexport function isHumanInputEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return (\n event.type === \"session.humanInput.requested\" ||\n event.type === \"user.humanInputResponse\" ||\n event.type === \"turn.completed\" ||\n event.type === \"turn.failed\" ||\n event.type === \"turn.cancelled\"\n );\n}\n\nexport type UseHumanInputRequestsOptions = EmbeddedHumanInputClientOverride &\n SessionEventFeedOptions & {\n /** Optional safety-net polling. Durable events drive refresh by default. */\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseHumanInputRequestsResult = {\n requests: SessionHumanInputRequest[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n respond: (\n requestId: string,\n response: SubmitHumanInputResponseRequest,\n ) => Promise<SessionEvent | null>;\n respondingRequestId: string | null;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Authoritative structured-human-input hook. The server's pending-request\n * table is the read model; events only trigger reconciliation. This lets an\n * embedded host use the same primitive with a shared event feed or its own SDK\n * proxy without rebuilding request lifecycle logic.\n */\nexport function useHumanInputRequests(\n sessionId: string | null | undefined,\n options: UseHumanInputRequestsOptions = {},\n): UseHumanInputRequestsResult {\n const { client, workspaceId, registerSessionReconciler } = useEmbeddedHumanInputSession(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const load = useCallback(\n async (): Promise<SessionHumanInputRequest[]> =>\n sessionId\n ? await client.listHumanInputRequests(workspaceId, sessionId, { status: \"pending\" })\n : [],\n [client, sessionId, workspaceId],\n );\n const state = usePolledValue(load, {\n enabled,\n pollIntervalMs: options.pollIntervalMs,\n });\n const mutation = useMutationRunner(`${workspaceId}\\u0000${sessionId ?? \"\"}`);\n const [respondingRequestId, setRespondingRequestId] = useState<string | null>(null);\n const respondingRequestRef = useRef<string | null>(null);\n\n useEffect(() => {\n respondingRequestRef.current = null;\n setRespondingRequestId(null);\n }, [sessionId, workspaceId]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"human-input\", state.refresh);\n }, [enabled, registerSessionReconciler, sessionId, state.refresh]);\n\n const scheduleRefresh = useDebouncedCallback(() => void state.refresh());\n useSessionEventTrigger(client, workspaceId, sessionId, isHumanInputEvent, scheduleRefresh, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n const respond = useCallback(\n async (\n requestId: string,\n response: SubmitHumanInputResponseRequest,\n ): Promise<SessionEvent | null> => {\n if (!sessionId || respondingRequestRef.current !== null) return null;\n respondingRequestRef.current = requestId;\n setRespondingRequestId(requestId);\n try {\n const event = await mutation.run(() =>\n client.submitHumanInputResponse(workspaceId, sessionId, requestId, response, {\n clientEventId: globalThis.crypto.randomUUID(),\n }),\n );\n if (event) await state.refresh();\n return event;\n } finally {\n if (respondingRequestRef.current === requestId) {\n respondingRequestRef.current = null;\n setRespondingRequestId(null);\n }\n }\n },\n [client, mutation, sessionId, state, workspaceId],\n );\n\n return {\n requests: [...(state.data ?? [])].sort(\n (left, right) =>\n left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id),\n ),\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n respond,\n respondingRequestId,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n"],"mappings":"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","names":["asRecord","useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useCallback","useEffect","useMemo","useCallback","useLayoutEffect","useRef","useRef","useLayoutEffect","useCallback","useCallback","useEffect","useRef","useState","useCallback","useState","useRef","useEffect"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/queue-surface-state.tsx"],"sourcesContent":["import { Loader2Icon, RotateCwIcon } from \"lucide-react\";\n\nimport type { UseTurnQueueResult } from \"../hooks/use-turn-queue\";\n\ntype QueueStateProps = {\n queue: UseTurnQueueResult;\n};\n\nexport function EmptyQueueStateSurface({ queue }: QueueStateProps) {\n const hasError = Boolean(queue.error || queue.mutationError);\n return (\n <div\n className=\"mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6\"\n data-testid=\"queue-surface\"\n >\n <div className=\"overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm\">\n {queue.stoppingPreviousAttempt ? (\n <QueueStoppingStatus queue={queue} dividerAfter={hasError} />\n ) : null}\n {hasError ? <QueueErrorAlert queue={queue} /> : null}\n </div>\n </div>\n );\n}\n\nexport function QueueStoppingStatus({\n queue,\n dividerAfter = false,\n}: QueueStateProps & { dividerAfter?: boolean }) {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={`flex min-h-11 items-center gap-2.5 bg-status-waiting/[0.07] px-3 py-2 text-xs text-fg ${\n dividerAfter ? \"border-b border-status-waiting/20\" : \"\"\n }`}\n data-testid=\"stopping-previous-attempt\"\n >\n <Loader2Icon\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 animate-spin text-status-waiting motion-reduce:animate-none\"\n />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">\n {queue.effectiveControl?.state === \"paused\"\n ? \"Stopping current attempt…\"\n : \"Stopping previous attempt…\"}\n </span>{\" \"}\n <span className=\"text-fg-muted\">\n {queue.effectiveControl?.state === \"paused\"\n ? \"Queued work stays saved until you resume.\"\n : \"Queued work is saved and starts automatically.\"}\n </span>\n </span>\n </div>\n );\n}\n\nexport function QueueErrorAlert({\n queue,\n dividerBefore = false,\n}: QueueStateProps & { dividerBefore?: boolean }) {\n return (\n <div className={`${dividerBefore ? \"border-t border-border\" : \"\"} p-2`}>\n <div\n role=\"alert\"\n className=\"flex min-w-0 max-w-full flex-wrap items-start gap-2 rounded-md bg-status-failed/10 px-2 py-1.5 text-xs text-status-failed\"\n >\n <span\n role=\"region\"\n aria-label=\"Queue error details\"\n tabIndex={0}\n className=\"max-h-[min(5rem,20dvh)] min-w-0 max-w-full flex-[1_1_5rem] overflow-auto overscroll-contain whitespace-pre-wrap rounded-sm outline-none [overflow-wrap:anywhere] [unicode-bidi:plaintext] focus-visible:ring-2 focus-visible:ring-ring/40\"\n data-testid=\"queue-error-message\"\n dir=\"auto\"\n >\n {(queue.mutationError ?? queue.error)?.message}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n queue.clearMutationError();\n void queue.refresh();\n }}\n aria-label=\"Dismiss queue error and retry\"\n title=\"Retry loading the queue\"\n className=\"ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-none transition-colors hover:bg-surface-3 focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none pointer-coarse:size-[44px]\"\n >\n <RotateCwIcon className=\"size-3.5\" />\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":";AAAA,SAAS,aAAa,oBAAoB;AAepC,SAEI,KAFJ;AAPC,SAAS,uBAAuB,EAAE,MAAM,GAAoB;AACjE,QAAM,WAAW,QAAQ,MAAM,SAAS,MAAM,aAAa;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAY;AAAA,MAEZ,+BAAC,SAAI,WAAU,2EACZ;AAAA,cAAM,0BACL,oBAAC,uBAAoB,OAAc,cAAc,UAAU,IACzD;AAAA,QACH,WAAW,oBAAC,mBAAgB,OAAc,IAAK;AAAA,SAClD;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,eAAe;AACjB,GAAiD;AAC/C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,WAAW,yFACT,eAAe,sCAAsC,EACvD;AAAA,MACA,eAAY;AAAA,MAEZ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,eAAY;AAAA,YACZ,WAAU;AAAA;AAAA,QACZ;AAAA,QACA,qBAAC,UAAK,WAAU,WACd;AAAA,8BAAC,UAAK,WAAU,eACb,gBAAM,kBAAkB,UAAU,WAC/B,mCACA,mCACN;AAAA,UAAQ;AAAA,UACR,oBAAC,UAAK,WAAU,iBACb,gBAAM,kBAAkB,UAAU,WAC/B,8CACA,kDACN;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,gBAAgB;AAClB,GAAkD;AAChD,SACE,oBAAC,SAAI,WAAW,GAAG,gBAAgB,2BAA2B,EAAE,QAC9D;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MAEV;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,UAAU;AAAA,YACV,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,KAAI;AAAA,YAEF,iBAAM,iBAAiB,MAAM,QAAQ;AAAA;AAAA,QACzC;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM;AACb,oBAAM,mBAAmB;AACzB,mBAAK,MAAM,QAAQ;AAAA,YACrB;AAAA,YACA,cAAW;AAAA,YACX,OAAM;AAAA,YACN,WAAU;AAAA,YAEV,8BAAC,gBAAa,WAAU,YAAW;AAAA;AAAA,QACrC;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/session-context.ts","../src/lib/format.ts","../src/hooks/internal.ts"],"sourcesContent":["import type { StreamConnectionState, WorkspaceControlEvent } from \"@opengeni/sdk\";\nimport { createContext, useContext } from \"react\";\nimport type {\n EmbeddedHumanInputSessionClientLike,\n EmbeddedSessionClientLike,\n SessionClientLike,\n} from \"./client\";\n\nexport type OpenGeniContextValue = {\n client: SessionClientLike;\n workspaceId: string;\n workspaceControlEvent: WorkspaceControlEvent | null;\n workspaceControlConnectionState: StreamConnectionState | \"idle\" | \"error\";\n registerSessionReconciler: (\n sessionId: string,\n key: string,\n reconcile: () => Promise<void>,\n ) => () => void;\n reconcileSession: (sessionId: string) => Promise<void>;\n};\n\nexport const OpenGeniContext = createContext<OpenGeniContextValue | null>(null);\n\nconst NOOP_REGISTER_RECONCILER: OpenGeniContextValue[\"registerSessionReconciler\"] = () => () =>\n undefined;\nconst NOOP_RECONCILE_SESSION: OpenGeniContextValue[\"reconcileSession\"] = async () => undefined;\n\nexport type ClientOverride = {\n client?: SessionClientLike | undefined;\n workspaceId?: string | undefined;\n};\n\nexport type EmbeddedSessionClientOverride = {\n client?: EmbeddedSessionClientLike | undefined;\n workspaceId?: string | undefined;\n};\n\nexport type EmbeddedHumanInputClientOverride = {\n client?: EmbeddedHumanInputSessionClientLike | undefined;\n workspaceId?: string | undefined;\n};\n\nexport type EmbeddedSessionContextValue = Omit<OpenGeniContextValue, \"client\"> & {\n client: EmbeddedSessionClientLike;\n};\n\n/** Resolve client + workspace from explicit overrides or the provider. */\nexport function useOpenGeni(override: ClientOverride = {}): OpenGeniContextValue {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n const workspaceId = override.workspaceId ?? context?.workspaceId;\n if (!client || !workspaceId) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client/workspace available. Wrap the tree in <OpenGeniProvider> or pass { client, workspaceId } to the hook.\",\n );\n }\n return {\n client,\n workspaceId,\n workspaceControlEvent: context?.workspaceControlEvent ?? null,\n workspaceControlConnectionState: context?.workspaceControlConnectionState ?? \"idle\",\n registerSessionReconciler: context?.registerSessionReconciler ?? NOOP_REGISTER_RECONCILER,\n reconcileSession: context?.reconcileSession ?? NOOP_RECONCILE_SESSION,\n };\n}\n\n/**\n * Resolve the narrow client required by the session-only hooks. The full\n * provider client is structurally compatible, while an explicit host proxy\n * only needs to expose session/event/composer/queue/control operations.\n */\nexport function useEmbeddedSession(\n override: EmbeddedSessionClientOverride = {},\n): EmbeddedSessionContextValue {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n const workspaceId = override.workspaceId ?? context?.workspaceId;\n if (!client || !workspaceId) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client/workspace available. Wrap the tree in <OpenGeniProvider> or pass { client, workspaceId } to the hook.\",\n );\n }\n return {\n client,\n workspaceId,\n workspaceControlEvent: context?.workspaceControlEvent ?? null,\n workspaceControlConnectionState: context?.workspaceControlConnectionState ?? \"idle\",\n registerSessionReconciler: context?.registerSessionReconciler ?? NOOP_REGISTER_RECONCILER,\n reconcileSession: context?.reconcileSession ?? NOOP_RECONCILE_SESSION,\n };\n}\n\n/**\n * Resolve the structured-input refinement without widening the baseline\n * session-only proxy contract.\n */\nexport function useEmbeddedHumanInputSession(override: EmbeddedHumanInputClientOverride = {}): Omit<\n EmbeddedSessionContextValue,\n \"client\"\n> & {\n client: EmbeddedHumanInputSessionClientLike;\n} {\n const embedded = useEmbeddedSession(override);\n const client = embedded.client as Partial<EmbeddedHumanInputSessionClientLike>;\n if (\n typeof client.listHumanInputRequests !== \"function\" ||\n typeof client.getHumanInputRequest !== \"function\" ||\n typeof client.submitHumanInputResponse !== \"function\"\n ) {\n throw new Error(\n \"@opengeni/react: useHumanInputRequests requires listHumanInputRequests, getHumanInputRequest, and submitHumanInputResponse.\",\n );\n }\n return {\n ...embedded,\n client: client as EmbeddedHumanInputSessionClientLike,\n };\n}\n\n/**\n * Resolve the client only — for hooks that are not workspace-scoped\n * (`useWorkspaces`, `useBillingUsage`).\n */\nexport function useOpenGeniClient(\n override: Pick<ClientOverride, \"client\"> = {},\n): SessionClientLike {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n if (!client) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client available. Wrap the tree in <OpenGeniProvider> or pass { client } to the hook.\",\n );\n }\n return client;\n}\n","/** Compact relative time: \"now\", \"42s\", \"7m\", \"3h\", \"2d\", then a date. */\nexport function formatRelativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) {\n return \"\";\n }\n const seconds = Math.max(0, Math.floor((now.getTime() - then) / 1000));\n if (seconds < 10) {\n return \"now\";\n }\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n if (hours < 24) {\n return `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n if (days < 14) {\n return `${days}d`;\n }\n return new Date(iso).toLocaleDateString();\n}\n\n/** Human-readable byte size: \"512 B\", \"8.0 KB\", \"1.4 MB\", \"3 GB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = bytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value < 10 ? 1 : 0)} ${unit}`;\n }\n value /= 1024;\n }\n return `${bytes} B`;\n}\n\n/** Single-line preview of arbitrary text, for tiles and collapsed rows. */\nexport function truncate(text: string, maxLength: number): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Render an unknown payload as readable text (pretty JSON when possible). */\nexport function stringifyPayload(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n const parsed = tryParseJson(value);\n if (parsed !== undefined && typeof parsed === \"object\") {\n return stringifyPayload(parsed);\n }\n return value;\n }\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** JSON.parse that returns `undefined` instead of throwing. */\nexport function tryParseJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\") && !trimmed.startsWith('\"')) {\n return undefined;\n }\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The canonical credit-death sentence. Credit exhaustion is the one failure a\n * user can fix themselves — the copy must say what happened (empty balance),\n * what to do (add credits), and what is safe (nothing was lost). Crucially it\n * must NOT say \"send a message to revive\": a revive turn burns credits the\n * workspace no longer has.\n */\nexport const CREDIT_EXHAUSTION_MESSAGE =\n \"Out of OpenGeni credits — this workspace's balance is empty. Add credits to continue; the conversation is preserved.\";\n\n/**\n * Does this failure/completion payload (or raw error string) mean the\n * workspace ran out of OpenGeni credits? Matches the engine's\n * \"insufficient OpenGeni credits\" text (case-insensitive, substring — it\n * arrives both bare and wrapped in \"Activity task failed: …\") and the\n * budget-exhausted segment limit the engine stamps on a turn it ended early.\n */\nexport function isCreditExhaustion(\n input: { error?: string | null; detail?: string | null; segmentLimit?: string | null } | string,\n): boolean {\n if (typeof input === \"string\") {\n return input.toLowerCase().includes(\"insufficient opengeni credits\");\n }\n if (input.segmentLimit === \"budget_exhausted\") {\n return true;\n }\n for (const text of [input.error, input.detail]) {\n if (typeof text === \"string\" && text.toLowerCase().includes(\"insufficient opengeni credits\")) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Humanize engine/provider failure text before it reaches the timeline or a\n * failure banner. Raw provider errors leak the wrong audience's instructions —\n * \"Incorrect API key … find your API key at platform.openai.com\" tells a\n * managed-deployment USER to fix credentials only an OPERATOR controls (and is\n * flatly wrong for Azure or subscription-backed engines). Auth, quota, and\n * credit-exhaustion failures collapse to one neutral, honest sentence; every\n * other reason passes through untouched. Raw payloads stay available in the\n * debug surfaces.\n */\nexport function humanizeFailureReason(reason: string | null): string | null {\n if (!reason) {\n return reason;\n }\n if (isCreditExhaustion(reason)) {\n return CREDIT_EXHAUSTION_MESSAGE;\n }\n const normalized = reason.toLowerCase();\n const authFailure =\n normalized.includes(\"incorrect api key\") ||\n normalized.includes(\"invalid api key\") ||\n normalized.includes(\"invalid_api_key\") ||\n normalized.includes(\"platform.openai.com/account/api-keys\") ||\n (normalized.includes(\"401\") &&\n (normalized.includes(\"api key\") || normalized.includes(\"unauthorized\")));\n if (authFailure) {\n return \"The model provider rejected this deployment's engine credentials. Sending messages won't help until the deployment's engine configuration is fixed.\";\n }\n const quotaFailure =\n normalized.includes(\"insufficient_quota\") || normalized.includes(\"exceeded your current quota\");\n if (quotaFailure) {\n return \"The model provider refused the request: this deployment's provider quota is exhausted.\";\n }\n return reason;\n}\n","import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { EmbeddedSessionClientLike } from \"../client\";\n\nexport type AsyncListState<T> = {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Shared fetch + optional polling loop for the list/read hooks. Stale\n * responses (superseded by a newer load or an unmount) are dropped.\n */\nexport function usePolledValue<T>(\n load: (signal?: AbortSignal) => Promise<T>,\n options: { pollIntervalMs?: number | undefined; enabled?: boolean | undefined } = {},\n): AsyncListState<T> {\n const enabled = options.enabled ?? true;\n const pollIntervalMs = options.pollIntervalMs;\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const generation = useRef(0);\n const activeLoadRef = useRef(load);\n useLayoutEffect(() => {\n activeLoadRef.current = load;\n }, [load]);\n const requestAbortRef = useRef<AbortController | null>(null);\n const [stateIdentity, setStateIdentity] = useState<{ load: typeof load }>(() => ({ load }));\n\n // A new loader identity means a new query (different session/workspace/...):\n // drop the previous result instead of showing it as the new query's data.\n useEffect(() => {\n if (stateIdentity.load !== load) {\n setStateIdentity({ load });\n setData(null);\n setError(null);\n }\n }, [load, stateIdentity.load]);\n\n const run = useCallback(async () => {\n // A callback retained by a completed mutation from the previous query must\n // not supersede or settle the current query's request.\n if (activeLoadRef.current !== load) return;\n const ticket = ++generation.current;\n requestAbortRef.current?.abort();\n const requestAbort = new AbortController();\n requestAbortRef.current = requestAbort;\n try {\n const result = await load(requestAbort.signal);\n if (\n ticket === generation.current &&\n activeLoadRef.current === load &&\n !requestAbort.signal.aborted\n ) {\n setData(result);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (\n ticket === generation.current &&\n activeLoadRef.current === load &&\n !requestAbort.signal.aborted\n ) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setLoading(false);\n }\n } finally {\n if (requestAbortRef.current === requestAbort) {\n requestAbortRef.current = null;\n }\n }\n }, [load]);\n\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void run();\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n requestAbortRef.current?.abort();\n };\n }\n const timer = setInterval(() => void run(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n requestAbortRef.current?.abort();\n };\n }, [run, enabled, pollIntervalMs]);\n\n const identityMatches = stateIdentity.load === load;\n return {\n data: identityMatches ? data : null,\n loading: identityMatches ? loading : enabled,\n error: identityMatches ? error : null,\n refresh: run,\n };\n}\n\nexport type MutationState = {\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Shared async mutation runner for the write hooks. `run` resolves with the\n * operation's value, or `null` after capturing the error in `mutationError`\n * (callers then roll back optimistic state).\n */\nexport function useMutationRunner(identity: unknown = undefined): MutationState & {\n run: <T>(operation: () => Promise<T>) => Promise<T | null>;\n} {\n const [mutating, setMutating] = useState(false);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const [stateIdentity, setStateIdentity] = useState<unknown>(() => identity);\n const inFlight = useRef(0);\n const generation = useRef(0);\n const identityRef = useRef(identity);\n useLayoutEffect(() => {\n if (Object.is(identityRef.current, identity)) return;\n identityRef.current = identity;\n generation.current += 1;\n inFlight.current = 0;\n }, [identity]);\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n useEffect(() => {\n if (!Object.is(stateIdentity, identity)) {\n setStateIdentity(() => identity);\n setMutating(false);\n setMutationError(null);\n }\n }, [identity, stateIdentity]);\n const run = useCallback(\n async <T>(operation: () => Promise<T>): Promise<T | null> => {\n const ownedIdentity = identity;\n const ownedGeneration = generation.current;\n if (!Object.is(identityRef.current, ownedIdentity)) return null;\n inFlight.current += 1;\n if (mounted.current) {\n setMutating(true);\n setMutationError(null);\n }\n try {\n const result = await operation();\n if (\n !mounted.current ||\n generation.current !== ownedGeneration ||\n !Object.is(identityRef.current, ownedIdentity)\n ) {\n return null;\n }\n return result;\n } catch (cause) {\n if (\n mounted.current &&\n generation.current === ownedGeneration &&\n Object.is(identityRef.current, ownedIdentity)\n ) {\n setMutationError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n return null;\n } finally {\n if (\n generation.current === ownedGeneration &&\n Object.is(identityRef.current, ownedIdentity)\n ) {\n inFlight.current -= 1;\n if (mounted.current && inFlight.current === 0) {\n setMutating(false);\n }\n }\n }\n },\n [identity],\n );\n const identityMatches = Object.is(stateIdentity, identity);\n return {\n mutating: identityMatches && mutating,\n mutationError: identityMatches ? mutationError : null,\n clearMutationError: useCallback(() => {\n if (Object.is(identityRef.current, identity)) setMutationError(null);\n }, [identity]),\n run,\n };\n}\n\nexport type SessionEventFeedOptions = {\n /**\n * Share an existing event log (from `useSessionEvents`) instead of opening\n * a second stream. When omitted the hook tails the session's event stream\n * itself, starting at the current `lastSequence`.\n */\n events?: SessionEvent[] | undefined;\n enabled?: boolean | undefined;\n};\n\n/**\n * Invoke `onEvent` for every session event matching `match` — the live-update\n * primitive behind `useTurnQueue` and `useGoal`. Either watches a shared\n * `events` log or tails the stream directly (reconnect handled by the SDK).\n */\nexport function useSessionEventTrigger(\n client: EmbeddedSessionClientLike,\n workspaceId: string,\n sessionId: string | null | undefined,\n match: (event: SessionEvent) => boolean,\n onEvent: (event: SessionEvent) => void,\n options: SessionEventFeedOptions = {},\n reconcileBeforeLive?: (() => void | Promise<void>) | undefined,\n): void {\n const enabled = options.enabled ?? true;\n const events = options.events;\n const sharedFeed = events !== undefined;\n const matchRef = useRef(match);\n const onEventRef = useRef(onEvent);\n const reconcileBeforeLiveRef = useRef(reconcileBeforeLive);\n useLayoutEffect(() => {\n matchRef.current = match;\n onEventRef.current = onEvent;\n reconcileBeforeLiveRef.current = reconcileBeforeLive;\n }, [match, onEvent, reconcileBeforeLive]);\n const consumedRef = useRef(0);\n const feedKeyRef = useRef<string | null>(null);\n\n // Shared-log mode: scan only the unseen tail on every append.\n useEffect(() => {\n if (!sharedFeed || !enabled || !sessionId) {\n return;\n }\n const feedKey = `${workspaceId}\\u0000${sessionId}`;\n const firstSequence = events[0]?.sequence ?? 0;\n // A new session target or a log reset (sequence restarted below the\n // cursor) restarts consumption from the top of the shared log.\n if (feedKeyRef.current !== feedKey || firstSequence > consumedRef.current + 1) {\n feedKeyRef.current = feedKey;\n consumedRef.current = 0;\n }\n for (const event of events) {\n if (event.sequence <= consumedRef.current) {\n continue;\n }\n consumedRef.current = event.sequence;\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n }, [sharedFeed, enabled, events, workspaceId, sessionId]);\n\n // Self-stream mode: tail from the session's current lastSequence.\n useEffect(() => {\n if (sharedFeed || !enabled || !sessionId) {\n return;\n }\n const controller = new AbortController();\n void (async () => {\n try {\n const session = await client.getSession(workspaceId, sessionId);\n if (controller.signal.aborted) {\n return;\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: session.lastSequence,\n signal: controller.signal,\n beforeLive: async () => await reconcileBeforeLiveRef.current?.(),\n });\n for await (const event of stream) {\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n } catch {\n // Live updates are best-effort: the read hooks still expose refresh()\n // and the initial load already populated state.\n }\n })();\n return () => {\n controller.abort();\n };\n }, [sharedFeed, enabled, client, workspaceId, sessionId]);\n}\n\n/** Debounce rapid event bursts into one trailing call (default 150ms). */\nexport function useDebouncedCallback(callback: () => void, delayMs = 150): () => void {\n const callbackRef = useRef(callback);\n useLayoutEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n return useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n callbackRef.current();\n }, delayMs);\n }, [delayMs]);\n}\n"],"mappings":"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","names":[]}