@opengeni/react 7.0.0 → 7.1.0-canary.35916963870001

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 (68) hide show
  1. package/README.md +34 -0
  2. package/dist/approvals.d.ts +2 -1
  3. package/dist/{chunk-D5NOQPLR.js → chunk-CJCVYUKK.js} +25 -15
  4. package/dist/chunk-CJCVYUKK.js.map +1 -0
  5. package/dist/{chunk-IYUPN32E.js → chunk-DBPVUGQT.js} +6 -1
  6. package/dist/{chunk-IYUPN32E.js.map → chunk-DBPVUGQT.js.map} +1 -1
  7. package/dist/{chunk-JKLGJQO5.js → chunk-HJDDS2L6.js} +35 -15
  8. package/dist/chunk-HJDDS2L6.js.map +1 -0
  9. package/dist/{chunk-5GAL23FF.js → chunk-IOLPHOF4.js} +2 -5
  10. package/dist/chunk-IOLPHOF4.js.map +1 -0
  11. package/dist/{chunk-D7GAPJ3V.js → chunk-RAJYEBEG.js} +63 -30
  12. package/dist/chunk-RAJYEBEG.js.map +1 -0
  13. package/dist/{chunk-IP4BUBKH.js → chunk-TA4W6KBP.js} +24 -13
  14. package/dist/chunk-TA4W6KBP.js.map +1 -0
  15. package/dist/{chunk-UXE5SSNN.js → chunk-U56XI627.js} +2 -2
  16. package/dist/{chunk-JPHDWKZE.js → chunk-X7YDBAQD.js} +12 -7
  17. package/dist/chunk-X7YDBAQD.js.map +1 -0
  18. package/dist/{chunk-HJ5VJ4JB.js → chunk-ZA4K7YY2.js} +73 -15
  19. package/dist/chunk-ZA4K7YY2.js.map +1 -0
  20. package/dist/components/markdown.d.ts +2 -0
  21. package/dist/components/model-policy-picker.d.ts +17 -1
  22. package/dist/components/session-conversation.d.ts +3 -0
  23. package/dist/composer.d.ts +1 -1
  24. package/dist/composer.js +4 -4
  25. package/dist/connect.js +1 -1
  26. package/dist/hooks/use-session-events.d.ts +6 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +10 -13
  29. package/dist/index.js.map +1 -1
  30. package/dist/machines.js +1 -1
  31. package/dist/{model-policy-picker-menu-RVOQ4ZZG.js → model-policy-picker-menu-S3SF65AH.js} +4 -4
  32. package/dist/model-policy.js +1 -1
  33. package/dist/realtime.js +2 -2
  34. package/dist/session-ui.js +6 -6
  35. package/dist/session.js +2 -2
  36. package/dist/timeline/tool-display-name.d.ts +2 -1
  37. package/dist/timeline/types.d.ts +2 -1
  38. package/package.json +3 -3
  39. package/src/approvals.ts +8 -1
  40. package/src/components/approval-surface.tsx +12 -2
  41. package/src/components/machine-card.tsx +5 -5
  42. package/src/components/machine-dock-bar.tsx +1 -1
  43. package/src/components/machines/machine-detail.tsx +5 -2
  44. package/src/components/markdown.tsx +101 -55
  45. package/src/components/model-policy-picker-menu.tsx +131 -33
  46. package/src/components/model-policy-picker.tsx +61 -12
  47. package/src/components/session-commands-panel.tsx +8 -3
  48. package/src/components/session-conversation.tsx +5 -1
  49. package/src/composer.ts +1 -0
  50. package/src/hooks/use-last-started-turn-policy.ts +3 -7
  51. package/src/hooks/use-session-events.ts +32 -7
  52. package/src/index.ts +1 -0
  53. package/src/model-policy.ts +1 -4
  54. package/src/timeline/projection.ts +4 -0
  55. package/src/timeline/rolling-activity.tsx +4 -2
  56. package/src/timeline/tool-display-name.ts +8 -6
  57. package/src/timeline/tool-renderers.tsx +5 -3
  58. package/src/timeline/types.ts +2 -0
  59. package/styles/compiled.css +15 -0
  60. package/dist/chunk-5GAL23FF.js.map +0 -1
  61. package/dist/chunk-D5NOQPLR.js.map +0 -1
  62. package/dist/chunk-D7GAPJ3V.js.map +0 -1
  63. package/dist/chunk-HJ5VJ4JB.js.map +0 -1
  64. package/dist/chunk-IP4BUBKH.js.map +0 -1
  65. package/dist/chunk-JKLGJQO5.js.map +0 -1
  66. package/dist/chunk-JPHDWKZE.js.map +0 -1
  67. /package/dist/{chunk-UXE5SSNN.js.map → chunk-U56XI627.js.map} +0 -0
  68. /package/dist/{model-policy-picker-menu-RVOQ4ZZG.js.map → model-policy-picker-menu-S3SF65AH.js.map} +0 -0
@@ -841,6 +841,9 @@ function useSessionLineage(sessionId, options = {}) {
841
841
  }
842
842
 
843
843
  // src/approvals.ts
