@opengeni/react 7.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/approvals.d.ts +2 -1
- package/dist/artifacts.js +17 -17
- package/dist/{browser-viewer-LGH4IP47.js → browser-viewer-MN7MOYQT.js} +5 -5
- package/dist/{chunk-YS24CFDI.js → chunk-2O2HXRGP.js} +7 -7
- package/dist/{chunk-IP4BUBKH.js → chunk-3LL47F4U.js} +28 -17
- package/dist/chunk-3LL47F4U.js.map +1 -0
- package/dist/{chunk-UXE5SSNN.js → chunk-4ACTWOOW.js} +8 -8
- package/dist/{chunk-IYUPN32E.js → chunk-DBPVUGQT.js} +6 -1
- package/dist/{chunk-IYUPN32E.js.map → chunk-DBPVUGQT.js.map} +1 -1
- package/dist/{chunk-5GAL23FF.js → chunk-IOLPHOF4.js} +2 -5
- package/dist/chunk-IOLPHOF4.js.map +1 -0
- package/dist/{chunk-JPHDWKZE.js → chunk-PFDNB3U7.js} +15 -10
- package/dist/chunk-PFDNB3U7.js.map +1 -0
- package/dist/{chunk-D7GAPJ3V.js → chunk-SHRCATV6.js} +67 -34
- package/dist/chunk-SHRCATV6.js.map +1 -0
- package/dist/{chunk-H5YGYNXS.js → chunk-TV5PP2PE.js} +11 -11
- package/dist/chunk-TV5PP2PE.js.map +1 -0
- package/dist/{chunk-PNAVEK2U.js → chunk-UQS7BGNQ.js} +12 -12
- package/dist/{chunk-JKLGJQO5.js → chunk-VI7HELBI.js} +40 -20
- package/dist/chunk-VI7HELBI.js.map +1 -0
- package/dist/{chunk-HJ5VJ4JB.js → chunk-WKFFRFJF.js} +73 -15
- package/dist/chunk-WKFFRFJF.js.map +1 -0
- package/dist/{chunk-D5NOQPLR.js → chunk-ZC2DK5SC.js} +75 -65
- package/dist/chunk-ZC2DK5SC.js.map +1 -0
- package/dist/components/markdown.d.ts +2 -0
- package/dist/components/model-policy-picker.d.ts +17 -1
- package/dist/components/session-conversation.d.ts +3 -0
- package/dist/composer.d.ts +1 -1
- package/dist/composer.js +7 -7
- package/dist/{computer-viewer-CTFCJVS7.js → computer-viewer-FX4WOZMX.js} +4 -4
- package/dist/connect.js +5 -5
- package/dist/hooks/use-session-events.d.ts +6 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +112 -115
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +5 -5
- package/dist/machines.js +2 -2
- package/dist/{model-policy-picker-menu-RVOQ4ZZG.js → model-policy-picker-menu-AGXXJZ2B.js} +4 -4
- package/dist/model-policy.js +1 -1
- package/dist/realtime.js +5 -5
- package/dist/session-ui.js +12 -12
- package/dist/session.js +3 -3
- package/dist/timeline/tool-display-name.d.ts +2 -1
- package/dist/timeline/types.d.ts +2 -1
- package/package.json +2 -2
- package/src/approvals.ts +8 -1
- package/src/components/approval-surface.tsx +12 -2
- package/src/components/machine-card.tsx +5 -5
- package/src/components/machine-dock-bar.tsx +1 -1
- package/src/components/machines/machine-detail.tsx +5 -2
- package/src/components/markdown.tsx +101 -55
- package/src/components/model-policy-picker-menu.tsx +131 -33
- package/src/components/model-policy-picker.tsx +61 -12
- package/src/components/session-commands-panel.tsx +8 -3
- package/src/components/session-conversation.tsx +5 -1
- package/src/composer.ts +1 -0
- package/src/hooks/use-last-started-turn-policy.ts +3 -7
- package/src/hooks/use-session-events.ts +32 -7
- package/src/index.ts +1 -0
- package/src/model-policy.ts +1 -4
- package/src/timeline/projection.ts +4 -0
- package/src/timeline/rolling-activity.tsx +4 -2
- package/src/timeline/tool-display-name.ts +8 -6
- package/src/timeline/tool-renderers.tsx +5 -3
- package/src/timeline/types.ts +2 -0
- package/styles/compiled.css +15 -0
- package/dist/chunk-5GAL23FF.js.map +0 -1
- package/dist/chunk-D5NOQPLR.js.map +0 -1
- package/dist/chunk-D7GAPJ3V.js.map +0 -1
- package/dist/chunk-H5YGYNXS.js.map +0 -1
- package/dist/chunk-HJ5VJ4JB.js.map +0 -1
- package/dist/chunk-IP4BUBKH.js.map +0 -1
- package/dist/chunk-JKLGJQO5.js.map +0 -1
- package/dist/chunk-JPHDWKZE.js.map +0 -1
- /package/dist/{browser-viewer-LGH4IP47.js.map → browser-viewer-MN7MOYQT.js.map} +0 -0
- /package/dist/{chunk-YS24CFDI.js.map → chunk-2O2HXRGP.js.map} +0 -0
- /package/dist/{chunk-UXE5SSNN.js.map → chunk-4ACTWOOW.js.map} +0 -0
- /package/dist/{chunk-PNAVEK2U.js.map → chunk-UQS7BGNQ.js.map} +0 -0
- /package/dist/{computer-viewer-CTFCJVS7.js.map → computer-viewer-FX4WOZMX.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-RVOQ4ZZG.js.map → model-policy-picker-menu-AGXXJZ2B.js.map} +0 -0
|
@@ -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"]}
|
|
@@ -159,10 +159,7 @@ function organizationProviderPayerSummary(model) {
|
|
|
159
159
|
return "Billed to the organization provider account";
|
|
160
160
|
}
|
|
161
161
|
function projectPickerRows(models) {
|
|
162
|
-
return models.filter((catalog) => {
|
|
163
|
-
const billingClass = billingClassForModel(catalog);
|
|
164
|
-
return billingClass === "opengeni_credits" || catalog.credentialReadiness.status === "ready";
|
|
165
|
-
}).map((catalog) => {
|
|
162
|
+
return models.filter((catalog) => catalog.credentialReadiness.status === "ready").map((catalog) => {
|
|
166
163
|
const billingClass = billingClassForModel(catalog);
|
|
167
164
|
return {
|
|
168
165
|
id: catalog.id,
|
|
@@ -246,4 +243,4 @@ export {
|
|
|
246
243
|
findPickerRow,
|
|
247
244
|
groupPickerRowsByBillingClass
|
|
248
245
|
};
|
|
249
|
-
//# sourceMappingURL=chunk-
|
|
246
|
+
//# sourceMappingURL=chunk-IOLPHOF4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/model-policy.ts"],"sourcesContent":["import {\n compareModelPickerOrder,\n modelPickerBillingClassFor,\n type ModelPickerBillingClass,\n} from \"@opengeni/sdk/model-picker-order\";\nimport type { ClientModel, ReasoningEffort, WorkspaceModelCatalogModel } from \"@opengeni/sdk\";\n\nexport type PickerBillingClass = ModelPickerBillingClass;\n\nexport type PickerModelRow<TCatalog extends ClientModel = WorkspaceModelCatalogModel> = {\n id: string;\n label: string;\n /** Catalog-curated compact label for dense UI; fall back to `label` when absent. */\n shortLabel?: string | undefined;\n billingClass: PickerBillingClass;\n billingClassLabel: string;\n selectable: boolean;\n unavailableReason: string | null;\n provider: string;\n providerLabel: string;\n catalog: TCatalog;\n};\n\nexport type LatencyModeId = \"standard\" | \"priority\" | \"fast\";\n\nconst BILLING_CLASS_LABELS: Record<PickerBillingClass, string> = {\n opengeni_credits: \"OpenGeni\",\n external: \"External\",\n codex_subscription: \"Codex\",\n supergrok_subscription: \"SuperGrok\",\n byok: \"Workspace providers\",\n organization_byok: \"Organization providers\",\n};\n\nconst AVAILABILITY_REASON_LABELS: Record<string, string> = {\n missing_credential: \"Credentials required\",\n needs_reauth: \"Reconnect required\",\n credential_not_ready: \"Credential not ready\",\n not_entitled: \"Not entitled\",\n provider_unhealthy: \"Provider unavailable\",\n policy_blocked: \"Blocked by workspace policy\",\n unsupported: \"Unsupported\",\n};\n\nexport function billingClassForModel(model: ClientModel): PickerBillingClass {\n if (model.provider === \"organization-gateway\" || model.provider === \"organization-openrouter\") {\n return \"organization_byok\";\n }\n if (model.provider === \"workspace-gateway\" || model.provider === \"workspace-openrouter\") {\n return \"byok\";\n }\n return modelPickerBillingClassFor(model);\n}\n\nexport function billingClassLabel(billingClass: PickerBillingClass): string {\n return BILLING_CLASS_LABELS[billingClass];\n}\n\nexport function availabilityReasonLabel(\n reason: WorkspaceModelCatalogModel[\"availability\"][\"reason\"],\n): string | null {\n if (!reason) {\n return null;\n }\n return AVAILABILITY_REASON_LABELS[reason] ?? \"Unavailable\";\n}\n\nexport function effortOptionsForModel(model: ClientModel): ReasoningEffort[] {\n const efforts = model.capabilities?.reasoning.efforts;\n if (!efforts || efforts.length === 0) {\n return [\"low\"];\n }\n const order: ReasoningEffort[] = [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n return order.filter((effort) => efforts.includes(effort));\n}\n\nexport function defaultEffortForModel(model: ClientModel): ReasoningEffort {\n const options = effortOptionsForModel(model);\n const configured = model.capabilities?.reasoning.defaultEffort;\n if (configured && options.includes(configured)) {\n return configured;\n }\n return options[0] ?? \"low\";\n}\n\nexport function coerceReasoningEffortForModel(\n model: ClientModel,\n effort: ReasoningEffort,\n): ReasoningEffort {\n const options = effortOptionsForModel(model);\n if (options.includes(effort)) {\n return effort;\n }\n return defaultEffortForModel(model);\n}\n\nexport function runnableLatencyModesForModel(model: ClientModel): LatencyModeId[] {\n const modes = model.capabilities?.latencyModes ?? [];\n return modes.filter((mode) => mode.runnable).map((mode) => mode.id);\n}\n\nexport function labelLatencyMode(mode: LatencyModeId): string {\n if (mode === \"fast\") {\n return \"Fast\";\n }\n if (mode === \"priority\") {\n return \"Priority\";\n }\n return \"Standard\";\n}\n\nexport function labelReasoningEffort(effort: ReasoningEffort): string {\n if (effort === \"xhigh\") {\n return \"Extra high\";\n }\n return effort.slice(0, 1).toUpperCase() + effort.slice(1);\n}\n\n/** Payment prompts must use cost policy, never the presentation group. */\nexport function modelUsesCredits(model: ClientModel | undefined): boolean {\n if (model?.cost !== undefined) return model.cost === \"credits\";\n return model?.billing?.metering === \"opengeni_credits\";\n}\n\nexport function payerSummaryForModel(model: ClientModel): string {\n if (model.cost === \"free\") {\n return \"Free in this deployment\";\n }\n if (model.cost === \"credits\") {\n return \"OpenGeni credits\";\n }\n if (model.cost === \"subscription\") {\n return model.source === \"supergrok\"\n ? \"SuperGrok subscription · external billing\"\n : \"Codex subscription · external billing\";\n }\n if (model.cost === \"workspace\") {\n return workspaceProviderPayerSummary(model);\n }\n if (model.cost === \"organization\") {\n return organizationProviderPayerSummary(model);\n }\n\n // Older client-config payloads do not carry `cost`; preserve their existing\n // settlement-derived label until every deployment has rolled forward.\n const billing = model.billing;\n if (!billing) {\n return \"Route unknown\";\n }\n if (billing.metering === \"opengeni_credits\") {\n return \"OpenGeni credits · automatic managed route\";\n }\n if (billing.upstreamPayer === \"connected_subscription\") {\n return model.source === \"supergrok\"\n ? \"SuperGrok subscription · external billing\"\n : \"Codex subscription · external billing\";\n }\n if (billing.upstreamPayer === \"workspace\") {\n return workspaceProviderPayerSummary(model);\n }\n if (billing.upstreamPayer === \"organization\") {\n return organizationProviderPayerSummary(model);\n }\n return billing.upstreamPayer === \"deployment\"\n ? \"OpenGeni · no model credits\"\n : \"External provider · no OpenGeni credits\";\n}\n\nexport function advancedSourceSummary(model: ClientModel): string | null {\n const source = model.credentialSource;\n if (!source) {\n return model.billing?.metering === \"external\" && model.billing.upstreamPayer === \"deployment\"\n ? \"Deployment-provided connection\"\n : null;\n }\n if (source.kind === \"connected_subscription\") {\n return source.provider === \"xai\"\n ? \"Connected SuperGrok subscription\"\n : \"Connected Codex subscription\";\n }\n if (source.kind === \"workspace_connection\") {\n if (model.provider === \"workspace-openrouter\") {\n return \"Workspace OpenRouter connection\";\n }\n if (model.provider === \"workspace-gateway\" || model.source === \"workspace_gateway\") {\n return \"Workspace Vercel AI Gateway\";\n }\n return \"Workspace provider connection\";\n }\n if (source.kind === \"deployment\") {\n return source.mechanism === \"azure_ad_bearer\"\n ? \"Deployment Azure identity\"\n : \"Deployment API key\";\n }\n return null;\n}\n\nfunction workspaceProviderPayerSummary(model: ClientModel): string {\n if (model.provider === \"workspace-openrouter\") {\n return \"Billed to the workspace OpenRouter account\";\n }\n if (model.provider === \"workspace-gateway\" || model.source === \"workspace_gateway\") {\n return \"Billed to the workspace Vercel account\";\n }\n return \"Billed to the workspace provider account\";\n}\n\nfunction organizationProviderPayerSummary(model: ClientModel): string {\n if (model.provider === \"organization-openrouter\") {\n return \"Billed to the organization OpenRouter account\";\n }\n if (model.provider === \"organization-gateway\") {\n return \"Billed to the organization Vercel account\";\n }\n return \"Billed to the organization provider account\";\n}\n\nexport function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerModelRow[] {\n return models\n .filter((catalog) => catalog.credentialReadiness.status === \"ready\")\n .map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: catalog.availability.selectable,\n unavailableReason: catalog.availability.selectable\n ? null\n : availabilityReasonLabel(catalog.availability.reason),\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\n/** Project the lightweight client-config model list into the same picker contract. */\nexport function projectClientModelRows(models: ClientModel[]): PickerModelRow<ClientModel>[] {\n return models.map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: true,\n unavailableReason: null,\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\nexport function sortPickerRows<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): PickerModelRow<TCatalog>[] {\n return [...rows].sort(compareModelPickerOrder);\n}\n\nexport function findPickerRow<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n modelId: string,\n): PickerModelRow<TCatalog> | null {\n return rows.find((row) => row.id === modelId) ?? null;\n}\n\nexport function groupPickerRowsByBillingClass(\n rows: PickerModelRow[],\n options?: { codexOnly?: boolean },\n): Array<{ billingClass: PickerBillingClass; label: string; rows: PickerModelRow[] }>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n options?: { codexOnly?: boolean },\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n options?: { codexOnly?: boolean },\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}> {\n const sorted = sortPickerRows(rows);\n const groups: Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n }> = [];\n for (const row of sorted) {\n const existing = groups.find((group) => group.billingClass === row.billingClass);\n if (existing) {\n existing.rows.push(row);\n continue;\n }\n groups.push({\n billingClass: row.billingClass,\n label: row.billingClassLabel,\n rows: [row],\n });\n }\n const codexIndex = groups.findIndex((group) => group.billingClass === \"codex_subscription\");\n const codex = groups[codexIndex];\n const selectableOpenGeni = groups\n .find((group) => group.billingClass === \"opengeni_credits\")\n ?.rows.filter((row) => row.selectable);\n // Presentation only: never change the catalog/default model ordering or selection.\n const onlyFreeOpenGeni =\n selectableOpenGeni !== undefined &&\n selectableOpenGeni.length > 0 &&\n selectableOpenGeni.every((row) => row.catalog.cost === \"free\");\n if (\n codex &&\n codex.rows.some((row) => row.selectable) &&\n (options?.codexOnly || onlyFreeOpenGeni)\n ) {\n groups.splice(codexIndex, 1);\n groups.unshift(codex);\n }\n return groups;\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAqBP,IAAM,uBAA2D;AAAA,EAC/D,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,wBAAwB;AAAA,EACxB,MAAM;AAAA,EACN,mBAAmB;AACrB;AAEA,IAAM,6BAAqD;AAAA,EACzD,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,aAAa;AACf;AAEO,SAAS,qBAAqB,OAAwC;AAC3E,MAAI,MAAM,aAAa,0BAA0B,MAAM,aAAa,2BAA2B;AAC7F,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa,uBAAuB,MAAM,aAAa,wBAAwB;AACvF,WAAO;AAAA,EACT;AACA,SAAO,2BAA2B,KAAK;AACzC;AAEO,SAAS,kBAAkB,cAA0C;AAC1E,SAAO,qBAAqB,YAAY;AAC1C;AAEO,SAAS,wBACd,QACe;AACf,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,SAAO,2BAA2B,MAAM,KAAK;AAC/C;AAEO,SAAS,sBAAsB,OAAuC;AAC3E,QAAM,UAAU,MAAM,cAAc,UAAU;AAC9C,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,WAAO,CAAC,KAAK;AAAA,EACf;AACA,QAAM,QAA2B,CAAC,QAAQ,WAAW,OAAO,UAAU,QAAQ,SAAS,KAAK;AAC5F,SAAO,MAAM,OAAO,CAAC,WAAW,QAAQ,SAAS,MAAM,CAAC;AAC1D;AAEO,SAAS,sBAAsB,OAAqC;AACzE,QAAM,UAAU,sBAAsB,KAAK;AAC3C,QAAM,aAAa,MAAM,cAAc,UAAU;AACjD,MAAI,cAAc,QAAQ,SAAS,UAAU,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,CAAC,KAAK;AACvB;AAEO,SAAS,8BACd,OACA,QACiB;AACjB,QAAM,UAAU,sBAAsB,KAAK;AAC3C,MAAI,QAAQ,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,sBAAsB,KAAK;AACpC;AAEO,SAAS,6BAA6B,OAAqC;AAChF,QAAM,QAAQ,MAAM,cAAc,gBAAgB,CAAC;AACnD,SAAO,MAAM,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE;AACpE;AAEO,SAAS,iBAAiB,MAA6B;AAC5D,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,EACT;AACA,MAAI,SAAS,YAAY;AACvB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,qBAAqB,QAAiC;AACpE,MAAI,WAAW,SAAS;AACtB,WAAO;AAAA,EACT;AACA,SAAO,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAC1D;AAGO,SAAS,iBAAiB,OAAyC;AACxE,MAAI,OAAO,SAAS,OAAW,QAAO,MAAM,SAAS;AACrD,SAAO,OAAO,SAAS,aAAa;AACtC;AAEO,SAAS,qBAAqB,OAA4B;AAC/D,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,SAAS,WAAW;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,SAAS,gBAAgB;AACjC,WAAO,MAAM,WAAW,cACpB,iDACA;AAAA,EACN;AACA,MAAI,MAAM,SAAS,aAAa;AAC9B,WAAO,8BAA8B,KAAK;AAAA,EAC5C;AACA,MAAI,MAAM,SAAS,gBAAgB;AACjC,WAAO,iCAAiC,KAAK;AAAA,EAC/C;AAIA,QAAM,UAAU,MAAM;AACtB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,aAAa,oBAAoB;AAC3C,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,kBAAkB,0BAA0B;AACtD,WAAO,MAAM,WAAW,cACpB,iDACA;AAAA,EACN;AACA,MAAI,QAAQ,kBAAkB,aAAa;AACzC,WAAO,8BAA8B,KAAK;AAAA,EAC5C;AACA,MAAI,QAAQ,kBAAkB,gBAAgB;AAC5C,WAAO,iCAAiC,KAAK;AAAA,EAC/C;AACA,SAAO,QAAQ,kBAAkB,eAC7B,mCACA;AACN;AAEO,SAAS,sBAAsB,OAAmC;AACvE,QAAM,SAAS,MAAM;AACrB,MAAI,CAAC,QAAQ;AACX,WAAO,MAAM,SAAS,aAAa,cAAc,MAAM,QAAQ,kBAAkB,eAC7E,mCACA;AAAA,EACN;AACA,MAAI,OAAO,SAAS,0BAA0B;AAC5C,WAAO,OAAO,aAAa,QACvB,qCACA;AAAA,EACN;AACA,MAAI,OAAO,SAAS,wBAAwB;AAC1C,QAAI,MAAM,aAAa,wBAAwB;AAC7C,aAAO;AAAA,IACT;AACA,QAAI,MAAM,aAAa,uBAAuB,MAAM,WAAW,qBAAqB;AAClF,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,SAAS,cAAc;AAChC,WAAO,OAAO,cAAc,oBACxB,8BACA;AAAA,EACN;AACA,SAAO;AACT;AAEA,SAAS,8BAA8B,OAA4B;AACjE,MAAI,MAAM,aAAa,wBAAwB;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa,uBAAuB,MAAM,WAAW,qBAAqB;AAClF,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,iCAAiC,OAA4B;AACpE,MAAI,MAAM,aAAa,2BAA2B;AAChD,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa,wBAAwB;AAC7C,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,QAAwD;AACxF,SAAO,OACJ,OAAO,CAAC,YAAY,QAAQ,oBAAoB,WAAW,OAAO,EAClE,IAAI,CAAC,YAAY;AAChB,UAAM,eAAe,qBAAqB,OAAO;AACjD,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,MAC/D;AAAA,MACA,mBAAmB,kBAAkB,YAAY;AAAA,MACjD,YAAY,QAAQ,aAAa;AAAA,MACjC,mBAAmB,QAAQ,aAAa,aACpC,OACA,wBAAwB,QAAQ,aAAa,MAAM;AAAA,MACvD,UAAU,QAAQ;AAAA,MAClB,eAAe,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AACL;AAGO,SAAS,uBAAuB,QAAsD;AAC3F,SAAO,OAAO,IAAI,CAAC,YAAY;AAC7B,UAAM,eAAe,qBAAqB,OAAO;AACjD,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,MAC/D;AAAA,MACA,mBAAmB,kBAAkB,YAAY;AAAA,MACjD,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,eAAe,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,eACd,MAC4B;AAC5B,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,uBAAuB;AAC/C;AAEO,SAAS,cACd,MACA,SACiC;AACjC,SAAO,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,OAAO,KAAK;AACnD;AAcO,SAAS,8BACd,MACA,SAKC;AACD,QAAM,SAAS,eAAe,IAAI;AAClC,QAAM,SAID,CAAC;AACN,aAAW,OAAO,QAAQ;AACxB,UAAM,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,iBAAiB,IAAI,YAAY;AAC/E,QAAI,UAAU;AACZ,eAAS,KAAK,KAAK,GAAG;AACtB;AAAA,IACF;AACA,WAAO,KAAK;AAAA,MACV,cAAc,IAAI;AAAA,MAClB,OAAO,IAAI;AAAA,MACX,MAAM,CAAC,GAAG;AAAA,IACZ,CAAC;AAAA,EACH;AACA,QAAM,aAAa,OAAO,UAAU,CAAC,UAAU,MAAM,iBAAiB,oBAAoB;AAC1F,QAAM,QAAQ,OAAO,UAAU;AAC/B,QAAM,qBAAqB,OACxB,KAAK,CAAC,UAAU,MAAM,iBAAiB,kBAAkB,GACxD,KAAK,OAAO,CAAC,QAAQ,IAAI,UAAU;AAEvC,QAAM,mBACJ,uBAAuB,UACvB,mBAAmB,SAAS,KAC5B,mBAAmB,MAAM,CAAC,QAAQ,IAAI,QAAQ,SAAS,MAAM;AAC/D,MACE,SACA,MAAM,KAAK,KAAK,CAAC,QAAQ,IAAI,UAAU,MACtC,SAAS,aAAa,mBACvB;AACA,WAAO,OAAO,YAAY,CAAC;AAC3B,WAAO,QAAQ,KAAK;AAAA,EACtB;AACA,SAAO;AACT;","names":[]}
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
useMutationRunner,
|
|
3
3
|
usePageLiveActivity
|
|
4
4
|
} from "./chunk-KZ73RL76.js";
|
|
5
|
+
import {
|
|
6
|
+
useOpenGeni
|
|
7
|
+
} from "./chunk-NEXLLTP4.js";
|
|
5
8
|
import {
|
|
6
9
|
formatBytes,
|
|
7
10
|
formatRelativeTime
|
|
8
11
|
} from "./chunk-PLYRL5ER.js";
|
|
9
|
-
import {
|
|
10
|
-
useOpenGeni
|
|
11
|
-
} from "./chunk-NEXLLTP4.js";
|
|
12
12
|
import {
|
|
13
13
|
cn
|
|
14
14
|
} from "./chunk-22KP6LR5.js";
|
|
@@ -498,10 +498,12 @@ function MetricSparkline({
|
|
|
498
498
|
// src/components/machine-card.tsx
|
|
499
499
|
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
500
500
|
function KindIcon({ machine }) {
|
|
501
|
-
if (machine.
|
|
501
|
+
if (machine.kind === "local" || machine.kind === "selfhosted")
|
|
502
|
+
return /* @__PURE__ */ jsx5(LaptopIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
503
|
+
if (machine.kind === "docker" || machine.isSessionGroup)
|
|
502
504
|
return /* @__PURE__ */ jsx5(ServerIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
503
505
|
if (machine.kind === "modal") return /* @__PURE__ */ jsx5(CpuIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
504
|
-
return /* @__PURE__ */ jsx5(
|
|
506
|
+
return /* @__PURE__ */ jsx5(ServerIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
505
507
|
}
|
|
506
508
|
function MachineCard({
|
|
507
509
|
machine,
|
|
@@ -590,7 +592,7 @@ function MachineCard({
|
|
|
590
592
|
/* @__PURE__ */ jsxs5("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-og-xs text-og-fg-subtle", children: [
|
|
591
593
|
/* @__PURE__ */ jsx5("span", { "data-machine-scope": machine.scope, className: "capitalize", children: machine.scope === "user" ? "personal" : machine.scope }),
|
|
592
594
|
/* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
|
|
593
|
-
/* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.
|
|
595
|
+
/* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.kind }),
|
|
594
596
|
/* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
|
|
595
597
|
/* @__PURE__ */ jsxs5("span", { className: "font-og-mono", children: [
|
|
596
598
|
machine.os,
|
|
@@ -1227,9 +1229,12 @@ function MachineOperationPolicyEditor({
|
|
|
1227
1229
|
// src/components/machines/machine-detail.tsx
|
|
1228
1230
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1229
1231
|
function KindIcon2({ kind, session }) {
|
|
1230
|
-
if (
|
|
1232
|
+
if (kind === "local" || kind === "selfhosted")
|
|
1233
|
+
return /* @__PURE__ */ jsx8(LaptopIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
1234
|
+
if (kind === "docker" || session)
|
|
1235
|
+
return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
1231
1236
|
if (kind === "modal") return /* @__PURE__ */ jsx8(CpuIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
1232
|
-
return /* @__PURE__ */ jsx8(
|
|
1237
|
+
return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
|
|
1233
1238
|
}
|
|
1234
1239
|
function MachineDetail({
|
|
1235
1240
|
machine,
|
|
@@ -1571,7 +1576,7 @@ function MachinesDashboard({
|
|
|
1571
1576
|
import { LaptopIcon as LaptopIcon4, CpuIcon as CpuIcon3, UsersIcon as UsersIcon2 } from "lucide-react";
|
|
1572
1577
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1573
1578
|
function MachineDockBar({ name, kind, state, className }) {
|
|
1574
|
-
const Icon = kind === "selfhosted" ? LaptopIcon4 : CpuIcon3;
|
|
1579
|
+
const Icon = kind === "selfhosted" || kind === "local" ? LaptopIcon4 : CpuIcon3;
|
|
1575
1580
|
const stateBadge = MACHINE_STATE_BADGE_META[state];
|
|
1576
1581
|
return /* @__PURE__ */ jsxs10(
|
|
1577
1582
|
"div",
|
|
@@ -2442,4 +2447,4 @@ export {
|
|
|
2442
2447
|
EnrollmentDeviceFlow,
|
|
2443
2448
|
EnrollmentConsent
|
|
2444
2449
|
};
|
|
2445
|
-
//# sourceMappingURL=chunk-
|
|
2450
|
+
//# sourceMappingURL=chunk-PFDNB3U7.js.map
|