844
+ import {
845
+ parseToolDisplayMetadata
846
+ } from "@opengeni/sdk";
844
847
  function approvalsFromRequiresAction(payload) {
845
848
  const approvals = payload && typeof payload === "object" ? payload.approvals : void 0;
846
849
  if (!Array.isArray(approvals)) {
@@ -849,11 +852,13 @@ function approvalsFromRequiresAction(payload) {
849
852
  return approvals.map((approval, index) => {
850
853
  const raw = approval && typeof approval === "object" ? approval : {};
851
854
  const rawItem = raw.rawItem && typeof raw.rawItem === "object" ? raw.rawItem : {};
855
+ const display = parseToolDisplayMetadata(raw.display);
852
856
  return {
853
857
  // Mirror the runtime's canonical interruption identity before retaining
854
858
  // the legacy top-level callId fallback for already-normalized payloads.
855
859
  id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),
856
860
  name: String(raw.name ?? raw.toolName ?? rawItem.name ?? "approval"),
861
+ ...display ? { display } : {},
857
862
  arguments: raw.arguments ?? rawItem.arguments,
858
863
  raw: approval
859
864
  };
@@ -905,4 +910,4 @@ export {
905
910
  approvalsFromRequiresAction,
906
911
  projectPendingApprovals
907
912
  };
908
- //# sourceMappingURL=chunk-IYUPN32E.js.map
913
+ //# sourceMappingURL=chunk-DBPVUGQT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/embedded-session-client.ts","../src/hooks/use-file-attachments.ts","../src/hooks/use-goal.ts","../src/hooks/use-session-control.ts","../src/hooks/use-session-mcp-approval-policy.ts","../src/hooks/use-session-lineage.ts","../src/approvals.ts"],"sourcesContent":["import type { ComposerDraft } from \"@opengeni/sdk\";\nimport type { EmbeddedSessionClientLike } from \"./client\";\n\nexport type ComposerDraftMapContext = {\n operation: \"read\" | \"save\" | \"submit\";\n workspaceId: string;\n sessionId: string;\n};\n\nexport type CreateEmbeddedSessionClientOptions = {\n /**\n * Explicit host-owned method replacements. Methods inherited from `base`\n * retain `base` as their receiver; overrides retain this object as theirs.\n */\n overrides?: Partial<EmbeddedSessionClientLike> | undefined;\n /** Presentation/policy projection for every draft entering the React layer. */\n mapComposerDraft?:\n | ((draft: ComposerDraft, context: ComposerDraftMapContext) => ComposerDraft)\n | undefined;\n};\n\nconst requiredMethods = [\n \"getSession\",\n \"listEvents\",\n \"streamEvents\",\n \"getComposerDraft\",\n \"saveComposerDraft\",\n \"submitComposerDraft\",\n \"sendMessage\",\n \"steerMessage\",\n \"getQueue\",\n \"moveQueueItem\",\n \"editQueueItem\",\n \"steerQueueItem\",\n \"deleteQueueItem\",\n \"pauseSession\",\n \"resumeSession\",\n \"sendApprovalDecision\",\n] as const satisfies readonly (keyof EmbeddedSessionClientLike)[];\n\n/**\n * Build the exact client required by `@opengeni/react/session` from a full SDK\n * client or host proxy. The constructor binds every delegated method once,\n * supports a host-owned atomic composer-submit override, and fails at creation\n * time instead of waiting for a missing method to be exercised by a hook.\n */\nexport function createEmbeddedSessionClient(\n base: EmbeddedSessionClientLike,\n options: CreateEmbeddedSessionClientOptions = {},\n): EmbeddedSessionClientLike {\n const overrides = options.overrides ?? {};\n const client = {} as EmbeddedSessionClientLike;\n for (const key of requiredMethods) {\n const override = overrides[key];\n const method = override ?? base[key];\n if (typeof method !== \"function\") {\n throw new TypeError(`Embedded session client method is required: ${key}`);\n }\n client[key] = method.bind(override === undefined ? base : overrides) as never;\n }\n\n const inferenceOverride = overrides.setWorkspaceInferenceState;\n const inferenceBase = base.setWorkspaceInferenceState;\n const inferenceMethod = inferenceOverride ?? inferenceBase;\n if (typeof inferenceMethod === \"function\") {\n client.setWorkspaceInferenceState = inferenceMethod.bind(\n inferenceOverride === undefined ? base : overrides,\n );\n }\n\n const mapDraft = options.mapComposerDraft;\n if (!mapDraft) return client;\n\n const getComposerDraft = client.getComposerDraft;\n client.getComposerDraft = async (workspaceId, sessionId) =>\n mapDraft(await getComposerDraft(workspaceId, sessionId), {\n operation: \"read\",\n workspaceId,\n sessionId,\n });\n\n const saveComposerDraft = client.saveComposerDraft;\n client.saveComposerDraft = async (workspaceId, sessionId, request) =>\n mapDraft(await saveComposerDraft(workspaceId, sessionId, request), {\n operation: \"save\",\n workspaceId,\n sessionId,\n });\n\n const submitComposerDraft = client.submitComposerDraft;\n client.submitComposerDraft = async (workspaceId, sessionId, request) => {\n const response = await submitComposerDraft(workspaceId, sessionId, request);\n return {\n ...response,\n draft: mapDraft(response.draft, {\n operation: \"submit\",\n workspaceId,\n sessionId,\n }),\n };\n };\n\n return client;\n}\n","import type { FileAsset, FileResourceRef } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n useEmbeddedFileAttachments,\n type EmbeddedFileAttachmentClientOverride,\n} from \"../session-context\";\n\nexport type UseFileAttachmentsOptions = EmbeddedFileAttachmentClientOverride & {\n /**\n * Only files matching this predicate are accepted by {@link\n * UseFileAttachmentsResult.addFromPaste} (the clipboard path). Defaults to\n * `image/*` — the console's historical paste filter. {@link\n * UseFileAttachmentsResult.addFiles} (the explicit picker / drop path)\n * bypasses it.\n */\n /** Retain original uploads in the chat owner’s personal scope when private. */\n scope?: \"workspace\" | \"personal\";\n pasteFilter?: ((file: File) => boolean) | undefined;\n};\n\nexport type FileAttachment = {\n id: string;\n name: string;\n contentType: string;\n sizeBytes: number;\n status: \"uploading\" | \"ready\" | \"failed\";\n /** The SDK `FileAsset` once the upload finishes. */\n file?: FileAsset | undefined;\n /** Object-URL for an inline preview; minted for `image/*` files only. */\n previewUrl?: string | undefined;\n /** Stable SDK failure code for UI behavior that must not parse error copy. */\n errorCode?: \"secure_context_required\" | undefined;\n error?: string | undefined;\n};\n\nexport type UseFileAttachmentsResult = {\n attachments: FileAttachment[];\n /**\n * `FileResourceRef[]` for every attachment that finished uploading — feed\n * straight into `useComposer`'s `sendExtras.resources`.\n */\n readyResources: FileResourceRef[];\n /** True while any attachment is still uploading (drives progress UI). */\n uploading: boolean;\n /**\n * True while any attachment still needs an explicit outcome: wait for an\n * upload, retry a failure, or remove it. This is the loss-prevention send\n * gate; failed cards must never be silently omitted from a message.\n */\n hasUnresolved: boolean;\n /** Explicit picker / drop path — uploads every file, no filter. */\n addFiles: (files: Iterable<File>) => void;\n /** Clipboard path — applies `pasteFilter` (default `image/*`) then uploads. */\n addFromPaste: (event: { clipboardData: DataTransfer | null }) => void;\n /** Restore already-ready server assets without recreating browser-local bytes. */\n restoreReadyFiles: (files: Iterable<FileAsset>) => void;\n /**\n * Resolve a ready image's short-lived server preview URL on demand. Optional\n * for upload-only embedded clients; local object-URL previews remain usable\n * without it.\n */\n loadPreview?: ((id: string, signal?: AbortSignal) => Promise<string | undefined>) | undefined;\n /**\n * Re-run the upload for a `failed` attachment, in place (same id, same\n * source file). No-op for an id that isn't a known failed upload.\n */\n retry: (id: string) => void;\n /**\n * Keep an attachment's object-URL alive for a consumer that outlives its\n * queue entry (for example, an open route-level lightbox). The returned\n * release is idempotent; pending revocation finishes after the last holder\n * releases. Returns `undefined` when the attachment has no local preview.\n */\n retainPreview: (id: string) => (() => void) | undefined;\n /** Remove one attachment; revokes its object-URL after retained users finish. */\n remove: (id: string) => void;\n /**\n * Remove only finalized files whose durable ids were accepted by a send.\n * Attachments added while that request was in flight remain queued for the\n * next message.\n */\n removeReadyFiles: (fileIds: Iterable<string>) => void;\n /** Remove all attachments and revoke every unretained object-URL. */\n clear: () => void;\n};\n\nconst isImage = (file: File): boolean => file.type.startsWith(\"image/\");\n\nlet fallbackAttachmentId = 0;\n\nfunction createAttachmentId(): string {\n const cryptoSource = globalThis.crypto;\n if (typeof cryptoSource?.randomUUID === \"function\") return cryptoSource.randomUUID();\n fallbackAttachmentId += 1;\n // This id is only a browser-local React key and retry lookup, never durable\n // authority. Keep attachment tracking usable when HTTP withholds randomUUID\n // or Web Crypto is unavailable so the SDK's typed failure reaches the card.\n return `attachment:${Date.now().toString(36)}:${fallbackAttachmentId.toString(36)}`;\n}\n\nfunction secureContextRequiredErrorCode(error: unknown): \"secure_context_required\" | undefined {\n return typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"secure_context_required\"\n ? error.code\n : undefined;\n}\n\n/**\n * Upload-and-track state for files attached to the next message. Owns the\n * full client-side upload layer: a per-file `uploading | ready | failed`\n * status machine driven by the SDK's `client.uploadFile`, object-URL image\n * previews with create/revoke lifecycle, the `image/*` clipboard paste filter,\n * and a `FileResourceRef[]` projection that drops straight into a message's\n * `resources`. Workspace-scoped, so it resolves both client and workspace from\n * the {@link OpenGeniProvider} (or a per-call `{ client, workspaceId }`).\n */\nexport function useFileAttachments(\n options: UseFileAttachmentsOptions = {},\n): UseFileAttachmentsResult {\n const { client, workspaceId } = useEmbeddedFileAttachments(options);\n const pasteFilter = options.pasteFilter ?? isImage;\n const [attachments, setAttachments] = useState<FileAttachment[]>([]);\n const attachmentsRef = useRef(attachments);\n attachmentsRef.current = attachments;\n // Keep the source File per attachment id so a failed upload can be retried\n // in place. Cleared on remove/clear so it never outlives its attachment.\n const sources = useRef<Map<string, File>>(new Map());\n // Object URLs must be owned synchronously: React may discard an attachment\n // state update when its component unmounts in the same batch that minted the\n // preview. The registry remains available to cleanup even before a render.\n const previewUrls = useRef<Map<string, string>>(new Map());\n const previewRetainers = useRef<Map<string, number>>(new Map());\n const pendingPreviewRevocations = useRef<Set<string>>(new Set());\n const revokePreview = useCallback((id: string) => {\n const previewUrl = previewUrls.current.get(id);\n if (!previewUrl) return;\n if ((previewRetainers.current.get(id) ?? 0) > 0) {\n pendingPreviewRevocations.current.add(id);\n return;\n }\n previewUrls.current.delete(id);\n pendingPreviewRevocations.current.delete(id);\n URL.revokeObjectURL(previewUrl);\n }, []);\n const revokeAllPreviews = useCallback(() => {\n for (const id of previewUrls.current.keys()) revokePreview(id);\n }, [revokePreview]);\n const retainPreview = useCallback(\n (id: string): (() => void) | undefined => {\n if (!previewUrls.current.has(id)) return undefined;\n previewRetainers.current.set(id, (previewRetainers.current.get(id) ?? 0) + 1);\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const remaining = (previewRetainers.current.get(id) ?? 1) - 1;\n if (remaining > 0) {\n previewRetainers.current.set(id, remaining);\n return;\n }\n previewRetainers.current.delete(id);\n if (pendingPreviewRevocations.current.has(id)) revokePreview(id);\n };\n },\n [revokePreview],\n );\n // Ready-file reconciliation uses functional state updaters, which React may\n // evaluate during a concurrent render that later suspends or is abandoned.\n // Diff only committed attachment sets here so URL revocation cannot run from\n // render-phase code while the previously committed DOM still uses a preview.\n const committedAttachmentIds = useRef<Set<string>>(new Set());\n useEffect(() => {\n const currentIds = new Set(attachments.map((attachment) => attachment.id));\n for (const id of committedAttachmentIds.current) {\n if (!currentIds.has(id)) revokePreview(id);\n }\n committedAttachmentIds.current = currentIds;\n }, [attachments, revokePreview]);\n // Upload promises are not cancellable at this layer. Fence their settlements\n // when the hook changes client/workspace or unmounts so an old tenant/session\n // cannot mutate the next attachment queue (or an already-unmounted component).\n const scopeGeneration = useRef(0);\n const previousScope = useRef({ client, workspaceId });\n\n useEffect(() => {\n const previous = previousScope.current;\n if (previous.client === client && previous.workspaceId === workspaceId) return;\n previousScope.current = { client, workspaceId };\n scopeGeneration.current += 1;\n sources.current.clear();\n revokeAllPreviews();\n setAttachments([]);\n }, [client, revokeAllPreviews, workspaceId]);\n\n useEffect(\n () => () => {\n scopeGeneration.current += 1;\n sources.current.clear();\n revokeAllPreviews();\n },\n [revokeAllPreviews],\n );\n\n // Run (or re-run) the upload for one already-tracked attachment id. Sets it\n // back to `uploading`, then resolves to `ready` (with the asset) or `failed`\n // (with the error message).\n const startUpload = useCallback(\n (id: string, file: File) => {\n const generation = scopeGeneration.current;\n void client\n .uploadFile(workspaceId, {\n filename: file.name || \"file\",\n contentType: file.type || \"application/octet-stream\",\n data: file,\n ...(options.scope ? { scope: options.scope } : {}),\n })\n .then((asset) => {\n if (scopeGeneration.current !== generation) return;\n // Retry bytes are useful only until durable finalization succeeds.\n // Drop the source File immediately; restored/ready attachments must\n // never retain browser-local byte authority.\n sources.current.delete(id);\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"ready\",\n file: asset,\n name: asset.filename,\n contentType: asset.contentType,\n sizeBytes: asset.sizeBytes,\n errorCode: undefined,\n error: undefined,\n }\n : attachment,\n ),\n );\n })\n .catch((error: unknown) => {\n if (scopeGeneration.current !== generation) return;\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"failed\",\n errorCode: secureContextRequiredErrorCode(error),\n error: error instanceof Error ? error.message : String(error),\n }\n : attachment,\n ),\n );\n });\n },\n [client, workspaceId, options.scope],\n );\n\n const addFiles = useCallback(\n (files: Iterable<File>) => {\n for (const file of files) {\n const id = createAttachmentId();\n sources.current.set(id, file);\n const previewUrl = isImage(file) ? URL.createObjectURL(file) : undefined;\n if (previewUrl) previewUrls.current.set(id, previewUrl);\n setAttachments((current) => [\n ...current,\n {\n id,\n name: file.name || \"image\",\n contentType: file.type || \"application/octet-stream\",\n sizeBytes: file.size,\n status: \"uploading\",\n ...(previewUrl ? { previewUrl } : {}),\n },\n ]);\n startUpload(id, file);\n }\n },\n [startUpload],\n );\n\n const retry = useCallback(\n (id: string) => {\n const file = sources.current.get(id);\n if (!file) {\n return;\n }\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? { ...attachment, status: \"uploading\", errorCode: undefined, error: undefined }\n : attachment,\n ),\n );\n startUpload(id, file);\n },\n [startUpload],\n );\n\n const addFromPaste = useCallback(\n (event: { clipboardData: DataTransfer | null }) => {\n const clipboardFiles = event.clipboardData?.files;\n if (!clipboardFiles) {\n return;\n }\n const files = [...clipboardFiles].filter(pasteFilter);\n if (files.length > 0) {\n addFiles(files);\n }\n },\n [addFiles, pasteFilter],\n );\n\n const restoreReadyFiles = useCallback(\n (files: Iterable<FileAsset>) => {\n const incoming = new Map<string, FileAsset>();\n for (const file of files) {\n if (file.status === \"ready\" && file.workspaceId === workspaceId) {\n incoming.set(file.id, file);\n }\n }\n setAttachments((current) => {\n const unresolved = current.filter((attachment) => attachment.status !== \"ready\");\n const existingReady = new Map(\n current.flatMap((attachment) =>\n attachment.status === \"ready\" && attachment.file\n ? ([[attachment.file.id, attachment]] as const)\n : [],\n ),\n );\n const restored = [...incoming.values()].map((file): FileAttachment => {\n const existing = existingReady.get(file.id);\n return existing\n ? {\n ...existing,\n name: file.filename,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n status: \"ready\",\n file,\n errorCode: undefined,\n error: undefined,\n }\n : {\n id: `restored:${file.id}`,\n name: file.filename,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n status: \"ready\",\n file,\n // No source File and no object URL: server metadata is the\n // only authority restored across page/device boundaries.\n };\n });\n // A server restoration is authoritative for finalized assets, but an\n // upload that has not finalized still belongs to the local actor. Keep\n // those unresolved entries while replacing the ready set exactly.\n return [...unresolved, ...restored];\n });\n },\n [workspaceId],\n );\n\n const loadPreview = useCallback(\n async (id: string, signal?: AbortSignal): Promise<string | undefined> => {\n const generation = scopeGeneration.current;\n const attachment = attachmentsRef.current.find((candidate) => candidate.id === id);\n const createDownloadUrl = client.createFileDownloadUrl;\n if (\n !attachment ||\n attachment.status !== \"ready\" ||\n !attachment.file ||\n !attachment.contentType.startsWith(\"image/\") ||\n typeof createDownloadUrl !== \"function\" ||\n signal?.aborted\n ) {\n return undefined;\n }\n const fileId = attachment.file.id;\n const signed = await createDownloadUrl.call(client, workspaceId, fileId, { signal });\n if (scopeGeneration.current !== generation || signal?.aborted) return undefined;\n const current = attachmentsRef.current.find((candidate) => candidate.id === id);\n if (current?.status !== \"ready\" || current.file?.id !== fileId) return undefined;\n return signed.url;\n },\n [client, workspaceId],\n );\n\n const remove = useCallback(\n (id: string) => {\n sources.current.delete(id);\n revokePreview(id);\n setAttachments((current) => current.filter((attachment) => attachment.id !== id));\n },\n [revokePreview],\n );\n\n const removeReadyFiles = useCallback((fileIds: Iterable<string>) => {\n const accepted = new Set(fileIds);\n if (accepted.size === 0) return;\n setAttachments((current) =>\n current.filter((attachment) => {\n return !(\n attachment.status === \"ready\" &&\n attachment.file !== undefined &&\n accepted.has(attachment.file.id)\n );\n }),\n );\n }, []);\n\n const clear = useCallback(() => {\n sources.current.clear();\n revokeAllPreviews();\n setAttachments([]);\n }, [revokeAllPreviews]);\n\n return {\n attachments,\n readyResources: attachments.flatMap((attachment): FileResourceRef[] =>\n attachment.status === \"ready\" && attachment.file\n ? [{ kind: \"file\", fileId: attachment.file.id }]\n : [],\n ),\n uploading: attachments.some((attachment) => attachment.status === \"uploading\"),\n hasUnresolved: attachments.some((attachment) => attachment.status !== \"ready\"),\n addFiles,\n addFromPaste,\n restoreReadyFiles,\n ...(typeof client.createFileDownloadUrl === \"function\" ? { loadPreview } : {}),\n retry,\n retainPreview,\n remove,\n removeReadyFiles,\n clear,\n };\n}\n","import { OpenGeniApiError, type SessionEvent, type SessionGoal } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useEmbeddedGoal, type EmbeddedGoalClientOverride } from \"../session-context\";\nimport {\n useDebouncedCallback,\n useMutationRunner,\n usePageLiveActivity,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\n/** Event types that change the session goal (set/updated/completed/paused/...). */\nexport function isGoalEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return event.type.startsWith(\"goal.\");\n}\n\n/**\n * Events that can change the server-authoritative continuation projection.\n * The projection is derived from durable turn, session, control, and system\n * update state, so those events refresh the goal without model polling.\n */\nexport function isGoalRefreshEvent(event: Pick<SessionEvent, \"type\">): boolean {\n const type = event.type;\n return (\n isGoalEvent(event) ||\n type.startsWith(\"turn.\") ||\n type.startsWith(\"session.\") ||\n type.startsWith(\"system.update.\") ||\n type.startsWith(\"workspace.inference.\") ||\n type.startsWith(\"user.\")\n );\n}\n\nexport type UseGoalOptions = EmbeddedGoalClientOverride &\n SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default — event refreshes drive updates. */\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseGoalResult = {\n /** The session goal, or null when the session has none. */\n goal: SessionGoal | null;\n /** Convenience flags over `goal.status`. */\n isActive: boolean;\n isPaused: boolean;\n isCompleted: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Pause the goal loop (PATCH status=paused). */\n pause: (rationale?: string) => Promise<SessionGoal | null>;\n /** Resume a paused goal: resets counters and re-arms continuations. */\n resume: () => Promise<SessionGoal | null>;\n /** Clear the session goal; goal-less sessions remain a successful no-op. */\n clearGoal: () => Promise<void>;\n /** Alias for `clearGoal`. */\n deleteGoal: () => Promise<void>;\n /** True while a pause/resume/clear is in flight. */\n updating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The session's goal: state, the autonomy counters (`autoContinuations`,\n * `noProgressStreak`), and pause/resume control. A goal-less session yields\n * `goal: null` (the 404 is absorbed). Live-updates on goal, turn, session,\n * control, and system-update events — pass `options.events` from\n * `useSessionEvents` to reuse its stream.\n */\nexport function useGoal(\n sessionId: string | null | undefined,\n options: UseGoalOptions = {},\n): UseGoalResult {\n const { client, workspaceId } = useEmbeddedGoal(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const sharedEvents = options.events;\n const sharedFeed = sharedEvents !== undefined;\n const pageLive = usePageLiveActivity();\n const [goal, setGoal] = useState<SessionGoal | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const { run, mutating, mutationError, clearMutationError } = useMutationRunner();\n const generation = useRef(0);\n const targetKeyRef = useRef<string | null>(null);\n const loadAbort = useRef<AbortController | null>(null);\n\n const retireLoads = useCallback(() => {\n generation.current += 1;\n loadAbort.current?.abort();\n loadAbort.current = null;\n }, []);\n\n const load = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n const ticket = ++generation.current;\n loadAbort.current?.abort();\n const controller = new AbortController();\n loadAbort.current = controller;\n try {\n const fetched = await client.getGoal(workspaceId, sessionId, {\n signal: controller.signal,\n });\n if (ticket === generation.current) {\n setGoal(fetched);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (ticket !== generation.current) {\n return;\n }\n if (cause instanceof OpenGeniApiError && cause.status === 404) {\n // No goal is a normal state, not an error.\n setGoal(null);\n setError(null);\n } else {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n setLoading(false);\n } finally {\n if (loadAbort.current === controller) loadAbort.current = null;\n }\n }, [client, workspaceId, sessionId]);\n\n useEffect(() => {\n const targetKey = `${workspaceId} ${sessionId ?? \"\"}`;\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n setGoal(null);\n setError(null);\n }\n if (!enabled || !pageLive) {\n retireLoads();\n setLoading(false);\n return;\n }\n if (sharedFeed) {\n // A shared log supplies invalidations, not the authoritative goal snapshot.\n setLoading(true);\n void load();\n return () => {\n retireLoads();\n };\n }\n setLoading(true);\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n void load();\n return () => {\n retireLoads();\n };\n }\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const schedule = () => {\n if (cancelled) return;\n timer = setTimeout(() => {\n timer = null;\n void load().finally(schedule);\n }, pollIntervalMs);\n };\n void load().finally(schedule);\n return () => {\n cancelled = true;\n if (timer !== null) clearTimeout(timer);\n retireLoads();\n };\n }, [\n load,\n enabled,\n pageLive,\n workspaceId,\n sessionId,\n options.pollIntervalMs,\n retireLoads,\n sharedFeed,\n ]);\n\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(client, workspaceId, sessionId, isGoalRefreshEvent, scheduleRefresh, {\n enabled,\n ...(sharedEvents !== undefined ? { events: sharedEvents } : {}),\n });\n\n const pause = useCallback(\n async (rationale?: string): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await run(() =>\n client.updateGoal(workspaceId, sessionId, {\n status: \"paused\",\n ...(rationale !== undefined ? { rationale } : {}),\n }),\n );\n if (result) {\n setGoal(result);\n }\n return result;\n },\n [client, workspaceId, sessionId, run],\n );\n\n const resume = useCallback(async (): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await run(() => client.updateGoal(workspaceId, sessionId, { status: \"active\" }));\n if (result) {\n setGoal(result);\n }\n return result;\n }, [client, workspaceId, sessionId, run]);\n\n const clearGoal = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n // deleteGoal resolves void, so distinguish success (a truthy sentinel) from\n // mutation.run's null-on-failure. Only a SUCCESSFUL delete hides the goal:\n // a failed one leaves the pill up so its mutationError renders. And invalidate\n // any in-flight load first so a slower getGoal started before the delete can't\n // commit and repopulate the just-cleared goal.\n const ok = await run(async () => {\n await client.deleteGoal(workspaceId, sessionId);\n return true as const;\n });\n if (ok) {\n retireLoads();\n setGoal(null);\n setError(null);\n }\n }, [client, workspaceId, sessionId, run, retireLoads]);\n\n return {\n goal,\n isActive: goal?.status === \"active\",\n isPaused: goal?.status === \"paused\",\n isCompleted: goal?.status === \"completed\",\n loading,\n error,\n refresh: load,\n pause,\n resume,\n clearGoal,\n deleteGoal: clearGoal,\n updating: mutating,\n mutationError,\n clearMutationError,\n };\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 {\n SessionEvent,\n SessionMcpApprovalPolicy,\n SessionMcpApprovalPolicyTarget,\n UpdateSessionMcpApprovalPolicyResponse,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useEmbeddedSessionMcpApprovalPolicy,\n type EmbeddedSessionMcpApprovalPolicyClientOverride,\n} from \"../session-context\";\nimport {\n useDebouncedCallback,\n useMutationRunner,\n usePolledValue,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\nexport function isSessionMcpApprovalPolicyEvent(\n event: Pick<SessionEvent, \"type\" | \"payload\">,\n serverId?: string,\n): boolean {\n if (event.type !== \"session.mcp.approval_policy.updated\") {\n return false;\n }\n if (serverId === undefined) {\n return true;\n }\n const payload = event.payload as { serverId?: unknown } | null;\n return payload?.serverId === serverId;\n}\n\nexport type UseSessionMcpApprovalPolicyOptions = EmbeddedSessionMcpApprovalPolicyClientOverride &\n SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default; policy events drive refreshes. */\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseSessionMcpApprovalPolicyResult = {\n server: SessionMcpApprovalPolicyTarget | null;\n policy: SessionMcpApprovalPolicy | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n update: (\n policy: SessionMcpApprovalPolicy,\n ) => Promise<UpdateSessionMcpApprovalPolicyResponse | null>;\n updating: boolean;\n clearError: () => void;\n};\n\n/**\n * Read and update one existing session MCP server's approval policy. Updates\n * become effective for the next claimed attempt; current work is unchanged.\n */\nexport function useSessionMcpApprovalPolicy(\n sessionId: string | null | undefined,\n serverId: string | null | undefined,\n options: UseSessionMcpApprovalPolicyOptions = {},\n): UseSessionMcpApprovalPolicyResult {\n const { client, workspaceId } = useEmbeddedSessionMcpApprovalPolicy(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId && serverId);\n const [override, setOverride] = useState<SessionMcpApprovalPolicyTarget | null>(null);\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${serverId ?? \"\"}`;\n const authoritativeGeneration = useRef(0);\n const mutationIdentity = useMemo(() => ({ client, targetKey }), [client, targetKey]);\n const { run, mutating, mutationError, clearMutationError } = useMutationRunner(mutationIdentity);\n\n useLayoutEffect(() => {\n authoritativeGeneration.current += 1;\n setOverride(null);\n }, [client, targetKey]);\n\n type PolicyRead = {\n targetKey: string;\n generation: number;\n server: SessionMcpApprovalPolicyTarget | null;\n };\n const load = useCallback(async (): Promise<PolicyRead> => {\n const generation = authoritativeGeneration.current;\n if (!sessionId || !serverId) {\n return { targetKey, generation, server: null };\n }\n const session = await client.getSession(workspaceId, sessionId);\n return {\n targetKey,\n generation,\n server:\n session.mcpServers.find((server) => server.id === serverId) ??\n (session.mcpApprovalPolicies && Object.hasOwn(session.mcpApprovalPolicies, serverId)\n ? {\n id: serverId,\n source: \"workspace\",\n requireApproval: session.mcpApprovalPolicies[serverId]!,\n }\n : null),\n };\n }, [client, serverId, sessionId, targetKey, workspaceId]);\n const {\n data,\n loading,\n error: loadError,\n refresh,\n } = usePolledValue(load, {\n enabled,\n pollIntervalMs: options.pollIntervalMs,\n });\n useEffect(() => {\n if (data?.targetKey === targetKey && data.generation === authoritativeGeneration.current) {\n setOverride(null);\n }\n }, [data, targetKey]);\n\n const scheduleRefresh = useDebouncedCallback(() => void refresh());\n const matchesPolicyEvent = useCallback(\n (event: Pick<SessionEvent, \"type\" | \"payload\">) =>\n isSessionMcpApprovalPolicyEvent(event, serverId ?? undefined),\n [serverId],\n );\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n matchesPolicyEvent,\n scheduleRefresh,\n {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n },\n async () => await refresh(),\n );\n\n const update = useCallback(\n async (\n policy: SessionMcpApprovalPolicy,\n ): Promise<UpdateSessionMcpApprovalPolicyResponse | null> => {\n if (!sessionId || !serverId) {\n return null;\n }\n const response = await run(() =>\n client.updateSessionMcpApprovalPolicy(workspaceId, sessionId, serverId, {\n requireApproval: policy,\n }),\n );\n if (response) {\n authoritativeGeneration.current += 1;\n setOverride(response.server);\n void refresh();\n }\n return response;\n },\n [client, refresh, run, serverId, sessionId, workspaceId],\n );\n\n const server = override ?? data?.server ?? null;\n return {\n server,\n policy: server?.requireApproval ?? null,\n loading,\n error: mutationError ?? loadError,\n refresh: async () => {\n await refresh();\n },\n update,\n updating: mutating,\n clearError: clearMutationError,\n };\n}\n","import type { SessionEvent, SessionLineageResponse } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport {\n useEmbeddedSessionLineage,\n type EmbeddedSessionLineageClientOverride,\n} from \"../session-context\";\nimport { useDebouncedCallback, usePolledValue, useSessionEventTrigger } from \"./internal\";\n\nexport type UseSessionLineageOptions = EmbeddedSessionLineageClientOverride & {\n events?: SessionEvent[] | undefined;\n /** Refresh interval (ms). Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n /** Optional shared causal clock invoked when each network read starts. */\n beginRead?: (() => number) | undefined;\n};\n\nexport type UseSessionLineageResult = {\n lineage: SessionLineageResponse | null;\n loading: boolean;\n error: Error | null;\n /** Causal generation captured when the accepted lineage read started. */\n readGeneration: number;\n refresh: () => Promise<void>;\n};\n\nexport function isLineageRefreshEvent(event: SessionEvent): boolean {\n if (event.type === \"session.status.changed\" || event.type === \"session.created\") {\n return true;\n }\n // A child's creation never appears on the PARENT's stream as session.created —\n // the parent sees its own spawn as an agent.toolCall.* for session_create.\n // Created events are handled separately so they can refresh immediately and\n // once after the child row has had time to commit.\n if (event.type === \"agent.toolCall.output\") {\n const payload = event.payload as { name?: unknown; toolName?: unknown } | null | undefined;\n const name =\n typeof payload?.name === \"string\"\n ? payload.name\n : typeof payload?.toolName === \"string\"\n ? payload.toolName\n : \"\";\n return name === \"session_create\" || name.endsWith(\"__session_create\");\n }\n return false;\n}\n\nfunction isSessionCreateToolCallCreated(event: SessionEvent): boolean {\n if (event.type !== \"agent.toolCall.created\") {\n return false;\n }\n const payload = event.payload as { name?: unknown; toolName?: unknown } | null | undefined;\n const name =\n typeof payload?.name === \"string\"\n ? payload.name\n : typeof payload?.toolName === \"string\"\n ? payload.toolName\n : \"\";\n return name === \"session_create\" || name.endsWith(\"__session_create\");\n}\n\n/** Read the ancestors + descendant tree for one session. Data-only; no UI state. */\nexport function useSessionLineage(\n sessionId: string | null | undefined,\n options: UseSessionLineageOptions = {},\n): UseSessionLineageResult {\n const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } =\n useEmbeddedSessionLineage(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const nextReadGeneration = useRef(0);\n const beginRead = options.beginRead;\n const load = useCallback(\n async (signal?: AbortSignal) => {\n if (!sessionId) {\n return {\n lineage: { ancestors: [], children: [], truncated: false },\n readGeneration: 0,\n };\n }\n let readGeneration = 0;\n const lineage = await client.getSessionLineage(workspaceId, sessionId, {\n signal,\n onRequestStart: (sharedReadGeneration) => {\n readGeneration = sharedReadGeneration ?? beginRead?.() ?? ++nextReadGeneration.current;\n },\n });\n return {\n lineage,\n readGeneration,\n };\n },\n [beginRead, client, workspaceId, sessionId],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });\n const refresh = state.refresh;\n useEffect(() => {\n if (enabled && workspaceControlEvent) void refresh();\n }, [enabled, refresh, workspaceControlEvent]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"lineage\", refresh);\n }, [enabled, refresh, registerSessionReconciler, sessionId]);\n const refreshSoon = useDebouncedCallback(() => void refresh(), 150);\n const delayedChildRefreshRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Clear a pending delayed refresh on session/workspace SWITCH (not just\n // unmount): otherwise a timer scheduled for the previous session can fire\n // ~2.5s later and commit that session's lineage onto the new one.\n useEffect(() => {\n return () => {\n if (delayedChildRefreshRef.current !== null) {\n clearTimeout(delayedChildRefreshRef.current);\n delayedChildRefreshRef.current = null;\n }\n };\n }, [sessionId, workspaceId]);\n const refreshAfterChildCreate = useCallback(() => {\n void refresh();\n if (delayedChildRefreshRef.current !== null) {\n clearTimeout(delayedChildRefreshRef.current);\n }\n delayedChildRefreshRef.current = setTimeout(() => {\n delayedChildRefreshRef.current = null;\n void refresh();\n }, 2500);\n }, [refresh]);\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isLineageRefreshEvent,\n refreshSoon,\n // SHARED-FEED ONLY: without a caller-provided events log the trigger would\n // open its OWN streamEvents tail — a second live SSE connection next to the\n // session route's useSessionEvents. A caller with no feed opts into polling\n // (pollIntervalMs), never a duplicate stream.\n { events: options.events, enabled: enabled && options.events !== undefined },\n );\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isSessionCreateToolCallCreated,\n refreshAfterChildCreate,\n { events: options.events, enabled: enabled && options.events !== undefined },\n );\n return {\n lineage: state.data?.lineage ?? null,\n loading: state.loading,\n error: state.error,\n readGeneration: state.data?.readGeneration ?? 0,\n refresh,\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"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useRef","useRef","useCallback","useCallback","useEffect","useLayoutEffect","useRef","useState","useState","useRef","useLayoutEffect","useCallback","server","useEffect","useCallback","useEffect","useRef","useRef","useCallback","useEffect"]}
1
+ {"version":3,"sources":["../src/embedded-session-client.ts","../src/hooks/use-file-attachments.ts","../src/hooks/use-goal.ts","../src/hooks/use-session-control.ts","../src/hooks/use-session-mcp-approval-policy.ts","../src/hooks/use-session-lineage.ts","../src/approvals.ts"],"sourcesContent":["import type { ComposerDraft } from \"@opengeni/sdk\";\nimport type { EmbeddedSessionClientLike } from \"./client\";\n\nexport type ComposerDraftMapContext = {\n operation: \"read\" | \"save\" | \"submit\";\n workspaceId: string;\n sessionId: string;\n};\n\nexport type CreateEmbeddedSessionClientOptions = {\n /**\n * Explicit host-owned method replacements. Methods inherited from `base`\n * retain `base` as their receiver; overrides retain this object as theirs.\n */\n overrides?: Partial<EmbeddedSessionClientLike> | undefined;\n /** Presentation/policy projection for every draft entering the React layer. */\n mapComposerDraft?:\n | ((draft: ComposerDraft, context: ComposerDraftMapContext) => ComposerDraft)\n | undefined;\n};\n\nconst requiredMethods = [\n \"getSession\",\n \"listEvents\",\n \"streamEvents\",\n \"getComposerDraft\",\n \"saveComposerDraft\",\n \"submitComposerDraft\",\n \"sendMessage\",\n \"steerMessage\",\n \"getQueue\",\n \"moveQueueItem\",\n \"editQueueItem\",\n \"steerQueueItem\",\n \"deleteQueueItem\",\n \"pauseSession\",\n \"resumeSession\",\n \"sendApprovalDecision\",\n] as const satisfies readonly (keyof EmbeddedSessionClientLike)[];\n\n/**\n * Build the exact client required by `@opengeni/react/session` from a full SDK\n * client or host proxy. The constructor binds every delegated method once,\n * supports a host-owned atomic composer-submit override, and fails at creation\n * time instead of waiting for a missing method to be exercised by a hook.\n */\nexport function createEmbeddedSessionClient(\n base: EmbeddedSessionClientLike,\n options: CreateEmbeddedSessionClientOptions = {},\n): EmbeddedSessionClientLike {\n const overrides = options.overrides ?? {};\n const client = {} as EmbeddedSessionClientLike;\n for (const key of requiredMethods) {\n const override = overrides[key];\n const method = override ?? base[key];\n if (typeof method !== \"function\") {\n throw new TypeError(`Embedded session client method is required: ${key}`);\n }\n client[key] = method.bind(override === undefined ? base : overrides) as never;\n }\n\n const inferenceOverride = overrides.setWorkspaceInferenceState;\n const inferenceBase = base.setWorkspaceInferenceState;\n const inferenceMethod = inferenceOverride ?? inferenceBase;\n if (typeof inferenceMethod === \"function\") {\n client.setWorkspaceInferenceState = inferenceMethod.bind(\n inferenceOverride === undefined ? base : overrides,\n );\n }\n\n const mapDraft = options.mapComposerDraft;\n if (!mapDraft) return client;\n\n const getComposerDraft = client.getComposerDraft;\n client.getComposerDraft = async (workspaceId, sessionId) =>\n mapDraft(await getComposerDraft(workspaceId, sessionId), {\n operation: \"read\",\n workspaceId,\n sessionId,\n });\n\n const saveComposerDraft = client.saveComposerDraft;\n client.saveComposerDraft = async (workspaceId, sessionId, request) =>\n mapDraft(await saveComposerDraft(workspaceId, sessionId, request), {\n operation: \"save\",\n workspaceId,\n sessionId,\n });\n\n const submitComposerDraft = client.submitComposerDraft;\n client.submitComposerDraft = async (workspaceId, sessionId, request) => {\n const response = await submitComposerDraft(workspaceId, sessionId, request);\n return {\n ...response,\n draft: mapDraft(response.draft, {\n operation: \"submit\",\n workspaceId,\n sessionId,\n }),\n };\n };\n\n return client;\n}\n","import type { FileAsset, FileResourceRef } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n useEmbeddedFileAttachments,\n type EmbeddedFileAttachmentClientOverride,\n} from \"../session-context\";\n\nexport type UseFileAttachmentsOptions = EmbeddedFileAttachmentClientOverride & {\n /**\n * Only files matching this predicate are accepted by {@link\n * UseFileAttachmentsResult.addFromPaste} (the clipboard path). Defaults to\n * `image/*` — the console's historical paste filter. {@link\n * UseFileAttachmentsResult.addFiles} (the explicit picker / drop path)\n * bypasses it.\n */\n /** Retain original uploads in the chat owner’s personal scope when private. */\n scope?: \"workspace\" | \"personal\";\n pasteFilter?: ((file: File) => boolean) | undefined;\n};\n\nexport type FileAttachment = {\n id: string;\n name: string;\n contentType: string;\n sizeBytes: number;\n status: \"uploading\" | \"ready\" | \"failed\";\n /** The SDK `FileAsset` once the upload finishes. */\n file?: FileAsset | undefined;\n /** Object-URL for an inline preview; minted for `image/*` files only. */\n previewUrl?: string | undefined;\n /** Stable SDK failure code for UI behavior that must not parse error copy. */\n errorCode?: \"secure_context_required\" | undefined;\n error?: string | undefined;\n};\n\nexport type UseFileAttachmentsResult = {\n attachments: FileAttachment[];\n /**\n * `FileResourceRef[]` for every attachment that finished uploading — feed\n * straight into `useComposer`'s `sendExtras.resources`.\n */\n readyResources: FileResourceRef[];\n /** True while any attachment is still uploading (drives progress UI). */\n uploading: boolean;\n /**\n * True while any attachment still needs an explicit outcome: wait for an\n * upload, retry a failure, or remove it. This is the loss-prevention send\n * gate; failed cards must never be silently omitted from a message.\n */\n hasUnresolved: boolean;\n /** Explicit picker / drop path — uploads every file, no filter. */\n addFiles: (files: Iterable<File>) => void;\n /** Clipboard path — applies `pasteFilter` (default `image/*`) then uploads. */\n addFromPaste: (event: { clipboardData: DataTransfer | null }) => void;\n /** Restore already-ready server assets without recreating browser-local bytes. */\n restoreReadyFiles: (files: Iterable<FileAsset>) => void;\n /**\n * Resolve a ready image's short-lived server preview URL on demand. Optional\n * for upload-only embedded clients; local object-URL previews remain usable\n * without it.\n */\n loadPreview?: ((id: string, signal?: AbortSignal) => Promise<string | undefined>) | undefined;\n /**\n * Re-run the upload for a `failed` attachment, in place (same id, same\n * source file). No-op for an id that isn't a known failed upload.\n */\n retry: (id: string) => void;\n /**\n * Keep an attachment's object-URL alive for a consumer that outlives its\n * queue entry (for example, an open route-level lightbox). The returned\n * release is idempotent; pending revocation finishes after the last holder\n * releases. Returns `undefined` when the attachment has no local preview.\n */\n retainPreview: (id: string) => (() => void) | undefined;\n /** Remove one attachment; revokes its object-URL after retained users finish. */\n remove: (id: string) => void;\n /**\n * Remove only finalized files whose durable ids were accepted by a send.\n * Attachments added while that request was in flight remain queued for the\n * next message.\n */\n removeReadyFiles: (fileIds: Iterable<string>) => void;\n /** Remove all attachments and revoke every unretained object-URL. */\n clear: () => void;\n};\n\nconst isImage = (file: File): boolean => file.type.startsWith(\"image/\");\n\nlet fallbackAttachmentId = 0;\n\nfunction createAttachmentId(): string {\n const cryptoSource = globalThis.crypto;\n if (typeof cryptoSource?.randomUUID === \"function\") return cryptoSource.randomUUID();\n fallbackAttachmentId += 1;\n // This id is only a browser-local React key and retry lookup, never durable\n // authority. Keep attachment tracking usable when HTTP withholds randomUUID\n // or Web Crypto is unavailable so the SDK's typed failure reaches the card.\n return `attachment:${Date.now().toString(36)}:${fallbackAttachmentId.toString(36)}`;\n}\n\nfunction secureContextRequiredErrorCode(error: unknown): \"secure_context_required\" | undefined {\n return typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"secure_context_required\"\n ? error.code\n : undefined;\n}\n\n/**\n * Upload-and-track state for files attached to the next message. Owns the\n * full client-side upload layer: a per-file `uploading | ready | failed`\n * status machine driven by the SDK's `client.uploadFile`, object-URL image\n * previews with create/revoke lifecycle, the `image/*` clipboard paste filter,\n * and a `FileResourceRef[]` projection that drops straight into a message's\n * `resources`. Workspace-scoped, so it resolves both client and workspace from\n * the {@link OpenGeniProvider} (or a per-call `{ client, workspaceId }`).\n */\nexport function useFileAttachments(\n options: UseFileAttachmentsOptions = {},\n): UseFileAttachmentsResult {\n const { client, workspaceId } = useEmbeddedFileAttachments(options);\n const pasteFilter = options.pasteFilter ?? isImage;\n const [attachments, setAttachments] = useState<FileAttachment[]>([]);\n const attachmentsRef = useRef(attachments);\n attachmentsRef.current = attachments;\n // Keep the source File per attachment id so a failed upload can be retried\n // in place. Cleared on remove/clear so it never outlives its attachment.\n const sources = useRef<Map<string, File>>(new Map());\n // Object URLs must be owned synchronously: React may discard an attachment\n // state update when its component unmounts in the same batch that minted the\n // preview. The registry remains available to cleanup even before a render.\n const previewUrls = useRef<Map<string, string>>(new Map());\n const previewRetainers = useRef<Map<string, number>>(new Map());\n const pendingPreviewRevocations = useRef<Set<string>>(new Set());\n const revokePreview = useCallback((id: string) => {\n const previewUrl = previewUrls.current.get(id);\n if (!previewUrl) return;\n if ((previewRetainers.current.get(id) ?? 0) > 0) {\n pendingPreviewRevocations.current.add(id);\n return;\n }\n previewUrls.current.delete(id);\n pendingPreviewRevocations.current.delete(id);\n URL.revokeObjectURL(previewUrl);\n }, []);\n const revokeAllPreviews = useCallback(() => {\n for (const id of previewUrls.current.keys()) revokePreview(id);\n }, [revokePreview]);\n const retainPreview = useCallback(\n (id: string): (() => void) | undefined => {\n if (!previewUrls.current.has(id)) return undefined;\n previewRetainers.current.set(id, (previewRetainers.current.get(id) ?? 0) + 1);\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const remaining = (previewRetainers.current.get(id) ?? 1) - 1;\n if (remaining > 0) {\n previewRetainers.current.set(id, remaining);\n return;\n }\n previewRetainers.current.delete(id);\n if (pendingPreviewRevocations.current.has(id)) revokePreview(id);\n };\n },\n [revokePreview],\n );\n // Ready-file reconciliation uses functional state updaters, which React may\n // evaluate during a concurrent render that later suspends or is abandoned.\n // Diff only committed attachment sets here so URL revocation cannot run from\n // render-phase code while the previously committed DOM still uses a preview.\n const committedAttachmentIds = useRef<Set<string>>(new Set());\n useEffect(() => {\n const currentIds = new Set(attachments.map((attachment) => attachment.id));\n for (const id of committedAttachmentIds.current) {\n if (!currentIds.has(id)) revokePreview(id);\n }\n committedAttachmentIds.current = currentIds;\n }, [attachments, revokePreview]);\n // Upload promises are not cancellable at this layer. Fence their settlements\n // when the hook changes client/workspace or unmounts so an old tenant/session\n // cannot mutate the next attachment queue (or an already-unmounted component).\n const scopeGeneration = useRef(0);\n const previousScope = useRef({ client, workspaceId });\n\n useEffect(() => {\n const previous = previousScope.current;\n if (previous.client === client && previous.workspaceId === workspaceId) return;\n previousScope.current = { client, workspaceId };\n scopeGeneration.current += 1;\n sources.current.clear();\n revokeAllPreviews();\n setAttachments([]);\n }, [client, revokeAllPreviews, workspaceId]);\n\n useEffect(\n () => () => {\n scopeGeneration.current += 1;\n sources.current.clear();\n revokeAllPreviews();\n },\n [revokeAllPreviews],\n );\n\n // Run (or re-run) the upload for one already-tracked attachment id. Sets it\n // back to `uploading`, then resolves to `ready` (with the asset) or `failed`\n // (with the error message).\n const startUpload = useCallback(\n (id: string, file: File) => {\n const generation = scopeGeneration.current;\n void client\n .uploadFile(workspaceId, {\n filename: file.name || \"file\",\n contentType: file.type || \"application/octet-stream\",\n data: file,\n ...(options.scope ? { scope: options.scope } : {}),\n })\n .then((asset) => {\n if (scopeGeneration.current !== generation) return;\n // Retry bytes are useful only until durable finalization succeeds.\n // Drop the source File immediately; restored/ready attachments must\n // never retain browser-local byte authority.\n sources.current.delete(id);\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"ready\",\n file: asset,\n name: asset.filename,\n contentType: asset.contentType,\n sizeBytes: asset.sizeBytes,\n errorCode: undefined,\n error: undefined,\n }\n : attachment,\n ),\n );\n })\n .catch((error: unknown) => {\n if (scopeGeneration.current !== generation) return;\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"failed\",\n errorCode: secureContextRequiredErrorCode(error),\n error: error instanceof Error ? error.message : String(error),\n }\n : attachment,\n ),\n );\n });\n },\n [client, workspaceId, options.scope],\n );\n\n const addFiles = useCallback(\n (files: Iterable<File>) => {\n for (const file of files) {\n const id = createAttachmentId();\n sources.current.set(id, file);\n const previewUrl = isImage(file) ? URL.createObjectURL(file) : undefined;\n if (previewUrl) previewUrls.current.set(id, previewUrl);\n setAttachments((current) => [\n ...current,\n {\n id,\n name: file.name || \"image\",\n contentType: file.type || \"application/octet-stream\",\n sizeBytes: file.size,\n status: \"uploading\",\n ...(previewUrl ? { previewUrl } : {}),\n },\n ]);\n startUpload(id, file);\n }\n },\n [startUpload],\n );\n\n const retry = useCallback(\n (id: string) => {\n const file = sources.current.get(id);\n if (!file) {\n return;\n }\n setAttachments((current) =>\n current.map((attachment) =>\n attachment.id === id\n ? { ...attachment, status: \"uploading\", errorCode: undefined, error: undefined }\n : attachment,\n ),\n );\n startUpload(id, file);\n },\n [startUpload],\n );\n\n const addFromPaste = useCallback(\n (event: { clipboardData: DataTransfer | null }) => {\n const clipboardFiles = event.clipboardData?.files;\n if (!clipboardFiles) {\n return;\n }\n const files = [...clipboardFiles].filter(pasteFilter);\n if (files.length > 0) {\n addFiles(files);\n }\n },\n [addFiles, pasteFilter],\n );\n\n const restoreReadyFiles = useCallback(\n (files: Iterable<FileAsset>) => {\n const incoming = new Map<string, FileAsset>();\n for (const file of files) {\n if (file.status === \"ready\" && file.workspaceId === workspaceId) {\n incoming.set(file.id, file);\n }\n }\n setAttachments((current) => {\n const unresolved = current.filter((attachment) => attachment.status !== \"ready\");\n const existingReady = new Map(\n current.flatMap((attachment) =>\n attachment.status === \"ready\" && attachment.file\n ? ([[attachment.file.id, attachment]] as const)\n : [],\n ),\n );\n const restored = [...incoming.values()].map((file): FileAttachment => {\n const existing = existingReady.get(file.id);\n return existing\n ? {\n ...existing,\n name: file.filename,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n status: \"ready\",\n file,\n errorCode: undefined,\n error: undefined,\n }\n : {\n id: `restored:${file.id}`,\n name: file.filename,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n status: \"ready\",\n file,\n // No source File and no object URL: server metadata is the\n // only authority restored across page/device boundaries.\n };\n });\n // A server restoration is authoritative for finalized assets, but an\n // upload that has not finalized still belongs to the local actor. Keep\n // those unresolved entries while replacing the ready set exactly.\n return [...unresolved, ...restored];\n });\n },\n [workspaceId],\n );\n\n const loadPreview = useCallback(\n async (id: string, signal?: AbortSignal): Promise<string | undefined> => {\n const generation = scopeGeneration.current;\n const attachment = attachmentsRef.current.find((candidate) => candidate.id === id);\n const createDownloadUrl = client.createFileDownloadUrl;\n if (\n !attachment ||\n attachment.status !== \"ready\" ||\n !attachment.file ||\n !attachment.contentType.startsWith(\"image/\") ||\n typeof createDownloadUrl !== \"function\" ||\n signal?.aborted\n ) {\n return undefined;\n }\n const fileId = attachment.file.id;\n const signed = await createDownloadUrl.call(client, workspaceId, fileId, { signal });\n if (scopeGeneration.current !== generation || signal?.aborted) return undefined;\n const current = attachmentsRef.current.find((candidate) => candidate.id === id);\n if (current?.status !== \"ready\" || current.file?.id !== fileId) return undefined;\n return signed.url;\n },\n [client, workspaceId],\n );\n\n const remove = useCallback(\n (id: string) => {\n sources.current.delete(id);\n revokePreview(id);\n setAttachments((current) => current.filter((attachment) => attachment.id !== id));\n },\n [revokePreview],\n );\n\n const removeReadyFiles = useCallback((fileIds: Iterable<string>) => {\n const accepted = new Set(fileIds);\n if (accepted.size === 0) return;\n setAttachments((current) =>\n current.filter((attachment) => {\n return !(\n attachment.status === \"ready\" &&\n attachment.file !== undefined &&\n accepted.has(attachment.file.id)\n );\n }),\n );\n }, []);\n\n const clear = useCallback(() => {\n sources.current.clear();\n revokeAllPreviews();\n setAttachments([]);\n }, [revokeAllPreviews]);\n\n return {\n attachments,\n readyResources: attachments.flatMap((attachment): FileResourceRef[] =>\n attachment.status === \"ready\" && attachment.file\n ? [{ kind: \"file\", fileId: attachment.file.id }]\n : [],\n ),\n uploading: attachments.some((attachment) => attachment.status === \"uploading\"),\n hasUnresolved: attachments.some((attachment) => attachment.status !== \"ready\"),\n addFiles,\n addFromPaste,\n restoreReadyFiles,\n ...(typeof client.createFileDownloadUrl === \"function\" ? { loadPreview } : {}),\n retry,\n retainPreview,\n remove,\n removeReadyFiles,\n clear,\n };\n}\n","import { OpenGeniApiError, type SessionEvent, type SessionGoal } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useEmbeddedGoal, type EmbeddedGoalClientOverride } from \"../session-context\";\nimport {\n useDebouncedCallback,\n useMutationRunner,\n usePageLiveActivity,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\n/** Event types that change the session goal (set/updated/completed/paused/...). */\nexport function isGoalEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return event.type.startsWith(\"goal.\");\n}\n\n/**\n * Events that can change the server-authoritative continuation projection.\n * The projection is derived from durable turn, session, control, and system\n * update state, so those events refresh the goal without model polling.\n */\nexport function isGoalRefreshEvent(event: Pick<SessionEvent, \"type\">): boolean {\n const type = event.type;\n return (\n isGoalEvent(event) ||\n type.startsWith(\"turn.\") ||\n type.startsWith(\"session.\") ||\n type.startsWith(\"system.update.\") ||\n type.startsWith(\"workspace.inference.\") ||\n type.startsWith(\"user.\")\n );\n}\n\nexport type UseGoalOptions = EmbeddedGoalClientOverride &\n SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default — event refreshes drive updates. */\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseGoalResult = {\n /** The session goal, or null when the session has none. */\n goal: SessionGoal | null;\n /** Convenience flags over `goal.status`. */\n isActive: boolean;\n isPaused: boolean;\n isCompleted: boolean;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Pause the goal loop (PATCH status=paused). */\n pause: (rationale?: string) => Promise<SessionGoal | null>;\n /** Resume a paused goal: resets counters and re-arms continuations. */\n resume: () => Promise<SessionGoal | null>;\n /** Clear the session goal; goal-less sessions remain a successful no-op. */\n clearGoal: () => Promise<void>;\n /** Alias for `clearGoal`. */\n deleteGoal: () => Promise<void>;\n /** True while a pause/resume/clear is in flight. */\n updating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The session's goal: state, the autonomy counters (`autoContinuations`,\n * `noProgressStreak`), and pause/resume control. A goal-less session yields\n * `goal: null` (the 404 is absorbed). Live-updates on goal, turn, session,\n * control, and system-update events — pass `options.events` from\n * `useSessionEvents` to reuse its stream.\n */\nexport function useGoal(\n sessionId: string | null | undefined,\n options: UseGoalOptions = {},\n): UseGoalResult {\n const { client, workspaceId } = useEmbeddedGoal(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const sharedEvents = options.events;\n const sharedFeed = sharedEvents !== undefined;\n const pageLive = usePageLiveActivity();\n const [goal, setGoal] = useState<SessionGoal | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const { run, mutating, mutationError, clearMutationError } = useMutationRunner();\n const generation = useRef(0);\n const targetKeyRef = useRef<string | null>(null);\n const loadAbort = useRef<AbortController | null>(null);\n\n const retireLoads = useCallback(() => {\n generation.current += 1;\n loadAbort.current?.abort();\n loadAbort.current = null;\n }, []);\n\n const load = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n const ticket = ++generation.current;\n loadAbort.current?.abort();\n const controller = new AbortController();\n loadAbort.current = controller;\n try {\n const fetched = await client.getGoal(workspaceId, sessionId, {\n signal: controller.signal,\n });\n if (ticket === generation.current) {\n setGoal(fetched);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (ticket !== generation.current) {\n return;\n }\n if (cause instanceof OpenGeniApiError && cause.status === 404) {\n // No goal is a normal state, not an error.\n setGoal(null);\n setError(null);\n } else {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n setLoading(false);\n } finally {\n if (loadAbort.current === controller) loadAbort.current = null;\n }\n }, [client, workspaceId, sessionId]);\n\n useEffect(() => {\n const targetKey = `${workspaceId} ${sessionId ?? \"\"}`;\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n setGoal(null);\n setError(null);\n }\n if (!enabled || !pageLive) {\n retireLoads();\n setLoading(false);\n return;\n }\n if (sharedFeed) {\n // A shared log supplies invalidations, not the authoritative goal snapshot.\n setLoading(true);\n void load();\n return () => {\n retireLoads();\n };\n }\n setLoading(true);\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n void load();\n return () => {\n retireLoads();\n };\n }\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const schedule = () => {\n if (cancelled) return;\n timer = setTimeout(() => {\n timer = null;\n void load().finally(schedule);\n }, pollIntervalMs);\n };\n void load().finally(schedule);\n return () => {\n cancelled = true;\n if (timer !== null) clearTimeout(timer);\n retireLoads();\n };\n }, [\n load,\n enabled,\n pageLive,\n workspaceId,\n sessionId,\n options.pollIntervalMs,\n retireLoads,\n sharedFeed,\n ]);\n\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(client, workspaceId, sessionId, isGoalRefreshEvent, scheduleRefresh, {\n enabled,\n ...(sharedEvents !== undefined ? { events: sharedEvents } : {}),\n });\n\n const pause = useCallback(\n async (rationale?: string): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await run(() =>\n client.updateGoal(workspaceId, sessionId, {\n status: \"paused\",\n ...(rationale !== undefined ? { rationale } : {}),\n }),\n );\n if (result) {\n setGoal(result);\n }\n return result;\n },\n [client, workspaceId, sessionId, run],\n );\n\n const resume = useCallback(async (): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await run(() => client.updateGoal(workspaceId, sessionId, { status: \"active\" }));\n if (result) {\n setGoal(result);\n }\n return result;\n }, [client, workspaceId, sessionId, run]);\n\n const clearGoal = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n // deleteGoal resolves void, so distinguish success (a truthy sentinel) from\n // mutation.run's null-on-failure. Only a SUCCESSFUL delete hides the goal:\n // a failed one leaves the pill up so its mutationError renders. And invalidate\n // any in-flight load first so a slower getGoal started before the delete can't\n // commit and repopulate the just-cleared goal.\n const ok = await run(async () => {\n await client.deleteGoal(workspaceId, sessionId);\n return true as const;\n });\n if (ok) {\n retireLoads();\n setGoal(null);\n setError(null);\n }\n }, [client, workspaceId, sessionId, run, retireLoads]);\n\n return {\n goal,\n isActive: goal?.status === \"active\",\n isPaused: goal?.status === \"paused\",\n isCompleted: goal?.status === \"completed\",\n loading,\n error,\n refresh: load,\n pause,\n resume,\n clearGoal,\n deleteGoal: clearGoal,\n updating: mutating,\n mutationError,\n clearMutationError,\n };\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 {\n SessionEvent,\n SessionMcpApprovalPolicy,\n SessionMcpApprovalPolicyTarget,\n UpdateSessionMcpApprovalPolicyResponse,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useEmbeddedSessionMcpApprovalPolicy,\n type EmbeddedSessionMcpApprovalPolicyClientOverride,\n} from \"../session-context\";\nimport {\n useDebouncedCallback,\n useMutationRunner,\n usePolledValue,\n useSessionEventTrigger,\n type SessionEventFeedOptions,\n} from \"./internal\";\n\nexport function isSessionMcpApprovalPolicyEvent(\n event: Pick<SessionEvent, \"type\" | \"payload\">,\n serverId?: string,\n): boolean {\n if (event.type !== \"session.mcp.approval_policy.updated\") {\n return false;\n }\n if (serverId === undefined) {\n return true;\n }\n const payload = event.payload as { serverId?: unknown } | null;\n return payload?.serverId === serverId;\n}\n\nexport type UseSessionMcpApprovalPolicyOptions = EmbeddedSessionMcpApprovalPolicyClientOverride &\n SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default; policy events drive refreshes. */\n pollIntervalMs?: number | undefined;\n };\n\nexport type UseSessionMcpApprovalPolicyResult = {\n server: SessionMcpApprovalPolicyTarget | null;\n policy: SessionMcpApprovalPolicy | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n update: (\n policy: SessionMcpApprovalPolicy,\n ) => Promise<UpdateSessionMcpApprovalPolicyResponse | null>;\n updating: boolean;\n clearError: () => void;\n};\n\n/**\n * Read and update one existing session MCP server's approval policy. Updates\n * become effective for the next claimed attempt; current work is unchanged.\n */\nexport function useSessionMcpApprovalPolicy(\n sessionId: string | null | undefined,\n serverId: string | null | undefined,\n options: UseSessionMcpApprovalPolicyOptions = {},\n): UseSessionMcpApprovalPolicyResult {\n const { client, workspaceId } = useEmbeddedSessionMcpApprovalPolicy(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId && serverId);\n const [override, setOverride] = useState<SessionMcpApprovalPolicyTarget | null>(null);\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${serverId ?? \"\"}`;\n const authoritativeGeneration = useRef(0);\n const mutationIdentity = useMemo(() => ({ client, targetKey }), [client, targetKey]);\n const { run, mutating, mutationError, clearMutationError } = useMutationRunner(mutationIdentity);\n\n useLayoutEffect(() => {\n authoritativeGeneration.current += 1;\n setOverride(null);\n }, [client, targetKey]);\n\n type PolicyRead = {\n targetKey: string;\n generation: number;\n server: SessionMcpApprovalPolicyTarget | null;\n };\n const load = useCallback(async (): Promise<PolicyRead> => {\n const generation = authoritativeGeneration.current;\n if (!sessionId || !serverId) {\n return { targetKey, generation, server: null };\n }\n const session = await client.getSession(workspaceId, sessionId);\n return {\n targetKey,\n generation,\n server:\n session.mcpServers.find((server) => server.id === serverId) ??\n (session.mcpApprovalPolicies && Object.hasOwn(session.mcpApprovalPolicies, serverId)\n ? {\n id: serverId,\n source: \"workspace\",\n requireApproval: session.mcpApprovalPolicies[serverId]!,\n }\n : null),\n };\n }, [client, serverId, sessionId, targetKey, workspaceId]);\n const {\n data,\n loading,\n error: loadError,\n refresh,\n } = usePolledValue(load, {\n enabled,\n pollIntervalMs: options.pollIntervalMs,\n });\n useEffect(() => {\n if (data?.targetKey === targetKey && data.generation === authoritativeGeneration.current) {\n setOverride(null);\n }\n }, [data, targetKey]);\n\n const scheduleRefresh = useDebouncedCallback(() => void refresh());\n const matchesPolicyEvent = useCallback(\n (event: Pick<SessionEvent, \"type\" | \"payload\">) =>\n isSessionMcpApprovalPolicyEvent(event, serverId ?? undefined),\n [serverId],\n );\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n matchesPolicyEvent,\n scheduleRefresh,\n {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n },\n async () => await refresh(),\n );\n\n const update = useCallback(\n async (\n policy: SessionMcpApprovalPolicy,\n ): Promise<UpdateSessionMcpApprovalPolicyResponse | null> => {\n if (!sessionId || !serverId) {\n return null;\n }\n const response = await run(() =>\n client.updateSessionMcpApprovalPolicy(workspaceId, sessionId, serverId, {\n requireApproval: policy,\n }),\n );\n if (response) {\n authoritativeGeneration.current += 1;\n setOverride(response.server);\n void refresh();\n }\n return response;\n },\n [client, refresh, run, serverId, sessionId, workspaceId],\n );\n\n const server = override ?? data?.server ?? null;\n return {\n server,\n policy: server?.requireApproval ?? null,\n loading,\n error: mutationError ?? loadError,\n refresh: async () => {\n await refresh();\n },\n update,\n updating: mutating,\n clearError: clearMutationError,\n };\n}\n","import type { SessionEvent, SessionLineageResponse } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport {\n useEmbeddedSessionLineage,\n type EmbeddedSessionLineageClientOverride,\n} from \"../session-context\";\nimport { useDebouncedCallback, usePolledValue, useSessionEventTrigger } from \"./internal\";\n\nexport type UseSessionLineageOptions = EmbeddedSessionLineageClientOverride & {\n events?: SessionEvent[] | undefined;\n /** Refresh interval (ms). Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n /** Optional shared causal clock invoked when each network read starts. */\n beginRead?: (() => number) | undefined;\n};\n\nexport type UseSessionLineageResult = {\n lineage: SessionLineageResponse | null;\n loading: boolean;\n error: Error | null;\n /** Causal generation captured when the accepted lineage read started. */\n readGeneration: number;\n refresh: () => Promise<void>;\n};\n\nexport function isLineageRefreshEvent(event: SessionEvent): boolean {\n if (event.type === \"session.status.changed\" || event.type === \"session.created\") {\n return true;\n }\n // A child's creation never appears on the PARENT's stream as session.created —\n // the parent sees its own spawn as an agent.toolCall.* for session_create.\n // Created events are handled separately so they can refresh immediately and\n // once after the child row has had time to commit.\n if (event.type === \"agent.toolCall.output\") {\n const payload = event.payload as { name?: unknown; toolName?: unknown } | null | undefined;\n const name =\n typeof payload?.name === \"string\"\n ? payload.name\n : typeof payload?.toolName === \"string\"\n ? payload.toolName\n : \"\";\n return name === \"session_create\" || name.endsWith(\"__session_create\");\n }\n return false;\n}\n\nfunction isSessionCreateToolCallCreated(event: SessionEvent): boolean {\n if (event.type !== \"agent.toolCall.created\") {\n return false;\n }\n const payload = event.payload as { name?: unknown; toolName?: unknown } | null | undefined;\n const name =\n typeof payload?.name === \"string\"\n ? payload.name\n : typeof payload?.toolName === \"string\"\n ? payload.toolName\n : \"\";\n return name === \"session_create\" || name.endsWith(\"__session_create\");\n}\n\n/** Read the ancestors + descendant tree for one session. Data-only; no UI state. */\nexport function useSessionLineage(\n sessionId: string | null | undefined,\n options: UseSessionLineageOptions = {},\n): UseSessionLineageResult {\n const { client, workspaceId, workspaceControlEvent, registerSessionReconciler } =\n useEmbeddedSessionLineage(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const nextReadGeneration = useRef(0);\n const beginRead = options.beginRead;\n const load = useCallback(\n async (signal?: AbortSignal) => {\n if (!sessionId) {\n return {\n lineage: { ancestors: [], children: [], truncated: false },\n readGeneration: 0,\n };\n }\n let readGeneration = 0;\n const lineage = await client.getSessionLineage(workspaceId, sessionId, {\n signal,\n onRequestStart: (sharedReadGeneration) => {\n readGeneration = sharedReadGeneration ?? beginRead?.() ?? ++nextReadGeneration.current;\n },\n });\n return {\n lineage,\n readGeneration,\n };\n },\n [beginRead, client, workspaceId, sessionId],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled });\n const refresh = state.refresh;\n useEffect(() => {\n if (enabled && workspaceControlEvent) void refresh();\n }, [enabled, refresh, workspaceControlEvent]);\n useEffect(() => {\n if (!sessionId || !enabled) return;\n return registerSessionReconciler(sessionId, \"lineage\", refresh);\n }, [enabled, refresh, registerSessionReconciler, sessionId]);\n const refreshSoon = useDebouncedCallback(() => void refresh(), 150);\n const delayedChildRefreshRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // Clear a pending delayed refresh on session/workspace SWITCH (not just\n // unmount): otherwise a timer scheduled for the previous session can fire\n // ~2.5s later and commit that session's lineage onto the new one.\n useEffect(() => {\n return () => {\n if (delayedChildRefreshRef.current !== null) {\n clearTimeout(delayedChildRefreshRef.current);\n delayedChildRefreshRef.current = null;\n }\n };\n }, [sessionId, workspaceId]);\n const refreshAfterChildCreate = useCallback(() => {\n void refresh();\n if (delayedChildRefreshRef.current !== null) {\n clearTimeout(delayedChildRefreshRef.current);\n }\n delayedChildRefreshRef.current = setTimeout(() => {\n delayedChildRefreshRef.current = null;\n void refresh();\n }, 2500);\n }, [refresh]);\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isLineageRefreshEvent,\n refreshSoon,\n // SHARED-FEED ONLY: without a caller-provided events log the trigger would\n // open its OWN streamEvents tail — a second live SSE connection next to the\n // session route's useSessionEvents. A caller with no feed opts into polling\n // (pollIntervalMs), never a duplicate stream.\n { events: options.events, enabled: enabled && options.events !== undefined },\n );\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isSessionCreateToolCallCreated,\n refreshAfterChildCreate,\n { events: options.events, enabled: enabled && options.events !== undefined },\n );\n return {\n lineage: state.data?.lineage ?? null,\n loading: state.loading,\n error: state.error,\n readGeneration: state.data?.readGeneration ?? 0,\n refresh,\n };\n}\n","import {\n parseToolDisplayMetadata,\n type ToolDisplayMetadata,\n type SessionEvent,\n} 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 display?: ToolDisplayMetadata;\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 const display = parseToolDisplayMetadata(raw.display);\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 ...(display ? { display } : {}),\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"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useRef","useRef","useCallback","useCallback","useEffect","useLayoutEffect","useRef","useState","useState","useRef","useLayoutEffect","useCallback","server","useEffect","useCallback","useEffect","useRef","useRef","useCallback","useEffect"]}
@@ -72,12 +72,11 @@ function mcpToolLeaf(name) {
72
72
  function toolMatchesLeaf(wireName, leaf) {
73
73
  return wireName === leaf || wireName.endsWith(`__${leaf}`);
74
74
  }
75
- function toolDisplayName(name) {
76
- const phrase = mcpToolLeaf(name).replace(/[_-]+/g, " ").trim();
77
- if (!phrase) {
78
- return name;
79
- }
80
- return phrase.charAt(0).toUpperCase() + phrase.slice(1);
75
+ function toolDisplayName(name, display) {
76
+ if (!display && /^[a-f0-9]{64}$/.test(name)) return "Tool call";
77
+ const phrase = (display?.toolName ?? mcpToolLeaf(name)).replace(/[_-]+/g, " ").trim();
78
+ const title = display?.title ?? (phrase ? phrase.charAt(0).toUpperCase() + phrase.slice(1) : name);
79
+ return display?.accountLabel ? `${title} \u2014 ${display.accountLabel}` : title;
81
80
  }
82
81
 
83
82
  // src/older-history.ts
@@ -124,7 +123,8 @@ function createOlderHistoryLoadReceipt(load) {
124
123
 
125
124
  // src/timeline/projection.ts
126
125
  import {
127
- parseMediaGenerationResult
126
+ parseMediaGenerationResult,
127
+ parseToolDisplayMetadata
128
128
  } from "@opengeni/sdk";
129
129
 
130
130
  // src/timeline/fleet-decision-projection.ts
@@ -753,6 +753,7 @@ function buildTimeline(events, options = {}) {
753
753
  }
754
754
  case "agent.toolCall.created": {
755
755
  const name = typeof payload.name === "string" ? payload.name : "tool";
756
+ const display = parseToolDisplayMetadata(payload.display);
756
757
  const callId = typeof payload.id === "string" ? payload.id : null;
757
758
  const args = payload.arguments ?? null;
758
759
  closeStreamingTail();
@@ -782,6 +783,7 @@ function buildTimeline(events, options = {}) {
782
783
  (item) => item.kind === "tool-call" && item.callId === callId
783
784
  );
784
785
  if (existing) {
786
+ if (display) existing.display = display;
785
787
  if (args != null) {
786
788
  existing.arguments = args;
787
789
  }
@@ -798,6 +800,7 @@ function buildTimeline(events, options = {}) {
798
800
  turnId,
799
801
  callId,
800
802
  name,
803
+ ...display ? { display } : {},
801
804
  arguments: args,
802
805
  output: void 0,
803
806
  truncation: null,
@@ -2289,8 +2292,8 @@ var FOREGROUND_COMPACT_CATCHUP_MAX_GROUPS = 16;
2289
2292
  var FOREGROUND_COMPACT_CATCHUP_MAX_BYTES = 512 * 1024;
2290
2293
  var EMPTY_EVENTS = [];
2291
2294
  var encoder = new TextEncoder();
2292
- var SESSION_EVENT_BROWSER_MAX_BYTES = 8 * 1024 * 1024;
2293
- var SESSION_EVENT_BROWSER_MAX_COUNT = 1e4;
2295
+ var SESSION_EVENT_BROWSER_MAX_BYTES = 160 * 1024 * 1024;
2296
+ var SESSION_EVENT_BROWSER_MAX_COUNT = 2e5;
2294
2297
  var SESSION_EVENT_BROWSER_PENDING_MAX_BYTES = 1024 * 1024;
2295
2298
  var SESSION_EVENT_BROWSER_PENDING_MAX_COUNT = 256;
2296
2299
  var EMPTY_EVENT_WINDOW = {
@@ -2449,7 +2452,7 @@ function useSessionEvents(sessionId, options = {}) {
2449
2452
  setSessionStatusProjection(status);
2450
2453
  }
2451
2454
  const current = eventWindowRef.current;
2452
- const next = boundBrowserSessionEventWindow([...current.events, ...batch]);
2455
+ const next = appendBrowserSessionEventWindow(current, batch);
2453
2456
  const retained = {
2454
2457
  ...next,
2455
2458
  truncated: current.truncated || next.truncated
@@ -2486,7 +2489,7 @@ function useSessionEvents(sessionId, options = {}) {
2486
2489
  const current = eventWindowRef.current;
2487
2490
  assertAppendOrder(current.events, plan.events);
2488
2491
  const status = observeSessionStatus(plan.events, sessionStatusRef);
2489
- const next = boundBrowserSessionEventWindow([...current.events, ...plan.events]);
2492
+ const next = appendBrowserSessionEventWindow(current, plan.events);
2490
2493
  const retained = {
2491
2494
  ...next,
2492
2495
  truncated: current.truncated || next.truncated
@@ -2825,9 +2828,7 @@ function useSessionEvents(sessionId, options = {}) {
2825
2828
  assertAppendOrder(current.events, window.events);
2826
2829
  const status = observeSessionStatus(window.events, sessionStatusRef);
2827
2830
  const previousOldest = current.events[0]?.sequence ?? null;
2828
- const next = boundBrowserSessionEventWindow([...current.events, ...window.events], {
2829
- direction: "newest"
2830
- });
2831
+ const next = appendBrowserSessionEventWindow(current, window.events);
2831
2832
  const retained = {
2832
2833
  ...next,
2833
2834
  truncated: current.truncated || next.truncated || window.hasNewer
@@ -3056,6 +3057,25 @@ function boundBrowserSessionEventWindow(events, options = {}) {
3056
3057
  truncated: selected.length < safe.length
3057
3058
  };
3058
3059
  }
3060
+ function appendBrowserSessionEventWindow(current, batch, options = {}) {
3061
+ const maxBytes = Math.max(1024, options.maxBytes ?? SESSION_EVENT_BROWSER_MAX_BYTES);
3062
+ const maxCount = Math.max(1, Math.floor(options.maxCount ?? SESSION_EVENT_BROWSER_MAX_COUNT));
3063
+ const events = [...current.events, ...batch];
3064
+ let bytes = current.bytes;
3065
+ for (let index = 0; index < batch.length; index += 1) {
3066
+ bytes += browserJsonBytes(batch[index]) + (current.events.length + index > 0 ? 1 : 0);
3067
+ }
3068
+ let start = 0;
3069
+ while (events.length - start > 1 && (bytes > maxBytes || events.length - start > maxCount)) {
3070
+ bytes -= browserJsonBytes(events[start]) + 1;
3071
+ start += 1;
3072
+ }
3073
+ return {
3074
+ events: start === 0 ? events : events.slice(start),
3075
+ bytes,
3076
+ truncated: current.truncated || start > 0
3077
+ };
3078
+ }
3059
3079
  function browserJsonBytes(value) {
3060
3080
  return encoder.encode(JSON.stringify(value)).byteLength;
3061
3081
  }
@@ -3949,4 +3969,4 @@ export {
3949
3969
  useHumanInputRequests,
3950
3970
  conversationTimeline
3951
3971
  };
3952
- //# sourceMappingURL=chunk-JKLGJQO5.js.map
3972
+ //# sourceMappingURL=chunk-HJDDS2L6.js.map