@opengeni/react 0.2.0 → 0.3.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider.tsx","../src/hooks/use-session.ts","../src/hooks/internal.ts","../src/hooks/use-session-events.ts","../src/lib/format.ts","../src/timeline.ts","../src/hooks/use-composer.ts","../src/hooks/use-file-attachments.ts","../src/hooks/use-turn-queue.ts","../src/hooks/use-goal.ts","../src/hooks/use-session-control.ts","../src/hooks/use-scheduled-tasks.ts","../src/hooks/use-workspace-sessions.ts","../src/hooks/use-environments.ts","../src/hooks/use-packs.ts","../src/hooks/use-workspaces.ts","../src/hooks/use-billing-usage.ts","../src/approvals.ts","../src/commands/registry.ts","../src/hooks/use-slash-commands.ts","../src/components/command-palette.tsx","../src/lib/cn.ts","../src/components/chat-composer.tsx","../src/components/message-timeline.tsx","../src/components/session-status.tsx","../src/components/fleet-tile.tsx"],"sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { SessionClientLike } from \"./client\";\n\nexport type OpenGeniContextValue = {\n client: SessionClientLike;\n workspaceId: string;\n};\n\nconst OpenGeniContext = createContext<OpenGeniContextValue | null>(null);\n\nexport type OpenGeniProviderProps = {\n client: SessionClientLike;\n workspaceId: string;\n children?: ReactNode;\n};\n\n/**\n * Supplies the OpenGeni client + workspace to all hooks below it. Hooks also\n * accept `{ client, workspaceId }` overrides per call for multi-workspace UIs.\n */\nexport function OpenGeniProvider({ client, workspaceId, children }: OpenGeniProviderProps) {\n const value = useMemo(() => ({ client, workspaceId }), [client, workspaceId]);\n return <OpenGeniContext.Provider value={value}>{children}</OpenGeniContext.Provider>;\n}\n\nexport type ClientOverride = {\n client?: SessionClientLike | undefined;\n workspaceId?: string | undefined;\n};\n\n/** Resolve client + workspace from explicit overrides or the provider. */\nexport function useOpenGeni(override: ClientOverride = {}): OpenGeniContextValue {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n const workspaceId = override.workspaceId ?? context?.workspaceId;\n if (!client || !workspaceId) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client/workspace available. Wrap the tree in <OpenGeniProvider> or pass { client, workspaceId } to the hook.\",\n );\n }\n return { client, workspaceId };\n}\n\n/**\n * Resolve the client only — for hooks that are not workspace-scoped\n * (`useWorkspaces`, `useBillingUsage`).\n */\nexport function useOpenGeniClient(override: Pick<ClientOverride, \"client\"> = {}): SessionClientLike {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n if (!client) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client available. Wrap the tree in <OpenGeniProvider> or pass { client } to the hook.\",\n );\n }\n return client;\n}\n","import type { Session } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseSessionOptions = ClientOverride & {\n /** Re-fetch on an interval (ms). Off by default — pair with `useSessionEvents` for live status. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseSessionResult = {\n session: Session | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** Fetch one session (with optional polling). */\nexport function useSession(sessionId: string | null | undefined, options: UseSessionOptions = {}): UseSessionResult {\n const { client, workspaceId } = useOpenGeni(options);\n const load = useCallback(async () => {\n if (!sessionId) {\n return null;\n }\n return await client.getSession(workspaceId, sessionId);\n }, [client, workspaceId, sessionId]);\n const state = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled: (options.enabled ?? true) && Boolean(sessionId),\n });\n return { session: state.data ?? null, loading: state.loading, error: state.error, refresh: state.refresh };\n}\n","import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { SessionClientLike } from \"../client\";\n\nexport type AsyncListState<T> = {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Shared fetch + optional polling loop for the list/read hooks. Stale\n * responses (superseded by a newer load or an unmount) are dropped.\n */\nexport function usePolledValue<T>(load: () => Promise<T>, options: { pollIntervalMs?: number | undefined; enabled?: boolean | undefined } = {}): AsyncListState<T> {\n const enabled = options.enabled ?? true;\n const pollIntervalMs = options.pollIntervalMs;\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const generation = useRef(0);\n const loadRef = useRef(load);\n\n // A new loader identity means a new query (different session/workspace/...):\n // drop the previous result instead of showing it as the new query's data.\n useEffect(() => {\n if (loadRef.current !== load) {\n loadRef.current = load;\n setData(null);\n setError(null);\n }\n }, [load]);\n\n const run = useCallback(async () => {\n const ticket = ++generation.current;\n try {\n const result = await load();\n if (ticket === generation.current) {\n setData(result);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (ticket === generation.current) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setLoading(false);\n }\n }\n }, [load]);\n\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void run();\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n };\n }\n const timer = setInterval(() => void run(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n };\n }, [run, enabled, pollIntervalMs]);\n\n return { data, loading, error, refresh: run };\n}\n\nexport type MutationState = {\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Shared async mutation runner for the write hooks. `run` resolves with the\n * operation's value, or `null` after capturing the error in `mutationError`\n * (callers then roll back optimistic state).\n */\nexport function useMutationRunner(): MutationState & {\n run: <T>(operation: () => Promise<T>) => Promise<T | null>;\n} {\n const [mutating, setMutating] = useState(false);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const inFlight = useRef(0);\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const run = useCallback(async <T,>(operation: () => Promise<T>): Promise<T | null> => {\n inFlight.current += 1;\n if (mounted.current) {\n setMutating(true);\n setMutationError(null);\n }\n try {\n return await operation();\n } catch (cause) {\n if (mounted.current) {\n setMutationError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n return null;\n } finally {\n inFlight.current -= 1;\n if (mounted.current && inFlight.current === 0) {\n setMutating(false);\n }\n }\n }, []);\n return {\n mutating,\n mutationError,\n clearMutationError: useCallback(() => setMutationError(null), []),\n run,\n };\n}\n\nexport type SessionEventFeedOptions = {\n /**\n * Share an existing event log (from `useSessionEvents`) instead of opening\n * a second stream. When omitted the hook tails the session's event stream\n * itself, starting at the current `lastSequence`.\n */\n events?: SessionEvent[] | undefined;\n enabled?: boolean | undefined;\n};\n\n/**\n * Invoke `onEvent` for every session event matching `match` — the live-update\n * primitive behind `useTurnQueue` and `useGoal`. Either watches a shared\n * `events` log or tails the stream directly (reconnect handled by the SDK).\n */\nexport function useSessionEventTrigger(\n client: SessionClientLike,\n workspaceId: string,\n sessionId: string | null | undefined,\n match: (event: SessionEvent) => boolean,\n onEvent: (event: SessionEvent) => void,\n options: SessionEventFeedOptions = {},\n): void {\n const enabled = options.enabled ?? true;\n const events = options.events;\n const sharedFeed = events !== undefined;\n const matchRef = useRef(match);\n matchRef.current = match;\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n const consumedRef = useRef(0);\n const feedKeyRef = useRef<string | null>(null);\n\n // Shared-log mode: scan only the unseen tail on every append.\n useEffect(() => {\n if (!sharedFeed || !enabled || !sessionId) {\n return;\n }\n const feedKey = `${workspaceId}\\u0000${sessionId}`;\n const firstSequence = events[0]?.sequence ?? 0;\n // A new session target or a log reset (sequence restarted below the\n // cursor) restarts consumption from the top of the shared log.\n if (feedKeyRef.current !== feedKey || firstSequence > consumedRef.current + 1) {\n feedKeyRef.current = feedKey;\n consumedRef.current = 0;\n }\n for (const event of events) {\n if (event.sequence <= consumedRef.current) {\n continue;\n }\n consumedRef.current = event.sequence;\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n }, [sharedFeed, enabled, events, workspaceId, sessionId]);\n\n // Self-stream mode: tail from the session's current lastSequence.\n useEffect(() => {\n if (sharedFeed || !enabled || !sessionId) {\n return;\n }\n const controller = new AbortController();\n void (async () => {\n try {\n const session = await client.getSession(workspaceId, sessionId);\n if (controller.signal.aborted) {\n return;\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: session.lastSequence,\n signal: controller.signal,\n });\n for await (const event of stream) {\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n } catch {\n // Live updates are best-effort: the read hooks still expose refresh()\n // and the initial load already populated state.\n }\n })();\n return () => {\n controller.abort();\n };\n }, [sharedFeed, enabled, client, workspaceId, sessionId]);\n}\n\n/** Debounce rapid event bursts into one trailing call (default 150ms). */\nexport function useDebouncedCallback(callback: () => void, delayMs = 150): () => void {\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n return useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n callbackRef.current();\n }, delayMs);\n }, [delayMs]);\n}\n","import type { SessionEvent, SessionStatus, StreamConnectionState } from \"@opengeni/sdk\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { buildTimeline, sessionStatusFromEvents, type TimelineItem } from \"../timeline\";\n\nexport type SessionEventsConnectionState = StreamConnectionState | \"idle\" | \"ended\" | \"error\";\n\nexport type UseSessionEventsOptions = ClientOverride & {\n /** Resume after this sequence (exclusive). Defaults to 0 = full replay. */\n after?: number | undefined;\n /** Pause the stream without unmounting (e.g. hidden tab). Defaults to true. */\n enabled?: boolean | undefined;\n};\n\nexport type UseSessionEventsResult = {\n /** Replayed + live events, ordered by sequence, no gaps, no duplicates. */\n events: SessionEvent[];\n /** Projected, renderable timeline (memoized over `events`). */\n timeline: TimelineItem[];\n /** Latest session status observed in the event log, if any. */\n sessionStatus: SessionStatus | null;\n connectionState: SessionEventsConnectionState;\n /** Highest sequence seen so far (0 before the first event). */\n lastSequence: number;\n error: Error | null;\n};\n\n/**\n * Live-stream a session's event log with replay-by-sequence, reconnect, and\n * batched React updates. The SDK guarantees ordered, gap-free, exactly-once\n * delivery; this hook accumulates the log and projects it into a timeline.\n */\nexport function useSessionEvents(sessionId: string | null | undefined, options: UseSessionEventsOptions = {}): UseSessionEventsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = options.enabled ?? true;\n const after = options.after ?? 0;\n\n const [events, setEvents] = useState<SessionEvent[]>([]);\n const [connectionState, setConnectionState] = useState<SessionEventsConnectionState>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const lastSequenceRef = useRef(after);\n const streamKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n // Reset the accumulated log only when the stream identity changes —\n // pausing via `enabled: false` keeps the timeline visible.\n const streamKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${after}`;\n if (streamKeyRef.current !== streamKey) {\n streamKeyRef.current = streamKey;\n setEvents([]);\n setError(null);\n lastSequenceRef.current = after;\n }\n if (!sessionId || !enabled) {\n setConnectionState(\"idle\");\n return;\n }\n const controller = new AbortController();\n // Batch yielded events into one React update per flush window so a long\n // replay (thousands of events) does not render per event.\n let pending: SessionEvent[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n const flush = () => {\n flushTimer = null;\n if (pending.length === 0) {\n return;\n }\n const batch = pending;\n pending = [];\n // The resume cursor only advances with delivered batches: events still\n // sitting in `pending` when the stream is torn down are re-fetched on\n // the next connect instead of being skipped.\n const lastInBatch = batch[batch.length - 1];\n if (lastInBatch) {\n lastSequenceRef.current = lastInBatch.sequence;\n }\n setEvents((existing) => [...existing, ...batch]);\n };\n const scheduleFlush = () => {\n flushTimer ??= setTimeout(flush, 16);\n };\n\n void (async () => {\n try {\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: lastSequenceRef.current,\n signal: controller.signal,\n onStateChange: (state) => {\n if (!controller.signal.aborted) {\n setConnectionState(state);\n }\n },\n });\n for await (const event of stream) {\n pending.push(event);\n scheduleFlush();\n }\n if (!controller.signal.aborted) {\n flush();\n setConnectionState(\"ended\");\n }\n } catch (cause) {\n if (!controller.signal.aborted) {\n flush();\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setConnectionState(\"error\");\n }\n }\n })();\n\n return () => {\n controller.abort();\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n }\n };\n }, [client, workspaceId, sessionId, after, enabled]);\n\n const timeline = useMemo(() => buildTimeline(events), [events]);\n const sessionStatus = useMemo(() => sessionStatusFromEvents(events), [events]);\n\n return {\n events,\n timeline,\n sessionStatus,\n connectionState,\n lastSequence: lastSequenceRef.current,\n error,\n };\n}\n","/** Compact relative time: \"now\", \"42s\", \"7m\", \"3h\", \"2d\", then a date. */\nexport function formatRelativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) {\n return \"\";\n }\n const seconds = Math.max(0, Math.floor((now.getTime() - then) / 1000));\n if (seconds < 10) {\n return \"now\";\n }\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n if (hours < 24) {\n return `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n if (days < 14) {\n return `${days}d`;\n }\n return new Date(iso).toLocaleDateString();\n}\n\n/** Human-readable byte size: \"512 B\", \"8.0 KB\", \"1.4 MB\", \"3 GB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = bytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value < 10 ? 1 : 0)} ${unit}`;\n }\n value /= 1024;\n }\n return `${bytes} B`;\n}\n\n/** Single-line preview of arbitrary text, for tiles and collapsed rows. */\nexport function truncate(text: string, maxLength: number): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Render an unknown payload as readable text (pretty JSON when possible). */\nexport function stringifyPayload(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n const parsed = tryParseJson(value);\n if (parsed !== undefined && typeof parsed === \"object\") {\n return stringifyPayload(parsed);\n }\n return value;\n }\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** JSON.parse that returns `undefined` instead of throwing. */\nexport function tryParseJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\") && !trimmed.startsWith('\"')) {\n return undefined;\n }\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return undefined;\n }\n}\n","import type { ResourceRef, SessionEvent, SessionStatus, ToolRef } from \"@opengeni/sdk\";\nimport { stringifyPayload, tryParseJson } from \"./lib/format\";\n\n/* ----------------------------------------------------------------------------\n Timeline projection\n\n `buildTimeline` folds a session's raw event log (replayed + live, ordered by\n sequence) into renderable items: chat messages with accumulated streaming\n deltas, reasoning summaries, tool calls matched to their outputs, sandbox\n operations with command output, spawned-worker status (the manager's\n `session_create` / `session_send_message` orchestration calls), goal\n markers, status changes, and turn failures.\n\n It is a pure function — same events in, same items out — so it can be\n memoized, unit-tested, and re-run incrementally as new events stream in.\n -------------------------------------------------------------------------- */\n\nexport type UserMessageItem = {\n kind: \"user-message\";\n id: string;\n text: string;\n /** Resources attached to this message (file uploads, repositories). */\n resources: ResourceRef[];\n /** Tools requested for the turn this message starts. */\n tools: ToolRef[];\n occurredAt: string;\n};\n\nexport type AgentMessageItem = {\n kind: \"agent-message\";\n id: string;\n turnId: string | null;\n text: string;\n /** Still receiving deltas (no completed/turn-end seen yet). */\n streaming: boolean;\n occurredAt: string;\n};\n\nexport type ReasoningItem = {\n kind: \"reasoning\";\n id: string;\n turnId: string | null;\n text: string;\n streaming: boolean;\n occurredAt: string;\n};\n\nexport type ToolCallItem = {\n kind: \"tool-call\";\n id: string;\n turnId: string | null;\n callId: string | null;\n name: string;\n arguments: unknown;\n output: unknown;\n status: \"running\" | \"complete\";\n occurredAt: string;\n};\n\n/**\n * An orchestration call against another session — the manager spawning or\n * messaging a worker. Rendered as a first-class \"worker\" row, not a generic\n * tool call.\n */\nexport type WorkerItem = {\n kind: \"worker\";\n id: string;\n turnId: string | null;\n callId: string | null;\n action: \"spawn\" | \"message\";\n /** The worker's initial message / the message sent to it, when parseable. */\n prompt: string | null;\n /** The target/spawned worker session id, when parseable from args/output. */\n workerSessionId: string | null;\n status: \"running\" | \"complete\";\n occurredAt: string;\n};\n\nexport type SandboxItem = {\n kind: \"sandbox\";\n id: string;\n turnId: string | null;\n name: string;\n command: string | null;\n output: string;\n status: \"running\" | \"complete\" | \"failed\";\n occurredAt: string;\n};\n\nexport type SessionStatusItem = {\n kind: \"session-status\";\n id: string;\n status: SessionStatus;\n occurredAt: string;\n};\n\nexport type GoalItem = {\n kind: \"goal\";\n id: string;\n action: \"set\" | \"updated\" | \"completed\" | \"paused\" | \"resumed\" | \"continuation\";\n text: string | null;\n occurredAt: string;\n};\n\nexport type NoticeItem = {\n kind: \"notice\";\n id: string;\n tone: \"waiting\" | \"cancelled\" | \"failed\";\n text: string;\n occurredAt: string;\n};\n\nexport type TimelineItem =\n | UserMessageItem\n | AgentMessageItem\n | ReasoningItem\n | ToolCallItem\n | WorkerItem\n | SandboxItem\n | SessionStatusItem\n | GoalItem\n | NoticeItem;\n\n/** Tool names on the first-party OpenGeni MCP server that operate on sessions. */\nconst WORKER_SPAWN_TOOL = \"session_create\";\nconst WORKER_MESSAGE_TOOL = \"session_send_message\";\n\nexport function buildTimeline(events: SessionEvent[]): TimelineItem[] {\n const items: TimelineItem[] = [];\n const ordered = [...events].sort((a, b) => a.sequence - b.sequence);\n\n const last = (): TimelineItem | undefined => items[items.length - 1];\n\n /** A new item of a different kind ends whatever was streaming at the tail. */\n const closeStreamingTail = (): void => {\n const open = last();\n if ((open?.kind === \"agent-message\" || open?.kind === \"reasoning\") && open.streaming) {\n open.streaming = false;\n }\n };\n\n const finalizeOpen = (turnId?: string | null): void => {\n for (const item of items) {\n if (turnId !== undefined && \"turnId\" in item && item.turnId && turnId && item.turnId !== turnId) {\n continue;\n }\n if ((item.kind === \"agent-message\" || item.kind === \"reasoning\") && item.streaming) {\n item.streaming = false;\n }\n if ((item.kind === \"tool-call\" || item.kind === \"worker\") && item.status === \"running\") {\n item.status = \"complete\";\n }\n if (item.kind === \"sandbox\" && item.status === \"running\") {\n item.status = \"complete\";\n }\n }\n };\n\n for (const event of ordered) {\n const payload = asRecord(event.payload);\n const turnId = event.turnId ?? null;\n\n switch (event.type) {\n case \"user.message\": {\n // A steering message must not mark in-flight tools complete; it only\n // ends whatever text was streaming. Turn lifecycle events finalize.\n closeStreamingTail();\n items.push({\n kind: \"user-message\",\n id: event.id,\n text: typeof payload.text === \"string\" ? payload.text : \"\",\n resources: resourceRefs(payload.resources),\n tools: toolRefs(payload.tools),\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.message.delta\": {\n const text = typeof payload.text === \"string\" ? payload.text : \"\";\n if (!text) {\n break;\n }\n const open = last();\n if (open?.kind === \"agent-message\" && open.streaming && open.turnId === turnId) {\n open.text += text;\n break;\n }\n closeStreamingTail();\n items.push({\n kind: \"agent-message\",\n id: event.id,\n turnId,\n text,\n streaming: true,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.message.completed\": {\n const text = typeof payload.text === \"string\" ? payload.text : \"\";\n // Reconcile the most recent same-turn agent message — even when\n // activity (tool calls, reasoning) landed after its deltas — so the\n // completed text never duplicates the streamed one.\n const open = [...items]\n .reverse()\n .find((item): item is AgentMessageItem => item.kind === \"agent-message\" && item.turnId === turnId);\n if (open && (open.streaming || !open.text || text === open.text || text.startsWith(open.text))) {\n // The completed text is authoritative when it extends what streamed.\n if (!open.text || (text && text.startsWith(open.text))) {\n open.text = text || open.text;\n }\n open.streaming = false;\n break;\n }\n if (text) {\n items.push({\n kind: \"agent-message\",\n id: event.id,\n turnId,\n text,\n streaming: false,\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"agent.reasoning.delta\": {\n const text = reasoningText(event.payload);\n if (!text) {\n break;\n }\n const open = last();\n if (open?.kind === \"reasoning\" && open.streaming && open.turnId === turnId) {\n open.text += text;\n break;\n }\n closeStreamingTail();\n items.push({\n kind: \"reasoning\",\n id: event.id,\n turnId,\n text,\n streaming: true,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.toolCall.created\": {\n const name = typeof payload.name === \"string\" ? payload.name : \"tool\";\n const callId = typeof payload.id === \"string\" ? payload.id : null;\n const args = payload.arguments ?? null;\n closeStreamingTail();\n if (name === WORKER_SPAWN_TOOL || name === WORKER_MESSAGE_TOOL) {\n items.push({\n kind: \"worker\",\n id: event.id,\n turnId,\n callId,\n action: name === WORKER_SPAWN_TOOL ? \"spawn\" : \"message\",\n prompt: workerPrompt(args),\n workerSessionId: extractSessionRef(args),\n status: \"running\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n items.push({\n kind: \"tool-call\",\n id: event.id,\n turnId,\n callId,\n name,\n arguments: args,\n output: undefined,\n status: \"running\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.toolCall.output\": {\n const callId = typeof payload.id === \"string\" ? payload.id : null;\n const target = findOpenCall(items, callId);\n if (!target) {\n break;\n }\n if (target.kind === \"worker\") {\n target.status = \"complete\";\n target.workerSessionId = target.workerSessionId ?? extractSessionRef(payload.output);\n break;\n }\n target.status = \"complete\";\n target.output = payload.output;\n break;\n }\n\n case \"sandbox.operation.started\":\n case \"sandbox.operation.completed\":\n case \"sandbox.operation.failed\": {\n const name = typeof payload.name === \"string\" ? payload.name : \"sandbox\";\n const status = event.type.endsWith(\".failed\") ? \"failed\" : event.type.endsWith(\".completed\") ? \"complete\" : \"running\";\n const existing = findOpenSandbox(items, name);\n if (existing && status !== \"running\") {\n existing.status = status;\n const message = failureMessage(payload);\n if (message) {\n existing.output = existing.output ? `${existing.output}\\n${message}` : message;\n }\n break;\n }\n if (!existing) {\n closeStreamingTail();\n items.push({\n kind: \"sandbox\",\n id: event.id,\n turnId,\n name,\n command: typeof payload.command === \"string\" ? payload.command : null,\n output: failureMessage(payload) ?? \"\",\n status,\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"sandbox.command.output.delta\": {\n const text = typeof payload.text === \"string\" ? payload.text : typeof payload.output === \"string\" ? payload.output : \"\";\n if (!text) {\n break;\n }\n // Attach to the named operation when the payload carries one;\n // otherwise the latest running operation is the best available owner.\n const open =\n (typeof payload.name === \"string\" ? findOpenSandbox(items, payload.name) : undefined) ??\n [...items].reverse().find((item): item is SandboxItem => item.kind === \"sandbox\" && item.status === \"running\");\n if (open) {\n open.output += text;\n }\n break;\n }\n\n case \"session.status.changed\": {\n const status = payload.status;\n if (!isSessionStatus(status)) {\n break;\n }\n const previous = [...items].reverse().find((item): item is SessionStatusItem => item.kind === \"session-status\");\n if (previous?.status === status) {\n break;\n }\n items.push({ kind: \"session-status\", id: event.id, status, occurredAt: event.occurredAt });\n break;\n }\n\n case \"session.requiresAction\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"waiting\",\n text: \"Approval needed — the turn is paused until someone decides.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"turn.completed\": {\n finalizeOpen(turnId);\n break;\n }\n\n case \"turn.failed\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"failed\",\n text: failureMessage(payload) ?? \"The turn failed.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"turn.cancelled\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"cancelled\",\n text: \"Interrupted.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"goal.set\":\n case \"goal.updated\":\n case \"goal.completed\":\n case \"goal.paused\":\n case \"goal.resumed\":\n case \"goal.continuation\": {\n items.push({\n kind: \"goal\",\n id: event.id,\n action: event.type.slice(\"goal.\".length) as GoalItem[\"action\"],\n text: goalText(payload),\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n default:\n break;\n }\n }\n\n return items;\n}\n\n/** The latest session status carried in the event log, if any. */\nexport function sessionStatusFromEvents(events: SessionEvent[]): SessionStatus | null {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event?.type !== \"session.status.changed\") {\n continue;\n }\n const status = asRecord(event.payload).status;\n if (isSessionStatus(status)) {\n return status;\n }\n }\n return null;\n}\n\n/* ----------------------------------------------------------------------------\n Visual grouping: consecutive activity items (reasoning / tools / workers /\n sandbox) cluster into one collapsible block between chat messages.\n -------------------------------------------------------------------------- */\n\nexport type TimelineGroup =\n | { kind: \"item\"; item: TimelineItem }\n | { kind: \"activity\"; id: string; items: (ReasoningItem | ToolCallItem | WorkerItem | SandboxItem)[] };\n\nconst ACTIVITY_KINDS = new Set([\"reasoning\", \"tool-call\", \"worker\", \"sandbox\"]);\n\nexport function groupTimeline(items: TimelineItem[]): TimelineGroup[] {\n const groups: TimelineGroup[] = [];\n for (const item of items) {\n if (ACTIVITY_KINDS.has(item.kind)) {\n const open = groups[groups.length - 1];\n const activity = item as ReasoningItem | ToolCallItem | WorkerItem | SandboxItem;\n if (open?.kind === \"activity\") {\n open.items.push(activity);\n } else {\n groups.push({ kind: \"activity\", id: `activity-${item.id}`, items: [activity] });\n }\n continue;\n }\n groups.push({ kind: \"item\", item });\n }\n return groups;\n}\n\n/* --- helpers ---------------------------------------------------------------- */\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === \"object\" ? (value as Record<string, unknown>) : {};\n}\n\nconst SESSION_STATUSES: readonly SessionStatus[] = [\"queued\", \"running\", \"idle\", \"requires_action\", \"failed\", \"cancelled\"];\n\n/** Keep only entries that match the wire shapes; user payloads are untyped. */\nfunction resourceRefs(value: unknown): ResourceRef[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is ResourceRef => {\n const record = asRecord(entry);\n if (record.kind === \"repository\") {\n return typeof record.uri === \"string\" && typeof record.ref === \"string\";\n }\n return record.kind === \"file\" && typeof record.fileId === \"string\";\n });\n}\n\nfunction toolRefs(value: unknown): ToolRef[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is ToolRef => {\n const record = asRecord(entry);\n return record.kind === \"mcp\" && typeof record.id === \"string\";\n });\n}\n\nfunction isSessionStatus(value: unknown): value is SessionStatus {\n return typeof value === \"string\" && (SESSION_STATUSES as readonly string[]).includes(value);\n}\n\nfunction findOpenCall(items: TimelineItem[], callId: string | null): ToolCallItem | WorkerItem | undefined {\n const reversed = [...items].reverse();\n const isCall = (item: TimelineItem): item is ToolCallItem | WorkerItem => item.kind === \"tool-call\" || item.kind === \"worker\";\n if (callId) {\n const byId = reversed.find((item) => isCall(item) && item.callId === callId);\n if (byId) {\n return byId as ToolCallItem | WorkerItem;\n }\n }\n return reversed.find((item): item is ToolCallItem | WorkerItem => isCall(item) && item.status === \"running\");\n}\n\nfunction findOpenSandbox(items: TimelineItem[], name: string): SandboxItem | undefined {\n return [...items].reverse().find((item): item is SandboxItem => item.kind === \"sandbox\" && item.name === name && item.status === \"running\");\n}\n\nfunction failureMessage(payload: Record<string, unknown>): string | null {\n for (const key of [\"error\", \"message\"] as const) {\n const value = payload[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return null;\n}\n\nfunction goalText(payload: Record<string, unknown>): string | null {\n if (typeof payload.text === \"string\" && payload.text) {\n return payload.text;\n }\n const goal = asRecord(payload.goal);\n if (typeof goal.text === \"string\" && goal.text) {\n return goal.text;\n }\n if (typeof payload.prompt === \"string\" && payload.prompt) {\n return payload.prompt;\n }\n return null;\n}\n\nfunction reasoningText(payload: unknown): string {\n const record = asRecord(payload);\n if (typeof record.text === \"string\") {\n return record.text;\n }\n const content = asRecord(asRecord(record.item).rawItem).content;\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((part) => {\n const text = asRecord(part).text;\n return typeof text === \"string\" ? text : \"\";\n })\n .join(\"\");\n}\n\n/** The worker's initial/sent message from `session_create`/`session_send_message` args. */\nfunction workerPrompt(args: unknown): string | null {\n const record = asRecord(typeof args === \"string\" ? tryParseJson(args) : args);\n for (const key of [\"initialMessage\", \"message\", \"text\", \"prompt\"] as const) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return null;\n}\n\n/**\n * Find a session id in orchestration tool arguments or output. Handles raw\n * objects, JSON strings, and MCP tool results (`{ content: [{ type: \"text\",\n * text: \"{...}\" }], structuredContent? }`).\n */\nexport function extractSessionRef(value: unknown, depth = 0): string | null {\n if (depth > 6 || value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\") {\n return extractSessionRef(tryParseJson(value), depth + 1);\n }\n if (Array.isArray(value)) {\n for (const entry of value) {\n const found = extractSessionRef(entry, depth + 1);\n if (found) {\n return found;\n }\n }\n return null;\n }\n if (typeof value !== \"object\") {\n return null;\n }\n const record = value as Record<string, unknown>;\n if (typeof record.sessionId === \"string\" && looksLikeId(record.sessionId)) {\n return record.sessionId;\n }\n if (typeof record.id === \"string\" && looksLikeId(record.id) && (\"status\" in record || \"workspaceId\" in record || \"initialMessage\" in record)) {\n return record.id;\n }\n for (const key of [\"structuredContent\", \"session\", \"result\", \"content\"] as const) {\n if (key in record) {\n const found = extractSessionRef(record[key], depth + 1);\n if (found) {\n return found;\n }\n }\n }\n if (typeof record.text === \"string\") {\n return extractSessionRef(tryParseJson(record.text), depth + 1);\n }\n return null;\n}\n\nfunction looksLikeId(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n\n/** Readable label for a tool call (\"session_create\" -> \"session create\"). */\nexport function toolDisplayName(name: string): string {\n return name.replace(/[_-]+/g, \" \").trim();\n}\n\n/** Compact, single-line preview of tool arguments/outputs for collapsed rows. */\nexport function compactPayloadPreview(value: unknown, maxLength = 120): string {\n const text = stringifyPayload(value).replace(/\\s+/g, \" \").trim();\n return text.length > maxLength ? `${text.slice(0, maxLength - 1)}…` : text;\n}\n","import type { SendMessageInput } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\n\nexport type ComposerSendExtras = Omit<SendMessageInput, \"text\" | \"clientEventId\">;\n\n/**\n * Compose-time delivery choice. `queue` (the default) stacks the message\n * behind the running turn — visible, editable, reorderable until claimed.\n * `steer` interrupts the running turn and injects the message now.\n */\nexport type ComposerMode = \"queue\" | \"steer\";\n\nexport type UseComposerOptions = ClientOverride & {\n /** Called with the accepted text after a successful send. */\n onSent?: ((text: string) => void) | undefined;\n /**\n * Extra message fields (resources, tools, model, reasoningEffort) merged\n * into every send. A function is evaluated at send time so it can read the\n * surrounding UI state (attachment pickers, model selectors, ...).\n */\n sendExtras?: ComposerSendExtras | (() => ComposerSendExtras) | undefined;\n /** Initial delivery mode. Defaults to `\"queue\"`. */\n defaultMode?: ComposerMode | undefined;\n};\n\nexport type ComposerState = {\n value: string;\n setValue: (value: string) => void;\n /** Send the draft (or an explicit text) using the current mode. */\n send: (text?: string) => Promise<boolean>;\n sending: boolean;\n canSend: boolean;\n /** Queue (default) vs steer — the compose-time delivery choice. */\n mode: ComposerMode;\n setMode: (mode: ComposerMode) => void;\n /** Ask the agent to stop the current turn. */\n interrupt: (reason?: string) => Promise<void>;\n interrupting: boolean;\n error: Error | null;\n clearError: () => void;\n};\n\n/**\n * Draft + send + interrupt state for the chat composer — the only\n * human-to-agent input surface. The draft survives a failed send (nothing is\n * more hostile than losing a typed message); each send carries a generated\n * `clientEventId` so retries stay idempotent server-side.\n */\nexport function useComposer(sessionId: string | null | undefined, options: UseComposerOptions = {}): ComposerState {\n const { client, workspaceId } = useOpenGeni(options);\n const defaultMode = options.defaultMode ?? \"queue\";\n const [value, setValue] = useState(\"\");\n const [mode, setMode] = useState<ComposerMode>(defaultMode);\n const [sending, setSending] = useState(false);\n const [interrupting, setInterrupting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const pendingClientEventId = useRef<string | null>(null);\n const onSent = options.onSent;\n // Read at send time so an in-flight send uses the mode chosen at submit.\n const modeRef = useRef(mode);\n modeRef.current = mode;\n // Read through a ref so a new extras closure (created every render by\n // callers passing inline functions) does not invalidate `send`.\n const sendExtrasRef = useRef(options.sendExtras);\n sendExtrasRef.current = options.sendExtras;\n\n // A composer is bound to one session: switching targets must not leak the\n // previous session's draft, error, or retry idempotency key.\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n const targetKeyRef = useRef(targetKey);\n useEffect(() => {\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n pendingClientEventId.current = null;\n setValue(\"\");\n setError(null);\n setMode(defaultMode);\n }\n }, [targetKey, defaultMode]);\n\n const send = useCallback(\n async (explicit?: string): Promise<boolean> => {\n const draftAtSend = value;\n const text = (explicit ?? draftAtSend).trim();\n // Resolve the extras once: a file-only message (empty text + ≥1 ready\n // resource) is legitimate, so we must not bail on empty text alone.\n const extras = resolveSendExtras(sendExtrasRef.current);\n const hasResources = (extras.resources?.length ?? 0) > 0;\n if ((!text && !hasResources) || !sessionId || sending) {\n return false;\n }\n // Reuse the clientEventId across retries of the same draft so a\n // timeout + resend cannot double-deliver the message.\n pendingClientEventId.current ??= generateClientEventId();\n setSending(true);\n setError(null);\n try {\n // The wire contract requires non-empty text (z.string().min(1)) and the\n // worker rejects whitespace-only text; a file-only message therefore\n // carries a minimal default so the attachments still get delivered.\n const sendText = text || FILE_ONLY_MESSAGE_TEXT;\n const input = composeSendInput(sendText, pendingClientEventId.current, extras);\n if (modeRef.current === \"steer\") {\n await client.steerMessage(workspaceId, sessionId, input);\n } else {\n await client.sendMessage(workspaceId, sessionId, input);\n }\n pendingClientEventId.current = null;\n if (explicit === undefined) {\n // Clear only the draft that was sent: edits made while the request\n // was in flight were never delivered and must survive.\n setValue((current) => (current === draftAtSend ? \"\" : current));\n }\n onSent?.(sendText);\n return true;\n } catch (cause) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n return false;\n } finally {\n setSending(false);\n }\n },\n [client, workspaceId, sessionId, value, sending, onSent],\n );\n\n // A send is possible with non-empty text OR with ≥1 attached resource (a\n // file-only message). Resources ride in `sendExtras`, so we resolve them here\n // — keeping useComposer attachment-agnostic while still lighting up the send\n // affordance the moment a file is ready. ChatComposer additionally gates this\n // on its `attachments.uploading` flag so a message never departs mid-upload.\n const hasReadyResources = (resolveSendExtras(sendExtrasRef.current).resources?.length ?? 0) > 0;\n\n const interrupt = useCallback(\n async (reason?: string): Promise<void> => {\n if (!sessionId || interrupting) {\n return;\n }\n setInterrupting(true);\n setError(null);\n try {\n await client.interrupt(workspaceId, sessionId, reason !== undefined ? { reason } : {});\n } catch (cause) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n } finally {\n setInterrupting(false);\n }\n },\n [client, workspaceId, sessionId, interrupting],\n );\n\n const updateValue = useCallback((next: string) => {\n pendingClientEventId.current = null;\n setValue(next);\n }, []);\n\n return {\n value,\n setValue: updateValue,\n send,\n sending,\n canSend: Boolean(sessionId) && !sending && (value.trim().length > 0 || hasReadyResources),\n mode,\n setMode,\n interrupt,\n interrupting,\n error,\n clearError: useCallback(() => setError(null), []),\n };\n}\n\n/**\n * Default text for a file-only message (attachment(s) present, no typed draft).\n * Kept non-empty so the wire contract (`text: z.string().min(1)`) and the\n * worker's non-whitespace guard accept it; the attached files still ride in\n * `resources`. Exported for tests.\n */\nexport const FILE_ONLY_MESSAGE_TEXT = \"(see attached files)\";\n\n/** Resolve possibly-deferred extras to a concrete bag (function evaluated now). */\nexport function resolveSendExtras(\n extras: ComposerSendExtras | (() => ComposerSendExtras) | undefined,\n): ComposerSendExtras {\n return (typeof extras === \"function\" ? extras() : extras) ?? {};\n}\n\n/**\n * Merge the draft text + idempotency key with caller-provided extras. The\n * text and clientEventId always win over extras. Exported for tests.\n */\nexport function composeSendInput(\n text: string,\n clientEventId: string,\n extras: ComposerSendExtras | (() => ComposerSendExtras) | undefined,\n): SendMessageInput {\n return { ...resolveSendExtras(extras), text, clientEventId };\n}\n\n/** Submit on plain Enter; Shift+Enter inserts a newline. Exported for tests. */\nexport function shouldSubmitOnKey(event: { key: string; shiftKey: boolean; nativeEvent?: { isComposing?: boolean } }): boolean {\n if (event.key !== \"Enter\" || event.shiftKey) {\n return false;\n }\n return event.nativeEvent?.isComposing !== true;\n}\n\nfunction generateClientEventId(): string {\n const cryptoApi = globalThis.crypto;\n if (cryptoApi && \"randomUUID\" in cryptoApi) {\n return cryptoApi.randomUUID();\n }\n return `ce-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n","import type { FileAsset, FileResourceRef } from \"@opengeni/sdk\";\nimport { useCallback, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\n\nexport type UseFileAttachmentsOptions = ClientOverride & {\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 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 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 the send-gate). */\n uploading: 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 /** Remove one attachment; revokes its object-URL. */\n remove: (id: string) => void;\n /** Remove all; revokes every object-URL. Call from `useComposer`'s `onSent`. */\n clear: () => void;\n};\n\nconst isImage = (file: File): boolean => file.type.startsWith(\"image/\");\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(options: UseFileAttachmentsOptions = {}): UseFileAttachmentsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const pasteFilter = options.pasteFilter ?? isImage;\n const [attachments, setAttachments] = useState<FileAttachment[]>([]);\n\n const addFiles = useCallback((files: Iterable<File>) => {\n for (const file of files) {\n const id = crypto.randomUUID();\n const previewUrl = isImage(file) ? URL.createObjectURL(file) : undefined;\n setAttachments((current) => [...current, {\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 void client.uploadFile(workspaceId, {\n filename: file.name || \"file\",\n contentType: file.type || \"application/octet-stream\",\n data: file,\n }).then((asset) => {\n setAttachments((current) => current.map((attachment) => attachment.id === id\n ? { ...attachment, status: \"ready\", file: asset, name: asset.filename, contentType: asset.contentType, sizeBytes: asset.sizeBytes }\n : attachment));\n }).catch((error: unknown) => {\n setAttachments((current) => current.map((attachment) => attachment.id === id\n ? { ...attachment, status: \"failed\", error: error instanceof Error ? error.message : String(error) }\n : attachment));\n });\n }\n }, [client, workspaceId]);\n\n const addFromPaste = useCallback((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 }, [addFiles, pasteFilter]);\n\n const remove = useCallback((id: string) => {\n setAttachments((current) => {\n const removed = current.find((attachment) => attachment.id === id);\n if (removed?.previewUrl) {\n URL.revokeObjectURL(removed.previewUrl);\n }\n return current.filter((attachment) => attachment.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setAttachments((current) => {\n for (const attachment of current) {\n if (attachment.previewUrl) {\n URL.revokeObjectURL(attachment.previewUrl);\n }\n }\n return [];\n });\n }, []);\n\n return {\n attachments,\n readyResources: attachments.flatMap((attachment): FileResourceRef[] => attachment.status === \"ready\" && attachment.file\n ? [{ kind: \"file\", fileId: attachment.file.id }]\n : []),\n uploading: attachments.some((attachment) => attachment.status === \"uploading\"),\n addFiles,\n addFromPaste,\n remove,\n clear,\n };\n}\n","import type { SessionEvent, SessionTurn, UpdateSessionTurnRequest } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useDebouncedCallback, useMutationRunner, useSessionEventTrigger, type SessionEventFeedOptions } from \"./internal\";\n\n/** Event types that change the turn queue (queue/edit/reorder/claim/finish). */\nexport function isTurnQueueEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return event.type.startsWith(\"turn.\");\n}\n\n/** Queued turns in execution order (position, then creation time). */\nexport function queueFromTurns(turns: SessionTurn[]): SessionTurn[] {\n return turns\n .filter((turn) => turn.status === \"queued\")\n .sort((a, b) => a.position - b.position || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));\n}\n\n/** The turn currently holding the session (running or awaiting approval). */\nexport function activeTurnFromTurns(turns: SessionTurn[]): SessionTurn | null {\n return turns.find((turn) => turn.status === \"running\" || turn.status === \"requires_action\") ?? null;\n}\n\n/** Optimistic projection of a queued-turn edit. */\nexport function applyTurnEdit(turns: SessionTurn[], turnId: string, update: UpdateSessionTurnRequest): SessionTurn[] {\n return turns.map((turn) => {\n if (turn.id !== turnId || turn.status !== \"queued\") {\n return turn;\n }\n return {\n ...turn,\n ...(update.prompt !== undefined ? { prompt: update.prompt } : {}),\n ...(update.resources !== undefined ? { resources: update.resources } : {}),\n ...(update.tools !== undefined ? { tools: update.tools } : {}),\n ...(update.model !== undefined ? { model: update.model } : {}),\n ...(update.reasoningEffort !== undefined ? { reasoningEffort: update.reasoningEffort } : {}),\n ...(update.sandboxBackend !== undefined ? { sandboxBackend: update.sandboxBackend } : {}),\n ...(update.metadata !== undefined ? { metadata: update.metadata } : {}),\n };\n });\n}\n\n/**\n * Optimistic projection of a reorder, mirroring the server: the listed\n * queued turns get positions 1..n in the given order; everything else keeps\n * its position.\n */\nexport function applyTurnReorder(turns: SessionTurn[], turnIds: string[]): SessionTurn[] {\n const positions = new Map(turnIds.map((turnId, index) => [turnId, index + 1] as const));\n return turns.map((turn) => {\n const position = positions.get(turn.id);\n return position !== undefined && turn.status === \"queued\" ? { ...turn, position } : turn;\n });\n}\n\n/** Optimistic projection of a queued-turn delete (server marks it cancelled). */\nexport function applyTurnRemoval(turns: SessionTurn[], turnId: string): SessionTurn[] {\n return turns.map((turn) => (turn.id === turnId && turn.status === \"queued\" ? { ...turn, status: \"cancelled\" as const } : turn));\n}\n\nexport type UseTurnQueueOptions = ClientOverride & SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default — turn.* events drive updates. */\n pollIntervalMs?: number | undefined;\n};\n\nexport type UseTurnQueueResult = {\n /** All turns the API returned (history + queue), newest server view. */\n turns: SessionTurn[];\n /** Queued turns in execution order — render this as the editable queue. */\n queue: SessionTurn[];\n /** The running / requires_action turn, if any. */\n activeTurn: SessionTurn | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Edit a queued turn (optimistic; rolls back via refetch on failure). */\n editTurn: (turnId: string, update: UpdateSessionTurnRequest) => Promise<SessionTurn | null>;\n /** Reorder the queue to the given queued-turn id order (optimistic). */\n reorderTurns: (turnIds: string[]) => Promise<SessionTurn[] | null>;\n /** Delete (cancel) a queued turn before it is claimed (optimistic). */\n removeTurn: (turnId: string) => Promise<SessionTurn | null>;\n /** True while an edit/reorder/remove is in flight. */\n mutating: boolean;\n /** Last failed mutation, until the next mutation or clear. */\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The live turn queue — the heart of the queue-by-default interaction model.\n * Messages sent mid-turn stack up here, visible and editable/reorderable/\n * deletable until the worker claims them. Updates arrive over the session\n * event stream (`turn.*`), either shared via `options.events` (pass the log\n * from `useSessionEvents` to reuse its connection) or a dedicated tail\n * stream. All mutations apply optimistically and reconcile with the server.\n */\nexport function useTurnQueue(sessionId: string | null | undefined, options: UseTurnQueueOptions = {}): UseTurnQueueResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const [turns, setTurns] = useState<SessionTurn[]>([]);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const mutation = useMutationRunner();\n const generation = useRef(0);\n const targetKeyRef = useRef<string | null>(null);\n\n const load = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n const ticket = ++generation.current;\n try {\n const fetched = await client.listTurns(workspaceId, sessionId);\n if (ticket === generation.current) {\n setTurns(fetched);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (ticket === generation.current) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setLoading(false);\n }\n }\n }, [client, workspaceId, sessionId]);\n\n // Reset when the target session changes; initial load + optional polling.\n useEffect(() => {\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n setTurns([]);\n setError(null);\n }\n if (!enabled) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void load();\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n };\n }\n const timer = setInterval(() => void load(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n };\n }, [load, enabled, workspaceId, sessionId, options.pollIntervalMs]);\n\n // Live updates: any turn.* event re-syncs the queue (debounced).\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(client, workspaceId, sessionId, isTurnQueueEvent, scheduleRefresh, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n const editTurn = useCallback(\n async (turnId: string, update: UpdateSessionTurnRequest): Promise<SessionTurn | null> => {\n if (!sessionId) {\n return null;\n }\n setTurns((current) => applyTurnEdit(current, turnId, update));\n const result = await mutation.run(() => client.updateQueuedTurn(workspaceId, sessionId, turnId, update));\n if (result) {\n setTurns((current) => current.map((turn) => (turn.id === result.id ? result : turn)));\n } else {\n void load();\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run, load],\n );\n\n const reorderTurns = useCallback(\n async (turnIds: string[]): Promise<SessionTurn[] | null> => {\n if (!sessionId || turnIds.length === 0) {\n return null;\n }\n setTurns((current) => applyTurnReorder(current, turnIds));\n const result = await mutation.run(() => client.reorderQueuedTurns(workspaceId, sessionId, turnIds));\n if (result) {\n // The server returns the queued turns; merge them over local state.\n setTurns((current) => {\n const bySId = new Map(result.map((turn) => [turn.id, turn] as const));\n return current.map((turn) => bySId.get(turn.id) ?? turn);\n });\n } else {\n void load();\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run, load],\n );\n\n const removeTurn = useCallback(\n async (turnId: string): Promise<SessionTurn | null> => {\n if (!sessionId) {\n return null;\n }\n setTurns((current) => applyTurnRemoval(current, turnId));\n const result = await mutation.run(() => client.deleteQueuedTurn(workspaceId, sessionId, turnId));\n if (result) {\n setTurns((current) => current.map((turn) => (turn.id === result.id ? result : turn)));\n } else {\n void load();\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run, load],\n );\n\n return {\n turns,\n queue: queueFromTurns(turns),\n activeTurn: activeTurnFromTurns(turns),\n loading,\n error,\n refresh: load,\n editTurn,\n reorderTurns,\n removeTurn,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import { OpenGeniApiError, type SessionEvent, type SessionGoal } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useDebouncedCallback, useMutationRunner, useSessionEventTrigger, type SessionEventFeedOptions } 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\nexport type UseGoalOptions = ClientOverride & SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default — goal.* events 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 /** True while a pause/resume 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.*` events —\n * pass `options.events` from `useSessionEvents` to reuse its stream.\n */\nexport function useGoal(sessionId: string | null | undefined, options: UseGoalOptions = {}): UseGoalResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const [goal, setGoal] = useState<SessionGoal | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const mutation = useMutationRunner();\n const generation = useRef(0);\n const targetKeyRef = useRef<string | null>(null);\n\n const load = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n const ticket = ++generation.current;\n try {\n const fetched = await client.getGoal(workspaceId, sessionId);\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 }\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) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void load();\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n };\n }\n const timer = setInterval(() => void load(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n };\n }, [load, enabled, workspaceId, sessionId, options.pollIntervalMs]);\n\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(client, workspaceId, sessionId, isGoalEvent, scheduleRefresh, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n const pause = useCallback(\n async (rationale?: string): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await mutation.run(() =>\n client.updateGoal(workspaceId, sessionId, {\n status: \"paused\",\n ...(rationale !== undefined ? { rationale } : {}),\n }));\n if (result) {\n setGoal(result);\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run],\n );\n\n const resume = useCallback(async (): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await mutation.run(() => client.updateGoal(workspaceId, sessionId, { status: \"active\" }));\n if (result) {\n setGoal(result);\n }\n return result;\n }, [client, workspaceId, sessionId, mutation.run]);\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 updating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner } from \"./internal\";\n\nexport type UseSessionControlOptions = ClientOverride;\n\nexport type UseSessionControlResult = {\n /** Interrupt the running turn (the explicit alternative to queueing). */\n interrupt: (reason?: string) => Promise<SessionEvent | null>;\n interrupting: 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 control events: interrupt 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 } = useOpenGeni(options);\n const interruptMutation = useMutationRunner();\n const approvalMutation = useMutationRunner();\n\n const interrupt = useCallback(\n async (reason?: string): Promise<SessionEvent | null> => {\n if (!sessionId) {\n return null;\n }\n return await interruptMutation.run(() =>\n client.interrupt(workspaceId, sessionId, reason !== undefined ? { reason } : {}));\n },\n [client, workspaceId, sessionId, interruptMutation.run],\n );\n\n const decide = useCallback(\n async (approvalId: string, decision: \"approve\" | \"reject\", message?: string): Promise<SessionEvent | null> => {\n if (!sessionId) {\n return null;\n }\n return await approvalMutation.run(() =>\n client.sendApprovalDecision(workspaceId, sessionId, {\n approvalId,\n decision,\n ...(message !== undefined ? { message } : {}),\n }));\n },\n [client, workspaceId, sessionId, approvalMutation.run],\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 = approvalMutation.mutationError ?? interruptMutation.mutationError;\n const clearError = useCallback(() => {\n interruptMutation.clearMutationError();\n approvalMutation.clearMutationError();\n }, [interruptMutation.clearMutationError, approvalMutation.clearMutationError]);\n\n return {\n interrupt,\n interrupting: interruptMutation.mutating,\n approve,\n reject,\n responding: approvalMutation.mutating,\n error,\n clearError,\n };\n}\n","import type { ScheduledTask } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseScheduledTasksOptions = ClientOverride & {\n limit?: number | undefined;\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseScheduledTasksResult = {\n tasks: ScheduledTask[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** List the workspace's scheduled tasks (drift checks, sentinels, reapers, ...). */\nexport function useScheduledTasks(options: UseScheduledTasksOptions = {}): UseScheduledTasksResult {\n const { client, workspaceId } = useOpenGeni(options);\n const limit = options.limit;\n const load = useCallback(\n async () => await client.listScheduledTasks(workspaceId, limit !== undefined ? { limit } : {}),\n [client, workspaceId, limit],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return { tasks: state.data ?? [], loading: state.loading, error: state.error, refresh: state.refresh };\n}\n","import type { Session } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseWorkspaceSessionsOptions = ClientOverride & {\n limit?: number | undefined;\n /** Refresh interval (ms) for fleet/manager views. Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseWorkspaceSessionsResult = {\n sessions: Session[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** List the workspace's sessions — the data behind fleet and manager views. */\nexport function useWorkspaceSessions(options: UseWorkspaceSessionsOptions = {}): UseWorkspaceSessionsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const limit = options.limit;\n const load = useCallback(\n async () => await client.listSessions(workspaceId, limit !== undefined ? { limit } : {}),\n [client, workspaceId, limit],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return { sessions: state.data ?? [], loading: state.loading, error: state.error, refresh: state.refresh };\n}\n","import type {\n CreateWorkspaceEnvironmentRequest,\n UpdateWorkspaceEnvironmentRequest,\n WorkspaceEnvironment,\n WorkspaceEnvironmentVariableMetadata,\n} from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UseEnvironmentsOptions = ClientOverride & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseEnvironmentsResult = {\n environments: WorkspaceEnvironment[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (request: CreateWorkspaceEnvironmentRequest) => Promise<WorkspaceEnvironment | null>;\n update: (environmentId: string, request: UpdateWorkspaceEnvironmentRequest) => Promise<WorkspaceEnvironment | null>;\n remove: (environmentId: string) => Promise<boolean>;\n /** Set/rotate a variable. Values are write-only — reads expose metadata only. */\n setVariable: (environmentId: string, name: string, value: string) => Promise<WorkspaceEnvironmentVariableMetadata | null>;\n deleteVariable: (environmentId: string, name: string) => Promise<boolean>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Workspace environments (named, encrypted variable sets attached to sessions\n * and scheduled tasks). Variable values are write-only end to end: this hook\n * never sees a value after it is sent.\n */\nexport function useEnvironments(options: UseEnvironmentsOptions = {}): UseEnvironmentsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const load = useCallback(async () => await client.listEnvironments(workspaceId), [client, workspaceId]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n const mutation = useMutationRunner();\n\n const create = useCallback(\n async (request: CreateWorkspaceEnvironmentRequest): Promise<WorkspaceEnvironment | null> => {\n const result = await mutation.run(() => client.createEnvironment(workspaceId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const update = useCallback(\n async (environmentId: string, request: UpdateWorkspaceEnvironmentRequest): Promise<WorkspaceEnvironment | null> => {\n const result = await mutation.run(() => client.updateEnvironment(workspaceId, environmentId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const remove = useCallback(\n async (environmentId: string): Promise<boolean> => {\n const result = await mutation.run(async () => {\n await client.deleteEnvironment(workspaceId, environmentId);\n return true;\n });\n if (result) {\n await state.refresh();\n }\n return result === true;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const setVariable = useCallback(\n async (environmentId: string, name: string, value: string): Promise<WorkspaceEnvironmentVariableMetadata | null> => {\n const result = await mutation.run(() => client.setEnvironmentVariable(workspaceId, environmentId, name, value));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const deleteVariable = useCallback(\n async (environmentId: string, name: string): Promise<boolean> => {\n const result = await mutation.run(async () => {\n await client.deleteEnvironmentVariable(workspaceId, environmentId, name);\n return true;\n });\n if (result) {\n await state.refresh();\n }\n return result === true;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n return {\n environments: state.data ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n create,\n update,\n remove,\n setVariable,\n deleteVariable,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type {\n CapabilityPack,\n EnablePackRequest,\n PackInstallation,\n RegisterCapabilityPackRequest,\n WorkspaceRegisteredPack,\n} from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UsePacksOptions = ClientOverride & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UsePacksResult = {\n /** Built-in + registered packs available to the workspace. */\n packs: CapabilityPack[];\n /** Enable/disable state per pack. */\n installations: PackInstallation[];\n /** The installation for a pack id, if any. */\n installationFor: (packId: string) => PackInstallation | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Register (or replace) a workspace-scoped pack manifest. */\n register: (manifest: RegisterCapabilityPackRequest) => Promise<WorkspaceRegisteredPack | null>;\n enable: (packId: string, request?: EnablePackRequest) => Promise<PackInstallation | null>;\n /** Unregister a workspace-scoped pack (built-ins cannot be removed). */\n remove: (packId: string) => Promise<boolean>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/** Capability packs: catalog + installations + register/enable/unregister. */\nexport function usePacks(options: UsePacksOptions = {}): UsePacksResult {\n const { client, workspaceId } = useOpenGeni(options);\n const load = useCallback(async () => await client.listPacks(workspaceId), [client, workspaceId]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n const mutation = useMutationRunner();\n\n const register = useCallback(\n async (manifest: RegisterCapabilityPackRequest): Promise<WorkspaceRegisteredPack | null> => {\n const result = await mutation.run(() => client.registerPack(workspaceId, manifest));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const enable = useCallback(\n async (packId: string, request: EnablePackRequest = {}): Promise<PackInstallation | null> => {\n const result = await mutation.run(() => client.enablePack(workspaceId, packId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const remove = useCallback(\n async (packId: string): Promise<boolean> => {\n const result = await mutation.run(async () => {\n await client.deletePack(workspaceId, packId);\n return true;\n });\n if (result) {\n await state.refresh();\n }\n return result === true;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const installations = state.data?.installations ?? [];\n const installationFor = useCallback(\n (packId: string): PackInstallation | null =>\n installations.find((installation) => installation.packId === packId) ?? null,\n [installations],\n );\n\n return {\n packs: state.data?.packs ?? [],\n installations,\n installationFor,\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n register,\n enable,\n remove,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { CreateWorkspaceRequest, UpdateWorkspaceRequest, Workspace } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UseWorkspacesOptions = Pick<ClientOverride, \"client\"> & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseWorkspacesResult = {\n workspaces: Workspace[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (request: CreateWorkspaceRequest) => Promise<Workspace | null>;\n update: (workspaceId: string, request: UpdateWorkspaceRequest) => Promise<Workspace | null>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The caller's workspaces (workspace switchers, onboarding). Not scoped to\n * the provider's workspace, so it only needs the client.\n */\nexport function useWorkspaces(options: UseWorkspacesOptions = {}): UseWorkspacesResult {\n const client = useOpenGeniClient(options);\n const load = useCallback(async () => await client.listWorkspaces(), [client]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n const mutation = useMutationRunner();\n\n const create = useCallback(\n async (request: CreateWorkspaceRequest): Promise<Workspace | null> => {\n const result = await mutation.run(() => client.createWorkspace(request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, mutation.run, state.refresh],\n );\n\n const update = useCallback(\n async (workspaceId: string, request: UpdateWorkspaceRequest): Promise<Workspace | null> => {\n const result = await mutation.run(() => client.updateWorkspace(workspaceId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, mutation.run, state.refresh],\n );\n\n return {\n workspaces: state.data ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n create,\n update,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { BillingBalance, UsageEvent } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseBillingUsageOptions = Pick<ClientOverride, \"client\"> & {\n /** Account to read. Defaults to the caller's default account server-side. */\n accountId?: string | undefined;\n /** Filter usage to one workspace. */\n workspaceId?: string | undefined;\n /** Refresh interval (ms) for live billing meters. Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseBillingUsageResult = {\n /** Prepaid credit balance (micro-USD), null until loaded. */\n balance: BillingBalance | null;\n /** Recent usage events (runs, tokens, cost, uploads, ...). */\n usage: UsageEvent[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Account billing usage: credit balance + recent usage events — the data\n * behind per-call billing meters. Account-scoped, so it only needs the\n * client; pass `workspaceId` to narrow usage to one workspace.\n */\nexport function useBillingUsage(options: UseBillingUsageOptions = {}): UseBillingUsageResult {\n const client = useOpenGeniClient(options);\n const accountId = options.accountId;\n const workspaceId = options.workspaceId;\n const load = useCallback(\n async () =>\n await client.getBillingUsage({\n ...(accountId !== undefined ? { accountId } : {}),\n ...(workspaceId !== undefined ? { workspaceId } : {}),\n }),\n [client, accountId, workspaceId],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return {\n balance: state.data?.balance ?? null,\n usage: state.data?.usage ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.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 = payload && typeof payload === \"object\" ? (payload as { approvals?: unknown }).approvals : 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<string, unknown>;\n const rawItem = raw.rawItem && typeof raw.rawItem === \"object\" ? raw.rawItem as Record<string, unknown> : {};\n return {\n id: String(raw.id ?? raw.callId ?? rawItem.callId ?? index),\n name: String(raw.name ?? \"approval\"),\n arguments: raw.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 = event.payload && typeof event.payload === \"object\" ? event.payload as { approvalId?: unknown } : {};\n if (typeof payload.approvalId === \"string\") {\n pending = pending.filter((approval) => approval.id !== payload.approvalId);\n }\n break;\n }\n case \"turn.completed\":\n case \"turn.failed\":\n case \"turn.cancelled\": {\n // Scope clearing to the turn that raised the approvals when both\n // sides carry a turn id; clear conservatively when either is unknown.\n if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {\n pending = [];\n owningTurnId = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return pending;\n}\n","import type { Permission } from \"@opengeni/sdk\";\nimport type { CommandContext, SlashArg, SlashCommand } from \"./types\";\n\n/**\n * Parse a composer value into a command name + the rest. A command is\n * recognized ONLY when the value's first character is \"/\" (the start token);\n * anything else is plain chat and returns null.\n *\n * \"/cl\" -> { name: \"cl\", rest: \"\", hasTrailingSpace: false }\n * \"/goal \" -> { name: \"goal\", rest: \"\", hasTrailingSpace: true }\n * \"/goal pause\"-> { name: \"goal\", rest: \"pause\", hasTrailingSpace: false }\n */\nexport type ParsedCommandLine = {\n name: string;\n rest: string;\n /** True when the name token is closed by a space — arg-hint mode. */\n hasTrailingSpace: boolean;\n args: string[];\n};\n\nexport function parseCommandLine(value: string): ParsedCommandLine | null {\n if (value[0] !== \"/\") {\n return null;\n }\n const body = value.slice(1);\n const firstSpace = body.indexOf(\" \");\n if (firstSpace === -1) {\n return { name: body, rest: \"\", hasTrailingSpace: false, args: [] };\n }\n const name = body.slice(0, firstSpace);\n const rest = body.slice(firstSpace + 1);\n return {\n name,\n rest,\n hasTrailingSpace: true,\n args: rest.split(/\\s+/).filter((token) => token.length > 0),\n };\n}\n\nconst PERMISSION_SUPERUSER: Permission = \"workspace:admin\";\n\n/** Whether the operator's permission set satisfies a command's gate. */\nexport function hasPermission(required: Permission | undefined, permissions: Permission[]): boolean {\n if (!required) {\n return true;\n }\n return permissions.includes(required) || permissions.includes(PERMISSION_SUPERUSER);\n}\n\n/** Match a command (by name or alias) against the value. */\nexport function matchCommand(commands: readonly SlashCommand[], value: string): SlashCommand | null {\n const parsed = parseCommandLine(value);\n if (!parsed) {\n return null;\n }\n const token = parsed.name.toLowerCase();\n return commands.find((command) => command.name === token || command.aliases?.includes(token)) ?? null;\n}\n\ntype FilterCtx = Pick<CommandContext, \"sessionId\" | \"status\" | \"permissions\">;\n\n/**\n * The commands visible for the current token + context. Permission-absent and\n * `available()===false` commands are dropped entirely (a gated command is never\n * shown, not shown-disabled). Filtering is a prefix match on name/alias.\n */\nexport function filterCommands(commands: readonly SlashCommand[], token: string, ctx: FilterCtx): SlashCommand[] {\n const needle = token.toLowerCase();\n return commands.filter((command) => {\n if (!hasPermission(command.permission, ctx.permissions)) {\n return false;\n }\n if (command.available && !command.available(ctx)) {\n return false;\n }\n if (needle.length === 0) {\n return true;\n }\n return command.name.startsWith(needle) || (command.aliases?.some((alias) => alias.startsWith(needle)) ?? false);\n });\n}\n\n/** Render a command's arg hint for the palette footer / help, e.g. \"<pause|resume>\". */\nexport function argHint(args: readonly SlashArg[] | undefined): string {\n if (!args || args.length === 0) {\n return \"\";\n }\n return args\n .map((arg) => {\n const label = arg.oneOf ? arg.oneOf.join(\"|\") : arg.name;\n return arg.required ? `<${label}>` : `[${label}]`;\n })\n .join(\" \");\n}\n\n/** The first required arg that has not yet been supplied, if any. */\nexport function firstMissingRequiredArg(command: SlashCommand, args: string[]): SlashArg | null {\n const required = (command.args ?? []).filter((arg) => arg.required);\n for (let i = 0; i < required.length; i += 1) {\n const value = args[i];\n if (value === undefined || value.length === 0) {\n return required[i] ?? null;\n }\n }\n return null;\n}\n\nfunction requireSession(ctx: CommandContext): string {\n if (!ctx.sessionId) {\n throw new Error(\"No active session yet — start a session first.\");\n }\n return ctx.sessionId;\n}\n\nconst hasSession = (ctx: FilterCtx): boolean => ctx.sessionId !== null;\n\n/**\n * The default command set. Adding a command is one object literal here; the\n * palette list, filter, arg-hint footer, and /help all render from this array.\n * Apps concat their own commands via the ChatComposer `commands` prop.\n */\nexport const defaultCommands: readonly SlashCommand[] = [\n {\n name: \"help\",\n aliases: [\"?\"],\n description: \"Show available commands.\",\n run: (_args, ctx) => {\n ctx.openHelp();\n return { status: \"ok\" };\n },\n },\n {\n name: \"clear-view\",\n description: \"Clear the local timeline view (this device only; no server change).\",\n run: (_args, ctx) => {\n // clearView() reports whether the host actually wired a view-reset. If it\n // didn't (the console surface has no resettable local timeline), reporting\n // \"Local view cleared.\" would be a false success — return an honest error\n // instead so the operator isn't told something happened when nothing did.\n const cleared = ctx.clearView();\n if (!cleared) {\n return { status: \"error\", message: \"This view can't be cleared here (no local timeline to reset).\" };\n }\n return { status: \"ok\", message: \"Local view cleared.\" };\n },\n },\n {\n name: \"goal\",\n description: \"Pause or resume the session's goal loop.\",\n permission: \"sessions:control\",\n available: hasSession,\n args: [{ name: \"action\", required: true, oneOf: [\"pause\", \"resume\"], description: \"pause | resume\" }],\n run: async (args, ctx) => {\n const sessionId = requireSession(ctx);\n const action = args[0];\n if (action !== \"pause\" && action !== \"resume\") {\n return { status: \"error\", message: \"Usage: /goal pause | /goal resume\" };\n }\n try {\n await ctx.client.updateGoal(ctx.workspaceId, sessionId, { status: action === \"pause\" ? \"paused\" : \"active\" });\n return { status: \"ok\", message: action === \"pause\" ? \"Goal paused.\" : \"Goal resumed.\" };\n } catch (cause) {\n return { status: \"error\", message: goalErrorMessage(cause, action) };\n }\n },\n },\n {\n name: \"compact\",\n description: \"Compact the conversation context now.\",\n permission: \"sessions:control\",\n available: hasSession,\n run: async (_args, ctx) => {\n const sessionId = requireSession(ctx);\n try {\n const result = await ctx.client.compactSessionContext(ctx.workspaceId, sessionId);\n return { status: \"ok\", message: result.message };\n } catch (cause) {\n return { status: \"error\", message: errorMessage(cause) ?? \"Could not compact context.\" };\n }\n },\n },\n {\n name: \"clear\",\n description: \"Clear the conversation context (destructive; audit-preserved).\",\n permission: \"sessions:control\",\n danger: true,\n available: hasSession,\n run: async (_args, ctx) => {\n const sessionId = requireSession(ctx);\n const confirmed = await ctx.confirm();\n if (!confirmed) {\n // Canceled: no error, but keep the \"/clear\" draft so the operator who\n // backed out doesn't silently lose what they typed.\n return { status: \"ok\", keepDraft: true };\n }\n try {\n await ctx.client.clearSessionContext(ctx.workspaceId, sessionId);\n return { status: \"ok\", message: \"Context cleared.\" };\n } catch (cause) {\n return { status: \"error\", message: clearErrorMessage(cause) };\n }\n },\n },\n];\n\nfunction errorMessage(cause: unknown): string | undefined {\n if (cause && typeof cause === \"object\" && \"message\" in cause && typeof (cause as { message?: unknown }).message === \"string\") {\n return (cause as { message: string }).message;\n }\n return undefined;\n}\n\nfunction statusCode(cause: unknown): number | undefined {\n if (cause && typeof cause === \"object\" && \"status\" in cause && typeof (cause as { status?: unknown }).status === \"number\") {\n return (cause as { status: number }).status;\n }\n return undefined;\n}\n\nfunction goalErrorMessage(cause: unknown, action: \"pause\" | \"resume\"): string {\n const code = statusCode(cause);\n if (code === 404) {\n return \"This session has no goal to control.\";\n }\n if (code === 409) {\n return action === \"resume\" ? \"Only a paused goal can be resumed.\" : \"Goal is already in a terminal state.\";\n }\n return errorMessage(cause) ?? `Could not ${action} the goal.`;\n}\n\nfunction clearErrorMessage(cause: unknown): string {\n if (statusCode(cause) === 409) {\n return \"Can't clear context mid-turn — stop the current turn first.\";\n }\n return errorMessage(cause) ?? \"Could not clear context.\";\n}\n","import type { KeyboardEvent } from \"react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport {\n argHint,\n filterCommands,\n firstMissingRequiredArg,\n matchCommand,\n parseCommandLine,\n} from \"../commands/registry\";\nimport type { CommandContext, Notice, SlashCommand } from \"../commands/types\";\n\n/**\n * Context the composer supplies for command execution and visibility. The\n * composer owns the UI affordances (notice/openHelp/clearView/confirm), so they\n * are NOT part of this slice — the hook closes over them via `handlers`.\n */\nexport type SlashCommandContext = Pick<\n CommandContext,\n \"client\" | \"workspaceId\" | \"sessionId\" | \"status\" | \"permissions\"\n>;\n\n/**\n * UI affordances the composer supplies. `confirm` differs from the registry-\n * facing {@link CommandContext.confirm} (which takes no args): the composer's\n * confirm receives the command being run so the confirm bar renders from that\n * exact command's identity. The hook bridges the two in {@link buildContext}.\n */\nexport type SlashCommandHandlers = Pick<CommandContext, \"notice\" | \"openHelp\" | \"clearView\"> & {\n confirm: (command: SlashCommand) => Promise<boolean>;\n};\n\nexport type ConfirmState = {\n command: SlashCommand;\n /** Resolve the pending confirm() promise. */\n resolve: (confirmed: boolean) => void;\n} | null;\n\nexport type UseSlashCommandsOptions = {\n commands: readonly SlashCommand[];\n context: SlashCommandContext | undefined;\n handlers: SlashCommandHandlers;\n /** The current composer draft. */\n value: string;\n /** Replace the composer draft (autocomplete writes through this). */\n setValue: (value: string) => void;\n};\n\nexport type UseSlashCommandsResult = {\n /** Whether the palette is open (a command token is being typed). */\n open: boolean;\n /**\n * Whether the draft is a slash-command attempt (matches a registered command)\n * — true even after Escape dismisses the popover. The composer blocks its send\n * path while this holds so a command can't be delivered to the agent as chat.\n */\n isCommandDraft: boolean;\n /** Commands shown for the current token + context, in display order. */\n items: SlashCommand[];\n /** Index into `items` of the highlighted row. */\n highlight: number;\n setHighlight: (index: number) => void;\n /** The matched command once the name is closed by a space (arg-hint mode). */\n activeCommand: SlashCommand | null;\n /** The arg hint string for the active command (footer), or \"\". */\n activeArgHint: string;\n /**\n * Key handler for the textarea. Returns true when it consumed the event\n * (the composer must then NOT run its send path). Only consumes while open.\n */\n onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => boolean;\n /** Run the highlighted command (or the active command in arg-hint mode). */\n runHighlighted: () => Promise<void>;\n /**\n * Run the command at an explicitly chosen index (a pointer click on a row).\n * Bypasses the exact-match token heuristic that runHighlighted uses for\n * keyboard Enter, so an explicit click always runs the clicked command.\n */\n runAt: (index: number) => Promise<void>;\n /** Autocomplete the highlighted command name + a trailing space. */\n autocompleteHighlighted: () => void;\n};\n\nexport function useSlashCommands(options: UseSlashCommandsOptions): UseSlashCommandsResult {\n const { commands, context, handlers, value, setValue } = options;\n const [highlight, setHighlight] = useState(0);\n // Escape closes the palette but keeps the draft. We remember the dismissed\n // value; any further edit (value !== dismissed) re-opens the palette.\n const [dismissedValue, setDismissedValue] = useState<string | null>(null);\n const dismissed = dismissedValue !== null && dismissedValue === value;\n\n // Whether the operator has explicitly arrow-navigated the highlight for the\n // CURRENT draft. When they have, Enter is an explicit choice of the\n // highlighted row — the exact-match token override must NOT hijack it (else\n // ArrowDown to /clear-view + Enter would still fire the destructive /clear,\n // since \"clear\" exact-matches the token). Reset whenever the draft changes.\n const navigatedRef = useRef(false);\n const navTokenRef = useRef(value);\n if (navTokenRef.current !== value) {\n navTokenRef.current = value;\n navigatedRef.current = false;\n }\n\n const parsed = useMemo(() => parseCommandLine(value), [value]);\n const filterCtx = useMemo(\n () => ({\n sessionId: context?.sessionId ?? null,\n status: context?.status ?? null,\n permissions: context?.permissions ?? [],\n }),\n [context?.sessionId, context?.status, context?.permissions],\n );\n\n // In arg-hint mode (\"/name \"), the list collapses to the matched command so\n // the palette shows just its arg hint; while typing the name it filters.\n const activeCommand = useMemo(() => {\n if (!parsed || !parsed.hasTrailingSpace) {\n return null;\n }\n return matchCommand(commands, value);\n }, [commands, value, parsed]);\n\n const items = useMemo(() => {\n if (!parsed) {\n return [];\n }\n if (activeCommand) {\n return [activeCommand];\n }\n return filterCommands(commands, parsed.name, filterCtx);\n }, [commands, parsed, activeCommand, filterCtx]);\n\n const open = parsed !== null && items.length > 0 && !dismissed;\n\n // Whether the current draft is a slash-command ATTEMPT that should be run via\n // the palette, never delivered to the agent as plain chat. True even when the\n // palette is dismissed (Escape) — the draft still starts with \"/\" and matches\n // a command, so the composer must block its send path (button + Enter) to keep\n // commands from leaking into the conversation as messages the model reads.\n const isCommandDraft = parsed !== null && items.length > 0;\n\n // Keep highlight in range as items change.\n const clampedHighlight = items.length === 0 ? 0 : Math.min(highlight, items.length - 1);\n\n const activeArgHint = activeCommand ? argHint(activeCommand.args) : \"\";\n\n // Build the context for a SPECIFIC command. The danger confirm() is bound to\n // that command so the confirm bar names the command actually about to run —\n // not whatever near-match happens to sit highlighted in the palette (e.g.\n // typing \"/clear\"+Enter runs the destructive `clear`, but `clear-view` sorts\n // first and would otherwise mislabel the bar as a harmless local-view reset).\n const buildContext = useCallback(\n (command: SlashCommand): CommandContext | null => {\n if (!context) {\n return null;\n }\n return { ...context, ...handlers, confirm: () => handlers.confirm(command) };\n },\n [context, handlers],\n );\n\n const execute = useCallback(\n async (command: SlashCommand, args: string[]): Promise<void> => {\n const ctx = buildContext(command);\n if (!ctx) {\n return;\n }\n try {\n const result = await command.run(args, ctx);\n if (result.message) {\n ctx.notice({ tone: result.status === \"ok\" ? \"ok\" : \"error\", message: result.message });\n }\n if (result.status === \"ok\" && !result.keepDraft) {\n setValue(\"\");\n }\n } catch (cause) {\n ctx.notice({ tone: \"error\", message: errorMessage(cause) });\n }\n },\n [buildContext, setValue],\n );\n\n const autocomplete = useCallback(\n (command: SlashCommand) => {\n setValue(`/${command.name} `);\n setHighlight(0);\n },\n [setValue],\n );\n\n const autocompleteHighlighted = useCallback(() => {\n const command = items[clampedHighlight];\n if (command) {\n autocomplete(command);\n }\n }, [items, clampedHighlight, autocomplete]);\n\n // Resolve a SPECIFIC, already-chosen command against the current draft, then\n // either autocomplete (name-only / required arg missing) or execute. This is\n // the shared core for both Enter (which first resolves WHICH command via the\n // exact-match heuristic) and a pointer click (which has ALREADY chosen the\n // command — the clicked row — and must not re-resolve to a near-match).\n const runResolved = useCallback(\n async (command: SlashCommand, options?: { explicit?: boolean }): Promise<void> => {\n if (!parsed) {\n return;\n }\n const explicit = options?.explicit ?? false;\n // Token-vs-command equality is case-insensitive (matching the registry's\n // matchCommand/filterCommands), so a fully-typed \"/Clear\" counts as having\n // named `clear` and runs rather than autocompleting.\n const nameMatchesToken =\n command.name === parsed.name.toLowerCase() ||\n (command.aliases?.includes(parsed.name.toLowerCase()) ?? false);\n // A name-only token whose name doesn't yet equal the resolved command (e.g.\n // \"/cl\" -> clear) first autocompletes so the operator sees the full name.\n // An EXPLICIT pointer click skips this: the operator already chose the row,\n // so clicking \"/clear-view\" (while the token is \"clear\") runs it outright\n // rather than merely filling the name and waiting for a second Enter.\n if (!explicit && !activeCommand && !nameMatchesToken && !parsed.hasTrailingSpace) {\n autocomplete(command);\n return;\n }\n // When the click resolves a different command than the typed token, the\n // typed token's tail isn't this command's args — run with no positional\n // args and let the required-arg guard below prompt for them via autocomplete.\n const args = nameMatchesToken || parsed.hasTrailingSpace ? parsed.args : [];\n const missing = firstMissingRequiredArg(command, args);\n if (missing) {\n // A required arg is absent: keep the palette open at the arg hint rather\n // than firing a half-formed command.\n if (!parsed.hasTrailingSpace) {\n autocomplete(command);\n }\n return;\n }\n await execute(command, args);\n },\n [parsed, activeCommand, autocomplete, execute],\n );\n\n const runHighlighted = useCallback(async (): Promise<void> => {\n if (!parsed) {\n return;\n }\n // If the operator has arrow-navigated, Enter is an explicit choice of the\n // highlighted row — run it directly, exactly like a click. This makes\n // /clear-view reachable via ArrowDown+Enter even when \"/clear\" is fully\n // typed (otherwise the exact-match override below would hijack it).\n if (navigatedRef.current && !activeCommand) {\n const highlighted = items[clampedHighlight];\n if (highlighted) {\n await runResolved(highlighted, { explicit: true });\n }\n return;\n }\n // Otherwise (no explicit navigation): when the typed token is an exact\n // command name (e.g. \"/clear\" while the longer \"/clear-view\" sits first in\n // the filtered list), Enter should run THAT command, not autocomplete the\n // highlighted near-match. Exact match wins over the highlight; otherwise use\n // the highlighted row. A pointer click goes through runAt, never here.\n // Compare case-insensitively, matching filterCommands/matchCommand, so a\n // fully-typed \"/Clear\" still resolves to the exact (destructive) clear\n // rather than the highlighted prefix near-match.\n const token = parsed.name.toLowerCase();\n const exact = items.find((item) => item.name === token || item.aliases?.includes(token));\n const command = activeCommand ?? exact ?? items[clampedHighlight];\n if (!command) {\n return;\n }\n await runResolved(command);\n }, [parsed, activeCommand, items, clampedHighlight, runResolved]);\n\n // Run the command at an EXPLICITLY chosen index (a pointer click on a palette\n // row). Unlike runHighlighted this does NOT apply the exact-match override:\n // clicking the harmless `/clear-view` row while the draft is \"/clear\" must run\n // clear-view, never the destructive `/clear` that exact-matches the token. The\n // operator's pointer is the selection; token-resolution heuristics don't apply.\n const runAt = useCallback(\n async (index: number): Promise<void> => {\n const command = items[index];\n if (!command) {\n return;\n }\n await runResolved(command, { explicit: true });\n },\n [items, runResolved],\n );\n\n // Track an in-flight run so Enter can't double-fire.\n const runningRef = useRef(false);\n\n const onKeyDown = useCallback(\n (event: KeyboardEvent<HTMLTextAreaElement>): boolean => {\n if (!open) {\n return false;\n }\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n navigatedRef.current = true;\n setHighlight((current) => (items.length === 0 ? 0 : (Math.min(current, items.length - 1) + 1) % items.length));\n return true;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n navigatedRef.current = true;\n setHighlight((current) => {\n const base = Math.min(current, items.length - 1);\n return items.length === 0 ? 0 : (base - 1 + items.length) % items.length;\n });\n return true;\n }\n case \"Tab\": {\n event.preventDefault();\n autocompleteHighlighted();\n return true;\n }\n case \"Enter\": {\n if (event.shiftKey || event.nativeEvent?.isComposing) {\n return false;\n }\n event.preventDefault();\n if (runningRef.current) {\n return true;\n }\n runningRef.current = true;\n void runHighlighted().finally(() => {\n runningRef.current = false;\n });\n return true;\n }\n case \"Escape\": {\n event.preventDefault();\n // Close the palette but keep the draft intact. Remember the dismissed\n // value; the next edit re-opens (value !== dismissedValue).\n setDismissedValue(value);\n return true;\n }\n default:\n return false;\n }\n },\n [open, items, autocompleteHighlighted, runHighlighted, value],\n );\n\n return {\n open,\n isCommandDraft,\n items,\n highlight: clampedHighlight,\n setHighlight,\n activeCommand,\n activeArgHint,\n onKeyDown,\n runHighlighted,\n runAt,\n autocompleteHighlighted,\n };\n}\n\nfunction errorMessage(cause: unknown): string {\n if (cause instanceof Error) {\n return cause.message;\n }\n return String(cause);\n}\n","import { AnimatePresence, motion } from \"motion/react\";\nimport { argHint } from \"../commands/registry\";\nimport type { SlashCommand } from \"../commands/types\";\nimport { cn } from \"../lib/cn\";\n\nexport type CommandPaletteProps = {\n open: boolean;\n items: SlashCommand[];\n highlight: number;\n /** Hover/click selects a row. */\n onHighlight: (index: number) => void;\n /** Click runs the row (same path as Enter). */\n onRun: (index: number) => void;\n /** Footer arg hint shown in arg-hint mode (e.g. \"<pause|resume>\"). */\n argHintText: string;\n /** id used for aria-activedescendant wiring from the textarea. */\n listboxId: string;\n};\n\n/**\n * The slash-command palette: a popover anchored above the textarea, rendered\n * entirely from the filtered registry. Dark-first, Linear/Vercel-calm, using\n * the opengeni#46 design tokens. Full keyboard nav lives in useSlashCommands;\n * this component is presentational + aria.\n */\nexport function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintText, listboxId }: CommandPaletteProps) {\n return (\n <AnimatePresence>\n {open ? (\n <motion.div\n initial={{ opacity: 0, y: 6, scale: 0.99 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 6, scale: 0.99 }}\n transition={{ duration: 0.13, ease: \"easeOut\" }}\n className={cn(\n \"absolute bottom-full left-0 right-0 z-20 mb-2 overflow-hidden\",\n \"rounded-og-lg border border-og-border bg-og-surface-2 shadow-og-sm\",\n )}\n >\n <ul\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Slash commands\"\n className=\"max-h-72 overflow-y-auto py-1\"\n >\n {items.map((command, index) => {\n const selected = index === highlight;\n const hint = argHint(command.args);\n return (\n <li\n key={command.name}\n id={`${listboxId}-option-${index}`}\n role=\"option\"\n aria-selected={selected}\n onMouseEnter={() => onHighlight(index)}\n onMouseDown={(event) => {\n // Keep textarea focus; run on click.\n event.preventDefault();\n onRun(index);\n }}\n className={cn(\n \"mx-1 flex cursor-pointer items-center gap-2 rounded-og-md px-2.5 py-1.5\",\n \"transition-colors duration-100\",\n selected ? \"bg-og-accent/15 text-og-fg\" : \"text-og-fg-muted hover:bg-og-surface-3\",\n )}\n >\n <span className=\"flex min-w-0 items-baseline gap-1.5\">\n <span className={cn(\"font-mono text-[13px]\", selected ? \"text-og-accent\" : \"text-og-fg\")}>\n /{command.name}\n </span>\n {hint ? <span className=\"truncate font-mono text-[11px] text-og-fg-subtle\">{hint}</span> : null}\n </span>\n <span className=\"ml-auto flex items-center gap-1.5\">\n {command.danger ? (\n <span className=\"rounded-og-xs bg-og-status-failed/15 px-1 text-[10px] uppercase tracking-wide text-og-status-failed\">\n danger\n </span>\n ) : null}\n <span className=\"truncate text-[12px] text-og-fg-subtle max-sm:hidden\">{command.description}</span>\n </span>\n </li>\n );\n })}\n </ul>\n {argHintText ? (\n <div className=\"border-t border-og-border px-3 py-1.5 font-mono text-[11px] text-og-fg-subtle\">\n {argHintText}\n </div>\n ) : null}\n </motion.div>\n ) : null}\n </AnimatePresence>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/** Merge class names with Tailwind-aware conflict resolution. */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import type { SessionStatus } from \"@opengeni/sdk\";\nimport { ArrowUpIcon, FileIcon, ImageIcon, LoaderCircleIcon, PaperclipIcon, SquareIcon, XIcon } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, type ChangeEvent, type ClipboardEvent, type DragEvent, type KeyboardEvent, type ReactNode } from \"react\";\nimport { argHint } from \"../commands/registry\";\nimport type { Notice, SlashCommand } from \"../commands/types\";\nimport type { ComposerState } from \"../hooks/use-composer\";\nimport { shouldSubmitOnKey } from \"../hooks/use-composer\";\nimport type { UseFileAttachmentsResult } from \"../hooks/use-file-attachments\";\nimport { defaultCommands } from \"../commands/registry\";\nimport { useSlashCommands, type ConfirmState, type SlashCommandContext } from \"../hooks/use-slash-commands\";\nimport { cn } from \"../lib/cn\";\nimport { formatBytes } from \"../lib/format\";\nimport { CommandPalette } from \"./command-palette\";\n\nexport type ChatComposerProps = {\n composer: ComposerState;\n /** Current session status; shows the stop control while a turn runs. */\n status?: SessionStatus | null | undefined;\n placeholder?: string | undefined;\n disabled?: boolean | undefined;\n autoFocus?: boolean | undefined;\n /** Replaces the default keyboard hint under the field. */\n hint?: string | undefined;\n /** App controls (model picker, attach button, ...) in the footer row, replacing the hint. */\n controlsStart?: ReactNode | undefined;\n /** Content rendered above the textarea, inside the field chrome (e.g. attachment chips). */\n header?: ReactNode | undefined;\n /** Paste hook on the textarea (e.g. paste-image-to-attach). */\n onPaste?: ((event: ClipboardEvent<HTMLTextAreaElement>) => void) | undefined;\n /**\n * Opt-in file attachments. When supplied (e.g. from {@link useFileAttachments}),\n * the composer renders a built-in attach button (prepended to `controlsStart`),\n * an attachment-chips strip (above the textarea, before any host `header`),\n * routes paste through `addFromPaste` (image/* filter lives in the hook), and\n * gates send while `uploading` so a message never departs without its files.\n * Absent → no attachment UI renders and the composer behaves exactly as before.\n */\n attachments?: UseFileAttachmentsResult | undefined;\n className?: string | undefined;\n /**\n * Slash-command palette. Defaults to the built-in {@link defaultCommands};\n * apps concat their own. Backward-compatible: when `commandContext` is absent\n * the palette is inert and behavior is identical to before.\n */\n commands?: readonly SlashCommand[] | undefined;\n /**\n * Wiring the palette needs to run server commands and gate visibility. The\n * composer supplies notice/openHelp/clearView/confirm internally.\n */\n commandContext?: SlashCommandContext | undefined;\n /** Reset the local timeline view (the /clear-view command target). */\n onClearView?: (() => void) | undefined;\n};\n\nconst ACTIVE_STATUSES: ReadonlySet<SessionStatus> = new Set([\"queued\", \"running\"]);\n\n/**\n * The chat composer — the only human-to-agent input surface. Plain chat in,\n * everything else is the agent's job. Enter sends, Shift+Enter breaks the\n * line, and the stop control appears while a turn is running (sending while\n * running is legitimate steering, so send stays available too).\n *\n * Typing a leading \"/\" opens the slash-command palette — SESSION/OPERATOR\n * controls (clear, compact, pause goal, help), never a structured channel to\n * the agent. The palette is purely additive: with no `commandContext` it is\n * inert and the composer behaves exactly as before.\n */\nexport function ChatComposer({\n composer,\n status,\n placeholder,\n disabled,\n autoFocus,\n hint,\n controlsStart,\n header,\n onPaste,\n attachments,\n className,\n commands = defaultCommands,\n commandContext,\n onClearView,\n}: ChatComposerProps) {\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n const active = status != null && ACTIVE_STATUSES.has(status);\n\n // Block sends while attachments are still uploading so a message never\n // departs without the files the user attached to it. This gates BOTH the\n // Enter-to-send path (which calls composer.send directly, bypassing canSend)\n // and the send button — dropping either path could ship a fileless message.\n const blockedByUpload = attachments?.uploading === true;\n\n // A ready attachment makes a file-only message (empty draft) sendable. The\n // composer (when wired with `sendExtras.resources`) already reflects this in\n // `canSend`; we OR it in here too so send-enablement is correct even for a\n // composer whose canSend doesn't know about attachments — and so this stays\n // the single home of the attachment send-gate.\n const hasReadyAttachment = (attachments?.readyResources.length ?? 0) > 0;\n // The send affordance: text OR a ready attachment, never mid-upload or mid-send.\n const canSend = (composer.canSend || hasReadyAttachment) && !blockedByUpload && !composer.sending;\n\n // Drag-and-drop file attach: only a drop target when `attachments` is wired,\n // and only reacts to drags that actually carry files (so it never hijacks\n // normal text drag/drop). `dragging` drives the drop overlay.\n const [dragging, setDragging] = useState(false);\n const dragCarriesFiles = (event: { dataTransfer: DataTransfer | null }): boolean =>\n event.dataTransfer != null && [...event.dataTransfer.types].includes(\"Files\");\n const handleDragOver = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n if (!attachments || !dragCarriesFiles(event)) {\n return;\n }\n // preventDefault marks this a valid drop target so the browser fires drop.\n event.preventDefault();\n setDragging(true);\n },\n [attachments],\n );\n const handleDragLeave = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n if (!attachments) {\n return;\n }\n // Ignore leaves bubbling from children: only clear when the pointer left\n // the composer bounds entirely (the related target is outside it).\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) {\n return;\n }\n setDragging(false);\n },\n [attachments],\n );\n const handleDrop = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n if (!attachments || !dragCarriesFiles(event)) {\n return;\n }\n event.preventDefault();\n setDragging(false);\n // Same path the picker uses: addFiles accepts ALL files (no image filter).\n if (event.dataTransfer.files.length > 0) {\n attachments.addFiles(event.dataTransfer.files);\n }\n },\n [attachments],\n );\n\n const [notice, setNotice] = useState<Notice | null>(null);\n const [helpOpen, setHelpOpen] = useState(false);\n const [confirmState, setConfirmState] = useState<ConfirmState>(null);\n const listboxId = useId();\n\n const resize = useCallback(() => {\n const textarea = textareaRef.current;\n if (!textarea) {\n return;\n }\n textarea.style.height = \"0px\";\n textarea.style.height = `${Math.min(textarea.scrollHeight, 220)}px`;\n }, []);\n\n useEffect(() => {\n resize();\n }, [composer.value, resize]);\n\n // The UI affordances commands reach: surface a notice, open the help panel,\n // reset the local view, and the danger confirm flow (resolves when the\n // operator confirms/cancels in the confirm bar).\n const handlers = useMemo(\n () => ({\n notice: (next: Notice) => {\n setNotice(next);\n composer.clearError();\n },\n openHelp: () => setHelpOpen(true),\n // Report whether a view-reset was actually wired by the host: with no\n // onClearView the command is a no-op and must say so (not a false success).\n clearView: () => {\n if (!onClearView) {\n return false;\n }\n onClearView();\n return true;\n },\n // The hook binds the command actually being run into confirm() (see\n // use-slash-commands buildContext), so the confirm bar renders from THAT\n // command — never a near-match highlighted in the palette. This is what\n // keeps the destructive /clear from being mislabeled as /clear-view.\n confirm: (command: SlashCommand) =>\n new Promise<boolean>((resolve) => {\n setConfirmState({\n command,\n resolve: (confirmed) => {\n setConfirmState(null);\n resolve(confirmed);\n },\n });\n }),\n }),\n [composer, onClearView],\n );\n\n const palette = useSlashCommands({\n commands,\n context: commandContext,\n handlers,\n value: composer.value,\n setValue: composer.setValue,\n });\n\n // The confirm bar renders from the command the hook is actually running —\n // carried into confirmState by handlers.confirm — NOT a near-match that\n // happens to be highlighted/active in the palette. (Re-deriving it from\n // palette.items[palette.highlight] mislabeled the destructive /clear as the\n // harmless /clear-view, since clear-view prefix-matches \"clear\" and sorts\n // first.)\n const pendingDangerCommand = confirmState ? confirmState.command : null;\n\n const paletteEnabled = commandContext !== undefined;\n\n // A slash-command draft must never be delivered to the agent as chat — it is\n // an operator control, not a message. The palette consumes Enter while open,\n // but after Escape the popover is closed yet the draft still matches a command;\n // block the send path (here and on the send button) so \"/clear\" can't be sent.\n const commandDraftBlocked = paletteEnabled && palette.isCommandDraft;\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n // Palette key handling runs FIRST and only when the palette is open; when\n // closed it returns false and the existing send path is untouched.\n if (paletteEnabled && palette.onKeyDown(event)) {\n return;\n }\n if (shouldSubmitOnKey(event)) {\n event.preventDefault();\n if (commandDraftBlocked) {\n // Dismissed palette + a \"/command\" draft: don't send it as chat. Nudge\n // the operator to re-open the palette (any edit re-opens it) or clear it.\n setNotice({ tone: \"error\", message: \"That's a slash command — press Enter in the command list to run it, or edit the line to send a message.\" });\n return;\n }\n if (blockedByUpload) {\n // Files are still uploading: swallow the Enter so the message can't\n // depart without them. The send button is disabled in the same state.\n return;\n }\n void composer.send();\n }\n };\n\n // The host's onPaste still fires (model/tool/whatever paste handling); when\n // attachments are wired, also feed the clipboard through addFromPaste so the\n // image/* filter (owned by the hook) attaches pasted images.\n const handlePaste = useCallback(\n (event: ClipboardEvent<HTMLTextAreaElement>) => {\n onPaste?.(event);\n attachments?.addFromPaste(event);\n },\n [onPaste, attachments],\n );\n\n const handleFileChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (event.target.files) {\n attachments?.addFiles(event.target.files);\n }\n event.target.value = \"\";\n },\n [attachments],\n );\n\n const helpCommands = useMemo(\n () =>\n commands.filter((command) => {\n if (command.permission && commandContext) {\n const perms = commandContext.permissions;\n return perms.includes(command.permission) || perms.includes(\"workspace:admin\");\n }\n return true;\n }),\n [commands, commandContext],\n );\n\n const activeNotice = notice ?? (composer.error ? { tone: \"error\" as const, message: composer.error.message || \"Sending failed — your draft is still here. Try again.\" } : null);\n\n return (\n <div className={cn(\"og-root\", className)}>\n <div className=\"relative\">\n {paletteEnabled ? (\n <CommandPalette\n open={palette.open && confirmState === null}\n items={palette.items}\n highlight={palette.highlight}\n onHighlight={palette.setHighlight}\n onRun={(index) => {\n // Run the CLICKED row directly. We must not route a pointer click\n // through runHighlighted: its exact-match override would re-resolve\n // \"/clear\" to the destructive clear even when the operator clicked\n // the harmless clear-view row. runAt honors the explicit selection.\n palette.setHighlight(index);\n void palette.runAt(index);\n }}\n argHintText={palette.activeArgHint}\n listboxId={listboxId}\n />\n ) : null}\n <div\n // Drag-and-drop file attach lives on the field wrapper, but only when\n // `attachments` is wired — without it the composer is not a drop target\n // and behaves exactly as before.\n onDragOver={attachments ? handleDragOver : undefined}\n onDragLeave={attachments ? handleDragLeave : undefined}\n onDrop={attachments ? handleDrop : undefined}\n className={cn(\n \"relative rounded-og-lg border border-og-border bg-og-surface-1 shadow-og-sm\",\n \"transition-[border-color,box-shadow] duration-200\",\n \"focus-within:border-og-accent/60 focus-within:shadow-og-glow\",\n // While files are dragged over, swap to a dashed accent border to\n // signal a live drop target (the overlay carries the label).\n dragging && \"border-dashed border-og-accent\",\n )}\n >\n {dragging ? (\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 z-10 flex items-center justify-center\",\n \"rounded-og-lg bg-og-surface-1/85 text-sm font-medium text-og-accent backdrop-blur-[1px]\",\n )}\n >\n <span className=\"inline-flex items-center gap-2\">\n <PaperclipIcon className=\"size-4\" />\n Drop files to attach\n </span>\n </div>\n ) : null}\n {attachments && attachments.attachments.length > 0 ? (\n <AttachmentChips attachments={attachments.attachments} onRemove={attachments.remove} />\n ) : null}\n {header}\n <textarea\n ref={textareaRef}\n rows={1}\n value={composer.value}\n onChange={(event) => composer.setValue(event.target.value)}\n onKeyDown={onKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder ?? \"Message the agent…\"}\n disabled={disabled}\n autoFocus={autoFocus}\n aria-label=\"Message the agent\"\n role={paletteEnabled && palette.open ? \"combobox\" : undefined}\n aria-expanded={paletteEnabled ? palette.open : undefined}\n aria-controls={paletteEnabled && palette.open ? listboxId : undefined}\n aria-activedescendant={paletteEnabled && palette.open ? `${listboxId}-option-${palette.highlight}` : undefined}\n className={cn(\n \"block w-full resize-none bg-transparent px-4 pt-3.5 pb-1 text-[15px] leading-6\",\n // The wrapper owns the whole-composer focus affordance (focus-within\n // border + soft glow). Suppress any self-scoped focus outline on the\n // textarea itself: `focus:outline-none` alone only sets outline-style\n // on `:focus`, which a host app's zero-specificity\n // `:where(...):focus-visible { outline: ... }` base rule re-applies as\n // the full shorthand. `focus-visible:outline-none` matches the same\n // state at class specificity and wins, so no second highlight (the\n // top-half rectangle bounded to the textarea box) ever paints.\n \"text-og-fg placeholder:text-og-fg-subtle focus:outline-none focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-60\",\n )}\n />\n {confirmState && pendingDangerCommand ? (\n <ConfirmBar\n command={pendingDangerCommand}\n onCancel={() => confirmState.resolve(false)}\n onConfirm={() => confirmState.resolve(true)}\n />\n ) : (\n <div className=\"flex items-center justify-between gap-2 px-2.5 pb-2.5 pt-1\">\n {attachments || controlsStart ? (\n <span className=\"flex min-w-0 items-center gap-1.5\">\n {attachments ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={handleFileChange}\n />\n <button\n type=\"button\"\n disabled={disabled === true}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Attach files\"\n title=\"Attach files\"\n className={cn(\n \"inline-flex size-8 items-center justify-center rounded-og-md\",\n \"text-og-fg-muted transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n )}\n >\n <PaperclipIcon className=\"size-4\" />\n </button>\n </>\n ) : null}\n {controlsStart}\n </span>\n ) : (\n <span className=\"px-1.5 text-[11px] text-og-fg-subtle max-sm:hidden\">\n {hint ?? \"Enter to send · Shift+Enter for a new line · / for commands\"}\n </span>\n )}\n <span className=\"flex items-center gap-1.5\">\n <AnimatePresence initial={false}>\n {active ? (\n <motion.button\n key=\"stop\"\n type=\"button\"\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.8 }}\n transition={{ duration: 0.15, ease: \"easeOut\" }}\n onClick={() => void composer.interrupt()}\n disabled={composer.interrupting}\n aria-label=\"Stop the current turn\"\n title=\"Stop the current turn\"\n className={cn(\n \"inline-flex size-8 items-center justify-center rounded-og-md border border-og-border\",\n \"bg-og-surface-2 text-og-fg-muted transition-colors duration-150\",\n \"hover:border-og-status-failed/50 hover:text-og-status-failed\",\n \"disabled:opacity-50\",\n )}\n >\n {composer.interrupting ? (\n <LoaderCircleIcon className=\"size-3.5 animate-og-spin\" />\n ) : (\n <SquareIcon className=\"size-3 fill-current\" />\n )}\n </motion.button>\n ) : null}\n </AnimatePresence>\n <button\n type=\"button\"\n onClick={() => {\n if (blockedByUpload) {\n return;\n }\n void composer.send();\n }}\n disabled={!canSend || disabled === true || commandDraftBlocked}\n aria-label=\"Send message\"\n className={cn(\n \"inline-flex size-8 items-center justify-center rounded-og-md\",\n \"bg-og-accent text-og-accent-fg shadow-og-sm\",\n \"transition-[background-color,transform,opacity] duration-150 ease-og-spring\",\n \"hover:bg-og-accent-strong active:scale-95\",\n \"disabled:cursor-not-allowed disabled:bg-og-surface-3 disabled:text-og-fg-subtle disabled:shadow-none\",\n )}\n >\n {composer.sending ? <LoaderCircleIcon className=\"size-4 animate-og-spin\" /> : <ArrowUpIcon className=\"size-4\" />}\n </button>\n </span>\n </div>\n )}\n </div>\n </div>\n <AnimatePresence>\n {helpOpen ? (\n <HelpPanel commands={helpCommands} onClose={() => setHelpOpen(false)} />\n ) : null}\n </AnimatePresence>\n <AnimatePresence>\n {activeNotice ? (\n <motion.p\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className={cn(\n \"overflow-hidden px-1 pt-1.5 text-xs\",\n activeNotice.tone === \"ok\" ? \"text-og-fg-muted\" : \"text-og-status-failed\",\n )}\n role={activeNotice.tone === \"error\" ? \"alert\" : \"status\"}\n onAnimationComplete={() => {\n if (activeNotice.tone === \"ok\") {\n // Auto-dismiss success notices after a beat.\n window.setTimeout(() => setNotice((current) => (current === activeNotice ? null : current)), 2400);\n }\n }}\n >\n {activeNotice.message}\n </motion.p>\n ) : null}\n </AnimatePresence>\n </div>\n );\n}\n\n/** The danger confirm bar — reuses og-status-failed tokens (like the stop control). */\nfunction ConfirmBar({ command, onCancel, onConfirm }: { command: SlashCommand; onCancel: () => void; onConfirm: () => void }) {\n return (\n <div\n role=\"alertdialog\"\n aria-label={`Confirm /${command.name}`}\n data-testid=\"danger-confirm\"\n className=\"flex items-center justify-between gap-2 px-2.5 pb-2.5 pt-1\"\n >\n <span className=\"px-1.5 text-[12px] text-og-status-failed\">\n Run <span className=\"font-mono\">/{command.name}</span>? {command.description}\n </span>\n <span className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"rounded-og-md border border-og-border bg-og-surface-2 px-2.5 py-1 text-[12px] text-og-fg-muted hover:bg-og-surface-3\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n autoFocus\n onClick={onConfirm}\n className=\"rounded-og-md border border-og-status-failed/50 bg-og-status-failed/15 px-2.5 py-1 text-[12px] text-og-status-failed hover:bg-og-status-failed/25\"\n >\n Confirm\n </button>\n </span>\n </div>\n );\n}\n\n/**\n * The attachment-chips strip rendered above the textarea while files are\n * attached. Each chip shows an image preview (or a type icon), the filename,\n * an upload/size/failed status line, and a remove control. Styled with the\n * package's og-* tokens so it themes in any consumer.\n */\nfunction AttachmentChips({ attachments, onRemove }: {\n attachments: UseFileAttachmentsResult[\"attachments\"];\n onRemove: (id: string) => void;\n}) {\n return (\n <div className=\"flex flex-wrap gap-2 border-b border-og-border px-3 py-2\">\n {attachments.map((attachment) => (\n <div\n key={attachment.id}\n className={cn(\n \"flex min-w-0 max-w-[240px] items-center gap-2 rounded-og-md border px-2 py-1.5\",\n \"border-og-border bg-og-surface-2 text-xs\",\n )}\n >\n {attachment.previewUrl ? (\n <img src={attachment.previewUrl} alt=\"\" className=\"size-8 shrink-0 rounded object-cover\" />\n ) : attachment.contentType.startsWith(\"image/\") ? (\n <ImageIcon className=\"size-4 shrink-0 text-og-fg-muted\" />\n ) : (\n <FileIcon className=\"size-4 shrink-0 text-og-fg-muted\" />\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium text-og-fg\">{attachment.name}</div>\n <div className={cn(\n \"truncate text-[11px]\",\n attachment.status === \"failed\" ? \"text-og-status-failed\" : \"text-og-fg-subtle\",\n )}\n >\n {attachment.status === \"uploading\" ? \"Uploading\" : attachment.status === \"failed\" ? \"Upload failed\" : formatBytes(attachment.sizeBytes)}\n </div>\n </div>\n {attachment.status === \"uploading\" ? <LoaderCircleIcon className=\"size-3.5 shrink-0 animate-og-spin\" /> : null}\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n className=\"shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg\"\n aria-label={`Remove ${attachment.name}`}\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n ))}\n </div>\n );\n}\n\n/** The in-composer /help panel, rendered entirely from the registry. */\nfunction HelpPanel({ commands, onClose }: { commands: readonly SlashCommand[]; onClose: () => void }) {\n return (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className=\"mt-2 overflow-hidden rounded-og-lg border border-og-border bg-og-surface-2\"\n >\n <div className=\"flex items-center justify-between border-b border-og-border px-3 py-1.5\">\n <span className=\"text-[12px] font-medium text-og-fg\">Commands</span>\n <button type=\"button\" onClick={onClose} className=\"text-[11px] text-og-fg-subtle hover:text-og-fg\">\n Close\n </button>\n </div>\n <ul className=\"py-1\">\n {commands.map((command) => {\n const hint = argHint(command.args);\n return (\n <li key={command.name} className=\"flex items-baseline gap-2 px-3 py-1\">\n <span className=\"font-mono text-[12px] text-og-accent\">\n /{command.name}\n {hint ? <span className=\"ml-1 text-og-fg-subtle\">{hint}</span> : null}\n </span>\n <span className=\"text-[12px] text-og-fg-muted\">{command.description}</span>\n {command.danger ? (\n <span className=\"ml-auto rounded-og-xs bg-og-status-failed/15 px-1 text-[10px] uppercase tracking-wide text-og-status-failed\">\n danger\n </span>\n ) : null}\n </li>\n );\n })}\n </ul>\n </motion.div>\n );\n}\n","import type { SessionEvent, SessionStatus } from \"@opengeni/sdk\";\nimport {\n ArrowDownIcon,\n BotIcon,\n BrainIcon,\n ChevronRightIcon,\n SquareTerminalIcon,\n TargetIcon,\n TriangleAlertIcon,\n WrenchIcon,\n} from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Collapsible } from \"radix-ui\";\nimport { cn } from \"../lib/cn\";\nimport { formatRelativeTime, stringifyPayload, truncate } from \"../lib/format\";\nimport {\n buildTimeline,\n compactPayloadPreview,\n groupTimeline,\n toolDisplayName,\n type AgentMessageItem,\n type GoalItem,\n type NoticeItem,\n type ReasoningItem,\n type SandboxItem,\n type TimelineItem,\n type ToolCallItem,\n type UserMessageItem,\n type WorkerItem,\n} from \"../timeline\";\nimport { SESSION_STATUS_META, StatusDot } from \"./session-status\";\n\nexport type MessageTimelineProps = {\n /** Raw session events (projected internally) … */\n events?: SessionEvent[] | undefined;\n /** … or pre-projected items (e.g. from `useSessionEvents().timeline`). */\n items?: TimelineItem[] | undefined;\n /** Current session status; drives the live \"working\" indicator. */\n status?: SessionStatus | null | undefined;\n /** Plug a markdown renderer for message bodies (e.g. streamdown). */\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n /** Drill into a spawned worker session. */\n onOpenSession?: ((sessionId: string) => void) | undefined;\n /** Follow new events when pinned to the bottom. Defaults to true. */\n autoFollow?: boolean | undefined;\n emptyState?: ReactNode | undefined;\n className?: string | undefined;\n};\n\n/**\n * The session timeline: chat messages with streaming deltas, collapsed\n * activity clusters (reasoning, tool calls, sandbox work), spawned-worker\n * cards, goal markers, and status transitions. Owns stick-to-bottom scrolling\n * with a \"jump to latest\" affordance when the reader scrolls back.\n */\nexport function MessageTimeline({\n events,\n items,\n status,\n renderMessageText,\n onOpenSession,\n autoFollow = true,\n emptyState,\n className,\n}: MessageTimelineProps) {\n const resolvedItems = useMemo(() => items ?? buildTimeline(events ?? []), [items, events]);\n const groups = useMemo(() => groupTimeline(resolvedItems), [resolvedItems]);\n\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const [pinned, setPinned] = useState(true);\n const lastItem = resolvedItems[resolvedItems.length - 1];\n const streaming = lastItem !== undefined && (lastItem.kind === \"agent-message\" || lastItem.kind === \"reasoning\") && lastItem.streaming;\n const working = status === \"running\" && !streaming;\n\n // Follow the stream while pinned to the bottom; never fight the reader.\n useEffect(() => {\n const node = scrollRef.current;\n if (node && autoFollow && pinned) {\n node.scrollTop = node.scrollHeight;\n }\n }, [resolvedItems, working, autoFollow, pinned]);\n\n const onScroll = () => {\n const node = scrollRef.current;\n if (!node) {\n return;\n }\n setPinned(node.scrollHeight - node.scrollTop - node.clientHeight < 48);\n };\n\n return (\n <div className={cn(\"og-root relative min-h-0\", className)}>\n <div ref={scrollRef} onScroll={onScroll} className=\"h-full overflow-y-auto overscroll-contain px-4 py-6 sm:px-6\">\n <div className=\"mx-auto flex w-full max-w-3xl flex-col gap-5\">\n {groups.length === 0 && !working\n ? (emptyState ?? <p className=\"py-10 text-center text-sm text-og-fg-subtle\">No activity yet.</p>)\n : null}\n {groups.map((group) =>\n group.kind === \"activity\" ? (\n <ActivityCluster key={group.id} items={group.items} onOpenSession={onOpenSession} />\n ) : (\n <TimelineRow key={group.item.id} item={group.item} renderMessageText={renderMessageText} />\n ),\n )}\n {working ? (\n <div className=\"animate-og-enter flex items-center gap-2 text-sm\">\n <span className=\"og-shimmer-text font-medium\">Working…</span>\n </div>\n ) : null}\n </div>\n </div>\n <AnimatePresence>\n {!pinned && autoFollow ? (\n <motion.button\n type=\"button\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 8 }}\n transition={{ duration: 0.15, ease: \"easeOut\" }}\n onClick={() => {\n const node = scrollRef.current;\n if (node) {\n node.scrollTo({ top: node.scrollHeight, behavior: \"smooth\" });\n }\n setPinned(true);\n }}\n className={cn(\n \"absolute bottom-4 left-1/2 -translate-x-1/2\",\n \"inline-flex items-center gap-1.5 rounded-full border border-og-border bg-og-surface-3/90 px-3 py-1.5\",\n \"text-xs font-medium text-og-fg shadow-og-md backdrop-blur\",\n \"hover:border-og-border-strong\",\n )}\n >\n <ArrowDownIcon className=\"size-3.5\" />\n Jump to latest\n </motion.button>\n ) : null}\n </AnimatePresence>\n </div>\n );\n}\n\n/* --- single rows ------------------------------------------------------------ */\n\nfunction TimelineRow({\n item,\n renderMessageText,\n}: {\n item: TimelineItem;\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n}) {\n switch (item.kind) {\n case \"user-message\":\n return <UserMessageRow item={item} renderMessageText={renderMessageText} />;\n case \"agent-message\":\n return <AgentMessageRow item={item} renderMessageText={renderMessageText} />;\n case \"session-status\":\n return <SessionStatusRow item={item} />;\n case \"goal\":\n return <GoalRow item={item} />;\n case \"notice\":\n return <NoticeRow item={item} />;\n default:\n return null;\n }\n}\n\nfunction UserMessageRow({\n item,\n renderMessageText,\n}: {\n item: UserMessageItem;\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n}) {\n return (\n <div className=\"animate-og-enter flex justify-end\">\n <div className=\"max-w-[85%] rounded-og-lg rounded-br-og-xs border border-og-border bg-og-surface-2 px-4 py-2.5 text-[15px] leading-6 text-og-fg\">\n {renderMessageText ? renderMessageText(item.text, item) : <span className=\"whitespace-pre-wrap\">{item.text}</span>}\n </div>\n </div>\n );\n}\n\nfunction AgentMessageRow({\n item,\n renderMessageText,\n}: {\n item: AgentMessageItem;\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n}) {\n return (\n <div className=\"animate-og-enter text-[15px] leading-7 text-og-fg\">\n {renderMessageText ? renderMessageText(item.text, item) : <span className=\"whitespace-pre-wrap\">{item.text}</span>}\n {item.streaming ? <span className=\"ml-0.5 inline-block h-[1.1em] w-[2px] translate-y-[3px] animate-og-blink rounded-full bg-og-accent\" aria-hidden /> : null}\n </div>\n );\n}\n\nfunction SessionStatusRow({ item }: { item: { status: SessionStatus; occurredAt: string } }) {\n const meta = SESSION_STATUS_META[item.status];\n return (\n <div className=\"animate-og-enter flex items-center gap-3 text-[11px] text-og-fg-subtle\" role=\"status\">\n <span className=\"h-px flex-1 bg-og-border\" />\n <span className=\"inline-flex items-center gap-1.5\">\n <StatusDot status={item.status} className=\"size-1\" />\n {meta.label.toLowerCase()} · {formatRelativeTime(item.occurredAt)}\n </span>\n <span className=\"h-px flex-1 bg-og-border\" />\n </div>\n );\n}\n\nfunction GoalRow({ item }: { item: GoalItem }) {\n const label =\n item.action === \"set\"\n ? \"Goal set\"\n : item.action === \"updated\"\n ? \"Goal updated\"\n : item.action === \"completed\"\n ? \"Goal completed\"\n : item.action === \"paused\"\n ? \"Goal paused\"\n : item.action === \"resumed\"\n ? \"Goal resumed\"\n : \"Continuing toward the goal\";\n return (\n <div className=\"animate-og-enter flex justify-center\">\n <span className=\"inline-flex max-w-full items-center gap-1.5 rounded-full border border-og-border bg-og-surface-1 px-3 py-1 text-xs text-og-fg-muted\">\n <TargetIcon className=\"size-3.5 shrink-0 text-og-accent\" />\n <span className=\"truncate\">\n {label}\n {item.text ? `: ${truncate(item.text, 90)}` : \"\"}\n </span>\n </span>\n </div>\n );\n}\n\nfunction NoticeRow({ item }: { item: NoticeItem }) {\n const tone =\n item.tone === \"failed\"\n ? \"border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed\"\n : item.tone === \"waiting\"\n ? \"border-og-status-waiting/35 bg-og-status-waiting/10 text-og-status-waiting\"\n : \"border-og-border bg-og-surface-1 text-og-fg-muted\";\n return (\n <div className={cn(\"animate-og-enter flex items-start gap-2.5 rounded-og-md border px-3.5 py-2.5 text-sm\", tone)} role=\"status\">\n <TriangleAlertIcon className={cn(\"mt-0.5 size-4 shrink-0\", item.tone === \"cancelled\" && \"opacity-60\")} />\n <span className=\"min-w-0 whitespace-pre-wrap break-words\">{item.text}</span>\n </div>\n );\n}\n\n/* --- activity cluster -------------------------------------------------------- */\n\ntype ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem;\n\nfunction ActivityCluster({\n items,\n onOpenSession,\n}: {\n items: ActivityItem[];\n onOpenSession?: ((sessionId: string) => void) | undefined;\n}) {\n return (\n <div className=\"animate-og-enter flex flex-col gap-1.5 border-l-2 border-og-border pl-3 sm:pl-4\">\n {items.map((item) => {\n switch (item.kind) {\n case \"reasoning\":\n return <ReasoningRow key={item.id} item={item} />;\n case \"tool-call\":\n return <ToolCallRow key={item.id} item={item} />;\n case \"worker\":\n return <WorkerRow key={item.id} item={item} onOpenSession={onOpenSession} />;\n case \"sandbox\":\n return <SandboxRow key={item.id} item={item} />;\n }\n })}\n </div>\n );\n}\n\nfunction ActivityDisclosure({\n icon,\n title,\n running,\n failed,\n preview,\n children,\n}: {\n icon: ReactNode;\n title: string;\n running: boolean;\n failed?: boolean | undefined;\n preview?: string | undefined;\n children?: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <Collapsible.Root open={open} onOpenChange={setOpen}>\n <Collapsible.Trigger\n className={cn(\n \"group flex w-full min-w-0 items-center gap-2 rounded-og-sm px-1.5 py-1 text-left text-[13px]\",\n \"text-og-fg-muted transition-colors duration-150 hover:bg-og-surface-1 hover:text-og-fg\",\n )}\n >\n <ChevronRightIcon className=\"size-3.5 shrink-0 text-og-fg-subtle transition-transform duration-150 group-data-[state=open]:rotate-90\" />\n <span className={cn(\"shrink-0\", failed ? \"text-og-status-failed\" : running ? \"text-og-status-running\" : \"text-og-fg-subtle\")}>{icon}</span>\n <span className={cn(\"shrink-0 font-medium\", running && \"og-shimmer-text\", failed && \"text-og-status-failed\")}>{title}</span>\n {preview ? <span className=\"min-w-0 flex-1 truncate font-og-mono text-xs text-og-fg-subtle\">{preview}</span> : null}\n {running ? <span className=\"ml-auto size-1.5 shrink-0 animate-og-pulse rounded-full bg-og-status-running\" /> : null}\n </Collapsible.Trigger>\n <Collapsible.Content className=\"overflow-hidden\">\n <div className=\"mt-1 mb-1.5 ml-7 flex flex-col gap-2\">{children}</div>\n </Collapsible.Content>\n </Collapsible.Root>\n );\n}\n\nfunction PayloadBlock({ label, value }: { label: string; value: unknown }) {\n const text = stringifyPayload(value);\n if (!text) {\n return null;\n }\n return (\n <div className=\"min-w-0\">\n <p className=\"mb-1 text-[10px] font-medium uppercase tracking-[0.08em] text-og-fg-subtle\">{label}</p>\n <pre className=\"max-h-64 overflow-auto rounded-og-sm border border-og-border bg-og-bg/60 p-2.5 font-og-mono text-xs leading-5 text-og-fg-muted\">\n {text}\n </pre>\n </div>\n );\n}\n\nfunction ReasoningRow({ item }: { item: ReasoningItem }) {\n return (\n <ActivityDisclosure\n icon={<BrainIcon className=\"size-3.5\" />}\n title={item.streaming ? \"Thinking\" : \"Thought\"}\n running={item.streaming}\n preview={truncate(item.text, 110)}\n >\n <p className=\"whitespace-pre-wrap text-[13px] leading-6 text-og-fg-muted\">{item.text}</p>\n </ActivityDisclosure>\n );\n}\n\nfunction ToolCallRow({ item }: { item: ToolCallItem }) {\n return (\n <ActivityDisclosure\n icon={<WrenchIcon className=\"size-3.5\" />}\n title={toolDisplayName(item.name)}\n running={item.status === \"running\"}\n preview={compactPayloadPreview(item.arguments)}\n >\n <PayloadBlock label=\"Arguments\" value={item.arguments} />\n {item.status === \"complete\" ? <PayloadBlock label=\"Output\" value={item.output} /> : null}\n </ActivityDisclosure>\n );\n}\n\nfunction SandboxRow({ item }: { item: SandboxItem }) {\n return (\n <ActivityDisclosure\n icon={<SquareTerminalIcon className=\"size-3.5\" />}\n title={toolDisplayName(item.name)}\n running={item.status === \"running\"}\n failed={item.status === \"failed\"}\n preview={item.command ?? undefined}\n >\n {item.command ? <PayloadBlock label=\"Command\" value={item.command} /> : null}\n {item.output ? <PayloadBlock label=\"Output\" value={item.output} /> : null}\n </ActivityDisclosure>\n );\n}\n\n/** Spawned/messaged worker sessions get a first-class card, not a tool row. */\nfunction WorkerRow({ item, onOpenSession }: { item: WorkerItem; onOpenSession?: ((sessionId: string) => void) | undefined }) {\n const running = item.status === \"running\";\n const title = item.action === \"spawn\" ? (running ? \"Spawning worker\" : \"Worker spawned\") : running ? \"Messaging worker\" : \"Worker messaged\";\n return (\n <div className=\"my-0.5 flex items-start gap-3 rounded-og-md border border-og-border bg-og-surface-1 p-3 shadow-og-sm\">\n <span\n className={cn(\n \"mt-0.5 inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm\",\n \"bg-og-accent-soft text-og-accent\",\n )}\n >\n <BotIcon className=\"size-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className={cn(\"text-[13px] font-medium\", running ? \"og-shimmer-text\" : \"text-og-fg\")}>{title}</span>\n {running ? <span className=\"size-1.5 animate-og-pulse rounded-full bg-og-status-running\" /> : null}\n </div>\n {item.prompt ? <p className=\"mt-0.5 truncate text-xs text-og-fg-muted\">{truncate(item.prompt, 140)}</p> : null}\n {item.workerSessionId ? (\n <p className=\"mt-1 font-og-mono text-[11px] text-og-fg-subtle\">{item.workerSessionId.slice(0, 8)}</p>\n ) : null}\n </div>\n {item.workerSessionId && onOpenSession ? (\n <button\n type=\"button\"\n onClick={() => item.workerSessionId && onOpenSession(item.workerSessionId)}\n className={cn(\n \"shrink-0 self-center rounded-og-sm border border-og-border px-2.5 py-1 text-xs font-medium text-og-fg-muted\",\n \"transition-colors duration-150 hover:border-og-border-strong hover:text-og-fg\",\n )}\n >\n Open session\n </button>\n ) : null}\n </div>\n );\n}\n","import type { SessionStatus as SessionStatusValue } from \"@opengeni/sdk\";\nimport { cn } from \"../lib/cn\";\n\nexport type SessionStatusMeta = {\n label: string;\n /** Token-backed color classes for the dot and tinted badge. */\n dotClassName: string;\n badgeClassName: string;\n /** Live states breathe; terminal states hold still. */\n pulse: boolean;\n};\n\nexport const SESSION_STATUS_META: Record<SessionStatusValue, SessionStatusMeta> = {\n queued: {\n label: \"Queued\",\n dotClassName: \"bg-og-status-queued\",\n badgeClassName: \"text-og-fg-muted border-og-border bg-og-status-queued/10\",\n pulse: true,\n },\n running: {\n label: \"Running\",\n dotClassName: \"bg-og-status-running\",\n badgeClassName: \"text-og-status-running border-og-status-running/30 bg-og-status-running/10\",\n pulse: true,\n },\n idle: {\n label: \"Idle\",\n dotClassName: \"bg-og-status-idle\",\n badgeClassName: \"text-og-status-idle border-og-status-idle/30 bg-og-status-idle/10\",\n pulse: false,\n },\n requires_action: {\n label: \"Needs you\",\n dotClassName: \"bg-og-status-waiting\",\n badgeClassName: \"text-og-status-waiting border-og-status-waiting/35 bg-og-status-waiting/10\",\n pulse: true,\n },\n failed: {\n label: \"Failed\",\n dotClassName: \"bg-og-status-failed\",\n badgeClassName: \"text-og-status-failed border-og-status-failed/35 bg-og-status-failed/10\",\n pulse: false,\n },\n cancelled: {\n label: \"Cancelled\",\n dotClassName: \"bg-og-status-cancelled\",\n badgeClassName: \"text-og-fg-subtle border-og-border bg-og-status-cancelled/10\",\n pulse: false,\n },\n};\n\nexport type SessionStatusProps = {\n status: SessionStatusValue;\n /** Override the label (\"Running\" -> \"Deploying\", ...). */\n label?: string | undefined;\n size?: \"sm\" | \"md\" | undefined;\n className?: string | undefined;\n};\n\n/** Status badge with a breathing dot for live states. */\nexport function SessionStatus({ status, label, size = \"md\", className }: SessionStatusProps) {\n const meta = SESSION_STATUS_META[status];\n return (\n <span\n data-status={status}\n className={cn(\n \"og-root inline-flex shrink-0 items-center rounded-full border font-medium\",\n size === \"sm\" ? \"gap-1 px-1.5 py-px text-[10px]\" : \"gap-1.5 px-2 py-0.5 text-xs\",\n meta.badgeClassName,\n className,\n )}\n >\n <StatusDot status={status} className={size === \"sm\" ? \"size-1\" : \"size-1.5\"} />\n {label ?? meta.label}\n </span>\n );\n}\n\nexport type StatusDotProps = {\n status: SessionStatusValue;\n className?: string | undefined;\n};\n\n/** Just the dot — for dense rows and tiles. */\nexport function StatusDot({ status, className }: StatusDotProps) {\n const meta = SESSION_STATUS_META[status];\n return (\n <span className={cn(\"relative inline-flex size-1.5 shrink-0 rounded-full\", meta.dotClassName, className)}>\n {meta.pulse ? <span className={cn(\"absolute inset-0 animate-og-pulse rounded-full\", meta.dotClassName)} /> : null}\n </span>\n );\n}\n","import type { Session } from \"@opengeni/sdk\";\nimport { cn } from \"../lib/cn\";\nimport { formatRelativeTime, truncate } from \"../lib/format\";\nimport { SessionStatus } from \"./session-status\";\n\nexport type FleetTileProps = {\n session: Session;\n /** Overrides the derived title (metadata.title/name, else the initial message). */\n title?: string | undefined;\n /** Extra line under the title — e.g. \"drift check\" or the worker's task. */\n subtitle?: string | undefined;\n onOpen?: ((session: Session) => void) | undefined;\n className?: string | undefined;\n};\n\n/** Best-effort display title for a session. */\nexport function sessionDisplayTitle(session: Session): string {\n for (const key of [\"title\", \"name\"] as const) {\n const value = session.metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return truncate(session.initialMessage, 100) || session.id.slice(0, 8);\n}\n\n/**\n * One session in the fleet/manager view: title, live status, model, and\n * recency — dense but calm. Running sessions carry a breathing status dot\n * and a faint accent edge so the live ones read at a glance.\n */\nexport function FleetTile({ session, title, subtitle, onOpen, className }: FleetTileProps) {\n const running = session.status === \"running\" || session.status === \"queued\";\n const needsYou = session.status === \"requires_action\";\n return (\n <button\n type=\"button\"\n data-status={session.status}\n onClick={onOpen ? () => onOpen(session) : undefined}\n disabled={!onOpen}\n className={cn(\n \"og-root group relative flex w-full flex-col gap-2.5 overflow-hidden rounded-og-lg border border-og-border\",\n \"bg-og-surface-1 p-4 text-left shadow-og-sm\",\n \"transition-[border-color,background-color,box-shadow,transform] duration-200 ease-og-out\",\n onOpen && \"hover:-translate-y-px hover:border-og-border-strong hover:bg-og-surface-2 hover:shadow-og-md\",\n \"disabled:cursor-default\",\n className,\n )}\n >\n <span\n aria-hidden\n className={cn(\n \"absolute inset-y-0 left-0 w-0.5 transition-opacity duration-300\",\n running ? \"bg-og-accent opacity-100\" : needsYou ? \"bg-og-status-waiting opacity-100\" : \"opacity-0\",\n )}\n />\n <span className=\"flex w-full items-start justify-between gap-3\">\n <span className=\"line-clamp-2 min-w-0 text-sm font-medium leading-snug text-og-fg\">{title ?? sessionDisplayTitle(session)}</span>\n <SessionStatus status={session.status} size=\"sm\" className=\"mt-px\" />\n </span>\n {subtitle ? <span className=\"line-clamp-1 text-xs text-og-fg-muted\">{subtitle}</span> : null}\n <span className=\"mt-auto flex w-full items-center gap-2 text-[11px] text-og-fg-subtle\">\n <span className=\"font-og-mono\">{session.id.slice(0, 8)}</span>\n <span aria-hidden>·</span>\n <span className=\"truncate\">{session.model}</span>\n <span className=\"ml-auto shrink-0\" title={session.updatedAt}>\n {formatRelativeTime(session.updatedAt)}\n </span>\n </span>\n </button>\n );\n}\n"],"mappings":";AAAA,SAAS,eAAe,YAAY,eAA+B;AAsB1D;AAdT,IAAM,kBAAkB,cAA2C,IAAI;AAYhE,SAAS,iBAAiB,EAAE,QAAQ,aAAa,SAAS,GAA0B;AACzF,QAAM,QAAQ,QAAQ,OAAO,EAAE,QAAQ,YAAY,IAAI,CAAC,QAAQ,WAAW,CAAC;AAC5E,SAAO,oBAAC,gBAAgB,UAAhB,EAAyB,OAAe,UAAS;AAC3D;AAQO,SAAS,YAAY,WAA2B,CAAC,GAAyB;AAC/E,QAAM,UAAU,WAAW,eAAe;AAC1C,QAAM,SAAS,SAAS,UAAU,SAAS;AAC3C,QAAM,cAAc,SAAS,eAAe,SAAS;AACrD,MAAI,CAAC,UAAU,CAAC,aAAa;AAC3B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,YAAY;AAC/B;AAMO,SAAS,kBAAkB,WAA2C,CAAC,GAAsB;AAClG,QAAM,UAAU,WAAW,eAAe;AAC1C,QAAM,SAAS,SAAS,UAAU,SAAS;AAC3C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACvDA,SAAS,eAAAA,oBAAmB;;;ACA5B,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AAclD,SAAS,eAAkB,MAAwB,UAAkF,CAAC,GAAsB;AACjK,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,CAAC,MAAM,OAAO,IAAI,SAAmB,IAAI;AAC/C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,OAAO;AAC9C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AACrD,QAAM,aAAa,OAAO,CAAC;AAC3B,QAAM,UAAU,OAAO,IAAI;AAI3B,YAAU,MAAM;AACd,QAAI,QAAQ,YAAY,MAAM;AAC5B,cAAQ,UAAU;AAClB,cAAQ,IAAI;AACZ,eAAS,IAAI;AAAA,IACf;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,MAAM,YAAY,YAAY;AAClC,UAAM,SAAS,EAAE,WAAW;AAC5B,QAAI;AACF,YAAM,SAAS,MAAM,KAAK;AAC1B,UAAI,WAAW,WAAW,SAAS;AACjC,gBAAQ,MAAM;AACd,iBAAS,IAAI;AACb,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF,SAAS,OAAO;AACd,UAAI,WAAW,WAAW,SAAS;AACjC,iBAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAClE,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,YAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,eAAW,IAAI;AACf,SAAK,IAAI;AACT,QAAI,mBAAmB,UAAa,kBAAkB,GAAG;AACvD,aAAO,MAAM;AACX,mBAAW,WAAW;AAAA,MACxB;AAAA,IACF;AACA,UAAM,QAAQ,YAAY,MAAM,KAAK,IAAI,GAAG,cAAc;AAC1D,WAAO,MAAM;AACX,oBAAc,KAAK;AACnB,iBAAW,WAAW;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,KAAK,SAAS,cAAc,CAAC;AAEjC,SAAO,EAAE,MAAM,SAAS,OAAO,SAAS,IAAI;AAC9C;AAaO,SAAS,oBAEd;AACA,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAuB,IAAI;AACrE,QAAM,WAAW,OAAO,CAAC;AACzB,QAAM,UAAU,OAAO,IAAI;AAC3B,YAAU,MAAM;AACd,YAAQ,UAAU;AAClB,WAAO,MAAM;AACX,cAAQ,UAAU;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,CAAC;AACL,QAAM,MAAM,YAAY,OAAW,cAAmD;AACpF,aAAS,WAAW;AACpB,QAAI,QAAQ,SAAS;AACnB,kBAAY,IAAI;AAChB,uBAAiB,IAAI;AAAA,IACvB;AACA,QAAI;AACF,aAAO,MAAM,UAAU;AAAA,IACzB,SAAS,OAAO;AACd,UAAI,QAAQ,SAAS;AACnB,yBAAiB,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,MAC5E;AACA,aAAO;AAAA,IACT,UAAE;AACA,eAAS,WAAW;AACpB,UAAI,QAAQ,WAAW,SAAS,YAAY,GAAG;AAC7C,oBAAY,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AACL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,oBAAoB,YAAY,MAAM,iBAAiB,IAAI,GAAG,CAAC,CAAC;AAAA,IAChE;AAAA,EACF;AACF;AAiBO,SAAS,uBACd,QACA,aACA,WACA,OACA,SACA,UAAmC,CAAC,GAC9B;AACN,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,SAAS,QAAQ;AACvB,QAAM,aAAa,WAAW;AAC9B,QAAM,WAAW,OAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,cAAc,OAAO,CAAC;AAC5B,QAAM,aAAa,OAAsB,IAAI;AAG7C,YAAU,MAAM;AACd,QAAI,CAAC,cAAc,CAAC,WAAW,CAAC,WAAW;AACzC;AAAA,IACF;AACA,UAAM,UAAU,GAAG,WAAW,KAAS,SAAS;AAChD,UAAM,gBAAgB,OAAO,CAAC,GAAG,YAAY;AAG7C,QAAI,WAAW,YAAY,WAAW,gBAAgB,YAAY,UAAU,GAAG;AAC7E,iBAAW,UAAU;AACrB,kBAAY,UAAU;AAAA,IACxB;AACA,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,YAAY,YAAY,SAAS;AACzC;AAAA,MACF;AACA,kBAAY,UAAU,MAAM;AAC5B,UAAI,SAAS,QAAQ,KAAK,GAAG;AAC3B,mBAAW,QAAQ,KAAK;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,YAAY,SAAS,QAAQ,aAAa,SAAS,CAAC;AAGxD,YAAU,MAAM;AACd,QAAI,cAAc,CAAC,WAAW,CAAC,WAAW;AACxC;AAAA,IACF;AACA,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,UAAU,MAAM,OAAO,WAAW,aAAa,SAAS;AAC9D,YAAI,WAAW,OAAO,SAAS;AAC7B;AAAA,QACF;AACA,cAAM,SAAS,OAAO,aAAa,aAAa,WAAW;AAAA,UACzD,OAAO,QAAQ;AAAA,UACf,QAAQ,WAAW;AAAA,QACrB,CAAC;AACD,yBAAiB,SAAS,QAAQ;AAChC,cAAI,SAAS,QAAQ,KAAK,GAAG;AAC3B,uBAAW,QAAQ,KAAK;AAAA,UAC1B;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAGR;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AACX,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,YAAY,SAAS,QAAQ,aAAa,SAAS,CAAC;AAC1D;AAGO,SAAS,qBAAqB,UAAsB,UAAU,KAAiB;AACpF,QAAM,cAAc,OAAO,QAAQ;AACnC,cAAY,UAAU;AACtB,QAAM,WAAW,OAA6C,IAAI;AAClE,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,SAAS,YAAY,MAAM;AAC7B,qBAAa,SAAS,OAAO;AAAA,MAC/B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AACL,SAAO,YAAY,MAAM;AACvB,QAAI,SAAS,YAAY,MAAM;AAC7B,mBAAa,SAAS,OAAO;AAAA,IAC/B;AACA,aAAS,UAAU,WAAW,MAAM;AAClC,eAAS,UAAU;AACnB,kBAAY,QAAQ;AAAA,IACtB,GAAG,OAAO;AAAA,EACZ,GAAG,CAAC,OAAO,CAAC;AACd;;;ADxNO,SAAS,WAAW,WAAsC,UAA6B,CAAC,GAAqB;AAClH,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,OAAOC,aAAY,YAAY;AACnC,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AACA,WAAO,MAAM,OAAO,WAAW,aAAa,SAAS;AAAA,EACvD,GAAG,CAAC,QAAQ,aAAa,SAAS,CAAC;AACnC,QAAM,QAAQ,eAAe,MAAM;AAAA,IACjC,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ,WAAW,SAAS,QAAQ,SAAS;AAAA,EACzD,CAAC;AACD,SAAO,EAAE,SAAS,MAAM,QAAQ,MAAM,SAAS,MAAM,SAAS,OAAO,MAAM,OAAO,SAAS,MAAM,QAAQ;AAC3G;;;AE/BA,SAAS,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACA9C,SAAS,mBAAmB,KAAa,MAAY,oBAAI,KAAK,GAAW;AAC9E,QAAM,OAAO,IAAI,KAAK,GAAG,EAAE,QAAQ;AACnC,MAAI,OAAO,MAAM,IAAI,GAAG;AACtB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,QAAQ,IAAI,QAAQ,GAAI,CAAC;AACrE,MAAI,UAAU,IAAI;AAChB,WAAO;AAAA,EACT;AACA,MAAI,UAAU,IAAI;AAChB,WAAO,GAAG,OAAO;AAAA,EACnB;AACA,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,MAAI,UAAU,IAAI;AAChB,WAAO,GAAG,OAAO;AAAA,EACnB;AACA,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,MAAI,QAAQ,IAAI;AACd,WAAO,GAAG,KAAK;AAAA,EACjB;AACA,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,MAAI,OAAO,IAAI;AACb,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,SAAO,IAAI,KAAK,GAAG,EAAE,mBAAmB;AAC1C;AAGO,SAAS,YAAY,OAAuB;AACjD,MAAI,QAAQ,MAAM;AAChB,WAAO,GAAG,KAAK;AAAA,EACjB;AACA,QAAM,QAAQ,CAAC,MAAM,MAAM,IAAI;AAC/B,MAAI,QAAQ,QAAQ;AACpB,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,QAAQ,SAAS,MAAM;AACjC,aAAO,GAAG,MAAM,QAAQ,QAAQ,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI;AAAA,IACrD;AACA,aAAS;AAAA,EACX;AACA,SAAO,GAAG,KAAK;AACjB;AAGO,SAAS,SAAS,MAAc,WAA2B;AAChE,QAAM,YAAY,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACjD,MAAI,UAAU,UAAU,WAAW;AACjC,WAAO;AAAA,EACT;AACA,SAAO,GAAG,UAAU,MAAM,GAAG,KAAK,IAAI,GAAG,YAAY,CAAC,CAAC,EAAE,QAAQ,CAAC;AACpE;AAGO,SAAS,iBAAiB,OAAwB;AACvD,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAS,aAAa,KAAK;AACjC,QAAI,WAAW,UAAa,OAAO,WAAW,UAAU;AACtD,aAAO,iBAAiB,MAAM;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,UAAU,OAAO,MAAM,CAAC,KAAK,OAAO,KAAK;AAAA,EACvD,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAGO,SAAS,aAAa,MAAuB;AAClD,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,GAAG;AACpF,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACyCA,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AAErB,SAAS,cAAc,QAAwC;AACpE,QAAM,QAAwB,CAAC;AAC/B,QAAM,UAAU,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAElE,QAAM,OAAO,MAAgC,MAAM,MAAM,SAAS,CAAC;AAGnE,QAAM,qBAAqB,MAAY;AACrC,UAAM,OAAO,KAAK;AAClB,SAAK,MAAM,SAAS,mBAAmB,MAAM,SAAS,gBAAgB,KAAK,WAAW;AACpF,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,WAAiC;AACrD,eAAW,QAAQ,OAAO;AACxB,UAAI,WAAW,UAAa,YAAY,QAAQ,KAAK,UAAU,UAAU,KAAK,WAAW,QAAQ;AAC/F;AAAA,MACF;AACA,WAAK,KAAK,SAAS,mBAAmB,KAAK,SAAS,gBAAgB,KAAK,WAAW;AAClF,aAAK,YAAY;AAAA,MACnB;AACA,WAAK,KAAK,SAAS,eAAe,KAAK,SAAS,aAAa,KAAK,WAAW,WAAW;AACtF,aAAK,SAAS;AAAA,MAChB;AACA,UAAI,KAAK,SAAS,aAAa,KAAK,WAAW,WAAW;AACxD,aAAK,SAAS;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,UAAM,UAAU,SAAS,MAAM,OAAO;AACtC,UAAM,SAAS,MAAM,UAAU;AAE/B,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,gBAAgB;AAGnB,2BAAmB;AACnB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV,MAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAAA,UACxD,WAAW,aAAa,QAAQ,SAAS;AAAA,UACzC,OAAO,SAAS,QAAQ,KAAK;AAAA,UAC7B,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,uBAAuB;AAC1B,cAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAC/D,YAAI,CAAC,MAAM;AACT;AAAA,QACF;AACA,cAAM,OAAO,KAAK;AAClB,YAAI,MAAM,SAAS,mBAAmB,KAAK,aAAa,KAAK,WAAW,QAAQ;AAC9E,eAAK,QAAQ;AACb;AAAA,QACF;AACA,2BAAmB;AACnB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,2BAA2B;AAC9B,cAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAI/D,cAAM,OAAO,CAAC,GAAG,KAAK,EACnB,QAAQ,EACR,KAAK,CAAC,SAAmC,KAAK,SAAS,mBAAmB,KAAK,WAAW,MAAM;AACnG,YAAI,SAAS,KAAK,aAAa,CAAC,KAAK,QAAQ,SAAS,KAAK,QAAQ,KAAK,WAAW,KAAK,IAAI,IAAI;AAE9F,cAAI,CAAC,KAAK,QAAS,QAAQ,KAAK,WAAW,KAAK,IAAI,GAAI;AACtD,iBAAK,OAAO,QAAQ,KAAK;AAAA,UAC3B;AACA,eAAK,YAAY;AACjB;AAAA,QACF;AACA,YAAI,MAAM;AACR,gBAAM,KAAK;AAAA,YACT,MAAM;AAAA,YACN,IAAI,MAAM;AAAA,YACV;AAAA,YACA;AAAA,YACA,WAAW;AAAA,YACX,YAAY,MAAM;AAAA,UACpB,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MAEA,KAAK,yBAAyB;AAC5B,cAAM,OAAO,cAAc,MAAM,OAAO;AACxC,YAAI,CAAC,MAAM;AACT;AAAA,QACF;AACA,cAAM,OAAO,KAAK;AAClB,YAAI,MAAM,SAAS,eAAe,KAAK,aAAa,KAAK,WAAW,QAAQ;AAC1E,eAAK,QAAQ;AACb;AAAA,QACF;AACA,2BAAmB;AACnB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,0BAA0B;AAC7B,cAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAC/D,cAAM,SAAS,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAC7D,cAAM,OAAO,QAAQ,aAAa;AAClC,2BAAmB;AACnB,YAAI,SAAS,qBAAqB,SAAS,qBAAqB;AAC9D,gBAAM,KAAK;AAAA,YACT,MAAM;AAAA,YACN,IAAI,MAAM;AAAA,YACV;AAAA,YACA;AAAA,YACA,QAAQ,SAAS,oBAAoB,UAAU;AAAA,YAC/C,QAAQ,aAAa,IAAI;AAAA,YACzB,iBAAiB,kBAAkB,IAAI;AAAA,YACvC,QAAQ;AAAA,YACR,YAAY,MAAM;AAAA,UACpB,CAAC;AACD;AAAA,QACF;AACA,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,yBAAyB;AAC5B,cAAM,SAAS,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAC7D,cAAM,SAAS,aAAa,OAAO,MAAM;AACzC,YAAI,CAAC,QAAQ;AACX;AAAA,QACF;AACA,YAAI,OAAO,SAAS,UAAU;AAC5B,iBAAO,SAAS;AAChB,iBAAO,kBAAkB,OAAO,mBAAmB,kBAAkB,QAAQ,MAAM;AACnF;AAAA,QACF;AACA,eAAO,SAAS;AAChB,eAAO,SAAS,QAAQ;AACxB;AAAA,MACF;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,4BAA4B;AAC/B,cAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAC/D,cAAM,SAAS,MAAM,KAAK,SAAS,SAAS,IAAI,WAAW,MAAM,KAAK,SAAS,YAAY,IAAI,aAAa;AAC5G,cAAM,WAAW,gBAAgB,OAAO,IAAI;AAC5C,YAAI,YAAY,WAAW,WAAW;AACpC,mBAAS,SAAS;AAClB,gBAAM,UAAU,eAAe,OAAO;AACtC,cAAI,SAAS;AACX,qBAAS,SAAS,SAAS,SAAS,GAAG,SAAS,MAAM;AAAA,EAAK,OAAO,KAAK;AAAA,UACzE;AACA;AAAA,QACF;AACA,YAAI,CAAC,UAAU;AACb,6BAAmB;AACnB,gBAAM,KAAK;AAAA,YACT,MAAM;AAAA,YACN,IAAI,MAAM;AAAA,YACV;AAAA,YACA;AAAA,YACA,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;AAAA,YACjE,QAAQ,eAAe,OAAO,KAAK;AAAA,YACnC;AAAA,YACA,YAAY,MAAM;AAAA,UACpB,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MAEA,KAAK,gCAAgC;AACnC,cAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;AACrH,YAAI,CAAC,MAAM;AACT;AAAA,QACF;AAGA,cAAM,QACH,OAAO,QAAQ,SAAS,WAAW,gBAAgB,OAAO,QAAQ,IAAI,IAAI,WAC3E,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,SAA8B,KAAK,SAAS,aAAa,KAAK,WAAW,SAAS;AAC/G,YAAI,MAAM;AACR,eAAK,UAAU;AAAA,QACjB;AACA;AAAA,MACF;AAAA,MAEA,KAAK,0BAA0B;AAC7B,cAAM,SAAS,QAAQ;AACvB,YAAI,CAAC,gBAAgB,MAAM,GAAG;AAC5B;AAAA,QACF;AACA,cAAM,WAAW,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAoC,KAAK,SAAS,gBAAgB;AAC9G,YAAI,UAAU,WAAW,QAAQ;AAC/B;AAAA,QACF;AACA,cAAM,KAAK,EAAE,MAAM,kBAAkB,IAAI,MAAM,IAAI,QAAQ,YAAY,MAAM,WAAW,CAAC;AACzF;AAAA,MACF;AAAA,MAEA,KAAK,0BAA0B;AAC7B,qBAAa,MAAM;AACnB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AACrB,qBAAa,MAAM;AACnB;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAClB,qBAAa,MAAM;AACnB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV,MAAM;AAAA,UACN,MAAM,eAAe,OAAO,KAAK;AAAA,UACjC,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AACrB,qBAAa,MAAM;AACnB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,qBAAqB;AACxB,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM;AAAA,UACV,QAAQ,MAAM,KAAK,MAAM,QAAQ,MAAM;AAAA,UACvC,MAAM,SAAS,OAAO;AAAA,UACtB,YAAY,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACF;AAAA,MAEA;AACE;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,wBAAwB,QAA8C;AACpF,WAAS,QAAQ,OAAO,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC1D,UAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,OAAO,SAAS,0BAA0B;AAC5C;AAAA,IACF;AACA,UAAM,SAAS,SAAS,MAAM,OAAO,EAAE;AACvC,QAAI,gBAAgB,MAAM,GAAG;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAWA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,aAAa,aAAa,UAAU,SAAS,CAAC;AAEvE,SAAS,cAAc,OAAwC;AACpE,QAAM,SAA0B,CAAC;AACjC,aAAW,QAAQ,OAAO;AACxB,QAAI,eAAe,IAAI,KAAK,IAAI,GAAG;AACjC,YAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,YAAM,WAAW;AACjB,UAAI,MAAM,SAAS,YAAY;AAC7B,aAAK,MAAM,KAAK,QAAQ;AAAA,MAC1B,OAAO;AACL,eAAO,KAAK,EAAE,MAAM,YAAY,IAAI,YAAY,KAAK,EAAE,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;AAAA,MAChF;AACA;AAAA,IACF;AACA,WAAO,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,EACpC;AACA,SAAO;AACT;AAIA,SAAS,SAAS,OAAyC;AACzD,SAAO,UAAU,QAAQ,OAAO,UAAU,WAAY,QAAoC,CAAC;AAC7F;AAEA,IAAM,mBAA6C,CAAC,UAAU,WAAW,QAAQ,mBAAmB,UAAU,WAAW;AAGzH,SAAS,aAAa,OAA+B;AACnD,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AACA,SAAO,MAAM,OAAO,CAAC,UAAgC;AACnD,UAAM,SAAS,SAAS,KAAK;AAC7B,QAAI,OAAO,SAAS,cAAc;AAChC,aAAO,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,QAAQ;AAAA,IACjE;AACA,WAAO,OAAO,SAAS,UAAU,OAAO,OAAO,WAAW;AAAA,EAC5D,CAAC;AACH;AAEA,SAAS,SAAS,OAA2B;AAC3C,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AACA,SAAO,MAAM,OAAO,CAAC,UAA4B;AAC/C,UAAM,SAAS,SAAS,KAAK;AAC7B,WAAO,OAAO,SAAS,SAAS,OAAO,OAAO,OAAO;AAAA,EACvD,CAAC;AACH;AAEA,SAAS,gBAAgB,OAAwC;AAC/D,SAAO,OAAO,UAAU,YAAa,iBAAuC,SAAS,KAAK;AAC5F;AAEA,SAAS,aAAa,OAAuB,QAA8D;AACzG,QAAM,WAAW,CAAC,GAAG,KAAK,EAAE,QAAQ;AACpC,QAAM,SAAS,CAAC,SAA0D,KAAK,SAAS,eAAe,KAAK,SAAS;AACrH,MAAI,QAAQ;AACV,UAAM,OAAO,SAAS,KAAK,CAAC,SAAS,OAAO,IAAI,KAAK,KAAK,WAAW,MAAM;AAC3E,QAAI,MAAM;AACR,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,SAAS,KAAK,CAAC,SAA4C,OAAO,IAAI,KAAK,KAAK,WAAW,SAAS;AAC7G;AAEA,SAAS,gBAAgB,OAAuB,MAAuC;AACrF,SAAO,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,SAA8B,KAAK,SAAS,aAAa,KAAK,SAAS,QAAQ,KAAK,WAAW,SAAS;AAC5I;AAEA,SAAS,eAAe,SAAiD;AACvE,aAAW,OAAO,CAAC,SAAS,SAAS,GAAY;AAC/C,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,GAAG;AACxD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,SAAiD;AACjE,MAAI,OAAO,QAAQ,SAAS,YAAY,QAAQ,MAAM;AACpD,WAAO,QAAQ;AAAA,EACjB;AACA,QAAM,OAAO,SAAS,QAAQ,IAAI;AAClC,MAAI,OAAO,KAAK,SAAS,YAAY,KAAK,MAAM;AAC9C,WAAO,KAAK;AAAA,EACd;AACA,MAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,QAAQ;AACxD,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AAEA,SAAS,cAAc,SAA0B;AAC/C,QAAM,SAAS,SAAS,OAAO;AAC/B,MAAI,OAAO,OAAO,SAAS,UAAU;AACnC,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,UAAU,SAAS,SAAS,OAAO,IAAI,EAAE,OAAO,EAAE;AACxD,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,QACJ,IAAI,CAAC,SAAS;AACb,UAAM,OAAO,SAAS,IAAI,EAAE;AAC5B,WAAO,OAAO,SAAS,WAAW,OAAO;AAAA,EAC3C,CAAC,EACA,KAAK,EAAE;AACZ;AAGA,SAAS,aAAa,MAA8B;AAClD,QAAM,SAAS,SAAS,OAAO,SAAS,WAAW,aAAa,IAAI,IAAI,IAAI;AAC5E,aAAW,OAAO,CAAC,kBAAkB,WAAW,QAAQ,QAAQ,GAAY;AAC1E,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,GAAG;AACxD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,kBAAkB,OAAgB,QAAQ,GAAkB;AAC1E,MAAI,QAAQ,KAAK,UAAU,QAAQ,UAAU,QAAW;AACtD,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,kBAAkB,aAAa,KAAK,GAAG,QAAQ,CAAC;AAAA,EACzD;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,eAAW,SAAS,OAAO;AACzB,YAAM,QAAQ,kBAAkB,OAAO,QAAQ,CAAC;AAChD,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,cAAc,YAAY,YAAY,OAAO,SAAS,GAAG;AACzE,WAAO,OAAO;AAAA,EAChB;AACA,MAAI,OAAO,OAAO,OAAO,YAAY,YAAY,OAAO,EAAE,MAAM,YAAY,UAAU,iBAAiB,UAAU,oBAAoB,SAAS;AAC5I,WAAO,OAAO;AAAA,EAChB;AACA,aAAW,OAAO,CAAC,qBAAqB,WAAW,UAAU,SAAS,GAAY;AAChF,QAAI,OAAO,QAAQ;AACjB,YAAM,QAAQ,kBAAkB,OAAO,GAAG,GAAG,QAAQ,CAAC;AACtD,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,OAAO,SAAS,UAAU;AACnC,WAAO,kBAAkB,aAAa,OAAO,IAAI,GAAG,QAAQ,CAAC;AAAA,EAC/D;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAwB;AAC3C,SAAO,kEAAkE,KAAK,KAAK;AACrF;AAGO,SAAS,gBAAgB,MAAsB;AACpD,SAAO,KAAK,QAAQ,UAAU,GAAG,EAAE,KAAK;AAC1C;AAGO,SAAS,sBAAsB,OAAgB,YAAY,KAAa;AAC7E,QAAM,OAAO,iBAAiB,KAAK,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAC/D,SAAO,KAAK,SAAS,YAAY,GAAG,KAAK,MAAM,GAAG,YAAY,CAAC,CAAC,WAAM;AACxE;;;AFvlBO,SAAS,iBAAiB,WAAsC,UAAmC,CAAC,GAA2B;AACpI,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,QAAQ,QAAQ,SAAS;AAE/B,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAyB,CAAC,CAAC;AACvD,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,UAAuC,MAAM;AAC3F,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AACrD,QAAM,kBAAkBC,QAAO,KAAK;AACpC,QAAM,eAAeA,QAAsB,IAAI;AAE/C,EAAAC,WAAU,MAAM;AAGd,UAAM,YAAY,GAAG,WAAW,KAAS,aAAa,EAAE,KAAS,KAAK;AACtE,QAAI,aAAa,YAAY,WAAW;AACtC,mBAAa,UAAU;AACvB,gBAAU,CAAC,CAAC;AACZ,eAAS,IAAI;AACb,sBAAgB,UAAU;AAAA,IAC5B;AACA,QAAI,CAAC,aAAa,CAAC,SAAS;AAC1B,yBAAmB,MAAM;AACzB;AAAA,IACF;AACA,UAAM,aAAa,IAAI,gBAAgB;AAGvC,QAAI,UAA0B,CAAC;AAC/B,QAAI,aAAmD;AACvD,UAAM,QAAQ,MAAM;AAClB,mBAAa;AACb,UAAI,QAAQ,WAAW,GAAG;AACxB;AAAA,MACF;AACA,YAAM,QAAQ;AACd,gBAAU,CAAC;AAIX,YAAM,cAAc,MAAM,MAAM,SAAS,CAAC;AAC1C,UAAI,aAAa;AACf,wBAAgB,UAAU,YAAY;AAAA,MACxC;AACA,gBAAU,CAAC,aAAa,CAAC,GAAG,UAAU,GAAG,KAAK,CAAC;AAAA,IACjD;AACA,UAAM,gBAAgB,MAAM;AAC1B,qBAAe,WAAW,OAAO,EAAE;AAAA,IACrC;AAEA,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,SAAS,OAAO,aAAa,aAAa,WAAW;AAAA,UACzD,OAAO,gBAAgB;AAAA,UACvB,QAAQ,WAAW;AAAA,UACnB,eAAe,CAAC,UAAU;AACxB,gBAAI,CAAC,WAAW,OAAO,SAAS;AAC9B,iCAAmB,KAAK;AAAA,YAC1B;AAAA,UACF;AAAA,QACF,CAAC;AACD,yBAAiB,SAAS,QAAQ;AAChC,kBAAQ,KAAK,KAAK;AAClB,wBAAc;AAAA,QAChB;AACA,YAAI,CAAC,WAAW,OAAO,SAAS;AAC9B,gBAAM;AACN,6BAAmB,OAAO;AAAA,QAC5B;AAAA,MACF,SAAS,OAAO;AACd,YAAI,CAAC,WAAW,OAAO,SAAS;AAC9B,gBAAM;AACN,mBAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAClE,6BAAmB,OAAO;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,GAAG;AAEH,WAAO,MAAM;AACX,iBAAW,MAAM;AACjB,UAAI,eAAe,MAAM;AACvB,qBAAa,UAAU;AAAA,MACzB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,WAAW,OAAO,OAAO,CAAC;AAEnD,QAAM,WAAWC,SAAQ,MAAM,cAAc,MAAM,GAAG,CAAC,MAAM,CAAC;AAC9D,QAAM,gBAAgBA,SAAQ,MAAM,wBAAwB,MAAM,GAAG,CAAC,MAAM,CAAC;AAE7E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,gBAAgB;AAAA,IAC9B;AAAA,EACF;AACF;;;AGhIA,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAgDlD,SAAS,YAAY,WAAsC,UAA8B,CAAC,GAAkB;AACjH,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,EAAE;AACrC,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAuB,WAAW;AAC1D,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,IAAIA,UAAS,KAAK;AACtD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AACrD,QAAM,uBAAuBC,QAAsB,IAAI;AACvD,QAAM,SAAS,QAAQ;AAEvB,QAAM,UAAUA,QAAO,IAAI;AAC3B,UAAQ,UAAU;AAGlB,QAAM,gBAAgBA,QAAO,QAAQ,UAAU;AAC/C,gBAAc,UAAU,QAAQ;AAIhC,QAAM,YAAY,GAAG,WAAW,KAAS,aAAa,EAAE;AACxD,QAAM,eAAeA,QAAO,SAAS;AACrC,EAAAC,WAAU,MAAM;AACd,QAAI,aAAa,YAAY,WAAW;AACtC,mBAAa,UAAU;AACvB,2BAAqB,UAAU;AAC/B,eAAS,EAAE;AACX,eAAS,IAAI;AACb,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,WAAW,WAAW,CAAC;AAE3B,QAAM,OAAOC;AAAA,IACX,OAAO,aAAwC;AAC7C,YAAM,cAAc;AACpB,YAAM,QAAQ,YAAY,aAAa,KAAK;AAG5C,YAAM,SAAS,kBAAkB,cAAc,OAAO;AACtD,YAAM,gBAAgB,OAAO,WAAW,UAAU,KAAK;AACvD,UAAK,CAAC,QAAQ,CAAC,gBAAiB,CAAC,aAAa,SAAS;AACrD,eAAO;AAAA,MACT;AAGA,2BAAqB,YAAY,sBAAsB;AACvD,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AAIF,cAAM,WAAW,QAAQ;AACzB,cAAM,QAAQ,iBAAiB,UAAU,qBAAqB,SAAS,MAAM;AAC7E,YAAI,QAAQ,YAAY,SAAS;AAC/B,gBAAM,OAAO,aAAa,aAAa,WAAW,KAAK;AAAA,QACzD,OAAO;AACL,gBAAM,OAAO,YAAY,aAAa,WAAW,KAAK;AAAA,QACxD;AACA,6BAAqB,UAAU;AAC/B,YAAI,aAAa,QAAW;AAG1B,mBAAS,CAAC,YAAa,YAAY,cAAc,KAAK,OAAQ;AAAA,QAChE;AACA,iBAAS,QAAQ;AACjB,eAAO;AAAA,MACT,SAAS,OAAO;AACd,iBAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAClE,eAAO;AAAA,MACT,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,OAAO,SAAS,MAAM;AAAA,EACzD;AAOA,QAAM,qBAAqB,kBAAkB,cAAc,OAAO,EAAE,WAAW,UAAU,KAAK;AAE9F,QAAM,YAAYA;AAAA,IAChB,OAAO,WAAmC;AACxC,UAAI,CAAC,aAAa,cAAc;AAC9B;AAAA,MACF;AACA,sBAAgB,IAAI;AACpB,eAAS,IAAI;AACb,UAAI;AACF,cAAM,OAAO,UAAU,aAAa,WAAW,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC,CAAC;AAAA,MACvF,SAAS,OAAO;AACd,iBAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,MACpE,UAAE;AACA,wBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,YAAY;AAAA,EAC/C;AAEA,QAAM,cAAcA,aAAY,CAAC,SAAiB;AAChD,yBAAqB,UAAU;AAC/B,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,SAAS,QAAQ,SAAS,KAAK,CAAC,YAAY,MAAM,KAAK,EAAE,SAAS,KAAK;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAYA,aAAY,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AAAA,EAClD;AACF;AAQO,IAAM,yBAAyB;AAG/B,SAAS,kBACd,QACoB;AACpB,UAAQ,OAAO,WAAW,aAAa,OAAO,IAAI,WAAW,CAAC;AAChE;AAMO,SAAS,iBACd,MACA,eACA,QACkB;AAClB,SAAO,EAAE,GAAG,kBAAkB,MAAM,GAAG,MAAM,cAAc;AAC7D;AAGO,SAAS,kBAAkB,OAA6F;AAC7H,MAAI,MAAM,QAAQ,WAAW,MAAM,UAAU;AAC3C,WAAO;AAAA,EACT;AACA,SAAO,MAAM,aAAa,gBAAgB;AAC5C;AAEA,SAAS,wBAAgC;AACvC,QAAM,YAAY,WAAW;AAC7B,MAAI,aAAa,gBAAgB,WAAW;AAC1C,WAAO,UAAU,WAAW;AAAA,EAC9B;AACA,SAAO,MAAM,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACpE;;;ACnNA,SAAS,eAAAC,cAAa,YAAAC,iBAAgB;AA8CtC,IAAM,UAAU,CAAC,SAAwB,KAAK,KAAK,WAAW,QAAQ;AAW/D,SAAS,mBAAmB,UAAqC,CAAC,GAA6B;AACpG,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,CAAC,aAAa,cAAc,IAAIC,UAA2B,CAAC,CAAC;AAEnE,QAAM,WAAWC,aAAY,CAAC,UAA0B;AACtD,eAAW,QAAQ,OAAO;AACxB,YAAM,KAAK,OAAO,WAAW;AAC7B,YAAM,aAAa,QAAQ,IAAI,IAAI,IAAI,gBAAgB,IAAI,IAAI;AAC/D,qBAAe,CAAC,YAAY,CAAC,GAAG,SAAS;AAAA,QACvC;AAAA,QACA,MAAM,KAAK,QAAQ;AAAA,QACnB,aAAa,KAAK,QAAQ;AAAA,QAC1B,WAAW,KAAK;AAAA,QAChB,QAAQ;AAAA,QACR,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,MACrC,CAAC,CAAC;AACF,WAAK,OAAO,WAAW,aAAa;AAAA,QAClC,UAAU,KAAK,QAAQ;AAAA,QACvB,aAAa,KAAK,QAAQ;AAAA,QAC1B,MAAM;AAAA,MACR,CAAC,EAAE,KAAK,CAAC,UAAU;AACjB,uBAAe,CAAC,YAAY,QAAQ,IAAI,CAAC,eAAe,WAAW,OAAO,KACtE,EAAE,GAAG,YAAY,QAAQ,SAAS,MAAM,OAAO,MAAM,MAAM,UAAU,aAAa,MAAM,aAAa,WAAW,MAAM,UAAU,IAChI,UAAU,CAAC;AAAA,MACjB,CAAC,EAAE,MAAM,CAAC,UAAmB;AAC3B,uBAAe,CAAC,YAAY,QAAQ,IAAI,CAAC,eAAe,WAAW,OAAO,KACtE,EAAE,GAAG,YAAY,QAAQ,UAAU,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,IACjG,UAAU,CAAC;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,QAAQ,WAAW,CAAC;AAExB,QAAM,eAAeA,aAAY,CAAC,UAAkD;AAClF,UAAM,iBAAiB,MAAM,eAAe;AAC5C,QAAI,CAAC,gBAAgB;AACnB;AAAA,IACF;AACA,UAAM,QAAQ,CAAC,GAAG,cAAc,EAAE,OAAO,WAAW;AACpD,QAAI,MAAM,SAAS,GAAG;AACpB,eAAS,KAAK;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,UAAU,WAAW,CAAC;AAE1B,QAAM,SAASA,aAAY,CAAC,OAAe;AACzC,mBAAe,CAAC,YAAY;AAC1B,YAAM,UAAU,QAAQ,KAAK,CAAC,eAAe,WAAW,OAAO,EAAE;AACjE,UAAI,SAAS,YAAY;AACvB,YAAI,gBAAgB,QAAQ,UAAU;AAAA,MACxC;AACA,aAAO,QAAQ,OAAO,CAAC,eAAe,WAAW,OAAO,EAAE;AAAA,IAC5D,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQA,aAAY,MAAM;AAC9B,mBAAe,CAAC,YAAY;AAC1B,iBAAW,cAAc,SAAS;AAChC,YAAI,WAAW,YAAY;AACzB,cAAI,gBAAgB,WAAW,UAAU;AAAA,QAC3C;AAAA,MACF;AACA,aAAO,CAAC;AAAA,IACV,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA,gBAAgB,YAAY,QAAQ,CAAC,eAAkC,WAAW,WAAW,WAAW,WAAW,OAC/G,CAAC,EAAE,MAAM,QAAQ,QAAQ,WAAW,KAAK,GAAG,CAAC,IAC7C,CAAC,CAAC;AAAA,IACN,WAAW,YAAY,KAAK,CAAC,eAAe,WAAW,WAAW,WAAW;AAAA,IAC7E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACrIA,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAKlD,SAAS,iBAAiB,OAA4C;AAC3E,SAAO,MAAM,KAAK,WAAW,OAAO;AACtC;AAGO,SAAS,eAAe,OAAqC;AAClE,SAAO,MACJ,OAAO,CAAC,SAAS,KAAK,WAAW,QAAQ,EACzC,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,cAAc,EAAE,SAAS,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACjH;AAGO,SAAS,oBAAoB,OAA0C;AAC5E,SAAO,MAAM,KAAK,CAAC,SAAS,KAAK,WAAW,aAAa,KAAK,WAAW,iBAAiB,KAAK;AACjG;AAGO,SAAS,cAAc,OAAsB,QAAgB,QAAiD;AACnH,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,QAAI,KAAK,OAAO,UAAU,KAAK,WAAW,UAAU;AAClD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAI,OAAO,WAAW,SAAY,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,MAC/D,GAAI,OAAO,cAAc,SAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,MACxE,GAAI,OAAO,UAAU,SAAY,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,MAC5D,GAAI,OAAO,UAAU,SAAY,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,MAC5D,GAAI,OAAO,oBAAoB,SAAY,EAAE,iBAAiB,OAAO,gBAAgB,IAAI,CAAC;AAAA,MAC1F,GAAI,OAAO,mBAAmB,SAAY,EAAE,gBAAgB,OAAO,eAAe,IAAI,CAAC;AAAA,MACvF,GAAI,OAAO,aAAa,SAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,IACvE;AAAA,EACF,CAAC;AACH;AAOO,SAAS,iBAAiB,OAAsB,SAAkC;AACvF,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,QAAQ,CAAC,CAAU,CAAC;AACtF,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,WAAW,UAAU,IAAI,KAAK,EAAE;AACtC,WAAO,aAAa,UAAa,KAAK,WAAW,WAAW,EAAE,GAAG,MAAM,SAAS,IAAI;AAAA,EACtF,CAAC;AACH;AAGO,SAAS,iBAAiB,OAAsB,QAA+B;AACpF,SAAO,MAAM,IAAI,CAAC,SAAU,KAAK,OAAO,UAAU,KAAK,WAAW,WAAW,EAAE,GAAG,MAAM,QAAQ,YAAqB,IAAI,IAAK;AAChI;AAsCO,SAAS,aAAa,WAAsC,UAA+B,CAAC,GAAuB;AACxH,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,WAAW,QAAQ,WAAW,SAAS,QAAQ,SAAS;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAwB,CAAC,CAAC;AACpD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,OAAO;AAC9C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AACrD,QAAM,WAAW,kBAAkB;AACnC,QAAM,aAAaC,QAAO,CAAC;AAC3B,QAAM,eAAeA,QAAsB,IAAI;AAE/C,QAAM,OAAOC,aAAY,YAA2B;AAClD,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AACA,UAAM,SAAS,EAAE,WAAW;AAC5B,QAAI;AACF,YAAM,UAAU,MAAM,OAAO,UAAU,aAAa,SAAS;AAC7D,UAAI,WAAW,WAAW,SAAS;AACjC,iBAAS,OAAO;AAChB,iBAAS,IAAI;AACb,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF,SAAS,OAAO;AACd,UAAI,WAAW,WAAW,SAAS;AACjC,iBAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAClE,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,SAAS,CAAC;AAGnC,EAAAC,WAAU,MAAM;AACd,UAAM,YAAY,GAAG,WAAW,KAAS,aAAa,EAAE;AACxD,QAAI,aAAa,YAAY,WAAW;AACtC,mBAAa,UAAU;AACvB,eAAS,CAAC,CAAC;AACX,eAAS,IAAI;AAAA,IACf;AACA,QAAI,CAAC,SAAS;AACZ,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,eAAW,IAAI;AACf,SAAK,KAAK;AACV,UAAM,iBAAiB,QAAQ;AAC/B,QAAI,mBAAmB,UAAa,kBAAkB,GAAG;AACvD,aAAO,MAAM;AACX,mBAAW,WAAW;AAAA,MACxB;AAAA,IACF;AACA,UAAM,QAAQ,YAAY,MAAM,KAAK,KAAK,GAAG,cAAc;AAC3D,WAAO,MAAM;AACX,oBAAc,KAAK;AACnB,iBAAW,WAAW;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,MAAM,SAAS,aAAa,WAAW,QAAQ,cAAc,CAAC;AAGlE,QAAM,kBAAkB,qBAAqB,MAAM,KAAK,KAAK,CAAC;AAC9D,yBAAuB,QAAQ,aAAa,WAAW,kBAAkB,iBAAiB;AAAA,IACxF;AAAA,IACA,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACnE,CAAC;AAED,QAAM,WAAWD;AAAA,IACf,OAAO,QAAgB,WAAkE;AACvF,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,eAAS,CAAC,YAAY,cAAc,SAAS,QAAQ,MAAM,CAAC;AAC5D,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,iBAAiB,aAAa,WAAW,QAAQ,MAAM,CAAC;AACvG,UAAI,QAAQ;AACV,iBAAS,CAAC,YAAY,QAAQ,IAAI,CAAC,SAAU,KAAK,OAAO,OAAO,KAAK,SAAS,IAAK,CAAC;AAAA,MACtF,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,SAAS,KAAK,IAAI;AAAA,EACrD;AAEA,QAAM,eAAeA;AAAA,IACnB,OAAO,YAAqD;AAC1D,UAAI,CAAC,aAAa,QAAQ,WAAW,GAAG;AACtC,eAAO;AAAA,MACT;AACA,eAAS,CAAC,YAAY,iBAAiB,SAAS,OAAO,CAAC;AACxD,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,mBAAmB,aAAa,WAAW,OAAO,CAAC;AAClG,UAAI,QAAQ;AAEV,iBAAS,CAAC,YAAY;AACpB,gBAAM,QAAQ,IAAI,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAU,CAAC;AACpE,iBAAO,QAAQ,IAAI,CAAC,SAAS,MAAM,IAAI,KAAK,EAAE,KAAK,IAAI;AAAA,QACzD,CAAC;AAAA,MACH,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,SAAS,KAAK,IAAI;AAAA,EACrD;AAEA,QAAM,aAAaA;AAAA,IACjB,OAAO,WAAgD;AACrD,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,eAAS,CAAC,YAAY,iBAAiB,SAAS,MAAM,CAAC;AACvD,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,iBAAiB,aAAa,WAAW,MAAM,CAAC;AAC/F,UAAI,QAAQ;AACV,iBAAS,CAAC,YAAY,QAAQ,IAAI,CAAC,SAAU,KAAK,OAAO,OAAO,KAAK,SAAS,IAAK,CAAC;AAAA,MACtF,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,SAAS,KAAK,IAAI;AAAA,EACrD;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,eAAe,KAAK;AAAA,IAC3B,YAAY,oBAAoB,KAAK;AAAA,IACrC;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,EAC/B;AACF;;;ACpOA,SAAS,wBAA6D;AACtE,SAAS,eAAAE,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAKlD,SAAS,YAAY,OAA4C;AACtE,SAAO,MAAM,KAAK,WAAW,OAAO;AACtC;AAiCO,SAAS,QAAQ,WAAsC,UAA0B,CAAC,GAAkB;AACzG,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,WAAW,QAAQ,WAAW,SAAS,QAAQ,SAAS;AAC9D,QAAM,CAAC,MAAM,OAAO,IAAIC,UAA6B,IAAI;AACzD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,OAAO;AAC9C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AACrD,QAAM,WAAW,kBAAkB;AACnC,QAAM,aAAaC,QAAO,CAAC;AAC3B,QAAM,eAAeA,QAAsB,IAAI;AAE/C,QAAM,OAAOC,aAAY,YAA2B;AAClD,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AACA,UAAM,SAAS,EAAE,WAAW;AAC5B,QAAI;AACF,YAAM,UAAU,MAAM,OAAO,QAAQ,aAAa,SAAS;AAC3D,UAAI,WAAW,WAAW,SAAS;AACjC,gBAAQ,OAAO;AACf,iBAAS,IAAI;AACb,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF,SAAS,OAAO;AACd,UAAI,WAAW,WAAW,SAAS;AACjC;AAAA,MACF;AACA,UAAI,iBAAiB,oBAAoB,MAAM,WAAW,KAAK;AAE7D,gBAAQ,IAAI;AACZ,iBAAS,IAAI;AAAA,MACf,OAAO;AACL,iBAAS,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,MACpE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,SAAS,CAAC;AAEnC,EAAAC,WAAU,MAAM;AACd,UAAM,YAAY,GAAG,WAAW,IAAI,aAAa,EAAE;AACnD,QAAI,aAAa,YAAY,WAAW;AACtC,mBAAa,UAAU;AACvB,cAAQ,IAAI;AACZ,eAAS,IAAI;AAAA,IACf;AACA,QAAI,CAAC,SAAS;AACZ,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,eAAW,IAAI;AACf,SAAK,KAAK;AACV,UAAM,iBAAiB,QAAQ;AAC/B,QAAI,mBAAmB,UAAa,kBAAkB,GAAG;AACvD,aAAO,MAAM;AACX,mBAAW,WAAW;AAAA,MACxB;AAAA,IACF;AACA,UAAM,QAAQ,YAAY,MAAM,KAAK,KAAK,GAAG,cAAc;AAC3D,WAAO,MAAM;AACX,oBAAc,KAAK;AACnB,iBAAW,WAAW;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,MAAM,SAAS,aAAa,WAAW,QAAQ,cAAc,CAAC;AAElE,QAAM,kBAAkB,qBAAqB,MAAM,KAAK,KAAK,CAAC;AAC9D,yBAAuB,QAAQ,aAAa,WAAW,aAAa,iBAAiB;AAAA,IACnF;AAAA,IACA,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACnE,CAAC;AAED,QAAM,QAAQD;AAAA,IACZ,OAAO,cAAoD;AACzD,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,YAAM,SAAS,MAAM,SAAS,IAAI,MAChC,OAAO,WAAW,aAAa,WAAW;AAAA,QACxC,QAAQ;AAAA,QACR,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjD,CAAC,CAAC;AACJ,UAAI,QAAQ;AACV,gBAAQ,MAAM;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,SAAS,GAAG;AAAA,EAC/C;AAEA,QAAM,SAASA,aAAY,YAAyC;AAClE,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AACA,UAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,WAAW,aAAa,WAAW,EAAE,QAAQ,SAAS,CAAC,CAAC;AACvG,QAAI,QAAQ;AACV,cAAQ,MAAM;AAAA,IAChB;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,aAAa,WAAW,SAAS,GAAG,CAAC;AAEjD,SAAO;AAAA,IACL;AAAA,IACA,UAAU,MAAM,WAAW;AAAA,IAC3B,UAAU,MAAM,WAAW;AAAA,IAC3B,aAAa,MAAM,WAAW;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,EAC/B;AACF;;;ACxJA,SAAS,eAAAE,oBAAmB;AAyBrB,SAAS,kBACd,WACA,UAAoC,CAAC,GACZ;AACzB,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,oBAAoB,kBAAkB;AAC5C,QAAM,mBAAmB,kBAAkB;AAE3C,QAAM,YAAYC;AAAA,IAChB,OAAO,WAAkD;AACvD,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,aAAO,MAAM,kBAAkB,IAAI,MACjC,OAAO,UAAU,aAAa,WAAW,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC;AAAA,IACpF;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,kBAAkB,GAAG;AAAA,EACxD;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,YAAoB,UAAgC,YAAmD;AAC5G,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AACA,aAAO,MAAM,iBAAiB,IAAI,MAChC,OAAO,qBAAqB,aAAa,WAAW;AAAA,QAClD;AAAA,QACA;AAAA,QACA,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7C,CAAC,CAAC;AAAA,IACN;AAAA,IACA,CAAC,QAAQ,aAAa,WAAW,iBAAiB,GAAG;AAAA,EACvD;AAEA,QAAM,UAAUA;AAAA,IACd,OAAO,YAAoB,YAAqB,MAAM,OAAO,YAAY,WAAW,OAAO;AAAA,IAC3F,CAAC,MAAM;AAAA,EACT;AACA,QAAM,SAASA;AAAA,IACb,OAAO,YAAoB,YAAqB,MAAM,OAAO,YAAY,UAAU,OAAO;AAAA,IAC1F,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,QAAQ,iBAAiB,iBAAiB,kBAAkB;AAClE,QAAM,aAAaA,aAAY,MAAM;AACnC,sBAAkB,mBAAmB;AACrC,qBAAiB,mBAAmB;AAAA,EACtC,GAAG,CAAC,kBAAkB,oBAAoB,iBAAiB,kBAAkB,CAAC;AAE9E,SAAO;AAAA,IACL;AAAA,IACA,cAAc,kBAAkB;AAAA,IAChC;AAAA,IACA;AAAA,IACA,YAAY,iBAAiB;AAAA,IAC7B;AAAA,IACA;AAAA,EACF;AACF;;;ACnFA,SAAS,eAAAC,oBAAmB;AAkBrB,SAAS,kBAAkB,UAAoC,CAAC,GAA4B;AACjG,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,QAAQ,QAAQ;AACtB,QAAM,OAAOC;AAAA,IACX,YAAY,MAAM,OAAO,mBAAmB,aAAa,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IAC7F,CAAC,QAAQ,aAAa,KAAK;AAAA,EAC7B;AACA,QAAM,QAAQ,eAAe,MAAM,EAAE,gBAAgB,QAAQ,gBAAgB,SAAS,QAAQ,QAAQ,CAAC;AACvG,SAAO,EAAE,OAAO,MAAM,QAAQ,CAAC,GAAG,SAAS,MAAM,SAAS,OAAO,MAAM,OAAO,SAAS,MAAM,QAAQ;AACvG;;;AC3BA,SAAS,eAAAC,oBAAmB;AAmBrB,SAAS,qBAAqB,UAAuC,CAAC,GAA+B;AAC1G,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,QAAQ,QAAQ;AACtB,QAAM,OAAOC;AAAA,IACX,YAAY,MAAM,OAAO,aAAa,aAAa,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC,CAAC;AAAA,IACvF,CAAC,QAAQ,aAAa,KAAK;AAAA,EAC7B;AACA,QAAM,QAAQ,eAAe,MAAM,EAAE,gBAAgB,QAAQ,gBAAgB,SAAS,QAAQ,QAAQ,CAAC;AACvG,SAAO,EAAE,UAAU,MAAM,QAAQ,CAAC,GAAG,SAAS,MAAM,SAAS,OAAO,MAAM,OAAO,SAAS,MAAM,QAAQ;AAC1G;;;ACvBA,SAAS,eAAAC,qBAAmB;AA8BrB,SAAS,gBAAgB,UAAkC,CAAC,GAA0B;AAC3F,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,OAAOC,cAAY,YAAY,MAAM,OAAO,iBAAiB,WAAW,GAAG,CAAC,QAAQ,WAAW,CAAC;AACtG,QAAM,QAAQ,eAAe,MAAM,EAAE,gBAAgB,QAAQ,gBAAgB,SAAS,QAAQ,QAAQ,CAAC;AACvG,QAAM,WAAW,kBAAkB;AAEnC,QAAM,SAASA;AAAA,IACb,OAAO,YAAqF;AAC1F,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,kBAAkB,aAAa,OAAO,CAAC;AACtF,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,eAAuB,YAAqF;AACjH,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,kBAAkB,aAAa,eAAe,OAAO,CAAC;AACrG,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,kBAA4C;AACjD,YAAM,SAAS,MAAM,SAAS,IAAI,YAAY;AAC5C,cAAM,OAAO,kBAAkB,aAAa,aAAa;AACzD,eAAO;AAAA,MACT,CAAC;AACD,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,cAAcA;AAAA,IAClB,OAAO,eAAuB,MAAc,UAAwE;AAClH,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,uBAAuB,aAAa,eAAe,MAAM,KAAK,CAAC;AAC9G,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,iBAAiBA;AAAA,IACrB,OAAO,eAAuB,SAAmC;AAC/D,YAAM,SAAS,MAAM,SAAS,IAAI,YAAY;AAC5C,cAAM,OAAO,0BAA0B,aAAa,eAAe,IAAI;AACvE,eAAO;AAAA,MACT,CAAC;AACD,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,cAAc,MAAM,QAAQ,CAAC;AAAA,IAC7B,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,EAC/B;AACF;;;AC9GA,SAAS,eAAAC,qBAAmB;AA8BrB,SAAS,SAAS,UAA2B,CAAC,GAAmB;AACtE,QAAM,EAAE,QAAQ,YAAY,IAAI,YAAY,OAAO;AACnD,QAAM,OAAOC,cAAY,YAAY,MAAM,OAAO,UAAU,WAAW,GAAG,CAAC,QAAQ,WAAW,CAAC;AAC/F,QAAM,QAAQ,eAAe,MAAM,EAAE,gBAAgB,QAAQ,gBAAgB,SAAS,QAAQ,QAAQ,CAAC;AACvG,QAAM,WAAW,kBAAkB;AAEnC,QAAM,WAAWA;AAAA,IACf,OAAO,aAAqF;AAC1F,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,aAAa,aAAa,QAAQ,CAAC;AAClF,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,QAAgB,UAA6B,CAAC,MAAwC;AAC3F,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,WAAW,aAAa,QAAQ,OAAO,CAAC;AACvF,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,WAAqC;AAC1C,YAAM,SAAS,MAAM,SAAS,IAAI,YAAY;AAC5C,cAAM,OAAO,WAAW,aAAa,MAAM;AAC3C,eAAO;AAAA,MACT,CAAC;AACD,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM,OAAO;AAAA,EACnD;AAEA,QAAM,gBAAgB,MAAM,MAAM,iBAAiB,CAAC;AACpD,QAAM,kBAAkBA;AAAA,IACtB,CAAC,WACC,cAAc,KAAK,CAAC,iBAAiB,aAAa,WAAW,MAAM,KAAK;AAAA,IAC1E,CAAC,aAAa;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,OAAO,MAAM,MAAM,SAAS,CAAC;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,EAC/B;AACF;;;ACnGA,SAAS,eAAAC,qBAAmB;AAyBrB,SAAS,cAAc,UAAgC,CAAC,GAAwB;AACrF,QAAM,SAAS,kBAAkB,OAAO;AACxC,QAAM,OAAOC,cAAY,YAAY,MAAM,OAAO,eAAe,GAAG,CAAC,MAAM,CAAC;AAC5E,QAAM,QAAQ,eAAe,MAAM,EAAE,gBAAgB,QAAQ,gBAAgB,SAAS,QAAQ,QAAQ,CAAC;AACvG,QAAM,WAAW,kBAAkB;AAEnC,QAAM,SAASA;AAAA,IACb,OAAO,YAA+D;AACpE,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,gBAAgB,OAAO,CAAC;AACvE,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,SAAS,KAAK,MAAM,OAAO;AAAA,EACtC;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,aAAqB,YAA+D;AACzF,YAAM,SAAS,MAAM,SAAS,IAAI,MAAM,OAAO,gBAAgB,aAAa,OAAO,CAAC;AACpF,UAAI,QAAQ;AACV,cAAM,MAAM,QAAQ;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,SAAS,KAAK,MAAM,OAAO;AAAA,EACtC;AAEA,SAAO;AAAA,IACL,YAAY,MAAM,QAAQ,CAAC;AAAA,IAC3B,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,oBAAoB,SAAS;AAAA,EAC/B;AACF;;;AChEA,SAAS,eAAAC,qBAAmB;AA6BrB,SAAS,gBAAgB,UAAkC,CAAC,GAA0B;AAC3F,QAAM,SAAS,kBAAkB,OAAO;AACxC,QAAM,YAAY,QAAQ;AAC1B,QAAM,cAAc,QAAQ;AAC5B,QAAM,OAAOC;AAAA,IACX,YACE,MAAM,OAAO,gBAAgB;AAAA,MAC3B,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MAC/C,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,IACrD,CAAC;AAAA,IACH,CAAC,QAAQ,WAAW,WAAW;AAAA,EACjC;AACA,QAAM,QAAQ,eAAe,MAAM,EAAE,gBAAgB,QAAQ,gBAAgB,SAAS,QAAQ,QAAQ,CAAC;AACvG,SAAO;AAAA,IACL,SAAS,MAAM,MAAM,WAAW;AAAA,IAChC,OAAO,MAAM,MAAM,SAAS,CAAC;AAAA,IAC7B,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,EACjB;AACF;;;AChBO,SAAS,4BAA4B,SAAqC;AAC/E,QAAM,YAAY,WAAW,OAAO,YAAY,WAAY,QAAoC,YAAY;AAC5G,MAAI,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC7B,WAAO,CAAC;AAAA,EACV;AACA,SAAO,UAAU,IAAI,CAAC,UAAU,UAAU;AACxC,UAAM,MAAO,YAAY,OAAO,aAAa,WAAW,WAAW,CAAC;AACpE,UAAM,UAAU,IAAI,WAAW,OAAO,IAAI,YAAY,WAAW,IAAI,UAAqC,CAAC;AAC3G,WAAO;AAAA,MACL,IAAI,OAAO,IAAI,MAAM,IAAI,UAAU,QAAQ,UAAU,KAAK;AAAA,MAC1D,MAAM,OAAO,IAAI,QAAQ,UAAU;AAAA,MACnC,WAAW,IAAI;AAAA,MACf,KAAK;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAGO,SAAS,wBAAwB,QAA2C;AACjF,MAAI,UAA6B,CAAC;AAClC,MAAI,eAA8B;AAClC,aAAW,SAAS,QAAQ;AAC1B,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,0BAA0B;AAC7B,kBAAU,4BAA4B,MAAM,OAAO;AACnD,uBAAe,MAAM,UAAU;AAC/B;AAAA,MACF;AAAA,MACA,KAAK,yBAAyB;AAC5B,cAAM,UAAU,MAAM,WAAW,OAAO,MAAM,YAAY,WAAW,MAAM,UAAsC,CAAC;AAClH,YAAI,OAAO,QAAQ,eAAe,UAAU;AAC1C,oBAAU,QAAQ,OAAO,CAAC,aAAa,SAAS,OAAO,QAAQ,UAAU;AAAA,QAC3E;AACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,kBAAkB;AAGrB,YAAI,iBAAiB,QAAQ,MAAM,UAAU,QAAQ,MAAM,WAAW,cAAc;AAClF,oBAAU,CAAC;AACX,yBAAe;AAAA,QACjB;AACA;AAAA,MACF;AAAA,MACA;AACE;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;;;ACjEO,SAAS,iBAAiB,OAAyC;AACxE,MAAI,MAAM,CAAC,MAAM,KAAK;AACpB,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,QAAM,aAAa,KAAK,QAAQ,GAAG;AACnC,MAAI,eAAe,IAAI;AACrB,WAAO,EAAE,MAAM,MAAM,MAAM,IAAI,kBAAkB,OAAO,MAAM,CAAC,EAAE;AAAA,EACnE;AACA,QAAM,OAAO,KAAK,MAAM,GAAG,UAAU;AACrC,QAAM,OAAO,KAAK,MAAM,aAAa,CAAC;AACtC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB,MAAM,KAAK,MAAM,KAAK,EAAE,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC;AAAA,EAC5D;AACF;AAEA,IAAM,uBAAmC;AAGlC,SAAS,cAAc,UAAkC,aAAoC;AAClG,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,SAAO,YAAY,SAAS,QAAQ,KAAK,YAAY,SAAS,oBAAoB;AACpF;AAGO,SAAS,aAAa,UAAmC,OAAoC;AAClG,QAAM,SAAS,iBAAiB,KAAK;AACrC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,OAAO,KAAK,YAAY;AACtC,SAAO,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,SAAS,QAAQ,SAAS,SAAS,KAAK,CAAC,KAAK;AACnG;AASO,SAAS,eAAe,UAAmC,OAAe,KAAgC;AAC/G,QAAM,SAAS,MAAM,YAAY;AACjC,SAAO,SAAS,OAAO,CAAC,YAAY;AAClC,QAAI,CAAC,cAAc,QAAQ,YAAY,IAAI,WAAW,GAAG;AACvD,aAAO;AAAA,IACT;AACA,QAAI,QAAQ,aAAa,CAAC,QAAQ,UAAU,GAAG,GAAG;AAChD,aAAO;AAAA,IACT;AACA,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,KAAK,WAAW,MAAM,MAAM,QAAQ,SAAS,KAAK,CAAC,UAAU,MAAM,WAAW,MAAM,CAAC,KAAK;AAAA,EAC3G,CAAC;AACH;AAGO,SAAS,QAAQ,MAA+C;AACrE,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,KACJ,IAAI,CAAC,QAAQ;AACZ,UAAM,QAAQ,IAAI,QAAQ,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI;AACpD,WAAO,IAAI,WAAW,IAAI,KAAK,MAAM,IAAI,KAAK;AAAA,EAChD,CAAC,EACA,KAAK,GAAG;AACb;AAGO,SAAS,wBAAwB,SAAuB,MAAiC;AAC9F,QAAM,YAAY,QAAQ,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ;AAClE,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;AAC3C,UAAM,QAAQ,KAAK,CAAC;AACpB,QAAI,UAAU,UAAa,MAAM,WAAW,GAAG;AAC7C,aAAO,SAAS,CAAC,KAAK;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,KAA6B;AACnD,MAAI,CAAC,IAAI,WAAW;AAClB,UAAM,IAAI,MAAM,qDAAgD;AAAA,EAClE;AACA,SAAO,IAAI;AACb;AAEA,IAAM,aAAa,CAAC,QAA4B,IAAI,cAAc;AAO3D,IAAM,kBAA2C;AAAA,EACtD;AAAA,IACE,MAAM;AAAA,IACN,SAAS,CAAC,GAAG;AAAA,IACb,aAAa;AAAA,IACb,KAAK,CAAC,OAAO,QAAQ;AACnB,UAAI,SAAS;AACb,aAAO,EAAE,QAAQ,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,KAAK,CAAC,OAAO,QAAQ;AAKnB,YAAM,UAAU,IAAI,UAAU;AAC9B,UAAI,CAAC,SAAS;AACZ,eAAO,EAAE,QAAQ,SAAS,SAAS,gEAAgE;AAAA,MACrG;AACA,aAAO,EAAE,QAAQ,MAAM,SAAS,sBAAsB;AAAA,IACxD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,MAAM,CAAC,EAAE,MAAM,UAAU,UAAU,MAAM,OAAO,CAAC,SAAS,QAAQ,GAAG,aAAa,iBAAiB,CAAC;AAAA,IACpG,KAAK,OAAO,MAAM,QAAQ;AACxB,YAAM,YAAY,eAAe,GAAG;AACpC,YAAM,SAAS,KAAK,CAAC;AACrB,UAAI,WAAW,WAAW,WAAW,UAAU;AAC7C,eAAO,EAAE,QAAQ,SAAS,SAAS,oCAAoC;AAAA,MACzE;AACA,UAAI;AACF,cAAM,IAAI,OAAO,WAAW,IAAI,aAAa,WAAW,EAAE,QAAQ,WAAW,UAAU,WAAW,SAAS,CAAC;AAC5G,eAAO,EAAE,QAAQ,MAAM,SAAS,WAAW,UAAU,iBAAiB,gBAAgB;AAAA,MACxF,SAAS,OAAO;AACd,eAAO,EAAE,QAAQ,SAAS,SAAS,iBAAiB,OAAO,MAAM,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,KAAK,OAAO,OAAO,QAAQ;AACzB,YAAM,YAAY,eAAe,GAAG;AACpC,UAAI;AACF,cAAM,SAAS,MAAM,IAAI,OAAO,sBAAsB,IAAI,aAAa,SAAS;AAChF,eAAO,EAAE,QAAQ,MAAM,SAAS,OAAO,QAAQ;AAAA,MACjD,SAAS,OAAO;AACd,eAAO,EAAE,QAAQ,SAAS,SAAS,aAAa,KAAK,KAAK,6BAA6B;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,KAAK,OAAO,OAAO,QAAQ;AACzB,YAAM,YAAY,eAAe,GAAG;AACpC,YAAM,YAAY,MAAM,IAAI,QAAQ;AACpC,UAAI,CAAC,WAAW;AAGd,eAAO,EAAE,QAAQ,MAAM,WAAW,KAAK;AAAA,MACzC;AACA,UAAI;AACF,cAAM,IAAI,OAAO,oBAAoB,IAAI,aAAa,SAAS;AAC/D,eAAO,EAAE,QAAQ,MAAM,SAAS,mBAAmB;AAAA,MACrD,SAAS,OAAO;AACd,eAAO,EAAE,QAAQ,SAAS,SAAS,kBAAkB,KAAK,EAAE;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,OAAoC;AACxD,MAAI,SAAS,OAAO,UAAU,YAAY,aAAa,SAAS,OAAQ,MAAgC,YAAY,UAAU;AAC5H,WAAQ,MAA8B;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAAoC;AACtD,MAAI,SAAS,OAAO,UAAU,YAAY,YAAY,SAAS,OAAQ,MAA+B,WAAW,UAAU;AACzH,WAAQ,MAA6B;AAAA,EACvC;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAgB,QAAoC;AAC5E,QAAM,OAAO,WAAW,KAAK;AAC7B,MAAI,SAAS,KAAK;AAChB,WAAO;AAAA,EACT;AACA,MAAI,SAAS,KAAK;AAChB,WAAO,WAAW,WAAW,uCAAuC;AAAA,EACtE;AACA,SAAO,aAAa,KAAK,KAAK,aAAa,MAAM;AACnD;AAEA,SAAS,kBAAkB,OAAwB;AACjD,MAAI,WAAW,KAAK,MAAM,KAAK;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,aAAa,KAAK,KAAK;AAChC;;;AC1OA,SAAS,eAAAC,eAAa,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgB;AAiFhD,SAAS,iBAAiB,SAA0D;AACzF,QAAM,EAAE,UAAU,SAAS,UAAU,OAAO,SAAS,IAAI;AACzD,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,CAAC;AAG5C,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAwB,IAAI;AACxE,QAAM,YAAY,mBAAmB,QAAQ,mBAAmB;AAOhE,QAAM,eAAeC,QAAO,KAAK;AACjC,QAAM,cAAcA,QAAO,KAAK;AAChC,MAAI,YAAY,YAAY,OAAO;AACjC,gBAAY,UAAU;AACtB,iBAAa,UAAU;AAAA,EACzB;AAEA,QAAM,SAASC,SAAQ,MAAM,iBAAiB,KAAK,GAAG,CAAC,KAAK,CAAC;AAC7D,QAAM,YAAYA;AAAA,IAChB,OAAO;AAAA,MACL,WAAW,SAAS,aAAa;AAAA,MACjC,QAAQ,SAAS,UAAU;AAAA,MAC3B,aAAa,SAAS,eAAe,CAAC;AAAA,IACxC;AAAA,IACA,CAAC,SAAS,WAAW,SAAS,QAAQ,SAAS,WAAW;AAAA,EAC5D;AAIA,QAAM,gBAAgBA,SAAQ,MAAM;AAClC,QAAI,CAAC,UAAU,CAAC,OAAO,kBAAkB;AACvC,aAAO;AAAA,IACT;AACA,WAAO,aAAa,UAAU,KAAK;AAAA,EACrC,GAAG,CAAC,UAAU,OAAO,MAAM,CAAC;AAE5B,QAAM,QAAQA,SAAQ,MAAM;AAC1B,QAAI,CAAC,QAAQ;AACX,aAAO,CAAC;AAAA,IACV;AACA,QAAI,eAAe;AACjB,aAAO,CAAC,aAAa;AAAA,IACvB;AACA,WAAO,eAAe,UAAU,OAAO,MAAM,SAAS;AAAA,EACxD,GAAG,CAAC,UAAU,QAAQ,eAAe,SAAS,CAAC;AAE/C,QAAM,OAAO,WAAW,QAAQ,MAAM,SAAS,KAAK,CAAC;AAOrD,QAAM,iBAAiB,WAAW,QAAQ,MAAM,SAAS;AAGzD,QAAM,mBAAmB,MAAM,WAAW,IAAI,IAAI,KAAK,IAAI,WAAW,MAAM,SAAS,CAAC;AAEtF,QAAM,gBAAgB,gBAAgB,QAAQ,cAAc,IAAI,IAAI;AAOpE,QAAM,eAAeC;AAAA,IACnB,CAAC,YAAiD;AAChD,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,MACT;AACA,aAAO,EAAE,GAAG,SAAS,GAAG,UAAU,SAAS,MAAM,SAAS,QAAQ,OAAO,EAAE;AAAA,IAC7E;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,EACpB;AAEA,QAAM,UAAUA;AAAA,IACd,OAAO,SAAuB,SAAkC;AAC9D,YAAM,MAAM,aAAa,OAAO;AAChC,UAAI,CAAC,KAAK;AACR;AAAA,MACF;AACA,UAAI;AACF,cAAM,SAAS,MAAM,QAAQ,IAAI,MAAM,GAAG;AAC1C,YAAI,OAAO,SAAS;AAClB,cAAI,OAAO,EAAE,MAAM,OAAO,WAAW,OAAO,OAAO,SAAS,SAAS,OAAO,QAAQ,CAAC;AAAA,QACvF;AACA,YAAI,OAAO,WAAW,QAAQ,CAAC,OAAO,WAAW;AAC/C,mBAAS,EAAE;AAAA,QACb;AAAA,MACF,SAAS,OAAO;AACd,YAAI,OAAO,EAAE,MAAM,SAAS,SAASC,cAAa,KAAK,EAAE,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,IACA,CAAC,cAAc,QAAQ;AAAA,EACzB;AAEA,QAAM,eAAeD;AAAA,IACnB,CAAC,YAA0B;AACzB,eAAS,IAAI,QAAQ,IAAI,GAAG;AAC5B,mBAAa,CAAC;AAAA,IAChB;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,0BAA0BA,cAAY,MAAM;AAChD,UAAM,UAAU,MAAM,gBAAgB;AACtC,QAAI,SAAS;AACX,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,OAAO,kBAAkB,YAAY,CAAC;AAO1C,QAAM,cAAcA;AAAA,IAClB,OAAO,SAAuBE,aAAoD;AAChF,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AACA,YAAM,WAAWA,UAAS,YAAY;AAItC,YAAM,mBACJ,QAAQ,SAAS,OAAO,KAAK,YAAY,MACxC,QAAQ,SAAS,SAAS,OAAO,KAAK,YAAY,CAAC,KAAK;AAM3D,UAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,OAAO,kBAAkB;AAChF,qBAAa,OAAO;AACpB;AAAA,MACF;AAIA,YAAM,OAAO,oBAAoB,OAAO,mBAAmB,OAAO,OAAO,CAAC;AAC1E,YAAM,UAAU,wBAAwB,SAAS,IAAI;AACrD,UAAI,SAAS;AAGX,YAAI,CAAC,OAAO,kBAAkB;AAC5B,uBAAa,OAAO;AAAA,QACtB;AACA;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,IAAI;AAAA,IAC7B;AAAA,IACA,CAAC,QAAQ,eAAe,cAAc,OAAO;AAAA,EAC/C;AAEA,QAAM,iBAAiBF,cAAY,YAA2B;AAC5D,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAKA,QAAI,aAAa,WAAW,CAAC,eAAe;AAC1C,YAAM,cAAc,MAAM,gBAAgB;AAC1C,UAAI,aAAa;AACf,cAAM,YAAY,aAAa,EAAE,UAAU,KAAK,CAAC;AAAA,MACnD;AACA;AAAA,IACF;AASA,UAAM,QAAQ,OAAO,KAAK,YAAY;AACtC,UAAM,QAAQ,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK,CAAC;AACvF,UAAM,UAAU,iBAAiB,SAAS,MAAM,gBAAgB;AAChE,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,UAAM,YAAY,OAAO;AAAA,EAC3B,GAAG,CAAC,QAAQ,eAAe,OAAO,kBAAkB,WAAW,CAAC;AAOhE,QAAM,QAAQA;AAAA,IACZ,OAAO,UAAiC;AACtC,YAAM,UAAU,MAAM,KAAK;AAC3B,UAAI,CAAC,SAAS;AACZ;AAAA,MACF;AACA,YAAM,YAAY,SAAS,EAAE,UAAU,KAAK,CAAC;AAAA,IAC/C;AAAA,IACA,CAAC,OAAO,WAAW;AAAA,EACrB;AAGA,QAAM,aAAaF,QAAO,KAAK;AAE/B,QAAM,YAAYE;AAAA,IAChB,CAAC,UAAuD;AACtD,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,MACT;AACA,cAAQ,MAAM,KAAK;AAAA,QACjB,KAAK,aAAa;AAChB,gBAAM,eAAe;AACrB,uBAAa,UAAU;AACvB,uBAAa,CAAC,YAAa,MAAM,WAAW,IAAI,KAAK,KAAK,IAAI,SAAS,MAAM,SAAS,CAAC,IAAI,KAAK,MAAM,MAAO;AAC7G,iBAAO;AAAA,QACT;AAAA,QACA,KAAK,WAAW;AACd,gBAAM,eAAe;AACrB,uBAAa,UAAU;AACvB,uBAAa,CAAC,YAAY;AACxB,kBAAM,OAAO,KAAK,IAAI,SAAS,MAAM,SAAS,CAAC;AAC/C,mBAAO,MAAM,WAAW,IAAI,KAAK,OAAO,IAAI,MAAM,UAAU,MAAM;AAAA,UACpE,CAAC;AACD,iBAAO;AAAA,QACT;AAAA,QACA,KAAK,OAAO;AACV,gBAAM,eAAe;AACrB,kCAAwB;AACxB,iBAAO;AAAA,QACT;AAAA,QACA,KAAK,SAAS;AACZ,cAAI,MAAM,YAAY,MAAM,aAAa,aAAa;AACpD,mBAAO;AAAA,UACT;AACA,gBAAM,eAAe;AACrB,cAAI,WAAW,SAAS;AACtB,mBAAO;AAAA,UACT;AACA,qBAAW,UAAU;AACrB,eAAK,eAAe,EAAE,QAAQ,MAAM;AAClC,uBAAW,UAAU;AAAA,UACvB,CAAC;AACD,iBAAO;AAAA,QACT;AAAA,QACA,KAAK,UAAU;AACb,gBAAM,eAAe;AAGrB,4BAAkB,KAAK;AACvB,iBAAO;AAAA,QACT;AAAA,QACA;AACE,iBAAO;AAAA,MACX;AAAA,IACF;AAAA,IACA,CAAC,MAAM,OAAO,yBAAyB,gBAAgB,KAAK;AAAA,EAC9D;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAASC,cAAa,OAAwB;AAC5C,MAAI,iBAAiB,OAAO;AAC1B,WAAO,MAAM;AAAA,EACf;AACA,SAAO,OAAO,KAAK;AACrB;;;AC7WA,SAAS,iBAAiB,cAAc;;;ACAxC,SAAS,YAA6B;AACtC,SAAS,eAAe;AAGjB,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;AD6DoB,SAGQ,OAAAE,MAHR;AA1Cb,SAAS,eAAe,EAAE,MAAM,OAAO,WAAW,aAAa,OAAO,aAAa,UAAU,GAAwB;AAC1H,SACE,gBAAAA,KAAC,mBACE,iBACC;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG,OAAO,KAAK;AAAA,MACzC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG,OAAO,EAAE;AAAA,MACtC,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG,OAAO,KAAK;AAAA,MACtC,YAAY,EAAE,UAAU,MAAM,MAAM,UAAU;AAAA,MAC9C,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEA;AAAA,wBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,IAAI;AAAA,YACJ,MAAK;AAAA,YACL,cAAW;AAAA,YACX,WAAU;AAAA,YAET,gBAAM,IAAI,CAAC,SAAS,UAAU;AAC7B,oBAAM,WAAW,UAAU;AAC3B,oBAAM,OAAO,QAAQ,QAAQ,IAAI;AACjC,qBACE;AAAA,gBAAC;AAAA;AAAA,kBAEC,IAAI,GAAG,SAAS,WAAW,KAAK;AAAA,kBAChC,MAAK;AAAA,kBACL,iBAAe;AAAA,kBACf,cAAc,MAAM,YAAY,KAAK;AAAA,kBACrC,aAAa,CAAC,UAAU;AAEtB,0BAAM,eAAe;AACrB,0BAAM,KAAK;AAAA,kBACb;AAAA,kBACA,WAAW;AAAA,oBACT;AAAA,oBACA;AAAA,oBACA,WAAW,+BAA+B;AAAA,kBAC5C;AAAA,kBAEA;AAAA,yCAAC,UAAK,WAAU,uCACd;AAAA,2CAAC,UAAK,WAAW,GAAG,yBAAyB,WAAW,mBAAmB,YAAY,GAAG;AAAA;AAAA,wBACtF,QAAQ;AAAA,yBACZ;AAAA,sBACC,OAAO,gBAAAA,KAAC,UAAK,WAAU,oDAAoD,gBAAK,IAAU;AAAA,uBAC7F;AAAA,oBACA,qBAAC,UAAK,WAAU,qCACb;AAAA,8BAAQ,SACP,gBAAAA,KAAC,UAAK,WAAU,uGAAsG,oBAEtH,IACE;AAAA,sBACJ,gBAAAA,KAAC,UAAK,WAAU,wDAAwD,kBAAQ,aAAY;AAAA,uBAC9F;AAAA;AAAA;AAAA,gBA7BK,QAAQ;AAAA,cA8Bf;AAAA,YAEJ,CAAC;AAAA;AAAA,QACH;AAAA,QACC,cACC,gBAAAA,KAAC,SAAI,WAAU,iFACZ,uBACH,IACE;AAAA;AAAA;AAAA,EACN,IACE,MACN;AAEJ;;;AE5FA,SAAS,aAAa,UAAU,WAAW,kBAAkB,eAAe,YAAY,aAAa;AACrG,SAAS,mBAAAC,kBAAiB,UAAAC,eAAc;AACxC,SAAS,eAAAC,eAAa,aAAAC,YAAW,OAAO,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAA2G;AA+R1J,SA2FU,UA3FV,OAAAC,MAyCI,QAAAC,aAzCJ;AA3OV,IAAM,kBAA8C,oBAAI,IAAI,CAAC,UAAU,SAAS,CAAC;AAa1E,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,cAAcC,QAAmC,IAAI;AAC3D,QAAM,eAAeA,QAAgC,IAAI;AACzD,QAAM,SAAS,UAAU,QAAQ,gBAAgB,IAAI,MAAM;AAM3D,QAAM,kBAAkB,aAAa,cAAc;AAOnD,QAAM,sBAAsB,aAAa,eAAe,UAAU,KAAK;AAEvE,QAAM,WAAW,SAAS,WAAW,uBAAuB,CAAC,mBAAmB,CAAC,SAAS;AAK1F,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAS,KAAK;AAC9C,QAAM,mBAAmB,CAAC,UACxB,MAAM,gBAAgB,QAAQ,CAAC,GAAG,MAAM,aAAa,KAAK,EAAE,SAAS,OAAO;AAC9E,QAAM,iBAAiBC;AAAA,IACrB,CAAC,UAAqC;AACpC,UAAI,CAAC,eAAe,CAAC,iBAAiB,KAAK,GAAG;AAC5C;AAAA,MACF;AAEA,YAAM,eAAe;AACrB,kBAAY,IAAI;AAAA,IAClB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AACA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,UAAqC;AACpC,UAAI,CAAC,aAAa;AAChB;AAAA,MACF;AAGA,UAAI,MAAM,cAAc,SAAS,MAAM,aAA4B,GAAG;AACpE;AAAA,MACF;AACA,kBAAY,KAAK;AAAA,IACnB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AACA,QAAM,aAAaA;AAAA,IACjB,CAAC,UAAqC;AACpC,UAAI,CAAC,eAAe,CAAC,iBAAiB,KAAK,GAAG;AAC5C;AAAA,MACF;AACA,YAAM,eAAe;AACrB,kBAAY,KAAK;AAEjB,UAAI,MAAM,aAAa,MAAM,SAAS,GAAG;AACvC,oBAAY,SAAS,MAAM,aAAa,KAAK;AAAA,MAC/C;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,CAAC,QAAQ,SAAS,IAAID,UAAwB,IAAI;AACxD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,cAAc,eAAe,IAAIA,UAAuB,IAAI;AACnE,QAAM,YAAY,MAAM;AAExB,QAAM,SAASC,cAAY,MAAM;AAC/B,UAAM,WAAW,YAAY;AAC7B,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,aAAS,MAAM,SAAS;AACxB,aAAS,MAAM,SAAS,GAAG,KAAK,IAAI,SAAS,cAAc,GAAG,CAAC;AAAA,EACjE,GAAG,CAAC,CAAC;AAEL,EAAAC,WAAU,MAAM;AACd,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,OAAO,MAAM,CAAC;AAK3B,QAAM,WAAWC;AAAA,IACf,OAAO;AAAA,MACL,QAAQ,CAAC,SAAiB;AACxB,kBAAU,IAAI;AACd,iBAAS,WAAW;AAAA,MACtB;AAAA,MACA,UAAU,MAAM,YAAY,IAAI;AAAA;AAAA;AAAA,MAGhC,WAAW,MAAM;AACf,YAAI,CAAC,aAAa;AAChB,iBAAO;AAAA,QACT;AACA,oBAAY;AACZ,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,SAAS,CAAC,YACR,IAAI,QAAiB,CAAC,YAAY;AAChC,wBAAgB;AAAA,UACd;AAAA,UACA,SAAS,CAAC,cAAc;AACtB,4BAAgB,IAAI;AACpB,oBAAQ,SAAS;AAAA,UACnB;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACL;AAAA,IACA,CAAC,UAAU,WAAW;AAAA,EACxB;AAEA,QAAM,UAAU,iBAAiB;AAAA,IAC/B;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA,OAAO,SAAS;AAAA,IAChB,UAAU,SAAS;AAAA,EACrB,CAAC;AAQD,QAAM,uBAAuB,eAAe,aAAa,UAAU;AAEnE,QAAM,iBAAiB,mBAAmB;AAM1C,QAAM,sBAAsB,kBAAkB,QAAQ;AAEtD,QAAM,YAAY,CAAC,UAA8C;AAG/D,QAAI,kBAAkB,QAAQ,UAAU,KAAK,GAAG;AAC9C;AAAA,IACF;AACA,QAAI,kBAAkB,KAAK,GAAG;AAC5B,YAAM,eAAe;AACrB,UAAI,qBAAqB;AAGvB,kBAAU,EAAE,MAAM,SAAS,SAAS,+GAA0G,CAAC;AAC/I;AAAA,MACF;AACA,UAAI,iBAAiB;AAGnB;AAAA,MACF;AACA,WAAK,SAAS,KAAK;AAAA,IACrB;AAAA,EACF;AAKA,QAAM,cAAcF;AAAA,IAClB,CAAC,UAA+C;AAC9C,gBAAU,KAAK;AACf,mBAAa,aAAa,KAAK;AAAA,IACjC;AAAA,IACA,CAAC,SAAS,WAAW;AAAA,EACvB;AAEA,QAAM,mBAAmBA;AAAA,IACvB,CAAC,UAAyC;AACxC,UAAI,MAAM,OAAO,OAAO;AACtB,qBAAa,SAAS,MAAM,OAAO,KAAK;AAAA,MAC1C;AACA,YAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,eAAeE;AAAA,IACnB,MACE,SAAS,OAAO,CAAC,YAAY;AAC3B,UAAI,QAAQ,cAAc,gBAAgB;AACxC,cAAM,QAAQ,eAAe;AAC7B,eAAO,MAAM,SAAS,QAAQ,UAAU,KAAK,MAAM,SAAS,iBAAiB;AAAA,MAC/E;AACA,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,UAAU,cAAc;AAAA,EAC3B;AAEA,QAAM,eAAe,WAAW,SAAS,QAAQ,EAAE,MAAM,SAAkB,SAAS,SAAS,MAAM,WAAW,6DAAwD,IAAI;AAE1K,SACE,gBAAAL,MAAC,SAAI,WAAW,GAAG,WAAW,SAAS,GACrC;AAAA,oBAAAA,MAAC,SAAI,WAAU,YACZ;AAAA,uBACC,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,QAAQ,QAAQ,iBAAiB;AAAA,UACvC,OAAO,QAAQ;AAAA,UACf,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,UACrB,OAAO,CAAC,UAAU;AAKhB,oBAAQ,aAAa,KAAK;AAC1B,iBAAK,QAAQ,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa,QAAQ;AAAA,UACrB;AAAA;AAAA,MACF,IACE;AAAA,MACJ,gBAAAC;AAAA,QAAC;AAAA;AAAA,UAIC,YAAY,cAAc,iBAAiB;AAAA,UAC3C,aAAa,cAAc,kBAAkB;AAAA,UAC7C,QAAQ,cAAc,aAAa;AAAA,UACnC,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA;AAAA;AAAA,YAGA,YAAY;AAAA,UACd;AAAA,UAEC;AAAA,uBACC,gBAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,eAAW;AAAA,gBACX,WAAW;AAAA,kBACT;AAAA,kBACA;AAAA,gBACF;AAAA,gBAEA,0BAAAC,MAAC,UAAK,WAAU,kCACd;AAAA,kCAAAD,KAAC,iBAAc,WAAU,UAAS;AAAA,kBAAE;AAAA,mBAEtC;AAAA;AAAA,YACF,IACE;AAAA,YACH,eAAe,YAAY,YAAY,SAAS,IAC/C,gBAAAA,KAAC,mBAAgB,aAAa,YAAY,aAAa,UAAU,YAAY,QAAQ,IACnF;AAAA,YACH;AAAA,YACD,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN,OAAO,SAAS;AAAA,gBAChB,UAAU,CAAC,UAAU,SAAS,SAAS,MAAM,OAAO,KAAK;AAAA,gBACzD;AAAA,gBACA,SAAS;AAAA,gBACT,aAAa,eAAe;AAAA,gBAC5B;AAAA,gBACA;AAAA,gBACA,cAAW;AAAA,gBACX,MAAM,kBAAkB,QAAQ,OAAO,aAAa;AAAA,gBACpD,iBAAe,iBAAiB,QAAQ,OAAO;AAAA,gBAC/C,iBAAe,kBAAkB,QAAQ,OAAO,YAAY;AAAA,gBAC5D,yBAAuB,kBAAkB,QAAQ,OAAO,GAAG,SAAS,WAAW,QAAQ,SAAS,KAAK;AAAA,gBACrG,WAAW;AAAA,kBACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBASA;AAAA,kBACA;AAAA,gBACF;AAAA;AAAA,YACF;AAAA,YACC,gBAAgB,uBACf,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,UAAU,MAAM,aAAa,QAAQ,KAAK;AAAA,gBAC1C,WAAW,MAAM,aAAa,QAAQ,IAAI;AAAA;AAAA,YAC5C,IAEA,gBAAAC,MAAC,SAAI,WAAU,8DACZ;AAAA,6BAAe,gBACd,gBAAAA,MAAC,UAAK,WAAU,qCACb;AAAA,8BACC,gBAAAA,MAAA,YACE;AAAA,kCAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC,KAAK;AAAA,sBACL,MAAK;AAAA,sBACL,UAAQ;AAAA,sBACR,WAAU;AAAA,sBACV,UAAU;AAAA;AAAA,kBACZ;AAAA,kBACA,gBAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,UAAU,aAAa;AAAA,sBACvB,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,sBAC3C,cAAW;AAAA,sBACX,OAAM;AAAA,sBACN,WAAW;AAAA,wBACT;AAAA,wBACA;AAAA,wBACA;AAAA,sBACF;AAAA,sBAEA,0BAAAA,KAAC,iBAAc,WAAU,UAAS;AAAA;AAAA,kBACpC;AAAA,mBACF,IACE;AAAA,gBACH;AAAA,iBACH,IAEA,gBAAAA,KAAC,UAAK,WAAU,sDACb,kBAAQ,qEACX;AAAA,cAEF,gBAAAC,MAAC,UAAK,WAAU,6BACd;AAAA,gCAAAD,KAACO,kBAAA,EAAgB,SAAS,OACvB,mBACC,gBAAAP;AAAA,kBAACQ,QAAO;AAAA,kBAAP;AAAA,oBAEC,MAAK;AAAA,oBACL,SAAS,EAAE,SAAS,GAAG,OAAO,IAAI;AAAA,oBAClC,SAAS,EAAE,SAAS,GAAG,OAAO,EAAE;AAAA,oBAChC,MAAM,EAAE,SAAS,GAAG,OAAO,IAAI;AAAA,oBAC/B,YAAY,EAAE,UAAU,MAAM,MAAM,UAAU;AAAA,oBAC9C,SAAS,MAAM,KAAK,SAAS,UAAU;AAAA,oBACvC,UAAU,SAAS;AAAA,oBACnB,cAAW;AAAA,oBACX,OAAM;AAAA,oBACN,WAAW;AAAA,sBACT;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,oBACF;AAAA,oBAEC,mBAAS,eACR,gBAAAR,KAAC,oBAAiB,WAAU,4BAA2B,IAEvD,gBAAAA,KAAC,cAAW,WAAU,uBAAsB;AAAA;AAAA,kBApB1C;AAAA,gBAsBN,IACE,MACN;AAAA,gBACA,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM;AACb,0BAAI,iBAAiB;AACnB;AAAA,sBACF;AACA,2BAAK,SAAS,KAAK;AAAA,oBACrB;AAAA,oBACA,UAAU,CAAC,WAAW,aAAa,QAAQ;AAAA,oBAC3C,cAAW;AAAA,oBACX,WAAW;AAAA,sBACT;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,oBACF;AAAA,oBAEC,mBAAS,UAAU,gBAAAA,KAAC,oBAAiB,WAAU,0BAAyB,IAAK,gBAAAA,KAAC,eAAY,WAAU,UAAS;AAAA;AAAA,gBAChH;AAAA,iBACF;AAAA,eACF;AAAA;AAAA;AAAA,MAEJ;AAAA,OACF;AAAA,IACA,gBAAAA,KAACO,kBAAA,EACE,qBACC,gBAAAP,KAAC,aAAU,UAAU,cAAc,SAAS,MAAM,YAAY,KAAK,GAAG,IACpE,MACN;AAAA,IACA,gBAAAA,KAACO,kBAAA,EACE,yBACC,gBAAAP;AAAA,MAACQ,QAAO;AAAA,MAAP;AAAA,QACC,SAAS,EAAE,SAAS,GAAG,QAAQ,EAAE;AAAA,QACjC,SAAS,EAAE,SAAS,GAAG,QAAQ,OAAO;AAAA,QACtC,MAAM,EAAE,SAAS,GAAG,QAAQ,EAAE;AAAA,QAC9B,WAAW;AAAA,UACT;AAAA,UACA,aAAa,SAAS,OAAO,qBAAqB;AAAA,QACpD;AAAA,QACA,MAAM,aAAa,SAAS,UAAU,UAAU;AAAA,QAChD,qBAAqB,MAAM;AACzB,cAAI,aAAa,SAAS,MAAM;AAE9B,mBAAO,WAAW,MAAM,UAAU,CAAC,YAAa,YAAY,eAAe,OAAO,OAAQ,GAAG,IAAI;AAAA,UACnG;AAAA,QACF;AAAA,QAEC,uBAAa;AAAA;AAAA,IAChB,IACE,MACN;AAAA,KACF;AAEJ;AAGA,SAAS,WAAW,EAAE,SAAS,UAAU,UAAU,GAA2E;AAC5H,SACE,gBAAAP;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY,YAAY,QAAQ,IAAI;AAAA,MACpC,eAAY;AAAA,MACZ,WAAU;AAAA,MAEV;AAAA,wBAAAA,MAAC,UAAK,WAAU,4CAA2C;AAAA;AAAA,UACrD,gBAAAA,MAAC,UAAK,WAAU,aAAY;AAAA;AAAA,YAAE,QAAQ;AAAA,aAAK;AAAA,UAAO;AAAA,UAAG,QAAQ;AAAA,WACnE;AAAA,QACA,gBAAAA,MAAC,UAAK,WAAU,6BACd;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cACX;AAAA;AAAA,UAED;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAS;AAAA,cACT,SAAS;AAAA,cACT,WAAU;AAAA,cACX;AAAA;AAAA,UAED;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAQA,SAAS,gBAAgB,EAAE,aAAa,SAAS,GAG9C;AACD,SACE,gBAAAA,KAAC,SAAI,WAAU,4DACZ,sBAAY,IAAI,CAAC,eAChB,gBAAAC;AAAA,IAAC;AAAA;AAAA,MAEC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA,mBAAW,aACV,gBAAAD,KAAC,SAAI,KAAK,WAAW,YAAY,KAAI,IAAG,WAAU,wCAAuC,IACvF,WAAW,YAAY,WAAW,QAAQ,IAC5C,gBAAAA,KAAC,aAAU,WAAU,oCAAmC,IAExD,gBAAAA,KAAC,YAAS,WAAU,oCAAmC;AAAA,QAEzD,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,0BAAAD,KAAC,SAAI,WAAU,mCAAmC,qBAAW,MAAK;AAAA,UAClE,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAAI,WAAW;AAAA,gBACd;AAAA,gBACA,WAAW,WAAW,WAAW,0BAA0B;AAAA,cAC7D;AAAA,cAEG,qBAAW,WAAW,cAAc,cAAc,WAAW,WAAW,WAAW,kBAAkB,YAAY,WAAW,SAAS;AAAA;AAAA,UACxI;AAAA,WACF;AAAA,QACC,WAAW,WAAW,cAAc,gBAAAA,KAAC,oBAAiB,WAAU,qCAAoC,IAAK;AAAA,QAC1G,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM,SAAS,WAAW,EAAE;AAAA,YACrC,WAAU;AAAA,YACV,cAAY,UAAU,WAAW,IAAI;AAAA,YAErC,0BAAAA,KAAC,SAAM,WAAU,YAAW;AAAA;AAAA,QAC9B;AAAA;AAAA;AAAA,IA/BK,WAAW;AAAA,EAgClB,CACD,GACH;AAEJ;AAGA,SAAS,UAAU,EAAE,UAAU,QAAQ,GAA+D;AACpG,SACE,gBAAAC;AAAA,IAACO,QAAO;AAAA,IAAP;AAAA,MACC,SAAS,EAAE,SAAS,GAAG,QAAQ,EAAE;AAAA,MACjC,SAAS,EAAE,SAAS,GAAG,QAAQ,OAAO;AAAA,MACtC,MAAM,EAAE,SAAS,GAAG,QAAQ,EAAE;AAAA,MAC9B,WAAU;AAAA,MAEV;AAAA,wBAAAP,MAAC,SAAI,WAAU,2EACb;AAAA,0BAAAD,KAAC,UAAK,WAAU,sCAAqC,sBAAQ;AAAA,UAC7D,gBAAAA,KAAC,YAAO,MAAK,UAAS,SAAS,SAAS,WAAU,kDAAiD,mBAEnG;AAAA,WACF;AAAA,QACA,gBAAAA,KAAC,QAAG,WAAU,QACX,mBAAS,IAAI,CAAC,YAAY;AACzB,gBAAM,OAAO,QAAQ,QAAQ,IAAI;AACjC,iBACE,gBAAAC,MAAC,QAAsB,WAAU,uCAC/B;AAAA,4BAAAA,MAAC,UAAK,WAAU,wCAAuC;AAAA;AAAA,cACnD,QAAQ;AAAA,cACT,OAAO,gBAAAD,KAAC,UAAK,WAAU,0BAA0B,gBAAK,IAAU;AAAA,eACnE;AAAA,YACA,gBAAAA,KAAC,UAAK,WAAU,gCAAgC,kBAAQ,aAAY;AAAA,YACnE,QAAQ,SACP,gBAAAA,KAAC,UAAK,WAAU,+GAA8G,oBAE9H,IACE;AAAA,eAVG,QAAQ,IAWjB;AAAA,QAEJ,CAAC,GACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACzmBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAAS,kBAAiB,UAAAC,eAAc;AACxC,SAAS,aAAAC,YAAW,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,iBAAgC;AACrE,SAAS,mBAAmB;;;ACkDxB,SASE,OAAAC,MATF,QAAAC,aAAA;AAnDG,IAAM,sBAAqE;AAAA,EAChF,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,OAAO;AAAA,EACT;AACF;AAWO,SAAS,cAAc,EAAE,QAAQ,OAAO,OAAO,MAAM,UAAU,GAAuB;AAC3F,QAAM,OAAO,oBAAoB,MAAM;AACvC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,eAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,QACA,SAAS,OAAO,mCAAmC;AAAA,QACnD,KAAK;AAAA,QACL;AAAA,MACF;AAAA,MAEA;AAAA,wBAAAD,KAAC,aAAU,QAAgB,WAAW,SAAS,OAAO,WAAW,YAAY;AAAA,QAC5E,SAAS,KAAK;AAAA;AAAA;AAAA,EACjB;AAEJ;AAQO,SAAS,UAAU,EAAE,QAAQ,UAAU,GAAmB;AAC/D,QAAM,OAAO,oBAAoB,MAAM;AACvC,SACE,gBAAAA,KAAC,UAAK,WAAW,GAAG,uDAAuD,KAAK,cAAc,SAAS,GACpG,eAAK,QAAQ,gBAAAA,KAAC,UAAK,WAAW,GAAG,kDAAkD,KAAK,YAAY,GAAG,IAAK,MAC/G;AAEJ;;;ADGQ,SAEqB,OAAAE,MAFrB,QAAAC,aAAA;AAtCD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,gBAAgBC,SAAQ,MAAM,SAAS,cAAc,UAAU,CAAC,CAAC,GAAG,CAAC,OAAO,MAAM,CAAC;AACzF,QAAM,SAASA,SAAQ,MAAM,cAAc,aAAa,GAAG,CAAC,aAAa,CAAC;AAE1E,QAAM,YAAYC,QAA8B,IAAI;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,IAAI;AACzC,QAAM,WAAW,cAAc,cAAc,SAAS,CAAC;AACvD,QAAM,YAAY,aAAa,WAAc,SAAS,SAAS,mBAAmB,SAAS,SAAS,gBAAgB,SAAS;AAC7H,QAAM,UAAU,WAAW,aAAa,CAAC;AAGzC,EAAAC,WAAU,MAAM;AACd,UAAM,OAAO,UAAU;AACvB,QAAI,QAAQ,cAAc,QAAQ;AAChC,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,eAAe,SAAS,YAAY,MAAM,CAAC;AAE/C,QAAM,WAAW,MAAM;AACrB,UAAM,OAAO,UAAU;AACvB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,cAAU,KAAK,eAAe,KAAK,YAAY,KAAK,eAAe,EAAE;AAAA,EACvE;AAEA,SACE,gBAAAJ,MAAC,SAAI,WAAW,GAAG,4BAA4B,SAAS,GACtD;AAAA,oBAAAD,KAAC,SAAI,KAAK,WAAW,UAAoB,WAAU,+DACjD,0BAAAC,MAAC,SAAI,WAAU,gDACZ;AAAA,aAAO,WAAW,KAAK,CAAC,UACpB,cAAc,gBAAAD,KAAC,OAAE,WAAU,+CAA8C,8BAAgB,IAC1F;AAAA,MACH,OAAO;AAAA,QAAI,CAAC,UACX,MAAM,SAAS,aACb,gBAAAA,KAAC,mBAA+B,OAAO,MAAM,OAAO,iBAA9B,MAAM,EAAsD,IAElF,gBAAAA,KAAC,eAAgC,MAAM,MAAM,MAAM,qBAAjC,MAAM,KAAK,EAA4D;AAAA,MAE7F;AAAA,MACC,UACC,gBAAAA,KAAC,SAAI,WAAU,oDACb,0BAAAA,KAAC,UAAK,WAAU,+BAA8B,2BAAQ,GACxD,IACE;AAAA,OACN,GACF;AAAA,IACA,gBAAAA,KAACM,kBAAA,EACE,WAAC,UAAU,aACV,gBAAAL;AAAA,MAACM,QAAO;AAAA,MAAP;AAAA,QACC,MAAK;AAAA,QACL,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QAC5B,MAAM,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,QACzB,YAAY,EAAE,UAAU,MAAM,MAAM,UAAU;AAAA,QAC9C,SAAS,MAAM;AACb,gBAAM,OAAO,UAAU;AACvB,cAAI,MAAM;AACR,iBAAK,SAAS,EAAE,KAAK,KAAK,cAAc,UAAU,SAAS,CAAC;AAAA,UAC9D;AACA,oBAAU,IAAI;AAAA,QAChB;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QAEA;AAAA,0BAAAP,KAAC,iBAAc,WAAU,YAAW;AAAA,UAAE;AAAA;AAAA;AAAA,IAExC,IACE,MACN;AAAA,KACF;AAEJ;AAIA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGG;AACD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,gBAAAA,KAAC,kBAAe,MAAY,mBAAsC;AAAA,IAC3E,KAAK;AACH,aAAO,gBAAAA,KAAC,mBAAgB,MAAY,mBAAsC;AAAA,IAC5E,KAAK;AACH,aAAO,gBAAAA,KAAC,oBAAiB,MAAY;AAAA,IACvC,KAAK;AACH,aAAO,gBAAAA,KAAC,WAAQ,MAAY;AAAA,IAC9B,KAAK;AACH,aAAO,gBAAAA,KAAC,aAAU,MAAY;AAAA,IAChC;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAA,KAAC,SAAI,WAAU,qCACb,0BAAAA,KAAC,SAAI,WAAU,mIACZ,8BAAoB,kBAAkB,KAAK,MAAM,IAAI,IAAI,gBAAAA,KAAC,UAAK,WAAU,uBAAuB,eAAK,MAAK,GAC7G,GACF;AAEJ;AAEA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAC,MAAC,SAAI,WAAU,qDACZ;AAAA,wBAAoB,kBAAkB,KAAK,MAAM,IAAI,IAAI,gBAAAD,KAAC,UAAK,WAAU,uBAAuB,eAAK,MAAK;AAAA,IAC1G,KAAK,YAAY,gBAAAA,KAAC,UAAK,WAAU,sGAAqG,eAAW,MAAC,IAAK;AAAA,KAC1J;AAEJ;AAEA,SAAS,iBAAiB,EAAE,KAAK,GAA4D;AAC3F,QAAM,OAAO,oBAAoB,KAAK,MAAM;AAC5C,SACE,gBAAAC,MAAC,SAAI,WAAU,0EAAyE,MAAK,UAC3F;AAAA,oBAAAD,KAAC,UAAK,WAAU,4BAA2B;AAAA,IAC3C,gBAAAC,MAAC,UAAK,WAAU,oCACd;AAAA,sBAAAD,KAAC,aAAU,QAAQ,KAAK,QAAQ,WAAU,UAAS;AAAA,MAClD,KAAK,MAAM,YAAY;AAAA,MAAE;AAAA,MAAI,mBAAmB,KAAK,UAAU;AAAA,OAClE;AAAA,IACA,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,KAC7C;AAEJ;AAEA,SAAS,QAAQ,EAAE,KAAK,GAAuB;AAC7C,QAAM,QACJ,KAAK,WAAW,QACZ,aACA,KAAK,WAAW,YACd,iBACA,KAAK,WAAW,cACd,mBACA,KAAK,WAAW,WACd,gBACA,KAAK,WAAW,YACd,iBACA;AACd,SACE,gBAAAA,KAAC,SAAI,WAAU,wCACb,0BAAAC,MAAC,UAAK,WAAU,uIACd;AAAA,oBAAAD,KAAC,cAAW,WAAU,oCAAmC;AAAA,IACzD,gBAAAC,MAAC,UAAK,WAAU,YACb;AAAA;AAAA,MACA,KAAK,OAAO,KAAK,SAAS,KAAK,MAAM,EAAE,CAAC,KAAK;AAAA,OAChD;AAAA,KACF,GACF;AAEJ;AAEA,SAAS,UAAU,EAAE,KAAK,GAAyB;AACjD,QAAM,OACJ,KAAK,SAAS,WACV,4EACA,KAAK,SAAS,YACZ,+EACA;AACR,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,wFAAwF,IAAI,GAAG,MAAK,UACrH;AAAA,oBAAAD,KAAC,qBAAkB,WAAW,GAAG,0BAA0B,KAAK,SAAS,eAAe,YAAY,GAAG;AAAA,IACvG,gBAAAA,KAAC,UAAK,WAAU,2CAA2C,eAAK,MAAK;AAAA,KACvE;AAEJ;AAMA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAA,KAAC,SAAI,WAAU,mFACZ,gBAAM,IAAI,CAAC,SAAS;AACnB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,eAAO,gBAAAA,KAAC,gBAA2B,QAAT,KAAK,EAAgB;AAAA,MACjD,KAAK;AACH,eAAO,gBAAAA,KAAC,eAA0B,QAAT,KAAK,EAAgB;AAAA,MAChD,KAAK;AACH,eAAO,gBAAAA,KAAC,aAAwB,MAAY,iBAArB,KAAK,EAA8C;AAAA,MAC5E,KAAK;AACH,eAAO,gBAAAA,KAAC,cAAyB,QAAT,KAAK,EAAgB;AAAA,IACjD;AAAA,EACF,CAAC,GACH;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,CAAC,MAAM,OAAO,IAAII,UAAS,KAAK;AACtC,SACE,gBAAAH,MAAC,YAAY,MAAZ,EAAiB,MAAY,cAAc,SAC1C;AAAA,oBAAAA;AAAA,MAAC,YAAY;AAAA,MAAZ;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QAEA;AAAA,0BAAAD,KAAC,oBAAiB,WAAU,2GAA0G;AAAA,UACtI,gBAAAA,KAAC,UAAK,WAAW,GAAG,YAAY,SAAS,0BAA0B,UAAU,2BAA2B,mBAAmB,GAAI,gBAAK;AAAA,UACpI,gBAAAA,KAAC,UAAK,WAAW,GAAG,wBAAwB,WAAW,mBAAmB,UAAU,uBAAuB,GAAI,iBAAM;AAAA,UACpH,UAAU,gBAAAA,KAAC,UAAK,WAAU,kEAAkE,mBAAQ,IAAU;AAAA,UAC9G,UAAU,gBAAAA,KAAC,UAAK,WAAU,gFAA+E,IAAK;AAAA;AAAA;AAAA,IACjH;AAAA,IACA,gBAAAA,KAAC,YAAY,SAAZ,EAAoB,WAAU,mBAC7B,0BAAAA,KAAC,SAAI,WAAU,wCAAwC,UAAS,GAClE;AAAA,KACF;AAEJ;AAEA,SAAS,aAAa,EAAE,OAAO,MAAM,GAAsC;AACzE,QAAM,OAAO,iBAAiB,KAAK;AACnC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,SACE,gBAAAC,MAAC,SAAI,WAAU,WACb;AAAA,oBAAAD,KAAC,OAAE,WAAU,8EAA8E,iBAAM;AAAA,IACjG,gBAAAA,KAAC,SAAI,WAAU,kIACZ,gBACH;AAAA,KACF;AAEJ;AAEA,SAAS,aAAa,EAAE,KAAK,GAA4B;AACvD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,KAAC,aAAU,WAAU,YAAW;AAAA,MACtC,OAAO,KAAK,YAAY,aAAa;AAAA,MACrC,SAAS,KAAK;AAAA,MACd,SAAS,SAAS,KAAK,MAAM,GAAG;AAAA,MAEhC,0BAAAA,KAAC,OAAE,WAAU,8DAA8D,eAAK,MAAK;AAAA;AAAA,EACvF;AAEJ;AAEA,SAAS,YAAY,EAAE,KAAK,GAA2B;AACrD,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAD,KAAC,cAAW,WAAU,YAAW;AAAA,MACvC,OAAO,gBAAgB,KAAK,IAAI;AAAA,MAChC,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,sBAAsB,KAAK,SAAS;AAAA,MAE7C;AAAA,wBAAAA,KAAC,gBAAa,OAAM,aAAY,OAAO,KAAK,WAAW;AAAA,QACtD,KAAK,WAAW,aAAa,gBAAAA,KAAC,gBAAa,OAAM,UAAS,OAAO,KAAK,QAAQ,IAAK;AAAA;AAAA;AAAA,EACtF;AAEJ;AAEA,SAAS,WAAW,EAAE,KAAK,GAA0B;AACnD,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAD,KAAC,sBAAmB,WAAU,YAAW;AAAA,MAC/C,OAAO,gBAAgB,KAAK,IAAI;AAAA,MAChC,SAAS,KAAK,WAAW;AAAA,MACzB,QAAQ,KAAK,WAAW;AAAA,MACxB,SAAS,KAAK,WAAW;AAAA,MAExB;AAAA,aAAK,UAAU,gBAAAA,KAAC,gBAAa,OAAM,WAAU,OAAO,KAAK,SAAS,IAAK;AAAA,QACvE,KAAK,SAAS,gBAAAA,KAAC,gBAAa,OAAM,UAAS,OAAO,KAAK,QAAQ,IAAK;AAAA;AAAA;AAAA,EACvE;AAEJ;AAGA,SAAS,UAAU,EAAE,MAAM,cAAc,GAAoF;AAC3H,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,QAAQ,KAAK,WAAW,UAAW,UAAU,oBAAoB,mBAAoB,UAAU,qBAAqB;AAC1H,SACE,gBAAAC,MAAC,SAAI,WAAU,wGACb;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QAEA,0BAAAA,KAAC,WAAQ,WAAU,UAAS;AAAA;AAAA,IAC9B;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD,KAAC,UAAK,WAAW,GAAG,2BAA2B,UAAU,oBAAoB,YAAY,GAAI,iBAAM;AAAA,QAClG,UAAU,gBAAAA,KAAC,UAAK,WAAU,+DAA8D,IAAK;AAAA,SAChG;AAAA,MACC,KAAK,SAAS,gBAAAA,KAAC,OAAE,WAAU,4CAA4C,mBAAS,KAAK,QAAQ,GAAG,GAAE,IAAO;AAAA,MACzG,KAAK,kBACJ,gBAAAA,KAAC,OAAE,WAAU,mDAAmD,eAAK,gBAAgB,MAAM,GAAG,CAAC,GAAE,IAC/F;AAAA,OACN;AAAA,IACC,KAAK,mBAAmB,gBACvB,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,KAAK,mBAAmB,cAAc,KAAK,eAAe;AAAA,QACzE,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACD;AAAA;AAAA,IAED,IACE;AAAA,KACN;AAEJ;;;AE9WM,gBAAAQ,MAOA,QAAAC,aAPA;AAjCC,SAAS,oBAAoB,SAA0B;AAC5D,aAAW,OAAO,CAAC,SAAS,MAAM,GAAY;AAC5C,UAAM,QAAQ,QAAQ,SAAS,GAAG;AAClC,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,GAAG;AACxD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,SAAS,QAAQ,gBAAgB,GAAG,KAAK,QAAQ,GAAG,MAAM,GAAG,CAAC;AACvE;AAOO,SAAS,UAAU,EAAE,SAAS,OAAO,UAAU,QAAQ,UAAU,GAAmB;AACzF,QAAM,UAAU,QAAQ,WAAW,aAAa,QAAQ,WAAW;AACnE,QAAM,WAAW,QAAQ,WAAW;AACpC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,eAAa,QAAQ;AAAA,MACrB,SAAS,SAAS,MAAM,OAAO,OAAO,IAAI;AAAA,MAC1C,UAAU,CAAC;AAAA,MACX,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,WAAW;AAAA,cACT;AAAA,cACA,UAAU,6BAA6B,WAAW,qCAAqC;AAAA,YACzF;AAAA;AAAA,QACF;AAAA,QACA,gBAAAC,MAAC,UAAK,WAAU,iDACd;AAAA,0BAAAD,KAAC,UAAK,WAAU,oEAAoE,mBAAS,oBAAoB,OAAO,GAAE;AAAA,UAC1H,gBAAAA,KAAC,iBAAc,QAAQ,QAAQ,QAAQ,MAAK,MAAK,WAAU,SAAQ;AAAA,WACrE;AAAA,QACC,WAAW,gBAAAA,KAAC,UAAK,WAAU,yCAAyC,oBAAS,IAAU;AAAA,QACxF,gBAAAC,MAAC,UAAK,WAAU,wEACd;AAAA,0BAAAD,KAAC,UAAK,WAAU,gBAAgB,kBAAQ,GAAG,MAAM,GAAG,CAAC,GAAE;AAAA,UACvD,gBAAAA,KAAC,UAAK,eAAW,MAAC,kBAAC;AAAA,UACnB,gBAAAA,KAAC,UAAK,WAAU,YAAY,kBAAQ,OAAM;AAAA,UAC1C,gBAAAA,KAAC,UAAK,WAAU,oBAAmB,OAAO,QAAQ,WAC/C,6BAAmB,QAAQ,SAAS,GACvC;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":["useCallback","useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useEffect","useMemo","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","useCallback","useState","useState","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useMemo","useRef","useState","useState","useRef","useMemo","useCallback","errorMessage","options","jsx","AnimatePresence","motion","useCallback","useEffect","useMemo","useRef","useState","jsx","jsxs","useRef","useState","useCallback","useEffect","useMemo","AnimatePresence","motion","AnimatePresence","motion","useEffect","useMemo","useRef","useState","jsx","jsxs","jsx","jsxs","useMemo","useRef","useState","useEffect","AnimatePresence","motion","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/provider.tsx","../src/hooks/use-session.ts","../src/hooks/internal.ts","../src/hooks/use-session-events.ts","../src/lib/format.ts","../src/timeline.ts","../src/hooks/use-composer.ts","../src/hooks/use-file-attachments.ts","../src/hooks/use-turn-queue.ts","../src/hooks/use-goal.ts","../src/hooks/use-session-control.ts","../src/hooks/use-scheduled-tasks.ts","../src/hooks/use-workspace-sessions.ts","../src/hooks/use-environments.ts","../src/hooks/use-packs.ts","../src/hooks/use-workspaces.ts","../src/hooks/use-billing-usage.ts","../src/hooks/use-available-models.ts","../src/approvals.ts","../src/commands/registry.ts","../src/hooks/use-slash-commands.ts","../src/components/command-palette.tsx","../src/lib/cn.ts","../src/components/chat-composer.tsx","../src/components/model-picker.tsx","../src/components/message-timeline.tsx","../src/components/markdown.tsx","../src/components/session-status.tsx","../src/components/fleet-tile.tsx"],"sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { SessionClientLike } from \"./client\";\n\nexport type OpenGeniContextValue = {\n client: SessionClientLike;\n workspaceId: string;\n};\n\nconst OpenGeniContext = createContext<OpenGeniContextValue | null>(null);\n\nexport type OpenGeniProviderProps = {\n client: SessionClientLike;\n workspaceId: string;\n children?: ReactNode;\n};\n\n/**\n * Supplies the OpenGeni client + workspace to all hooks below it. Hooks also\n * accept `{ client, workspaceId }` overrides per call for multi-workspace UIs.\n */\nexport function OpenGeniProvider({ client, workspaceId, children }: OpenGeniProviderProps) {\n const value = useMemo(() => ({ client, workspaceId }), [client, workspaceId]);\n return <OpenGeniContext.Provider value={value}>{children}</OpenGeniContext.Provider>;\n}\n\nexport type ClientOverride = {\n client?: SessionClientLike | undefined;\n workspaceId?: string | undefined;\n};\n\n/** Resolve client + workspace from explicit overrides or the provider. */\nexport function useOpenGeni(override: ClientOverride = {}): OpenGeniContextValue {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n const workspaceId = override.workspaceId ?? context?.workspaceId;\n if (!client || !workspaceId) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client/workspace available. Wrap the tree in <OpenGeniProvider> or pass { client, workspaceId } to the hook.\",\n );\n }\n return { client, workspaceId };\n}\n\n/**\n * Resolve the client only — for hooks that are not workspace-scoped\n * (`useWorkspaces`, `useBillingUsage`).\n */\nexport function useOpenGeniClient(override: Pick<ClientOverride, \"client\"> = {}): SessionClientLike {\n const context = useContext(OpenGeniContext);\n const client = override.client ?? context?.client;\n if (!client) {\n throw new Error(\n \"@opengeni/react: no OpenGeni client available. Wrap the tree in <OpenGeniProvider> or pass { client } to the hook.\",\n );\n }\n return client;\n}\n","import type { Session } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseSessionOptions = ClientOverride & {\n /** Re-fetch on an interval (ms). Off by default — pair with `useSessionEvents` for live status. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseSessionResult = {\n session: Session | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** Fetch one session (with optional polling). */\nexport function useSession(sessionId: string | null | undefined, options: UseSessionOptions = {}): UseSessionResult {\n const { client, workspaceId } = useOpenGeni(options);\n const load = useCallback(async () => {\n if (!sessionId) {\n return null;\n }\n return await client.getSession(workspaceId, sessionId);\n }, [client, workspaceId, sessionId]);\n const state = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled: (options.enabled ?? true) && Boolean(sessionId),\n });\n return { session: state.data ?? null, loading: state.loading, error: state.error, refresh: state.refresh };\n}\n","import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { SessionClientLike } from \"../client\";\n\nexport type AsyncListState<T> = {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Shared fetch + optional polling loop for the list/read hooks. Stale\n * responses (superseded by a newer load or an unmount) are dropped.\n */\nexport function usePolledValue<T>(load: () => Promise<T>, options: { pollIntervalMs?: number | undefined; enabled?: boolean | undefined } = {}): AsyncListState<T> {\n const enabled = options.enabled ?? true;\n const pollIntervalMs = options.pollIntervalMs;\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const generation = useRef(0);\n const loadRef = useRef(load);\n\n // A new loader identity means a new query (different session/workspace/...):\n // drop the previous result instead of showing it as the new query's data.\n useEffect(() => {\n if (loadRef.current !== load) {\n loadRef.current = load;\n setData(null);\n setError(null);\n }\n }, [load]);\n\n const run = useCallback(async () => {\n const ticket = ++generation.current;\n try {\n const result = await load();\n if (ticket === generation.current) {\n setData(result);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (ticket === generation.current) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setLoading(false);\n }\n }\n }, [load]);\n\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void run();\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n };\n }\n const timer = setInterval(() => void run(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n };\n }, [run, enabled, pollIntervalMs]);\n\n return { data, loading, error, refresh: run };\n}\n\nexport type MutationState = {\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Shared async mutation runner for the write hooks. `run` resolves with the\n * operation's value, or `null` after capturing the error in `mutationError`\n * (callers then roll back optimistic state).\n */\nexport function useMutationRunner(): MutationState & {\n run: <T>(operation: () => Promise<T>) => Promise<T | null>;\n} {\n const [mutating, setMutating] = useState(false);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const inFlight = useRef(0);\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const run = useCallback(async <T,>(operation: () => Promise<T>): Promise<T | null> => {\n inFlight.current += 1;\n if (mounted.current) {\n setMutating(true);\n setMutationError(null);\n }\n try {\n return await operation();\n } catch (cause) {\n if (mounted.current) {\n setMutationError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n return null;\n } finally {\n inFlight.current -= 1;\n if (mounted.current && inFlight.current === 0) {\n setMutating(false);\n }\n }\n }, []);\n return {\n mutating,\n mutationError,\n clearMutationError: useCallback(() => setMutationError(null), []),\n run,\n };\n}\n\nexport type SessionEventFeedOptions = {\n /**\n * Share an existing event log (from `useSessionEvents`) instead of opening\n * a second stream. When omitted the hook tails the session's event stream\n * itself, starting at the current `lastSequence`.\n */\n events?: SessionEvent[] | undefined;\n enabled?: boolean | undefined;\n};\n\n/**\n * Invoke `onEvent` for every session event matching `match` — the live-update\n * primitive behind `useTurnQueue` and `useGoal`. Either watches a shared\n * `events` log or tails the stream directly (reconnect handled by the SDK).\n */\nexport function useSessionEventTrigger(\n client: SessionClientLike,\n workspaceId: string,\n sessionId: string | null | undefined,\n match: (event: SessionEvent) => boolean,\n onEvent: (event: SessionEvent) => void,\n options: SessionEventFeedOptions = {},\n): void {\n const enabled = options.enabled ?? true;\n const events = options.events;\n const sharedFeed = events !== undefined;\n const matchRef = useRef(match);\n matchRef.current = match;\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n const consumedRef = useRef(0);\n const feedKeyRef = useRef<string | null>(null);\n\n // Shared-log mode: scan only the unseen tail on every append.\n useEffect(() => {\n if (!sharedFeed || !enabled || !sessionId) {\n return;\n }\n const feedKey = `${workspaceId}\\u0000${sessionId}`;\n const firstSequence = events[0]?.sequence ?? 0;\n // A new session target or a log reset (sequence restarted below the\n // cursor) restarts consumption from the top of the shared log.\n if (feedKeyRef.current !== feedKey || firstSequence > consumedRef.current + 1) {\n feedKeyRef.current = feedKey;\n consumedRef.current = 0;\n }\n for (const event of events) {\n if (event.sequence <= consumedRef.current) {\n continue;\n }\n consumedRef.current = event.sequence;\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n }, [sharedFeed, enabled, events, workspaceId, sessionId]);\n\n // Self-stream mode: tail from the session's current lastSequence.\n useEffect(() => {\n if (sharedFeed || !enabled || !sessionId) {\n return;\n }\n const controller = new AbortController();\n void (async () => {\n try {\n const session = await client.getSession(workspaceId, sessionId);\n if (controller.signal.aborted) {\n return;\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: session.lastSequence,\n signal: controller.signal,\n });\n for await (const event of stream) {\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n } catch {\n // Live updates are best-effort: the read hooks still expose refresh()\n // and the initial load already populated state.\n }\n })();\n return () => {\n controller.abort();\n };\n }, [sharedFeed, enabled, client, workspaceId, sessionId]);\n}\n\n/** Debounce rapid event bursts into one trailing call (default 150ms). */\nexport function useDebouncedCallback(callback: () => void, delayMs = 150): () => void {\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n return useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n callbackRef.current();\n }, delayMs);\n }, [delayMs]);\n}\n","import type { SessionEvent, SessionStatus, StreamConnectionState } from \"@opengeni/sdk\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { buildTimeline, sessionStatusFromEvents, type TimelineItem } from \"../timeline\";\n\nexport type SessionEventsConnectionState = StreamConnectionState | \"idle\" | \"ended\" | \"error\";\n\nexport type UseSessionEventsOptions = ClientOverride & {\n /** Resume after this sequence (exclusive). Defaults to 0 = full replay. */\n after?: number | undefined;\n /** Pause the stream without unmounting (e.g. hidden tab). Defaults to true. */\n enabled?: boolean | undefined;\n};\n\nexport type UseSessionEventsResult = {\n /** Replayed + live events, ordered by sequence, no gaps, no duplicates. */\n events: SessionEvent[];\n /** Projected, renderable timeline (memoized over `events`). */\n timeline: TimelineItem[];\n /** Latest session status observed in the event log, if any. */\n sessionStatus: SessionStatus | null;\n connectionState: SessionEventsConnectionState;\n /** Highest sequence seen so far (0 before the first event). */\n lastSequence: number;\n error: Error | null;\n};\n\n/**\n * Live-stream a session's event log with replay-by-sequence, reconnect, and\n * batched React updates. The SDK guarantees ordered, gap-free, exactly-once\n * delivery; this hook accumulates the log and projects it into a timeline.\n */\nexport function useSessionEvents(sessionId: string | null | undefined, options: UseSessionEventsOptions = {}): UseSessionEventsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = options.enabled ?? true;\n const after = options.after ?? 0;\n\n const [events, setEvents] = useState<SessionEvent[]>([]);\n const [connectionState, setConnectionState] = useState<SessionEventsConnectionState>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const lastSequenceRef = useRef(after);\n const streamKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n // Reset the accumulated log only when the stream identity changes —\n // pausing via `enabled: false` keeps the timeline visible.\n const streamKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${after}`;\n if (streamKeyRef.current !== streamKey) {\n streamKeyRef.current = streamKey;\n setEvents([]);\n setError(null);\n lastSequenceRef.current = after;\n }\n if (!sessionId || !enabled) {\n setConnectionState(\"idle\");\n return;\n }\n const controller = new AbortController();\n // Batch yielded events into one React update per flush window so a long\n // replay (thousands of events) does not render per event.\n let pending: SessionEvent[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n const flush = () => {\n flushTimer = null;\n if (pending.length === 0) {\n return;\n }\n const batch = pending;\n pending = [];\n // The resume cursor only advances with delivered batches: events still\n // sitting in `pending` when the stream is torn down are re-fetched on\n // the next connect instead of being skipped.\n const lastInBatch = batch[batch.length - 1];\n if (lastInBatch) {\n lastSequenceRef.current = lastInBatch.sequence;\n }\n setEvents((existing) => [...existing, ...batch]);\n };\n const scheduleFlush = () => {\n flushTimer ??= setTimeout(flush, 16);\n };\n\n void (async () => {\n try {\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: lastSequenceRef.current,\n signal: controller.signal,\n onStateChange: (state) => {\n if (!controller.signal.aborted) {\n setConnectionState(state);\n }\n },\n });\n for await (const event of stream) {\n pending.push(event);\n scheduleFlush();\n }\n if (!controller.signal.aborted) {\n flush();\n setConnectionState(\"ended\");\n }\n } catch (cause) {\n if (!controller.signal.aborted) {\n flush();\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setConnectionState(\"error\");\n }\n }\n })();\n\n return () => {\n controller.abort();\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n }\n };\n }, [client, workspaceId, sessionId, after, enabled]);\n\n const timeline = useMemo(() => buildTimeline(events), [events]);\n const sessionStatus = useMemo(() => sessionStatusFromEvents(events), [events]);\n\n return {\n events,\n timeline,\n sessionStatus,\n connectionState,\n lastSequence: lastSequenceRef.current,\n error,\n };\n}\n","/** Compact relative time: \"now\", \"42s\", \"7m\", \"3h\", \"2d\", then a date. */\nexport function formatRelativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) {\n return \"\";\n }\n const seconds = Math.max(0, Math.floor((now.getTime() - then) / 1000));\n if (seconds < 10) {\n return \"now\";\n }\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n if (hours < 24) {\n return `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n if (days < 14) {\n return `${days}d`;\n }\n return new Date(iso).toLocaleDateString();\n}\n\n/** Human-readable byte size: \"512 B\", \"8.0 KB\", \"1.4 MB\", \"3 GB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = bytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value < 10 ? 1 : 0)} ${unit}`;\n }\n value /= 1024;\n }\n return `${bytes} B`;\n}\n\n/** Single-line preview of arbitrary text, for tiles and collapsed rows. */\nexport function truncate(text: string, maxLength: number): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Render an unknown payload as readable text (pretty JSON when possible). */\nexport function stringifyPayload(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n const parsed = tryParseJson(value);\n if (parsed !== undefined && typeof parsed === \"object\") {\n return stringifyPayload(parsed);\n }\n return value;\n }\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** JSON.parse that returns `undefined` instead of throwing. */\nexport function tryParseJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\") && !trimmed.startsWith('\"')) {\n return undefined;\n }\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return undefined;\n }\n}\n","import type { ResourceRef, SessionEvent, SessionStatus, ToolRef } from \"@opengeni/sdk\";\nimport { stringifyPayload, tryParseJson } from \"./lib/format\";\n\n/* ----------------------------------------------------------------------------\n Timeline projection\n\n `buildTimeline` folds a session's raw event log (replayed + live, ordered by\n sequence) into renderable items: chat messages with accumulated streaming\n deltas, reasoning summaries, tool calls matched to their outputs, sandbox\n operations with command output, spawned-worker status (the manager's\n `session_create` / `session_send_message` orchestration calls), goal\n markers, status changes, and turn failures.\n\n It is a pure function — same events in, same items out — so it can be\n memoized, unit-tested, and re-run incrementally as new events stream in.\n -------------------------------------------------------------------------- */\n\nexport type UserMessageItem = {\n kind: \"user-message\";\n id: string;\n text: string;\n /** Resources attached to this message (file uploads, repositories). */\n resources: ResourceRef[];\n /** Tools requested for the turn this message starts. */\n tools: ToolRef[];\n occurredAt: string;\n};\n\nexport type AgentMessageItem = {\n kind: \"agent-message\";\n id: string;\n turnId: string | null;\n text: string;\n /** Still receiving deltas (no completed/turn-end seen yet). */\n streaming: boolean;\n occurredAt: string;\n};\n\nexport type ReasoningItem = {\n kind: \"reasoning\";\n id: string;\n turnId: string | null;\n text: string;\n streaming: boolean;\n occurredAt: string;\n};\n\nexport type ToolCallItem = {\n kind: \"tool-call\";\n id: string;\n turnId: string | null;\n callId: string | null;\n name: string;\n arguments: unknown;\n output: unknown;\n status: \"running\" | \"complete\";\n occurredAt: string;\n};\n\n/**\n * An orchestration call against another session — the manager spawning or\n * messaging a worker. Rendered as a first-class \"worker\" row, not a generic\n * tool call.\n */\nexport type WorkerItem = {\n kind: \"worker\";\n id: string;\n turnId: string | null;\n callId: string | null;\n action: \"spawn\" | \"message\";\n /** The worker's initial message / the message sent to it, when parseable. */\n prompt: string | null;\n /** The target/spawned worker session id, when parseable from args/output. */\n workerSessionId: string | null;\n status: \"running\" | \"complete\";\n occurredAt: string;\n};\n\nexport type SandboxItem = {\n kind: \"sandbox\";\n id: string;\n turnId: string | null;\n name: string;\n command: string | null;\n output: string;\n status: \"running\" | \"complete\" | \"failed\";\n occurredAt: string;\n};\n\nexport type SessionStatusItem = {\n kind: \"session-status\";\n id: string;\n status: SessionStatus;\n occurredAt: string;\n};\n\nexport type GoalItem = {\n kind: \"goal\";\n id: string;\n action: \"set\" | \"updated\" | \"completed\" | \"paused\" | \"resumed\" | \"continuation\";\n text: string | null;\n occurredAt: string;\n};\n\nexport type NoticeItem = {\n kind: \"notice\";\n id: string;\n tone: \"waiting\" | \"cancelled\" | \"failed\";\n text: string;\n occurredAt: string;\n};\n\nexport type TimelineItem =\n | UserMessageItem\n | AgentMessageItem\n | ReasoningItem\n | ToolCallItem\n | WorkerItem\n | SandboxItem\n | SessionStatusItem\n | GoalItem\n | NoticeItem;\n\n/** Tool names on the first-party OpenGeni MCP server that operate on sessions. */\nconst WORKER_SPAWN_TOOL = \"session_create\";\nconst WORKER_MESSAGE_TOOL = \"session_send_message\";\n\nexport function buildTimeline(events: SessionEvent[]): TimelineItem[] {\n const items: TimelineItem[] = [];\n const ordered = [...events].sort((a, b) => a.sequence - b.sequence);\n\n const last = (): TimelineItem | undefined => items[items.length - 1];\n\n /** A new item of a different kind ends whatever was streaming at the tail. */\n const closeStreamingTail = (): void => {\n const open = last();\n if ((open?.kind === \"agent-message\" || open?.kind === \"reasoning\") && open.streaming) {\n open.streaming = false;\n }\n };\n\n const finalizeOpen = (turnId?: string | null): void => {\n for (const item of items) {\n if (turnId !== undefined && \"turnId\" in item && item.turnId && turnId && item.turnId !== turnId) {\n continue;\n }\n if ((item.kind === \"agent-message\" || item.kind === \"reasoning\") && item.streaming) {\n item.streaming = false;\n }\n if ((item.kind === \"tool-call\" || item.kind === \"worker\") && item.status === \"running\") {\n item.status = \"complete\";\n }\n if (item.kind === \"sandbox\" && item.status === \"running\") {\n item.status = \"complete\";\n }\n }\n };\n\n for (const event of ordered) {\n const payload = asRecord(event.payload);\n const turnId = event.turnId ?? null;\n\n switch (event.type) {\n case \"user.message\": {\n // A steering message must not mark in-flight tools complete; it only\n // ends whatever text was streaming. Turn lifecycle events finalize.\n closeStreamingTail();\n items.push({\n kind: \"user-message\",\n id: event.id,\n text: typeof payload.text === \"string\" ? payload.text : \"\",\n resources: resourceRefs(payload.resources),\n tools: toolRefs(payload.tools),\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.message.delta\": {\n const text = typeof payload.text === \"string\" ? payload.text : \"\";\n if (!text) {\n break;\n }\n const open = last();\n if (open?.kind === \"agent-message\" && open.streaming && open.turnId === turnId) {\n open.text += text;\n break;\n }\n closeStreamingTail();\n items.push({\n kind: \"agent-message\",\n id: event.id,\n turnId,\n text,\n streaming: true,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.message.completed\": {\n const text = typeof payload.text === \"string\" ? payload.text : \"\";\n // Reconcile the most recent same-turn agent message — even when\n // activity (tool calls, reasoning) landed after its deltas — so the\n // completed text never duplicates the streamed one.\n const open = [...items]\n .reverse()\n .find((item): item is AgentMessageItem => item.kind === \"agent-message\" && item.turnId === turnId);\n if (open && (open.streaming || !open.text || text === open.text || text.startsWith(open.text))) {\n // The completed text is authoritative when it extends what streamed.\n if (!open.text || (text && text.startsWith(open.text))) {\n open.text = text || open.text;\n }\n open.streaming = false;\n break;\n }\n if (text) {\n items.push({\n kind: \"agent-message\",\n id: event.id,\n turnId,\n text,\n streaming: false,\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"agent.reasoning.delta\": {\n const text = reasoningText(event.payload);\n if (!text) {\n break;\n }\n const open = last();\n if (open?.kind === \"reasoning\" && open.streaming && open.turnId === turnId) {\n open.text += text;\n break;\n }\n closeStreamingTail();\n items.push({\n kind: \"reasoning\",\n id: event.id,\n turnId,\n text,\n streaming: true,\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.toolCall.created\": {\n const name = typeof payload.name === \"string\" ? payload.name : \"tool\";\n const callId = typeof payload.id === \"string\" ? payload.id : null;\n const args = payload.arguments ?? null;\n closeStreamingTail();\n if (name === WORKER_SPAWN_TOOL || name === WORKER_MESSAGE_TOOL) {\n items.push({\n kind: \"worker\",\n id: event.id,\n turnId,\n callId,\n action: name === WORKER_SPAWN_TOOL ? \"spawn\" : \"message\",\n prompt: workerPrompt(args),\n workerSessionId: extractSessionRef(args),\n status: \"running\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n items.push({\n kind: \"tool-call\",\n id: event.id,\n turnId,\n callId,\n name,\n arguments: args,\n output: undefined,\n status: \"running\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"agent.toolCall.output\": {\n const callId = typeof payload.id === \"string\" ? payload.id : null;\n const target = findOpenCall(items, callId);\n if (!target) {\n break;\n }\n if (target.kind === \"worker\") {\n target.status = \"complete\";\n target.workerSessionId = target.workerSessionId ?? extractSessionRef(payload.output);\n break;\n }\n target.status = \"complete\";\n target.output = payload.output;\n break;\n }\n\n case \"sandbox.operation.started\":\n case \"sandbox.operation.completed\":\n case \"sandbox.operation.failed\": {\n const name = typeof payload.name === \"string\" ? payload.name : \"sandbox\";\n const status = event.type.endsWith(\".failed\") ? \"failed\" : event.type.endsWith(\".completed\") ? \"complete\" : \"running\";\n const existing = findOpenSandbox(items, name);\n if (existing && status !== \"running\") {\n existing.status = status;\n const message = failureMessage(payload);\n if (message) {\n existing.output = existing.output ? `${existing.output}\\n${message}` : message;\n }\n break;\n }\n if (!existing) {\n closeStreamingTail();\n items.push({\n kind: \"sandbox\",\n id: event.id,\n turnId,\n name,\n command: typeof payload.command === \"string\" ? payload.command : null,\n output: failureMessage(payload) ?? \"\",\n status,\n occurredAt: event.occurredAt,\n });\n }\n break;\n }\n\n case \"sandbox.command.output.delta\": {\n const text = typeof payload.text === \"string\" ? payload.text : typeof payload.output === \"string\" ? payload.output : \"\";\n if (!text) {\n break;\n }\n // Attach to the named operation when the payload carries one;\n // otherwise the latest running operation is the best available owner.\n const open =\n (typeof payload.name === \"string\" ? findOpenSandbox(items, payload.name) : undefined) ??\n [...items].reverse().find((item): item is SandboxItem => item.kind === \"sandbox\" && item.status === \"running\");\n if (open) {\n open.output += text;\n }\n break;\n }\n\n case \"session.status.changed\": {\n const status = payload.status;\n if (!isSessionStatus(status)) {\n break;\n }\n const previous = [...items].reverse().find((item): item is SessionStatusItem => item.kind === \"session-status\");\n if (previous?.status === status) {\n break;\n }\n items.push({ kind: \"session-status\", id: event.id, status, occurredAt: event.occurredAt });\n break;\n }\n\n case \"session.requiresAction\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"waiting\",\n text: \"Approval needed — the turn is paused until someone decides.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"turn.completed\": {\n finalizeOpen(turnId);\n break;\n }\n\n case \"turn.failed\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"failed\",\n text: failureMessage(payload) ?? \"The turn failed.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"turn.cancelled\": {\n finalizeOpen(turnId);\n items.push({\n kind: \"notice\",\n id: event.id,\n tone: \"cancelled\",\n text: \"Interrupted.\",\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n case \"goal.set\":\n case \"goal.updated\":\n case \"goal.completed\":\n case \"goal.paused\":\n case \"goal.resumed\":\n case \"goal.continuation\": {\n items.push({\n kind: \"goal\",\n id: event.id,\n action: event.type.slice(\"goal.\".length) as GoalItem[\"action\"],\n text: goalText(payload),\n occurredAt: event.occurredAt,\n });\n break;\n }\n\n default:\n break;\n }\n }\n\n return items;\n}\n\n/** The latest session status carried in the event log, if any. */\nexport function sessionStatusFromEvents(events: SessionEvent[]): SessionStatus | null {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event?.type !== \"session.status.changed\") {\n continue;\n }\n const status = asRecord(event.payload).status;\n if (isSessionStatus(status)) {\n return status;\n }\n }\n return null;\n}\n\n/* ----------------------------------------------------------------------------\n Visual grouping: consecutive activity items (reasoning / tools / workers /\n sandbox) cluster into one collapsible block between chat messages.\n -------------------------------------------------------------------------- */\n\nexport type TimelineGroup =\n | { kind: \"item\"; item: TimelineItem }\n | { kind: \"activity\"; id: string; items: (ReasoningItem | ToolCallItem | WorkerItem | SandboxItem)[] };\n\nconst ACTIVITY_KINDS = new Set([\"reasoning\", \"tool-call\", \"worker\", \"sandbox\"]);\n\nexport function groupTimeline(items: TimelineItem[]): TimelineGroup[] {\n const groups: TimelineGroup[] = [];\n for (const item of items) {\n if (ACTIVITY_KINDS.has(item.kind)) {\n const open = groups[groups.length - 1];\n const activity = item as ReasoningItem | ToolCallItem | WorkerItem | SandboxItem;\n if (open?.kind === \"activity\") {\n open.items.push(activity);\n } else {\n groups.push({ kind: \"activity\", id: `activity-${item.id}`, items: [activity] });\n }\n continue;\n }\n groups.push({ kind: \"item\", item });\n }\n return groups;\n}\n\n/* --- helpers ---------------------------------------------------------------- */\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === \"object\" ? (value as Record<string, unknown>) : {};\n}\n\nconst SESSION_STATUSES: readonly SessionStatus[] = [\"queued\", \"running\", \"idle\", \"requires_action\", \"failed\", \"cancelled\"];\n\n/** Keep only entries that match the wire shapes; user payloads are untyped. */\nfunction resourceRefs(value: unknown): ResourceRef[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is ResourceRef => {\n const record = asRecord(entry);\n if (record.kind === \"repository\") {\n return typeof record.uri === \"string\" && typeof record.ref === \"string\";\n }\n return record.kind === \"file\" && typeof record.fileId === \"string\";\n });\n}\n\nfunction toolRefs(value: unknown): ToolRef[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is ToolRef => {\n const record = asRecord(entry);\n return record.kind === \"mcp\" && typeof record.id === \"string\";\n });\n}\n\nfunction isSessionStatus(value: unknown): value is SessionStatus {\n return typeof value === \"string\" && (SESSION_STATUSES as readonly string[]).includes(value);\n}\n\nfunction findOpenCall(items: TimelineItem[], callId: string | null): ToolCallItem | WorkerItem | undefined {\n const reversed = [...items].reverse();\n const isCall = (item: TimelineItem): item is ToolCallItem | WorkerItem => item.kind === \"tool-call\" || item.kind === \"worker\";\n if (callId) {\n const byId = reversed.find((item) => isCall(item) && item.callId === callId);\n if (byId) {\n return byId as ToolCallItem | WorkerItem;\n }\n }\n return reversed.find((item): item is ToolCallItem | WorkerItem => isCall(item) && item.status === \"running\");\n}\n\nfunction findOpenSandbox(items: TimelineItem[], name: string): SandboxItem | undefined {\n return [...items].reverse().find((item): item is SandboxItem => item.kind === \"sandbox\" && item.name === name && item.status === \"running\");\n}\n\nfunction failureMessage(payload: Record<string, unknown>): string | null {\n for (const key of [\"error\", \"message\"] as const) {\n const value = payload[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return null;\n}\n\nfunction goalText(payload: Record<string, unknown>): string | null {\n if (typeof payload.text === \"string\" && payload.text) {\n return payload.text;\n }\n const goal = asRecord(payload.goal);\n if (typeof goal.text === \"string\" && goal.text) {\n return goal.text;\n }\n if (typeof payload.prompt === \"string\" && payload.prompt) {\n return payload.prompt;\n }\n return null;\n}\n\nfunction reasoningText(payload: unknown): string {\n const record = asRecord(payload);\n if (typeof record.text === \"string\") {\n return record.text;\n }\n const content = asRecord(asRecord(record.item).rawItem).content;\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((part) => {\n const text = asRecord(part).text;\n return typeof text === \"string\" ? text : \"\";\n })\n .join(\"\");\n}\n\n/** The worker's initial/sent message from `session_create`/`session_send_message` args. */\nfunction workerPrompt(args: unknown): string | null {\n const record = asRecord(typeof args === \"string\" ? tryParseJson(args) : args);\n for (const key of [\"initialMessage\", \"message\", \"text\", \"prompt\"] as const) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return null;\n}\n\n/**\n * Find a session id in orchestration tool arguments or output. Handles raw\n * objects, JSON strings, and MCP tool results (`{ content: [{ type: \"text\",\n * text: \"{...}\" }], structuredContent? }`).\n */\nexport function extractSessionRef(value: unknown, depth = 0): string | null {\n if (depth > 6 || value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\") {\n return extractSessionRef(tryParseJson(value), depth + 1);\n }\n if (Array.isArray(value)) {\n for (const entry of value) {\n const found = extractSessionRef(entry, depth + 1);\n if (found) {\n return found;\n }\n }\n return null;\n }\n if (typeof value !== \"object\") {\n return null;\n }\n const record = value as Record<string, unknown>;\n if (typeof record.sessionId === \"string\" && looksLikeId(record.sessionId)) {\n return record.sessionId;\n }\n if (typeof record.id === \"string\" && looksLikeId(record.id) && (\"status\" in record || \"workspaceId\" in record || \"initialMessage\" in record)) {\n return record.id;\n }\n for (const key of [\"structuredContent\", \"session\", \"result\", \"content\"] as const) {\n if (key in record) {\n const found = extractSessionRef(record[key], depth + 1);\n if (found) {\n return found;\n }\n }\n }\n if (typeof record.text === \"string\") {\n return extractSessionRef(tryParseJson(record.text), depth + 1);\n }\n return null;\n}\n\nfunction looksLikeId(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n\n/** Readable label for a tool call (\"session_create\" -> \"session create\"). */\nexport function toolDisplayName(name: string): string {\n return name.replace(/[_-]+/g, \" \").trim();\n}\n\n/** Compact, single-line preview of tool arguments/outputs for collapsed rows. */\nexport function compactPayloadPreview(value: unknown, maxLength = 120): string {\n const text = stringifyPayload(value).replace(/\\s+/g, \" \").trim();\n return text.length > maxLength ? `${text.slice(0, maxLength - 1)}…` : text;\n}\n","import type { SendMessageInput } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\n\nexport type ComposerSendExtras = Omit<SendMessageInput, \"text\" | \"clientEventId\">;\n\n/**\n * Compose-time delivery choice. `queue` (the default) stacks the message\n * behind the running turn — visible, editable, reorderable until claimed.\n * `steer` interrupts the running turn and injects the message now.\n */\nexport type ComposerMode = \"queue\" | \"steer\";\n\nexport type UseComposerOptions = ClientOverride & {\n /** Called with the accepted text after a successful send. */\n onSent?: ((text: string) => void) | undefined;\n /**\n * Extra message fields (resources, tools, model, reasoningEffort) merged\n * into every send. A function is evaluated at send time so it can read the\n * surrounding UI state (attachment pickers, model selectors, ...).\n */\n sendExtras?: ComposerSendExtras | (() => ComposerSendExtras) | undefined;\n /** Initial delivery mode. Defaults to `\"queue\"`. */\n defaultMode?: ComposerMode | undefined;\n};\n\nexport type ComposerState = {\n value: string;\n setValue: (value: string) => void;\n /** Send the draft (or an explicit text) using the current mode. */\n send: (text?: string) => Promise<boolean>;\n sending: boolean;\n canSend: boolean;\n /** Queue (default) vs steer — the compose-time delivery choice. */\n mode: ComposerMode;\n setMode: (mode: ComposerMode) => void;\n /** Ask the agent to stop the current turn. */\n interrupt: (reason?: string) => Promise<void>;\n interrupting: boolean;\n error: Error | null;\n clearError: () => void;\n};\n\n/**\n * Draft + send + interrupt state for the chat composer — the only\n * human-to-agent input surface. The draft survives a failed send (nothing is\n * more hostile than losing a typed message); each send carries a generated\n * `clientEventId` so retries stay idempotent server-side.\n */\nexport function useComposer(sessionId: string | null | undefined, options: UseComposerOptions = {}): ComposerState {\n const { client, workspaceId } = useOpenGeni(options);\n const defaultMode = options.defaultMode ?? \"queue\";\n const [value, setValue] = useState(\"\");\n const [mode, setMode] = useState<ComposerMode>(defaultMode);\n const [sending, setSending] = useState(false);\n const [interrupting, setInterrupting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const pendingClientEventId = useRef<string | null>(null);\n const onSent = options.onSent;\n // Read at send time so an in-flight send uses the mode chosen at submit.\n const modeRef = useRef(mode);\n modeRef.current = mode;\n // Read through a ref so a new extras closure (created every render by\n // callers passing inline functions) does not invalidate `send`.\n const sendExtrasRef = useRef(options.sendExtras);\n sendExtrasRef.current = options.sendExtras;\n\n // A composer is bound to one session: switching targets must not leak the\n // previous session's draft, error, or retry idempotency key.\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n const targetKeyRef = useRef(targetKey);\n useEffect(() => {\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n pendingClientEventId.current = null;\n setValue(\"\");\n setError(null);\n setMode(defaultMode);\n }\n }, [targetKey, defaultMode]);\n\n const send = useCallback(\n async (explicit?: string): Promise<boolean> => {\n const draftAtSend = value;\n const text = (explicit ?? draftAtSend).trim();\n // Resolve the extras once: a file-only message (empty text + ≥1 ready\n // resource) is legitimate, so we must not bail on empty text alone.\n const extras = resolveSendExtras(sendExtrasRef.current);\n const hasResources = (extras.resources?.length ?? 0) > 0;\n if ((!text && !hasResources) || !sessionId || sending) {\n return false;\n }\n // Reuse the clientEventId across retries of the same draft so a\n // timeout + resend cannot double-deliver the message.\n pendingClientEventId.current ??= generateClientEventId();\n setSending(true);\n setError(null);\n try {\n // The wire contract requires non-empty text (z.string().min(1)) and the\n // worker rejects whitespace-only text; a file-only message therefore\n // carries a minimal default so the attachments still get delivered.\n const sendText = text || FILE_ONLY_MESSAGE_TEXT;\n const input = composeSendInput(sendText, pendingClientEventId.current, extras);\n if (modeRef.current === \"steer\") {\n await client.steerMessage(workspaceId, sessionId, input);\n } else {\n await client.sendMessage(workspaceId, sessionId, input);\n }\n pendingClientEventId.current = null;\n if (explicit === undefined) {\n // Clear only the draft that was sent: edits made while the request\n // was in flight were never delivered and must survive.\n setValue((current) => (current === draftAtSend ? \"\" : current));\n }\n onSent?.(sendText);\n return true;\n } catch (cause) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n return false;\n } finally {\n setSending(false);\n }\n },\n [client, workspaceId, sessionId, value, sending, onSent],\n );\n\n // A send is possible with non-empty text OR with ≥1 attached resource (a\n // file-only message). Resources ride in `sendExtras`, so we resolve them here\n // — keeping useComposer attachment-agnostic while still lighting up the send\n // affordance the moment a file is ready. ChatComposer additionally gates this\n // on its `attachments.uploading` flag so a message never departs mid-upload.\n const hasReadyResources = (resolveSendExtras(sendExtrasRef.current).resources?.length ?? 0) > 0;\n\n const interrupt = useCallback(\n async (reason?: string): Promise<void> => {\n if (!sessionId || interrupting) {\n return;\n }\n setInterrupting(true);\n setError(null);\n try {\n await client.interrupt(workspaceId, sessionId, reason !== undefined ? { reason } : {});\n } catch (cause) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n } finally {\n setInterrupting(false);\n }\n },\n [client, workspaceId, sessionId, interrupting],\n );\n\n const updateValue = useCallback((next: string) => {\n pendingClientEventId.current = null;\n setValue(next);\n }, []);\n\n return {\n value,\n setValue: updateValue,\n send,\n sending,\n canSend: Boolean(sessionId) && !sending && (value.trim().length > 0 || hasReadyResources),\n mode,\n setMode,\n interrupt,\n interrupting,\n error,\n clearError: useCallback(() => setError(null), []),\n };\n}\n\n/**\n * Default text for a file-only message (attachment(s) present, no typed draft).\n * Kept non-empty so the wire contract (`text: z.string().min(1)`) and the\n * worker's non-whitespace guard accept it; the attached files still ride in\n * `resources`. Exported for tests.\n */\nexport const FILE_ONLY_MESSAGE_TEXT = \"(see attached files)\";\n\n/** Resolve possibly-deferred extras to a concrete bag (function evaluated now). */\nexport function resolveSendExtras(\n extras: ComposerSendExtras | (() => ComposerSendExtras) | undefined,\n): ComposerSendExtras {\n return (typeof extras === \"function\" ? extras() : extras) ?? {};\n}\n\n/**\n * Merge the draft text + idempotency key with caller-provided extras. The\n * text and clientEventId always win over extras. Exported for tests.\n */\nexport function composeSendInput(\n text: string,\n clientEventId: string,\n extras: ComposerSendExtras | (() => ComposerSendExtras) | undefined,\n): SendMessageInput {\n return { ...resolveSendExtras(extras), text, clientEventId };\n}\n\n/** Submit on plain Enter; Shift+Enter inserts a newline. Exported for tests. */\nexport function shouldSubmitOnKey(event: { key: string; shiftKey: boolean; nativeEvent?: { isComposing?: boolean } }): boolean {\n if (event.key !== \"Enter\" || event.shiftKey) {\n return false;\n }\n return event.nativeEvent?.isComposing !== true;\n}\n\nfunction generateClientEventId(): string {\n const cryptoApi = globalThis.crypto;\n if (cryptoApi && \"randomUUID\" in cryptoApi) {\n return cryptoApi.randomUUID();\n }\n return `ce-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n","import type { FileAsset, FileResourceRef } from \"@opengeni/sdk\";\nimport { useCallback, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\n\nexport type UseFileAttachmentsOptions = ClientOverride & {\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 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 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 the send-gate). */\n uploading: 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 /** Remove one attachment; revokes its object-URL. */\n remove: (id: string) => void;\n /** Remove all; revokes every object-URL. Call from `useComposer`'s `onSent`. */\n clear: () => void;\n};\n\nconst isImage = (file: File): boolean => file.type.startsWith(\"image/\");\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(options: UseFileAttachmentsOptions = {}): UseFileAttachmentsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const pasteFilter = options.pasteFilter ?? isImage;\n const [attachments, setAttachments] = useState<FileAttachment[]>([]);\n\n const addFiles = useCallback((files: Iterable<File>) => {\n for (const file of files) {\n const id = crypto.randomUUID();\n const previewUrl = isImage(file) ? URL.createObjectURL(file) : undefined;\n setAttachments((current) => [...current, {\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 void client.uploadFile(workspaceId, {\n filename: file.name || \"file\",\n contentType: file.type || \"application/octet-stream\",\n data: file,\n }).then((asset) => {\n setAttachments((current) => current.map((attachment) => attachment.id === id\n ? { ...attachment, status: \"ready\", file: asset, name: asset.filename, contentType: asset.contentType, sizeBytes: asset.sizeBytes }\n : attachment));\n }).catch((error: unknown) => {\n setAttachments((current) => current.map((attachment) => attachment.id === id\n ? { ...attachment, status: \"failed\", error: error instanceof Error ? error.message : String(error) }\n : attachment));\n });\n }\n }, [client, workspaceId]);\n\n const addFromPaste = useCallback((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 }, [addFiles, pasteFilter]);\n\n const remove = useCallback((id: string) => {\n setAttachments((current) => {\n const removed = current.find((attachment) => attachment.id === id);\n if (removed?.previewUrl) {\n URL.revokeObjectURL(removed.previewUrl);\n }\n return current.filter((attachment) => attachment.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setAttachments((current) => {\n for (const attachment of current) {\n if (attachment.previewUrl) {\n URL.revokeObjectURL(attachment.previewUrl);\n }\n }\n return [];\n });\n }, []);\n\n return {\n attachments,\n readyResources: attachments.flatMap((attachment): FileResourceRef[] => attachment.status === \"ready\" && attachment.file\n ? [{ kind: \"file\", fileId: attachment.file.id }]\n : []),\n uploading: attachments.some((attachment) => attachment.status === \"uploading\"),\n addFiles,\n addFromPaste,\n remove,\n clear,\n };\n}\n","import type { SessionEvent, SessionTurn, UpdateSessionTurnRequest } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useDebouncedCallback, useMutationRunner, useSessionEventTrigger, type SessionEventFeedOptions } from \"./internal\";\n\n/** Event types that change the turn queue (queue/edit/reorder/claim/finish). */\nexport function isTurnQueueEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return event.type.startsWith(\"turn.\");\n}\n\n/** Queued turns in execution order (position, then creation time). */\nexport function queueFromTurns(turns: SessionTurn[]): SessionTurn[] {\n return turns\n .filter((turn) => turn.status === \"queued\")\n .sort((a, b) => a.position - b.position || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));\n}\n\n/** The turn currently holding the session (running or awaiting approval). */\nexport function activeTurnFromTurns(turns: SessionTurn[]): SessionTurn | null {\n return turns.find((turn) => turn.status === \"running\" || turn.status === \"requires_action\") ?? null;\n}\n\n/** Optimistic projection of a queued-turn edit. */\nexport function applyTurnEdit(turns: SessionTurn[], turnId: string, update: UpdateSessionTurnRequest): SessionTurn[] {\n return turns.map((turn) => {\n if (turn.id !== turnId || turn.status !== \"queued\") {\n return turn;\n }\n return {\n ...turn,\n ...(update.prompt !== undefined ? { prompt: update.prompt } : {}),\n ...(update.resources !== undefined ? { resources: update.resources } : {}),\n ...(update.tools !== undefined ? { tools: update.tools } : {}),\n ...(update.model !== undefined ? { model: update.model } : {}),\n ...(update.reasoningEffort !== undefined ? { reasoningEffort: update.reasoningEffort } : {}),\n ...(update.sandboxBackend !== undefined ? { sandboxBackend: update.sandboxBackend } : {}),\n ...(update.metadata !== undefined ? { metadata: update.metadata } : {}),\n };\n });\n}\n\n/**\n * Optimistic projection of a reorder, mirroring the server: the listed\n * queued turns get positions 1..n in the given order; everything else keeps\n * its position.\n */\nexport function applyTurnReorder(turns: SessionTurn[], turnIds: string[]): SessionTurn[] {\n const positions = new Map(turnIds.map((turnId, index) => [turnId, index + 1] as const));\n return turns.map((turn) => {\n const position = positions.get(turn.id);\n return position !== undefined && turn.status === \"queued\" ? { ...turn, position } : turn;\n });\n}\n\n/** Optimistic projection of a queued-turn delete (server marks it cancelled). */\nexport function applyTurnRemoval(turns: SessionTurn[], turnId: string): SessionTurn[] {\n return turns.map((turn) => (turn.id === turnId && turn.status === \"queued\" ? { ...turn, status: \"cancelled\" as const } : turn));\n}\n\nexport type UseTurnQueueOptions = ClientOverride & SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default — turn.* events drive updates. */\n pollIntervalMs?: number | undefined;\n};\n\nexport type UseTurnQueueResult = {\n /** All turns the API returned (history + queue), newest server view. */\n turns: SessionTurn[];\n /** Queued turns in execution order — render this as the editable queue. */\n queue: SessionTurn[];\n /** The running / requires_action turn, if any. */\n activeTurn: SessionTurn | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Edit a queued turn (optimistic; rolls back via refetch on failure). */\n editTurn: (turnId: string, update: UpdateSessionTurnRequest) => Promise<SessionTurn | null>;\n /** Reorder the queue to the given queued-turn id order (optimistic). */\n reorderTurns: (turnIds: string[]) => Promise<SessionTurn[] | null>;\n /** Delete (cancel) a queued turn before it is claimed (optimistic). */\n removeTurn: (turnId: string) => Promise<SessionTurn | null>;\n /** True while an edit/reorder/remove is in flight. */\n mutating: boolean;\n /** Last failed mutation, until the next mutation or clear. */\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The live turn queue — the heart of the queue-by-default interaction model.\n * Messages sent mid-turn stack up here, visible and editable/reorderable/\n * deletable until the worker claims them. Updates arrive over the session\n * event stream (`turn.*`), either shared via `options.events` (pass the log\n * from `useSessionEvents` to reuse its connection) or a dedicated tail\n * stream. All mutations apply optimistically and reconcile with the server.\n */\nexport function useTurnQueue(sessionId: string | null | undefined, options: UseTurnQueueOptions = {}): UseTurnQueueResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const [turns, setTurns] = useState<SessionTurn[]>([]);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const mutation = useMutationRunner();\n const generation = useRef(0);\n const targetKeyRef = useRef<string | null>(null);\n\n const load = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n const ticket = ++generation.current;\n try {\n const fetched = await client.listTurns(workspaceId, sessionId);\n if (ticket === generation.current) {\n setTurns(fetched);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (ticket === generation.current) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setLoading(false);\n }\n }\n }, [client, workspaceId, sessionId]);\n\n // Reset when the target session changes; initial load + optional polling.\n useEffect(() => {\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n if (targetKeyRef.current !== targetKey) {\n targetKeyRef.current = targetKey;\n setTurns([]);\n setError(null);\n }\n if (!enabled) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void load();\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n };\n }\n const timer = setInterval(() => void load(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n };\n }, [load, enabled, workspaceId, sessionId, options.pollIntervalMs]);\n\n // Live updates: any turn.* event re-syncs the queue (debounced).\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(client, workspaceId, sessionId, isTurnQueueEvent, scheduleRefresh, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n const editTurn = useCallback(\n async (turnId: string, update: UpdateSessionTurnRequest): Promise<SessionTurn | null> => {\n if (!sessionId) {\n return null;\n }\n setTurns((current) => applyTurnEdit(current, turnId, update));\n const result = await mutation.run(() => client.updateQueuedTurn(workspaceId, sessionId, turnId, update));\n if (result) {\n setTurns((current) => current.map((turn) => (turn.id === result.id ? result : turn)));\n } else {\n void load();\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run, load],\n );\n\n const reorderTurns = useCallback(\n async (turnIds: string[]): Promise<SessionTurn[] | null> => {\n if (!sessionId || turnIds.length === 0) {\n return null;\n }\n setTurns((current) => applyTurnReorder(current, turnIds));\n const result = await mutation.run(() => client.reorderQueuedTurns(workspaceId, sessionId, turnIds));\n if (result) {\n // The server returns the queued turns; merge them over local state.\n setTurns((current) => {\n const bySId = new Map(result.map((turn) => [turn.id, turn] as const));\n return current.map((turn) => bySId.get(turn.id) ?? turn);\n });\n } else {\n void load();\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run, load],\n );\n\n const removeTurn = useCallback(\n async (turnId: string): Promise<SessionTurn | null> => {\n if (!sessionId) {\n return null;\n }\n setTurns((current) => applyTurnRemoval(current, turnId));\n const result = await mutation.run(() => client.deleteQueuedTurn(workspaceId, sessionId, turnId));\n if (result) {\n setTurns((current) => current.map((turn) => (turn.id === result.id ? result : turn)));\n } else {\n void load();\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run, load],\n );\n\n return {\n turns,\n queue: queueFromTurns(turns),\n activeTurn: activeTurnFromTurns(turns),\n loading,\n error,\n refresh: load,\n editTurn,\n reorderTurns,\n removeTurn,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import { OpenGeniApiError, type SessionEvent, type SessionGoal } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useDebouncedCallback, useMutationRunner, useSessionEventTrigger, type SessionEventFeedOptions } 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\nexport type UseGoalOptions = ClientOverride & SessionEventFeedOptions & {\n /** Optional safety-net polling (ms). Off by default — goal.* events 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 /** True while a pause/resume 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.*` events —\n * pass `options.events` from `useSessionEvents` to reuse its stream.\n */\nexport function useGoal(sessionId: string | null | undefined, options: UseGoalOptions = {}): UseGoalResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const [goal, setGoal] = useState<SessionGoal | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const mutation = useMutationRunner();\n const generation = useRef(0);\n const targetKeyRef = useRef<string | null>(null);\n\n const load = useCallback(async (): Promise<void> => {\n if (!sessionId) {\n return;\n }\n const ticket = ++generation.current;\n try {\n const fetched = await client.getGoal(workspaceId, sessionId);\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 }\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) {\n setLoading(false);\n return;\n }\n setLoading(true);\n void load();\n const pollIntervalMs = options.pollIntervalMs;\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n generation.current += 1;\n };\n }\n const timer = setInterval(() => void load(), pollIntervalMs);\n return () => {\n clearInterval(timer);\n generation.current += 1;\n };\n }, [load, enabled, workspaceId, sessionId, options.pollIntervalMs]);\n\n const scheduleRefresh = useDebouncedCallback(() => void load());\n useSessionEventTrigger(client, workspaceId, sessionId, isGoalEvent, scheduleRefresh, {\n enabled,\n ...(options.events !== undefined ? { events: options.events } : {}),\n });\n\n const pause = useCallback(\n async (rationale?: string): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await mutation.run(() =>\n client.updateGoal(workspaceId, sessionId, {\n status: \"paused\",\n ...(rationale !== undefined ? { rationale } : {}),\n }));\n if (result) {\n setGoal(result);\n }\n return result;\n },\n [client, workspaceId, sessionId, mutation.run],\n );\n\n const resume = useCallback(async (): Promise<SessionGoal | null> => {\n if (!sessionId) {\n return null;\n }\n const result = await mutation.run(() => client.updateGoal(workspaceId, sessionId, { status: \"active\" }));\n if (result) {\n setGoal(result);\n }\n return result;\n }, [client, workspaceId, sessionId, mutation.run]);\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 updating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner } from \"./internal\";\n\nexport type UseSessionControlOptions = ClientOverride;\n\nexport type UseSessionControlResult = {\n /** Interrupt the running turn (the explicit alternative to queueing). */\n interrupt: (reason?: string) => Promise<SessionEvent | null>;\n interrupting: 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 control events: interrupt 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 } = useOpenGeni(options);\n const interruptMutation = useMutationRunner();\n const approvalMutation = useMutationRunner();\n\n const interrupt = useCallback(\n async (reason?: string): Promise<SessionEvent | null> => {\n if (!sessionId) {\n return null;\n }\n return await interruptMutation.run(() =>\n client.interrupt(workspaceId, sessionId, reason !== undefined ? { reason } : {}));\n },\n [client, workspaceId, sessionId, interruptMutation.run],\n );\n\n const decide = useCallback(\n async (approvalId: string, decision: \"approve\" | \"reject\", message?: string): Promise<SessionEvent | null> => {\n if (!sessionId) {\n return null;\n }\n return await approvalMutation.run(() =>\n client.sendApprovalDecision(workspaceId, sessionId, {\n approvalId,\n decision,\n ...(message !== undefined ? { message } : {}),\n }));\n },\n [client, workspaceId, sessionId, approvalMutation.run],\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 = approvalMutation.mutationError ?? interruptMutation.mutationError;\n const clearError = useCallback(() => {\n interruptMutation.clearMutationError();\n approvalMutation.clearMutationError();\n }, [interruptMutation.clearMutationError, approvalMutation.clearMutationError]);\n\n return {\n interrupt,\n interrupting: interruptMutation.mutating,\n approve,\n reject,\n responding: approvalMutation.mutating,\n error,\n clearError,\n };\n}\n","import type { ScheduledTask } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseScheduledTasksOptions = ClientOverride & {\n limit?: number | undefined;\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseScheduledTasksResult = {\n tasks: ScheduledTask[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** List the workspace's scheduled tasks (drift checks, sentinels, reapers, ...). */\nexport function useScheduledTasks(options: UseScheduledTasksOptions = {}): UseScheduledTasksResult {\n const { client, workspaceId } = useOpenGeni(options);\n const limit = options.limit;\n const load = useCallback(\n async () => await client.listScheduledTasks(workspaceId, limit !== undefined ? { limit } : {}),\n [client, workspaceId, limit],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return { tasks: state.data ?? [], loading: state.loading, error: state.error, refresh: state.refresh };\n}\n","import type { Session } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseWorkspaceSessionsOptions = ClientOverride & {\n limit?: number | undefined;\n /** Refresh interval (ms) for fleet/manager views. Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseWorkspaceSessionsResult = {\n sessions: Session[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** List the workspace's sessions — the data behind fleet and manager views. */\nexport function useWorkspaceSessions(options: UseWorkspaceSessionsOptions = {}): UseWorkspaceSessionsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const limit = options.limit;\n const load = useCallback(\n async () => await client.listSessions(workspaceId, limit !== undefined ? { limit } : {}),\n [client, workspaceId, limit],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return { sessions: state.data ?? [], loading: state.loading, error: state.error, refresh: state.refresh };\n}\n","import type {\n CreateWorkspaceEnvironmentRequest,\n UpdateWorkspaceEnvironmentRequest,\n WorkspaceEnvironment,\n WorkspaceEnvironmentVariableMetadata,\n} from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UseEnvironmentsOptions = ClientOverride & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseEnvironmentsResult = {\n environments: WorkspaceEnvironment[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (request: CreateWorkspaceEnvironmentRequest) => Promise<WorkspaceEnvironment | null>;\n update: (environmentId: string, request: UpdateWorkspaceEnvironmentRequest) => Promise<WorkspaceEnvironment | null>;\n remove: (environmentId: string) => Promise<boolean>;\n /** Set/rotate a variable. Values are write-only — reads expose metadata only. */\n setVariable: (environmentId: string, name: string, value: string) => Promise<WorkspaceEnvironmentVariableMetadata | null>;\n deleteVariable: (environmentId: string, name: string) => Promise<boolean>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Workspace environments (named, encrypted variable sets attached to sessions\n * and scheduled tasks). Variable values are write-only end to end: this hook\n * never sees a value after it is sent.\n */\nexport function useEnvironments(options: UseEnvironmentsOptions = {}): UseEnvironmentsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const load = useCallback(async () => await client.listEnvironments(workspaceId), [client, workspaceId]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n const mutation = useMutationRunner();\n\n const create = useCallback(\n async (request: CreateWorkspaceEnvironmentRequest): Promise<WorkspaceEnvironment | null> => {\n const result = await mutation.run(() => client.createEnvironment(workspaceId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const update = useCallback(\n async (environmentId: string, request: UpdateWorkspaceEnvironmentRequest): Promise<WorkspaceEnvironment | null> => {\n const result = await mutation.run(() => client.updateEnvironment(workspaceId, environmentId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const remove = useCallback(\n async (environmentId: string): Promise<boolean> => {\n const result = await mutation.run(async () => {\n await client.deleteEnvironment(workspaceId, environmentId);\n return true;\n });\n if (result) {\n await state.refresh();\n }\n return result === true;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const setVariable = useCallback(\n async (environmentId: string, name: string, value: string): Promise<WorkspaceEnvironmentVariableMetadata | null> => {\n const result = await mutation.run(() => client.setEnvironmentVariable(workspaceId, environmentId, name, value));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const deleteVariable = useCallback(\n async (environmentId: string, name: string): Promise<boolean> => {\n const result = await mutation.run(async () => {\n await client.deleteEnvironmentVariable(workspaceId, environmentId, name);\n return true;\n });\n if (result) {\n await state.refresh();\n }\n return result === true;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n return {\n environments: state.data ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n create,\n update,\n remove,\n setVariable,\n deleteVariable,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type {\n CapabilityPack,\n EnablePackRequest,\n PackInstallation,\n RegisterCapabilityPackRequest,\n WorkspaceRegisteredPack,\n} from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UsePacksOptions = ClientOverride & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UsePacksResult = {\n /** Built-in + registered packs available to the workspace. */\n packs: CapabilityPack[];\n /** Enable/disable state per pack. */\n installations: PackInstallation[];\n /** The installation for a pack id, if any. */\n installationFor: (packId: string) => PackInstallation | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Register (or replace) a workspace-scoped pack manifest. */\n register: (manifest: RegisterCapabilityPackRequest) => Promise<WorkspaceRegisteredPack | null>;\n enable: (packId: string, request?: EnablePackRequest) => Promise<PackInstallation | null>;\n /** Unregister a workspace-scoped pack (built-ins cannot be removed). */\n remove: (packId: string) => Promise<boolean>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/** Capability packs: catalog + installations + register/enable/unregister. */\nexport function usePacks(options: UsePacksOptions = {}): UsePacksResult {\n const { client, workspaceId } = useOpenGeni(options);\n const load = useCallback(async () => await client.listPacks(workspaceId), [client, workspaceId]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n const mutation = useMutationRunner();\n\n const register = useCallback(\n async (manifest: RegisterCapabilityPackRequest): Promise<WorkspaceRegisteredPack | null> => {\n const result = await mutation.run(() => client.registerPack(workspaceId, manifest));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const enable = useCallback(\n async (packId: string, request: EnablePackRequest = {}): Promise<PackInstallation | null> => {\n const result = await mutation.run(() => client.enablePack(workspaceId, packId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const remove = useCallback(\n async (packId: string): Promise<boolean> => {\n const result = await mutation.run(async () => {\n await client.deletePack(workspaceId, packId);\n return true;\n });\n if (result) {\n await state.refresh();\n }\n return result === true;\n },\n [client, workspaceId, mutation.run, state.refresh],\n );\n\n const installations = state.data?.installations ?? [];\n const installationFor = useCallback(\n (packId: string): PackInstallation | null =>\n installations.find((installation) => installation.packId === packId) ?? null,\n [installations],\n );\n\n return {\n packs: state.data?.packs ?? [],\n installations,\n installationFor,\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n register,\n enable,\n remove,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { CreateWorkspaceRequest, UpdateWorkspaceRequest, Workspace } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UseWorkspacesOptions = Pick<ClientOverride, \"client\"> & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseWorkspacesResult = {\n workspaces: Workspace[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (request: CreateWorkspaceRequest) => Promise<Workspace | null>;\n update: (workspaceId: string, request: UpdateWorkspaceRequest) => Promise<Workspace | null>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The caller's workspaces (workspace switchers, onboarding). Not scoped to\n * the provider's workspace, so it only needs the client.\n */\nexport function useWorkspaces(options: UseWorkspacesOptions = {}): UseWorkspacesResult {\n const client = useOpenGeniClient(options);\n const load = useCallback(async () => await client.listWorkspaces(), [client]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n const mutation = useMutationRunner();\n\n const create = useCallback(\n async (request: CreateWorkspaceRequest): Promise<Workspace | null> => {\n const result = await mutation.run(() => client.createWorkspace(request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, mutation.run, state.refresh],\n );\n\n const update = useCallback(\n async (workspaceId: string, request: UpdateWorkspaceRequest): Promise<Workspace | null> => {\n const result = await mutation.run(() => client.updateWorkspace(workspaceId, request));\n if (result) {\n await state.refresh();\n }\n return result;\n },\n [client, mutation.run, state.refresh],\n );\n\n return {\n workspaces: state.data ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n create,\n update,\n mutating: mutation.mutating,\n mutationError: mutation.mutationError,\n clearMutationError: mutation.clearMutationError,\n };\n}\n","import type { BillingBalance, UsageEvent } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseBillingUsageOptions = Pick<ClientOverride, \"client\"> & {\n /** Account to read. Defaults to the caller's default account server-side. */\n accountId?: string | undefined;\n /** Filter usage to one workspace. */\n workspaceId?: string | undefined;\n /** Refresh interval (ms) for live billing meters. Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseBillingUsageResult = {\n /** Prepaid credit balance (micro-USD), null until loaded. */\n balance: BillingBalance | null;\n /** Recent usage events (runs, tokens, cost, uploads, ...). */\n usage: UsageEvent[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Account billing usage: credit balance + recent usage events — the data\n * behind per-call billing meters. Account-scoped, so it only needs the\n * client; pass `workspaceId` to narrow usage to one workspace.\n */\nexport function useBillingUsage(options: UseBillingUsageOptions = {}): UseBillingUsageResult {\n const client = useOpenGeniClient(options);\n const accountId = options.accountId;\n const workspaceId = options.workspaceId;\n const load = useCallback(\n async () =>\n await client.getBillingUsage({\n ...(accountId !== undefined ? { accountId } : {}),\n ...(workspaceId !== undefined ? { workspaceId } : {}),\n }),\n [client, accountId, workspaceId],\n );\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return {\n balance: state.data?.balance ?? null,\n usage: state.data?.usage ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n };\n}\n","import type { ClientModel } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseAvailableModelsOptions = Pick<ClientOverride, \"client\"> & {\n /** Refresh interval (ms). Off by default — the host model list rarely moves. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseAvailableModelsResult = {\n /** The provider-grouped models the host exposes (empty until loaded). */\n models: ClientModel[];\n /** The deployment's default model id, null until loaded. */\n defaultModel: string | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * The host-exposed model list for a <ModelPicker>: fetches the deployment's\n * public client config (`GET /v1/config/client`) and surfaces the richer\n * provider-grouped `models` plus the `defaultModel` the picker should preselect.\n * Deployment-scoped, so it only needs the client (no workspace).\n */\nexport function useAvailableModels(options: UseAvailableModelsOptions = {}): UseAvailableModelsResult {\n const client = useOpenGeniClient(options);\n const load = useCallback(async () => await client.getClientConfig(), [client]);\n const state = usePolledValue(load, { pollIntervalMs: options.pollIntervalMs, enabled: options.enabled });\n return {\n models: state.data?.models ?? [],\n defaultModel: state.data?.defaultModel ?? null,\n loading: state.loading,\n error: state.error,\n refresh: state.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 = payload && typeof payload === \"object\" ? (payload as { approvals?: unknown }).approvals : 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<string, unknown>;\n const rawItem = raw.rawItem && typeof raw.rawItem === \"object\" ? raw.rawItem as Record<string, unknown> : {};\n return {\n id: String(raw.id ?? raw.callId ?? rawItem.callId ?? index),\n name: String(raw.name ?? \"approval\"),\n arguments: raw.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 = event.payload && typeof event.payload === \"object\" ? event.payload as { approvalId?: unknown } : {};\n if (typeof payload.approvalId === \"string\") {\n pending = pending.filter((approval) => approval.id !== payload.approvalId);\n }\n break;\n }\n case \"turn.completed\":\n case \"turn.failed\":\n case \"turn.cancelled\": {\n // Scope clearing to the turn that raised the approvals when both\n // sides carry a turn id; clear conservatively when either is unknown.\n if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {\n pending = [];\n owningTurnId = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return pending;\n}\n","import type { Permission } from \"@opengeni/sdk\";\nimport type { CommandContext, SlashArg, SlashCommand } from \"./types\";\n\n/**\n * Parse a composer value into a command name + the rest. A command is\n * recognized ONLY when the value's first character is \"/\" (the start token);\n * anything else is plain chat and returns null.\n *\n * \"/cl\" -> { name: \"cl\", rest: \"\", hasTrailingSpace: false }\n * \"/goal \" -> { name: \"goal\", rest: \"\", hasTrailingSpace: true }\n * \"/goal pause\"-> { name: \"goal\", rest: \"pause\", hasTrailingSpace: false }\n */\nexport type ParsedCommandLine = {\n name: string;\n rest: string;\n /** True when the name token is closed by a space — arg-hint mode. */\n hasTrailingSpace: boolean;\n args: string[];\n};\n\nexport function parseCommandLine(value: string): ParsedCommandLine | null {\n if (value[0] !== \"/\") {\n return null;\n }\n const body = value.slice(1);\n const firstSpace = body.indexOf(\" \");\n if (firstSpace === -1) {\n return { name: body, rest: \"\", hasTrailingSpace: false, args: [] };\n }\n const name = body.slice(0, firstSpace);\n const rest = body.slice(firstSpace + 1);\n return {\n name,\n rest,\n hasTrailingSpace: true,\n args: rest.split(/\\s+/).filter((token) => token.length > 0),\n };\n}\n\nconst PERMISSION_SUPERUSER: Permission = \"workspace:admin\";\n\n/** Whether the operator's permission set satisfies a command's gate. */\nexport function hasPermission(required: Permission | undefined, permissions: Permission[]): boolean {\n if (!required) {\n return true;\n }\n return permissions.includes(required) || permissions.includes(PERMISSION_SUPERUSER);\n}\n\n/** Match a command (by name or alias) against the value. */\nexport function matchCommand(commands: readonly SlashCommand[], value: string): SlashCommand | null {\n const parsed = parseCommandLine(value);\n if (!parsed) {\n return null;\n }\n const token = parsed.name.toLowerCase();\n return commands.find((command) => command.name === token || command.aliases?.includes(token)) ?? null;\n}\n\ntype FilterCtx = Pick<CommandContext, \"sessionId\" | \"status\" | \"permissions\">;\n\n/**\n * The commands visible for the current token + context. Permission-absent and\n * `available()===false` commands are dropped entirely (a gated command is never\n * shown, not shown-disabled). Filtering is a prefix match on name/alias.\n */\nexport function filterCommands(commands: readonly SlashCommand[], token: string, ctx: FilterCtx): SlashCommand[] {\n const needle = token.toLowerCase();\n return commands.filter((command) => {\n if (!hasPermission(command.permission, ctx.permissions)) {\n return false;\n }\n if (command.available && !command.available(ctx)) {\n return false;\n }\n if (needle.length === 0) {\n return true;\n }\n return command.name.startsWith(needle) || (command.aliases?.some((alias) => alias.startsWith(needle)) ?? false);\n });\n}\n\n/** Render a command's arg hint for the palette footer / help, e.g. \"<pause|resume>\". */\nexport function argHint(args: readonly SlashArg[] | undefined): string {\n if (!args || args.length === 0) {\n return \"\";\n }\n return args\n .map((arg) => {\n const label = arg.oneOf ? arg.oneOf.join(\"|\") : arg.name;\n return arg.required ? `<${label}>` : `[${label}]`;\n })\n .join(\" \");\n}\n\n/** The first required arg that has not yet been supplied, if any. */\nexport function firstMissingRequiredArg(command: SlashCommand, args: string[]): SlashArg | null {\n const required = (command.args ?? []).filter((arg) => arg.required);\n for (let i = 0; i < required.length; i += 1) {\n const value = args[i];\n if (value === undefined || value.length === 0) {\n return required[i] ?? null;\n }\n }\n return null;\n}\n\nfunction requireSession(ctx: CommandContext): string {\n if (!ctx.sessionId) {\n throw new Error(\"No active session yet — start a session first.\");\n }\n return ctx.sessionId;\n}\n\nconst hasSession = (ctx: FilterCtx): boolean => ctx.sessionId !== null;\n\n/**\n * The default command set. Adding a command is one object literal here; the\n * palette list, filter, arg-hint footer, and /help all render from this array.\n * Apps concat their own commands via the ChatComposer `commands` prop.\n */\nexport const defaultCommands: readonly SlashCommand[] = [\n {\n name: \"help\",\n aliases: [\"?\"],\n description: \"Show available commands.\",\n run: (_args, ctx) => {\n ctx.openHelp();\n return { status: \"ok\" };\n },\n },\n {\n name: \"clear-view\",\n description: \"Clear the local timeline view (this device only; no server change).\",\n run: (_args, ctx) => {\n // clearView() reports whether the host actually wired a view-reset. If it\n // didn't (the console surface has no resettable local timeline), reporting\n // \"Local view cleared.\" would be a false success — return an honest error\n // instead so the operator isn't told something happened when nothing did.\n const cleared = ctx.clearView();\n if (!cleared) {\n return { status: \"error\", message: \"This view can't be cleared here (no local timeline to reset).\" };\n }\n return { status: \"ok\", message: \"Local view cleared.\" };\n },\n },\n {\n name: \"goal\",\n description: \"Pause or resume the session's goal loop.\",\n permission: \"sessions:control\",\n available: hasSession,\n args: [{ name: \"action\", required: true, oneOf: [\"pause\", \"resume\"], description: \"pause | resume\" }],\n run: async (args, ctx) => {\n const sessionId = requireSession(ctx);\n const action = args[0];\n if (action !== \"pause\" && action !== \"resume\") {\n return { status: \"error\", message: \"Usage: /goal pause | /goal resume\" };\n }\n try {\n await ctx.client.updateGoal(ctx.workspaceId, sessionId, { status: action === \"pause\" ? \"paused\" : \"active\" });\n return { status: \"ok\", message: action === \"pause\" ? \"Goal paused.\" : \"Goal resumed.\" };\n } catch (cause) {\n return { status: \"error\", message: goalErrorMessage(cause, action) };\n }\n },\n },\n {\n name: \"compact\",\n description: \"Compact the conversation context now.\",\n permission: \"sessions:control\",\n available: hasSession,\n run: async (_args, ctx) => {\n const sessionId = requireSession(ctx);\n try {\n const result = await ctx.client.compactSessionContext(ctx.workspaceId, sessionId);\n return { status: \"ok\", message: result.message };\n } catch (cause) {\n return { status: \"error\", message: errorMessage(cause) ?? \"Could not compact context.\" };\n }\n },\n },\n {\n name: \"clear\",\n description: \"Clear the conversation context (destructive; audit-preserved).\",\n permission: \"sessions:control\",\n danger: true,\n available: hasSession,\n run: async (_args, ctx) => {\n const sessionId = requireSession(ctx);\n const confirmed = await ctx.confirm();\n if (!confirmed) {\n // Canceled: no error, but keep the \"/clear\" draft so the operator who\n // backed out doesn't silently lose what they typed.\n return { status: \"ok\", keepDraft: true };\n }\n try {\n await ctx.client.clearSessionContext(ctx.workspaceId, sessionId);\n return { status: \"ok\", message: \"Context cleared.\" };\n } catch (cause) {\n return { status: \"error\", message: clearErrorMessage(cause) };\n }\n },\n },\n];\n\nfunction errorMessage(cause: unknown): string | undefined {\n if (cause && typeof cause === \"object\" && \"message\" in cause && typeof (cause as { message?: unknown }).message === \"string\") {\n return (cause as { message: string }).message;\n }\n return undefined;\n}\n\nfunction statusCode(cause: unknown): number | undefined {\n if (cause && typeof cause === \"object\" && \"status\" in cause && typeof (cause as { status?: unknown }).status === \"number\") {\n return (cause as { status: number }).status;\n }\n return undefined;\n}\n\nfunction goalErrorMessage(cause: unknown, action: \"pause\" | \"resume\"): string {\n const code = statusCode(cause);\n if (code === 404) {\n return \"This session has no goal to control.\";\n }\n if (code === 409) {\n return action === \"resume\" ? \"Only a paused goal can be resumed.\" : \"Goal is already in a terminal state.\";\n }\n return errorMessage(cause) ?? `Could not ${action} the goal.`;\n}\n\nfunction clearErrorMessage(cause: unknown): string {\n if (statusCode(cause) === 409) {\n return \"Can't clear context mid-turn — stop the current turn first.\";\n }\n return errorMessage(cause) ?? \"Could not clear context.\";\n}\n","import type { KeyboardEvent } from \"react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport {\n argHint,\n filterCommands,\n firstMissingRequiredArg,\n matchCommand,\n parseCommandLine,\n} from \"../commands/registry\";\nimport type { CommandContext, Notice, SlashCommand } from \"../commands/types\";\n\n/**\n * Context the composer supplies for command execution and visibility. The\n * composer owns the UI affordances (notice/openHelp/clearView/confirm), so they\n * are NOT part of this slice — the hook closes over them via `handlers`.\n */\nexport type SlashCommandContext = Pick<\n CommandContext,\n \"client\" | \"workspaceId\" | \"sessionId\" | \"status\" | \"permissions\"\n>;\n\n/**\n * UI affordances the composer supplies. `confirm` differs from the registry-\n * facing {@link CommandContext.confirm} (which takes no args): the composer's\n * confirm receives the command being run so the confirm bar renders from that\n * exact command's identity. The hook bridges the two in {@link buildContext}.\n */\nexport type SlashCommandHandlers = Pick<CommandContext, \"notice\" | \"openHelp\" | \"clearView\"> & {\n confirm: (command: SlashCommand) => Promise<boolean>;\n};\n\nexport type ConfirmState = {\n command: SlashCommand;\n /** Resolve the pending confirm() promise. */\n resolve: (confirmed: boolean) => void;\n} | null;\n\nexport type UseSlashCommandsOptions = {\n commands: readonly SlashCommand[];\n context: SlashCommandContext | undefined;\n handlers: SlashCommandHandlers;\n /** The current composer draft. */\n value: string;\n /** Replace the composer draft (autocomplete writes through this). */\n setValue: (value: string) => void;\n};\n\nexport type UseSlashCommandsResult = {\n /** Whether the palette is open (a command token is being typed). */\n open: boolean;\n /**\n * Whether the draft is a slash-command attempt (matches a registered command)\n * — true even after Escape dismisses the popover. The composer blocks its send\n * path while this holds so a command can't be delivered to the agent as chat.\n */\n isCommandDraft: boolean;\n /** Commands shown for the current token + context, in display order. */\n items: SlashCommand[];\n /** Index into `items` of the highlighted row. */\n highlight: number;\n setHighlight: (index: number) => void;\n /** The matched command once the name is closed by a space (arg-hint mode). */\n activeCommand: SlashCommand | null;\n /** The arg hint string for the active command (footer), or \"\". */\n activeArgHint: string;\n /**\n * Key handler for the textarea. Returns true when it consumed the event\n * (the composer must then NOT run its send path). Only consumes while open.\n */\n onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => boolean;\n /** Run the highlighted command (or the active command in arg-hint mode). */\n runHighlighted: () => Promise<void>;\n /**\n * Run the command at an explicitly chosen index (a pointer click on a row).\n * Bypasses the exact-match token heuristic that runHighlighted uses for\n * keyboard Enter, so an explicit click always runs the clicked command.\n */\n runAt: (index: number) => Promise<void>;\n /** Autocomplete the highlighted command name + a trailing space. */\n autocompleteHighlighted: () => void;\n};\n\nexport function useSlashCommands(options: UseSlashCommandsOptions): UseSlashCommandsResult {\n const { commands, context, handlers, value, setValue } = options;\n const [highlight, setHighlight] = useState(0);\n // Escape closes the palette but keeps the draft. We remember the dismissed\n // value; any further edit (value !== dismissed) re-opens the palette.\n const [dismissedValue, setDismissedValue] = useState<string | null>(null);\n const dismissed = dismissedValue !== null && dismissedValue === value;\n\n // Whether the operator has explicitly arrow-navigated the highlight for the\n // CURRENT draft. When they have, Enter is an explicit choice of the\n // highlighted row — the exact-match token override must NOT hijack it (else\n // ArrowDown to /clear-view + Enter would still fire the destructive /clear,\n // since \"clear\" exact-matches the token). Reset whenever the draft changes.\n const navigatedRef = useRef(false);\n const navTokenRef = useRef(value);\n if (navTokenRef.current !== value) {\n navTokenRef.current = value;\n navigatedRef.current = false;\n }\n\n const parsed = useMemo(() => parseCommandLine(value), [value]);\n const filterCtx = useMemo(\n () => ({\n sessionId: context?.sessionId ?? null,\n status: context?.status ?? null,\n permissions: context?.permissions ?? [],\n }),\n [context?.sessionId, context?.status, context?.permissions],\n );\n\n // In arg-hint mode (\"/name \"), the list collapses to the matched command so\n // the palette shows just its arg hint; while typing the name it filters.\n const activeCommand = useMemo(() => {\n if (!parsed || !parsed.hasTrailingSpace) {\n return null;\n }\n return matchCommand(commands, value);\n }, [commands, value, parsed]);\n\n const items = useMemo(() => {\n if (!parsed) {\n return [];\n }\n if (activeCommand) {\n return [activeCommand];\n }\n return filterCommands(commands, parsed.name, filterCtx);\n }, [commands, parsed, activeCommand, filterCtx]);\n\n const open = parsed !== null && items.length > 0 && !dismissed;\n\n // Whether the current draft is a slash-command ATTEMPT that should be run via\n // the palette, never delivered to the agent as plain chat. True even when the\n // palette is dismissed (Escape) — the draft still starts with \"/\" and matches\n // a command, so the composer must block its send path (button + Enter) to keep\n // commands from leaking into the conversation as messages the model reads.\n const isCommandDraft = parsed !== null && items.length > 0;\n\n // Keep highlight in range as items change.\n const clampedHighlight = items.length === 0 ? 0 : Math.min(highlight, items.length - 1);\n\n const activeArgHint = activeCommand ? argHint(activeCommand.args) : \"\";\n\n // Build the context for a SPECIFIC command. The danger confirm() is bound to\n // that command so the confirm bar names the command actually about to run —\n // not whatever near-match happens to sit highlighted in the palette (e.g.\n // typing \"/clear\"+Enter runs the destructive `clear`, but `clear-view` sorts\n // first and would otherwise mislabel the bar as a harmless local-view reset).\n const buildContext = useCallback(\n (command: SlashCommand): CommandContext | null => {\n if (!context) {\n return null;\n }\n return { ...context, ...handlers, confirm: () => handlers.confirm(command) };\n },\n [context, handlers],\n );\n\n const execute = useCallback(\n async (command: SlashCommand, args: string[]): Promise<void> => {\n const ctx = buildContext(command);\n if (!ctx) {\n return;\n }\n try {\n const result = await command.run(args, ctx);\n if (result.message) {\n ctx.notice({ tone: result.status === \"ok\" ? \"ok\" : \"error\", message: result.message });\n }\n if (result.status === \"ok\" && !result.keepDraft) {\n setValue(\"\");\n }\n } catch (cause) {\n ctx.notice({ tone: \"error\", message: errorMessage(cause) });\n }\n },\n [buildContext, setValue],\n );\n\n const autocomplete = useCallback(\n (command: SlashCommand) => {\n setValue(`/${command.name} `);\n setHighlight(0);\n },\n [setValue],\n );\n\n const autocompleteHighlighted = useCallback(() => {\n const command = items[clampedHighlight];\n if (command) {\n autocomplete(command);\n }\n }, [items, clampedHighlight, autocomplete]);\n\n // Resolve a SPECIFIC, already-chosen command against the current draft, then\n // either autocomplete (name-only / required arg missing) or execute. This is\n // the shared core for both Enter (which first resolves WHICH command via the\n // exact-match heuristic) and a pointer click (which has ALREADY chosen the\n // command — the clicked row — and must not re-resolve to a near-match).\n const runResolved = useCallback(\n async (command: SlashCommand, options?: { explicit?: boolean }): Promise<void> => {\n if (!parsed) {\n return;\n }\n const explicit = options?.explicit ?? false;\n // Token-vs-command equality is case-insensitive (matching the registry's\n // matchCommand/filterCommands), so a fully-typed \"/Clear\" counts as having\n // named `clear` and runs rather than autocompleting.\n const nameMatchesToken =\n command.name === parsed.name.toLowerCase() ||\n (command.aliases?.includes(parsed.name.toLowerCase()) ?? false);\n // A name-only token whose name doesn't yet equal the resolved command (e.g.\n // \"/cl\" -> clear) first autocompletes so the operator sees the full name.\n // An EXPLICIT pointer click skips this: the operator already chose the row,\n // so clicking \"/clear-view\" (while the token is \"clear\") runs it outright\n // rather than merely filling the name and waiting for a second Enter.\n if (!explicit && !activeCommand && !nameMatchesToken && !parsed.hasTrailingSpace) {\n autocomplete(command);\n return;\n }\n // When the click resolves a different command than the typed token, the\n // typed token's tail isn't this command's args — run with no positional\n // args and let the required-arg guard below prompt for them via autocomplete.\n const args = nameMatchesToken || parsed.hasTrailingSpace ? parsed.args : [];\n const missing = firstMissingRequiredArg(command, args);\n if (missing) {\n // A required arg is absent: keep the palette open at the arg hint rather\n // than firing a half-formed command.\n if (!parsed.hasTrailingSpace) {\n autocomplete(command);\n }\n return;\n }\n await execute(command, args);\n },\n [parsed, activeCommand, autocomplete, execute],\n );\n\n const runHighlighted = useCallback(async (): Promise<void> => {\n if (!parsed) {\n return;\n }\n // If the operator has arrow-navigated, Enter is an explicit choice of the\n // highlighted row — run it directly, exactly like a click. This makes\n // /clear-view reachable via ArrowDown+Enter even when \"/clear\" is fully\n // typed (otherwise the exact-match override below would hijack it).\n if (navigatedRef.current && !activeCommand) {\n const highlighted = items[clampedHighlight];\n if (highlighted) {\n await runResolved(highlighted, { explicit: true });\n }\n return;\n }\n // Otherwise (no explicit navigation): when the typed token is an exact\n // command name (e.g. \"/clear\" while the longer \"/clear-view\" sits first in\n // the filtered list), Enter should run THAT command, not autocomplete the\n // highlighted near-match. Exact match wins over the highlight; otherwise use\n // the highlighted row. A pointer click goes through runAt, never here.\n // Compare case-insensitively, matching filterCommands/matchCommand, so a\n // fully-typed \"/Clear\" still resolves to the exact (destructive) clear\n // rather than the highlighted prefix near-match.\n const token = parsed.name.toLowerCase();\n const exact = items.find((item) => item.name === token || item.aliases?.includes(token));\n const command = activeCommand ?? exact ?? items[clampedHighlight];\n if (!command) {\n return;\n }\n await runResolved(command);\n }, [parsed, activeCommand, items, clampedHighlight, runResolved]);\n\n // Run the command at an EXPLICITLY chosen index (a pointer click on a palette\n // row). Unlike runHighlighted this does NOT apply the exact-match override:\n // clicking the harmless `/clear-view` row while the draft is \"/clear\" must run\n // clear-view, never the destructive `/clear` that exact-matches the token. The\n // operator's pointer is the selection; token-resolution heuristics don't apply.\n const runAt = useCallback(\n async (index: number): Promise<void> => {\n const command = items[index];\n if (!command) {\n return;\n }\n await runResolved(command, { explicit: true });\n },\n [items, runResolved],\n );\n\n // Track an in-flight run so Enter can't double-fire.\n const runningRef = useRef(false);\n\n const onKeyDown = useCallback(\n (event: KeyboardEvent<HTMLTextAreaElement>): boolean => {\n if (!open) {\n return false;\n }\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n navigatedRef.current = true;\n setHighlight((current) => (items.length === 0 ? 0 : (Math.min(current, items.length - 1) + 1) % items.length));\n return true;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n navigatedRef.current = true;\n setHighlight((current) => {\n const base = Math.min(current, items.length - 1);\n return items.length === 0 ? 0 : (base - 1 + items.length) % items.length;\n });\n return true;\n }\n case \"Tab\": {\n event.preventDefault();\n autocompleteHighlighted();\n return true;\n }\n case \"Enter\": {\n if (event.shiftKey || event.nativeEvent?.isComposing) {\n return false;\n }\n event.preventDefault();\n if (runningRef.current) {\n return true;\n }\n runningRef.current = true;\n void runHighlighted().finally(() => {\n runningRef.current = false;\n });\n return true;\n }\n case \"Escape\": {\n event.preventDefault();\n // Close the palette but keep the draft intact. Remember the dismissed\n // value; the next edit re-opens (value !== dismissedValue).\n setDismissedValue(value);\n return true;\n }\n default:\n return false;\n }\n },\n [open, items, autocompleteHighlighted, runHighlighted, value],\n );\n\n return {\n open,\n isCommandDraft,\n items,\n highlight: clampedHighlight,\n setHighlight,\n activeCommand,\n activeArgHint,\n onKeyDown,\n runHighlighted,\n runAt,\n autocompleteHighlighted,\n };\n}\n\nfunction errorMessage(cause: unknown): string {\n if (cause instanceof Error) {\n return cause.message;\n }\n return String(cause);\n}\n","import { AnimatePresence, motion } from \"motion/react\";\nimport { argHint } from \"../commands/registry\";\nimport type { SlashCommand } from \"../commands/types\";\nimport { cn } from \"../lib/cn\";\n\nexport type CommandPaletteProps = {\n open: boolean;\n items: SlashCommand[];\n highlight: number;\n /** Hover/click selects a row. */\n onHighlight: (index: number) => void;\n /** Click runs the row (same path as Enter). */\n onRun: (index: number) => void;\n /** Footer arg hint shown in arg-hint mode (e.g. \"<pause|resume>\"). */\n argHintText: string;\n /** id used for aria-activedescendant wiring from the textarea. */\n listboxId: string;\n};\n\n/**\n * The slash-command palette: a popover anchored above the textarea, rendered\n * entirely from the filtered registry. Dark-first, Linear/Vercel-calm, using\n * the opengeni#46 design tokens. Full keyboard nav lives in useSlashCommands;\n * this component is presentational + aria.\n */\nexport function CommandPalette({ open, items, highlight, onHighlight, onRun, argHintText, listboxId }: CommandPaletteProps) {\n return (\n <AnimatePresence>\n {open ? (\n <motion.div\n initial={{ opacity: 0, y: 6, scale: 0.99 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 6, scale: 0.99 }}\n transition={{ duration: 0.13, ease: \"easeOut\" }}\n className={cn(\n \"absolute bottom-full left-0 right-0 z-20 mb-2 overflow-hidden\",\n \"rounded-og-lg border border-og-border bg-og-surface-2 shadow-og-sm\",\n )}\n >\n <ul\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Slash commands\"\n className=\"max-h-72 overflow-y-auto py-1\"\n >\n {items.map((command, index) => {\n const selected = index === highlight;\n const hint = argHint(command.args);\n return (\n <li\n key={command.name}\n id={`${listboxId}-option-${index}`}\n role=\"option\"\n aria-selected={selected}\n onMouseEnter={() => onHighlight(index)}\n onMouseDown={(event) => {\n // Keep textarea focus; run on click.\n event.preventDefault();\n onRun(index);\n }}\n className={cn(\n \"mx-1 flex cursor-pointer items-center gap-2 rounded-og-md px-2.5 py-1.5\",\n \"transition-colors duration-100\",\n selected ? \"bg-og-accent/15 text-og-fg\" : \"text-og-fg-muted hover:bg-og-surface-3\",\n )}\n >\n <span className=\"flex min-w-0 items-baseline gap-1.5\">\n <span className={cn(\"font-mono text-[13px]\", selected ? \"text-og-accent\" : \"text-og-fg\")}>\n /{command.name}\n </span>\n {hint ? <span className=\"truncate font-mono text-[11px] text-og-fg-subtle\">{hint}</span> : null}\n </span>\n <span className=\"ml-auto flex items-center gap-1.5\">\n {command.danger ? (\n <span className=\"rounded-og-xs bg-og-status-failed/15 px-1 text-[10px] uppercase tracking-wide text-og-status-failed\">\n danger\n </span>\n ) : null}\n <span className=\"truncate text-[12px] text-og-fg-subtle max-sm:hidden\">{command.description}</span>\n </span>\n </li>\n );\n })}\n </ul>\n {argHintText ? (\n <div className=\"border-t border-og-border px-3 py-1.5 font-mono text-[11px] text-og-fg-subtle\">\n {argHintText}\n </div>\n ) : null}\n </motion.div>\n ) : null}\n </AnimatePresence>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/** Merge class names with Tailwind-aware conflict resolution. */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import type { ClientModel, SessionStatus } from \"@opengeni/sdk\";\nimport { ArrowUpIcon, FileIcon, ImageIcon, LoaderCircleIcon, PaperclipIcon, SquareIcon, XIcon } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, type ChangeEvent, type ClipboardEvent, type DragEvent, type KeyboardEvent, type ReactNode } from \"react\";\nimport { argHint } from \"../commands/registry\";\nimport type { Notice, SlashCommand } from \"../commands/types\";\nimport type { ComposerState } from \"../hooks/use-composer\";\nimport { shouldSubmitOnKey } from \"../hooks/use-composer\";\nimport type { UseFileAttachmentsResult } from \"../hooks/use-file-attachments\";\nimport { defaultCommands } from \"../commands/registry\";\nimport { useSlashCommands, type ConfirmState, type SlashCommandContext } from \"../hooks/use-slash-commands\";\nimport { cn } from \"../lib/cn\";\nimport { formatBytes } from \"../lib/format\";\nimport { CommandPalette } from \"./command-palette\";\nimport { ModelPicker } from \"./model-picker\";\n\nexport type ChatComposerProps = {\n composer: ComposerState;\n /** Current session status; shows the stop control while a turn runs. */\n status?: SessionStatus | null | undefined;\n placeholder?: string | undefined;\n disabled?: boolean | undefined;\n autoFocus?: boolean | undefined;\n /** Replaces the default keyboard hint under the field. */\n hint?: string | undefined;\n /** App controls (model picker, attach button, ...) in the footer row, replacing the hint. */\n controlsStart?: ReactNode | undefined;\n /** Content rendered above the textarea, inside the field chrome (e.g. attachment chips). */\n header?: ReactNode | undefined;\n /** Paste hook on the textarea (e.g. paste-image-to-attach). */\n onPaste?: ((event: ClipboardEvent<HTMLTextAreaElement>) => void) | undefined;\n /**\n * Opt-in file attachments. When supplied (e.g. from {@link useFileAttachments}),\n * the composer renders a built-in attach button (prepended to `controlsStart`),\n * an attachment-chips strip (above the textarea, before any host `header`),\n * routes paste through `addFromPaste` (image/* filter lives in the hook), and\n * gates send while `uploading` so a message never departs without its files.\n * Absent → no attachment UI renders and the composer behaves exactly as before.\n */\n attachments?: UseFileAttachmentsResult | undefined;\n /**\n * Opt-in model picker. When supplied (e.g. from {@link useAvailableModels}),\n * the composer renders a {@link ModelPicker} at the start of `controlsStart`\n * so the operator can choose which host-exposed model serves the next message.\n * The host owns the selection (`selectedModel`/`onSelectModel`) and is\n * responsible for threading it into the composer's `sendExtras` (typically\n * `useComposer({ sendExtras: () => ({ model }) })`) so `composeSendInput`\n * carries it. Absent → no picker renders and the composer behaves as before.\n */\n models?: ClientModel[] | undefined;\n /** The currently selected model id (the picker's controlled value). */\n selectedModel?: string | undefined;\n /** Called with the chosen model id when the operator picks one. */\n onSelectModel?: ((modelId: string) => void) | undefined;\n className?: string | undefined;\n /**\n * Slash-command palette. Defaults to the built-in {@link defaultCommands};\n * apps concat their own. Backward-compatible: when `commandContext` is absent\n * the palette is inert and behavior is identical to before.\n */\n commands?: readonly SlashCommand[] | undefined;\n /**\n * Wiring the palette needs to run server commands and gate visibility. The\n * composer supplies notice/openHelp/clearView/confirm internally.\n */\n commandContext?: SlashCommandContext | undefined;\n /** Reset the local timeline view (the /clear-view command target). */\n onClearView?: (() => void) | undefined;\n};\n\nconst ACTIVE_STATUSES: ReadonlySet<SessionStatus> = new Set([\"queued\", \"running\"]);\n\n/**\n * The chat composer — the only human-to-agent input surface. Plain chat in,\n * everything else is the agent's job. Enter sends, Shift+Enter breaks the\n * line, and the stop control appears while a turn is running (sending while\n * running is legitimate steering, so send stays available too).\n *\n * Typing a leading \"/\" opens the slash-command palette — SESSION/OPERATOR\n * controls (clear, compact, pause goal, help), never a structured channel to\n * the agent. The palette is purely additive: with no `commandContext` it is\n * inert and the composer behaves exactly as before.\n */\nexport function ChatComposer({\n composer,\n status,\n placeholder,\n disabled,\n autoFocus,\n hint,\n controlsStart,\n header,\n onPaste,\n attachments,\n models,\n selectedModel,\n onSelectModel,\n className,\n commands = defaultCommands,\n commandContext,\n onClearView,\n}: ChatComposerProps) {\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n const active = status != null && ACTIVE_STATUSES.has(status);\n\n // Block sends while attachments are still uploading so a message never\n // departs without the files the user attached to it. This gates BOTH the\n // Enter-to-send path (which calls composer.send directly, bypassing canSend)\n // and the send button — dropping either path could ship a fileless message.\n const blockedByUpload = attachments?.uploading === true;\n\n // A ready attachment makes a file-only message (empty draft) sendable. The\n // composer (when wired with `sendExtras.resources`) already reflects this in\n // `canSend`; we OR it in here too so send-enablement is correct even for a\n // composer whose canSend doesn't know about attachments — and so this stays\n // the single home of the attachment send-gate.\n const hasReadyAttachment = (attachments?.readyResources.length ?? 0) > 0;\n // The send affordance: text OR a ready attachment, never mid-upload or mid-send.\n const canSend = (composer.canSend || hasReadyAttachment) && !blockedByUpload && !composer.sending;\n\n // Drag-and-drop file attach: only a drop target when `attachments` is wired,\n // and only reacts to drags that actually carry files (so it never hijacks\n // normal text drag/drop). `dragging` drives the drop overlay.\n const [dragging, setDragging] = useState(false);\n const dragCarriesFiles = (event: { dataTransfer: DataTransfer | null }): boolean =>\n event.dataTransfer != null && [...event.dataTransfer.types].includes(\"Files\");\n const handleDragOver = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n if (!attachments || !dragCarriesFiles(event)) {\n return;\n }\n // preventDefault marks this a valid drop target so the browser fires drop.\n event.preventDefault();\n setDragging(true);\n },\n [attachments],\n );\n const handleDragLeave = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n if (!attachments) {\n return;\n }\n // Ignore leaves bubbling from children: only clear when the pointer left\n // the composer bounds entirely (the related target is outside it).\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) {\n return;\n }\n setDragging(false);\n },\n [attachments],\n );\n const handleDrop = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n if (!attachments || !dragCarriesFiles(event)) {\n return;\n }\n event.preventDefault();\n setDragging(false);\n // Same path the picker uses: addFiles accepts ALL files (no image filter).\n if (event.dataTransfer.files.length > 0) {\n attachments.addFiles(event.dataTransfer.files);\n }\n },\n [attachments],\n );\n\n const [notice, setNotice] = useState<Notice | null>(null);\n const [helpOpen, setHelpOpen] = useState(false);\n const [confirmState, setConfirmState] = useState<ConfirmState>(null);\n const listboxId = useId();\n\n const resize = useCallback(() => {\n const textarea = textareaRef.current;\n if (!textarea) {\n return;\n }\n textarea.style.height = \"0px\";\n textarea.style.height = `${Math.min(textarea.scrollHeight, 220)}px`;\n }, []);\n\n useEffect(() => {\n resize();\n }, [composer.value, resize]);\n\n // The UI affordances commands reach: surface a notice, open the help panel,\n // reset the local view, and the danger confirm flow (resolves when the\n // operator confirms/cancels in the confirm bar).\n const handlers = useMemo(\n () => ({\n notice: (next: Notice) => {\n setNotice(next);\n composer.clearError();\n },\n openHelp: () => setHelpOpen(true),\n // Report whether a view-reset was actually wired by the host: with no\n // onClearView the command is a no-op and must say so (not a false success).\n clearView: () => {\n if (!onClearView) {\n return false;\n }\n onClearView();\n return true;\n },\n // The hook binds the command actually being run into confirm() (see\n // use-slash-commands buildContext), so the confirm bar renders from THAT\n // command — never a near-match highlighted in the palette. This is what\n // keeps the destructive /clear from being mislabeled as /clear-view.\n confirm: (command: SlashCommand) =>\n new Promise<boolean>((resolve) => {\n setConfirmState({\n command,\n resolve: (confirmed) => {\n setConfirmState(null);\n resolve(confirmed);\n },\n });\n }),\n }),\n [composer, onClearView],\n );\n\n const palette = useSlashCommands({\n commands,\n context: commandContext,\n handlers,\n value: composer.value,\n setValue: composer.setValue,\n });\n\n // The confirm bar renders from the command the hook is actually running —\n // carried into confirmState by handlers.confirm — NOT a near-match that\n // happens to be highlighted/active in the palette. (Re-deriving it from\n // palette.items[palette.highlight] mislabeled the destructive /clear as the\n // harmless /clear-view, since clear-view prefix-matches \"clear\" and sorts\n // first.)\n const pendingDangerCommand = confirmState ? confirmState.command : null;\n\n const paletteEnabled = commandContext !== undefined;\n\n // A slash-command draft must never be delivered to the agent as chat — it is\n // an operator control, not a message. The palette consumes Enter while open,\n // but after Escape the popover is closed yet the draft still matches a command;\n // block the send path (here and on the send button) so \"/clear\" can't be sent.\n const commandDraftBlocked = paletteEnabled && palette.isCommandDraft;\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n // Palette key handling runs FIRST and only when the palette is open; when\n // closed it returns false and the existing send path is untouched.\n if (paletteEnabled && palette.onKeyDown(event)) {\n return;\n }\n if (shouldSubmitOnKey(event)) {\n event.preventDefault();\n if (commandDraftBlocked) {\n // Dismissed palette + a \"/command\" draft: don't send it as chat. Nudge\n // the operator to re-open the palette (any edit re-opens it) or clear it.\n setNotice({ tone: \"error\", message: \"That's a slash command — press Enter in the command list to run it, or edit the line to send a message.\" });\n return;\n }\n if (blockedByUpload) {\n // Files are still uploading: swallow the Enter so the message can't\n // depart without them. The send button is disabled in the same state.\n return;\n }\n void composer.send();\n }\n };\n\n // The host's onPaste still fires (model/tool/whatever paste handling); when\n // attachments are wired, also feed the clipboard through addFromPaste so the\n // image/* filter (owned by the hook) attaches pasted images.\n const handlePaste = useCallback(\n (event: ClipboardEvent<HTMLTextAreaElement>) => {\n onPaste?.(event);\n attachments?.addFromPaste(event);\n },\n [onPaste, attachments],\n );\n\n const handleFileChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (event.target.files) {\n attachments?.addFiles(event.target.files);\n }\n event.target.value = \"\";\n },\n [attachments],\n );\n\n const helpCommands = useMemo(\n () =>\n commands.filter((command) => {\n if (command.permission && commandContext) {\n const perms = commandContext.permissions;\n return perms.includes(command.permission) || perms.includes(\"workspace:admin\");\n }\n return true;\n }),\n [commands, commandContext],\n );\n\n const activeNotice = notice ?? (composer.error ? { tone: \"error\" as const, message: composer.error.message || \"Sending failed — your draft is still here. Try again.\" } : null);\n\n return (\n <div className={cn(\"og-root\", className)}>\n <div className=\"relative\">\n {paletteEnabled ? (\n <CommandPalette\n open={palette.open && confirmState === null}\n items={palette.items}\n highlight={palette.highlight}\n onHighlight={palette.setHighlight}\n onRun={(index) => {\n // Run the CLICKED row directly. We must not route a pointer click\n // through runHighlighted: its exact-match override would re-resolve\n // \"/clear\" to the destructive clear even when the operator clicked\n // the harmless clear-view row. runAt honors the explicit selection.\n palette.setHighlight(index);\n void palette.runAt(index);\n }}\n argHintText={palette.activeArgHint}\n listboxId={listboxId}\n />\n ) : null}\n <div\n // Drag-and-drop file attach lives on the field wrapper, but only when\n // `attachments` is wired — without it the composer is not a drop target\n // and behaves exactly as before.\n onDragOver={attachments ? handleDragOver : undefined}\n onDragLeave={attachments ? handleDragLeave : undefined}\n onDrop={attachments ? handleDrop : undefined}\n className={cn(\n \"relative rounded-og-lg border border-og-border bg-og-surface-1 shadow-og-sm\",\n \"transition-[border-color,box-shadow] duration-200\",\n \"focus-within:border-og-accent/60 focus-within:shadow-og-glow\",\n // While files are dragged over, swap to a dashed accent border to\n // signal a live drop target (the overlay carries the label).\n dragging && \"border-dashed border-og-accent\",\n )}\n >\n {dragging ? (\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 z-10 flex items-center justify-center\",\n \"rounded-og-lg bg-og-surface-1/85 text-sm font-medium text-og-accent backdrop-blur-[1px]\",\n )}\n >\n <span className=\"inline-flex items-center gap-2\">\n <PaperclipIcon className=\"size-4\" />\n Drop files to attach\n </span>\n </div>\n ) : null}\n {attachments && attachments.attachments.length > 0 ? (\n <AttachmentChips attachments={attachments.attachments} onRemove={attachments.remove} />\n ) : null}\n {header}\n <textarea\n ref={textareaRef}\n rows={1}\n value={composer.value}\n onChange={(event) => composer.setValue(event.target.value)}\n onKeyDown={onKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder ?? \"Message the agent…\"}\n disabled={disabled}\n autoFocus={autoFocus}\n aria-label=\"Message the agent\"\n role={paletteEnabled && palette.open ? \"combobox\" : undefined}\n aria-expanded={paletteEnabled ? palette.open : undefined}\n aria-controls={paletteEnabled && palette.open ? listboxId : undefined}\n aria-activedescendant={paletteEnabled && palette.open ? `${listboxId}-option-${palette.highlight}` : undefined}\n className={cn(\n \"block w-full resize-none bg-transparent px-4 pt-3.5 pb-1 text-[15px] leading-6\",\n // The wrapper owns the whole-composer focus affordance (focus-within\n // border + soft glow). Suppress any self-scoped focus outline on the\n // textarea itself: `focus:outline-none` alone only sets outline-style\n // on `:focus`, which a host app's zero-specificity\n // `:where(...):focus-visible { outline: ... }` base rule re-applies as\n // the full shorthand. `focus-visible:outline-none` matches the same\n // state at class specificity and wins, so no second highlight (the\n // top-half rectangle bounded to the textarea box) ever paints.\n \"text-og-fg placeholder:text-og-fg-subtle focus:outline-none focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-60\",\n )}\n />\n {confirmState && pendingDangerCommand ? (\n <ConfirmBar\n command={pendingDangerCommand}\n onCancel={() => confirmState.resolve(false)}\n onConfirm={() => confirmState.resolve(true)}\n />\n ) : (\n <div className=\"flex items-center justify-between gap-2 px-2.5 pb-2.5 pt-1\">\n {attachments || models || controlsStart ? (\n <span className=\"flex min-w-0 items-center gap-1.5\">\n {attachments ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={handleFileChange}\n />\n <button\n type=\"button\"\n disabled={disabled === true}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Attach files\"\n title=\"Attach files\"\n className={cn(\n \"inline-flex size-8 items-center justify-center rounded-og-md\",\n \"text-og-fg-muted transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n )}\n >\n <PaperclipIcon className=\"size-4\" />\n </button>\n </>\n ) : null}\n {models ? (\n <ModelPicker\n models={models}\n value={selectedModel}\n onChange={(modelId) => onSelectModel?.(modelId)}\n disabled={disabled === true}\n />\n ) : null}\n {controlsStart}\n </span>\n ) : (\n <span className=\"px-1.5 text-[11px] text-og-fg-subtle max-sm:hidden\">\n {hint ?? \"Enter to send · Shift+Enter for a new line · / for commands\"}\n </span>\n )}\n <span className=\"flex items-center gap-1.5\">\n <AnimatePresence initial={false}>\n {active ? (\n <motion.button\n key=\"stop\"\n type=\"button\"\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.8 }}\n transition={{ duration: 0.15, ease: \"easeOut\" }}\n onClick={() => void composer.interrupt()}\n disabled={composer.interrupting}\n aria-label=\"Stop the current turn\"\n title=\"Stop the current turn\"\n className={cn(\n \"inline-flex size-8 items-center justify-center rounded-og-md border border-og-border\",\n \"bg-og-surface-2 text-og-fg-muted transition-colors duration-150\",\n \"hover:border-og-status-failed/50 hover:text-og-status-failed\",\n \"disabled:opacity-50\",\n )}\n >\n {composer.interrupting ? (\n <LoaderCircleIcon className=\"size-3.5 animate-og-spin\" />\n ) : (\n <SquareIcon className=\"size-3 fill-current\" />\n )}\n </motion.button>\n ) : null}\n </AnimatePresence>\n <button\n type=\"button\"\n onClick={() => {\n if (blockedByUpload) {\n return;\n }\n void composer.send();\n }}\n disabled={!canSend || disabled === true || commandDraftBlocked}\n aria-label=\"Send message\"\n className={cn(\n \"inline-flex size-8 items-center justify-center rounded-og-md\",\n \"bg-og-accent text-og-accent-fg shadow-og-sm\",\n \"transition-[background-color,transform,opacity] duration-150 ease-og-spring\",\n \"hover:bg-og-accent-strong active:scale-95\",\n \"disabled:cursor-not-allowed disabled:bg-og-surface-3 disabled:text-og-fg-subtle disabled:shadow-none\",\n )}\n >\n {composer.sending ? <LoaderCircleIcon className=\"size-4 animate-og-spin\" /> : <ArrowUpIcon className=\"size-4\" />}\n </button>\n </span>\n </div>\n )}\n </div>\n </div>\n <AnimatePresence>\n {helpOpen ? (\n <HelpPanel commands={helpCommands} onClose={() => setHelpOpen(false)} />\n ) : null}\n </AnimatePresence>\n <AnimatePresence>\n {activeNotice ? (\n <motion.p\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className={cn(\n \"overflow-hidden px-1 pt-1.5 text-xs\",\n activeNotice.tone === \"ok\" ? \"text-og-fg-muted\" : \"text-og-status-failed\",\n )}\n role={activeNotice.tone === \"error\" ? \"alert\" : \"status\"}\n onAnimationComplete={() => {\n if (activeNotice.tone === \"ok\") {\n // Auto-dismiss success notices after a beat.\n window.setTimeout(() => setNotice((current) => (current === activeNotice ? null : current)), 2400);\n }\n }}\n >\n {activeNotice.message}\n </motion.p>\n ) : null}\n </AnimatePresence>\n </div>\n );\n}\n\n/** The danger confirm bar — reuses og-status-failed tokens (like the stop control). */\nfunction ConfirmBar({ command, onCancel, onConfirm }: { command: SlashCommand; onCancel: () => void; onConfirm: () => void }) {\n return (\n <div\n role=\"alertdialog\"\n aria-label={`Confirm /${command.name}`}\n data-testid=\"danger-confirm\"\n className=\"flex items-center justify-between gap-2 px-2.5 pb-2.5 pt-1\"\n >\n <span className=\"px-1.5 text-[12px] text-og-status-failed\">\n Run <span className=\"font-mono\">/{command.name}</span>? {command.description}\n </span>\n <span className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"rounded-og-md border border-og-border bg-og-surface-2 px-2.5 py-1 text-[12px] text-og-fg-muted hover:bg-og-surface-3\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n autoFocus\n onClick={onConfirm}\n className=\"rounded-og-md border border-og-status-failed/50 bg-og-status-failed/15 px-2.5 py-1 text-[12px] text-og-status-failed hover:bg-og-status-failed/25\"\n >\n Confirm\n </button>\n </span>\n </div>\n );\n}\n\n/**\n * The attachment-chips strip rendered above the textarea while files are\n * attached. Each chip shows an image preview (or a type icon), the filename,\n * an upload/size/failed status line, and a remove control. Styled with the\n * package's og-* tokens so it themes in any consumer.\n */\nfunction AttachmentChips({ attachments, onRemove }: {\n attachments: UseFileAttachmentsResult[\"attachments\"];\n onRemove: (id: string) => void;\n}) {\n return (\n <div className=\"flex flex-wrap gap-2 border-b border-og-border px-3 py-2\">\n {attachments.map((attachment) => (\n <div\n key={attachment.id}\n className={cn(\n \"flex min-w-0 max-w-[240px] items-center gap-2 rounded-og-md border px-2 py-1.5\",\n \"border-og-border bg-og-surface-2 text-xs\",\n )}\n >\n {attachment.previewUrl ? (\n <img src={attachment.previewUrl} alt=\"\" className=\"size-8 shrink-0 rounded object-cover\" />\n ) : attachment.contentType.startsWith(\"image/\") ? (\n <ImageIcon className=\"size-4 shrink-0 text-og-fg-muted\" />\n ) : (\n <FileIcon className=\"size-4 shrink-0 text-og-fg-muted\" />\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium text-og-fg\">{attachment.name}</div>\n <div className={cn(\n \"truncate text-[11px]\",\n attachment.status === \"failed\" ? \"text-og-status-failed\" : \"text-og-fg-subtle\",\n )}\n >\n {attachment.status === \"uploading\" ? \"Uploading\" : attachment.status === \"failed\" ? \"Upload failed\" : formatBytes(attachment.sizeBytes)}\n </div>\n </div>\n {attachment.status === \"uploading\" ? <LoaderCircleIcon className=\"size-3.5 shrink-0 animate-og-spin\" /> : null}\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n className=\"shrink-0 rounded-og-xs p-1 text-og-fg-muted hover:bg-og-surface-1 hover:text-og-fg\"\n aria-label={`Remove ${attachment.name}`}\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n ))}\n </div>\n );\n}\n\n/** The in-composer /help panel, rendered entirely from the registry. */\nfunction HelpPanel({ commands, onClose }: { commands: readonly SlashCommand[]; onClose: () => void }) {\n return (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={{ opacity: 0, height: 0 }}\n className=\"mt-2 overflow-hidden rounded-og-lg border border-og-border bg-og-surface-2\"\n >\n <div className=\"flex items-center justify-between border-b border-og-border px-3 py-1.5\">\n <span className=\"text-[12px] font-medium text-og-fg\">Commands</span>\n <button type=\"button\" onClick={onClose} className=\"text-[11px] text-og-fg-subtle hover:text-og-fg\">\n Close\n </button>\n </div>\n <ul className=\"py-1\">\n {commands.map((command) => {\n const hint = argHint(command.args);\n return (\n <li key={command.name} className=\"flex items-baseline gap-2 px-3 py-1\">\n <span className=\"font-mono text-[12px] text-og-accent\">\n /{command.name}\n {hint ? <span className=\"ml-1 text-og-fg-subtle\">{hint}</span> : null}\n </span>\n <span className=\"text-[12px] text-og-fg-muted\">{command.description}</span>\n {command.danger ? (\n <span className=\"ml-auto rounded-og-xs bg-og-status-failed/15 px-1 text-[10px] uppercase tracking-wide text-og-status-failed\">\n danger\n </span>\n ) : null}\n </li>\n );\n })}\n </ul>\n </motion.div>\n );\n}\n","import type { ClientModel } from \"@opengeni/sdk\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { useId, useMemo } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type ModelPickerProps = {\n /** The host-exposed models to choose from (typically {@link useAvailableModels}). */\n models: ClientModel[];\n /** Controlled selection — the model id, or undefined for \"nothing chosen yet\". */\n value?: string | undefined;\n /** Called with the chosen model id when the operator picks a row. */\n onChange: (modelId: string) => void;\n disabled?: boolean | undefined;\n className?: string | undefined;\n};\n\n/**\n * The model picker — a compact dropdown for the composer footer, grouping the\n * host-exposed models by `providerLabel` (so \"OpenAI\" and \"Fireworks AI\" head\n * their own sections) and showing each model's display `label`. A native\n * `<select>` keeps it keyboard- and screen-reader-accessible for free and\n * themes via the package's og-* tokens; the chevron is a decorative overlay.\n *\n * Controlled: the host owns `value`/`onChange` and threads the selection into\n * the send path. Renders nothing when no models are exposed, so a single-model\n * deployment shows no chrome.\n */\nexport function ModelPicker({ models, value, onChange, disabled, className }: ModelPickerProps) {\n const selectId = useId();\n // Group by provider, preserving first-seen order for both the providers and\n // the models within each — the server already orders the list (default model\n // and built-in provider first), so we must not re-sort it.\n const groups = useMemo(() => {\n const byProvider = new Map<string, { label: string; models: ClientModel[] }>();\n for (const model of models) {\n let group = byProvider.get(model.provider);\n if (!group) {\n group = { label: model.providerLabel, models: [] };\n byProvider.set(model.provider, group);\n }\n group.models.push(model);\n }\n return [...byProvider.values()];\n }, [models]);\n\n if (models.length === 0) {\n return null;\n }\n\n return (\n <span className={cn(\"relative inline-flex items-center\", className)}>\n <label htmlFor={selectId} className=\"sr-only\">\n Model\n </label>\n <select\n id={selectId}\n value={value ?? \"\"}\n onChange={(event) => onChange(event.target.value)}\n disabled={disabled === true}\n aria-label=\"Model\"\n className={cn(\n // Sized like the other footer controls; the chevron overlay needs the\n // right padding so the value never collides with it.\n \"h-8 max-w-[180px] cursor-pointer appearance-none truncate rounded-og-md bg-transparent\",\n \"py-0 pl-2 pr-6 text-[13px] text-og-fg-muted\",\n \"transition-colors duration-150 hover:bg-og-surface-2 hover:text-og-fg\",\n \"focus:outline-none focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n )}\n >\n {groups.map((group) => (\n <optgroup key={group.label} label={group.label}>\n {group.models.map((model) => (\n <option key={model.id} value={model.id}>\n {model.label}\n </option>\n ))}\n </optgroup>\n ))}\n </select>\n <ChevronDownIcon\n aria-hidden\n className=\"pointer-events-none absolute right-1.5 size-3.5 text-og-fg-subtle\"\n />\n </span>\n );\n}\n","import type { SessionEvent, SessionStatus } from \"@opengeni/sdk\";\nimport {\n ArrowDownIcon,\n BotIcon,\n BrainIcon,\n ChevronRightIcon,\n SquareTerminalIcon,\n TargetIcon,\n TriangleAlertIcon,\n WrenchIcon,\n} from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Collapsible } from \"radix-ui\";\nimport { cn } from \"../lib/cn\";\nimport { formatRelativeTime, stringifyPayload, truncate } from \"../lib/format\";\nimport { Markdown } from \"./markdown\";\nimport {\n buildTimeline,\n compactPayloadPreview,\n groupTimeline,\n toolDisplayName,\n type AgentMessageItem,\n type GoalItem,\n type NoticeItem,\n type ReasoningItem,\n type SandboxItem,\n type TimelineItem,\n type ToolCallItem,\n type UserMessageItem,\n type WorkerItem,\n} from \"../timeline\";\nimport { SESSION_STATUS_META, StatusDot } from \"./session-status\";\n\nexport type MessageTimelineProps = {\n /** Raw session events (projected internally) … */\n events?: SessionEvent[] | undefined;\n /** … or pre-projected items (e.g. from `useSessionEvents().timeline`). */\n items?: TimelineItem[] | undefined;\n /** Current session status; drives the live \"working\" indicator. */\n status?: SessionStatus | null | undefined;\n /** Plug a markdown renderer for message bodies (e.g. streamdown). */\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n /** Drill into a spawned worker session. */\n onOpenSession?: ((sessionId: string) => void) | undefined;\n /** Follow new events when pinned to the bottom. Defaults to true. */\n autoFollow?: boolean | undefined;\n emptyState?: ReactNode | undefined;\n className?: string | undefined;\n};\n\n/**\n * The session timeline: chat messages with streaming deltas, collapsed\n * activity clusters (reasoning, tool calls, sandbox work), spawned-worker\n * cards, goal markers, and status transitions. Owns stick-to-bottom scrolling\n * with a \"jump to latest\" affordance when the reader scrolls back.\n */\nexport function MessageTimeline({\n events,\n items,\n status,\n renderMessageText,\n onOpenSession,\n autoFollow = true,\n emptyState,\n className,\n}: MessageTimelineProps) {\n const resolvedItems = useMemo(() => items ?? buildTimeline(events ?? []), [items, events]);\n const groups = useMemo(() => groupTimeline(resolvedItems), [resolvedItems]);\n\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const [pinned, setPinned] = useState(true);\n const lastItem = resolvedItems[resolvedItems.length - 1];\n const streaming = lastItem !== undefined && (lastItem.kind === \"agent-message\" || lastItem.kind === \"reasoning\") && lastItem.streaming;\n const working = status === \"running\" && !streaming;\n\n // Follow the stream while pinned to the bottom; never fight the reader.\n useEffect(() => {\n const node = scrollRef.current;\n if (node && autoFollow && pinned) {\n node.scrollTop = node.scrollHeight;\n }\n }, [resolvedItems, working, autoFollow, pinned]);\n\n const onScroll = () => {\n const node = scrollRef.current;\n if (!node) {\n return;\n }\n setPinned(node.scrollHeight - node.scrollTop - node.clientHeight < 48);\n };\n\n return (\n <div className={cn(\"og-root relative min-h-0\", className)}>\n <div ref={scrollRef} onScroll={onScroll} className=\"h-full overflow-y-auto overscroll-contain px-4 py-6 sm:px-6\">\n <div className=\"mx-auto flex w-full max-w-3xl flex-col gap-5\">\n {groups.length === 0 && !working\n ? (emptyState ?? <p className=\"py-10 text-center text-sm text-og-fg-subtle\">No activity yet.</p>)\n : null}\n {groups.map((group) =>\n group.kind === \"activity\" ? (\n <ActivityCluster key={group.id} items={group.items} onOpenSession={onOpenSession} />\n ) : (\n <TimelineRow key={group.item.id} item={group.item} renderMessageText={renderMessageText} />\n ),\n )}\n {working ? (\n <div className=\"animate-og-enter flex items-center gap-2 text-sm\">\n <span className=\"og-shimmer-text font-medium\">Working…</span>\n </div>\n ) : null}\n </div>\n </div>\n <AnimatePresence>\n {!pinned && autoFollow ? (\n <motion.button\n type=\"button\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 8 }}\n transition={{ duration: 0.15, ease: \"easeOut\" }}\n onClick={() => {\n const node = scrollRef.current;\n if (node) {\n node.scrollTo({ top: node.scrollHeight, behavior: \"smooth\" });\n }\n setPinned(true);\n }}\n className={cn(\n \"absolute bottom-4 left-1/2 -translate-x-1/2\",\n \"inline-flex items-center gap-1.5 rounded-full border border-og-border bg-og-surface-3/90 px-3 py-1.5\",\n \"text-xs font-medium text-og-fg shadow-og-md backdrop-blur\",\n \"hover:border-og-border-strong\",\n )}\n >\n <ArrowDownIcon className=\"size-3.5\" />\n Jump to latest\n </motion.button>\n ) : null}\n </AnimatePresence>\n </div>\n );\n}\n\n/* --- single rows ------------------------------------------------------------ */\n\nfunction TimelineRow({\n item,\n renderMessageText,\n}: {\n item: TimelineItem;\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n}) {\n switch (item.kind) {\n case \"user-message\":\n return <UserMessageRow item={item} renderMessageText={renderMessageText} />;\n case \"agent-message\":\n return <AgentMessageRow item={item} renderMessageText={renderMessageText} />;\n case \"session-status\":\n return <SessionStatusRow item={item} />;\n case \"goal\":\n return <GoalRow item={item} />;\n case \"notice\":\n return <NoticeRow item={item} />;\n default:\n return null;\n }\n}\n\nfunction UserMessageRow({\n item,\n renderMessageText,\n}: {\n item: UserMessageItem;\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n}) {\n return (\n <div className=\"animate-og-enter flex justify-end\">\n <div className=\"max-w-[85%] min-w-0 rounded-og-lg rounded-br-og-xs border border-og-border bg-og-surface-2 px-4 py-2.5 text-[15px] leading-6 text-og-fg\">\n {renderMessageText ? renderMessageText(item.text, item) : <Markdown>{item.text}</Markdown>}\n </div>\n </div>\n );\n}\n\nfunction AgentMessageRow({\n item,\n renderMessageText,\n}: {\n item: AgentMessageItem;\n renderMessageText?: ((text: string, item: AgentMessageItem | UserMessageItem) => ReactNode) | undefined;\n}) {\n const caret = item.streaming ? (\n <span className=\"ml-0.5 inline-block h-[1.1em] w-[2px] translate-y-[3px] animate-og-blink rounded-full bg-og-accent\" aria-hidden />\n ) : null;\n return (\n <div className=\"animate-og-enter min-w-0 text-[15px] leading-7 text-og-fg\">\n {renderMessageText ? (\n <>\n {renderMessageText(item.text, item)}\n {caret}\n </>\n ) : (\n // While streaming, let the caret ride the end of the last rendered line:\n // the trailing block (usually a <p>) flows inline so the caret sits on\n // its baseline instead of dropping to a new line.\n <div className={item.streaming ? \"[&_>div>:last-child]:inline\" : undefined}>\n <Markdown>{item.text}</Markdown>\n {caret}\n </div>\n )}\n </div>\n );\n}\n\nfunction SessionStatusRow({ item }: { item: { status: SessionStatus; occurredAt: string } }) {\n const meta = SESSION_STATUS_META[item.status];\n return (\n <div className=\"animate-og-enter flex items-center gap-3 text-[11px] text-og-fg-subtle\" role=\"status\">\n <span className=\"h-px flex-1 bg-og-border\" />\n <span className=\"inline-flex items-center gap-1.5\">\n <StatusDot status={item.status} className=\"size-1\" />\n {meta.label.toLowerCase()} · {formatRelativeTime(item.occurredAt)}\n </span>\n <span className=\"h-px flex-1 bg-og-border\" />\n </div>\n );\n}\n\nfunction GoalRow({ item }: { item: GoalItem }) {\n const label =\n item.action === \"set\"\n ? \"Goal set\"\n : item.action === \"updated\"\n ? \"Goal updated\"\n : item.action === \"completed\"\n ? \"Goal completed\"\n : item.action === \"paused\"\n ? \"Goal paused\"\n : item.action === \"resumed\"\n ? \"Goal resumed\"\n : \"Continuing toward the goal\";\n return (\n <div className=\"animate-og-enter flex justify-center\">\n <span className=\"inline-flex max-w-full items-center gap-1.5 rounded-full border border-og-border bg-og-surface-1 px-3 py-1 text-xs text-og-fg-muted\">\n <TargetIcon className=\"size-3.5 shrink-0 text-og-accent\" />\n <span className=\"truncate\">\n {label}\n {item.text ? `: ${truncate(item.text, 90)}` : \"\"}\n </span>\n </span>\n </div>\n );\n}\n\nfunction NoticeRow({ item }: { item: NoticeItem }) {\n const tone =\n item.tone === \"failed\"\n ? \"border-og-status-failed/35 bg-og-status-failed/10 text-og-status-failed\"\n : item.tone === \"waiting\"\n ? \"border-og-status-waiting/35 bg-og-status-waiting/10 text-og-status-waiting\"\n : \"border-og-border bg-og-surface-1 text-og-fg-muted\";\n return (\n <div className={cn(\"animate-og-enter flex items-start gap-2.5 rounded-og-md border px-3.5 py-2.5 text-sm\", tone)} role=\"status\">\n <TriangleAlertIcon className={cn(\"mt-0.5 size-4 shrink-0\", item.tone === \"cancelled\" && \"opacity-60\")} />\n <span className=\"min-w-0 whitespace-pre-wrap break-words\">{item.text}</span>\n </div>\n );\n}\n\n/* --- activity cluster -------------------------------------------------------- */\n\ntype ActivityItem = ReasoningItem | ToolCallItem | WorkerItem | SandboxItem;\n\nfunction ActivityCluster({\n items,\n onOpenSession,\n}: {\n items: ActivityItem[];\n onOpenSession?: ((sessionId: string) => void) | undefined;\n}) {\n return (\n <div className=\"animate-og-enter flex flex-col gap-1.5 border-l-2 border-og-border pl-3 sm:pl-4\">\n {items.map((item) => {\n switch (item.kind) {\n case \"reasoning\":\n return <ReasoningRow key={item.id} item={item} />;\n case \"tool-call\":\n return <ToolCallRow key={item.id} item={item} />;\n case \"worker\":\n return <WorkerRow key={item.id} item={item} onOpenSession={onOpenSession} />;\n case \"sandbox\":\n return <SandboxRow key={item.id} item={item} />;\n }\n })}\n </div>\n );\n}\n\nfunction ActivityDisclosure({\n icon,\n title,\n running,\n failed,\n preview,\n children,\n}: {\n icon: ReactNode;\n title: string;\n running: boolean;\n failed?: boolean | undefined;\n preview?: string | undefined;\n children?: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <Collapsible.Root open={open} onOpenChange={setOpen}>\n <Collapsible.Trigger\n className={cn(\n \"group flex w-full min-w-0 items-center gap-2 rounded-og-sm px-1.5 py-1 text-left text-[13px]\",\n \"text-og-fg-muted transition-colors duration-150 hover:bg-og-surface-1 hover:text-og-fg\",\n )}\n >\n <ChevronRightIcon className=\"size-3.5 shrink-0 text-og-fg-subtle transition-transform duration-150 group-data-[state=open]:rotate-90\" />\n <span className={cn(\"shrink-0\", failed ? \"text-og-status-failed\" : running ? \"text-og-status-running\" : \"text-og-fg-subtle\")}>{icon}</span>\n <span className={cn(\"shrink-0 font-medium\", running && \"og-shimmer-text\", failed && \"text-og-status-failed\")}>{title}</span>\n {preview ? <span className=\"min-w-0 flex-1 truncate font-og-mono text-xs text-og-fg-subtle\">{preview}</span> : null}\n {running ? <span className=\"ml-auto size-1.5 shrink-0 animate-og-pulse rounded-full bg-og-status-running\" /> : null}\n </Collapsible.Trigger>\n <Collapsible.Content className=\"overflow-hidden\">\n <div className=\"mt-1 mb-1.5 ml-7 flex flex-col gap-2\">{children}</div>\n </Collapsible.Content>\n </Collapsible.Root>\n );\n}\n\nfunction PayloadBlock({ label, value }: { label: string; value: unknown }) {\n const text = stringifyPayload(value);\n if (!text) {\n return null;\n }\n return (\n <div className=\"min-w-0\">\n <p className=\"mb-1 text-[10px] font-medium uppercase tracking-[0.08em] text-og-fg-subtle\">{label}</p>\n <pre className=\"max-h-64 overflow-auto rounded-og-sm border border-og-border bg-og-bg/60 p-2.5 font-og-mono text-xs leading-5 text-og-fg-muted\">\n {text}\n </pre>\n </div>\n );\n}\n\nfunction ReasoningRow({ item }: { item: ReasoningItem }) {\n return (\n <ActivityDisclosure\n icon={<BrainIcon className=\"size-3.5\" />}\n title={item.streaming ? \"Thinking\" : \"Thought\"}\n running={item.streaming}\n preview={truncate(item.text, 110)}\n >\n <p className=\"whitespace-pre-wrap text-[13px] leading-6 text-og-fg-muted\">{item.text}</p>\n </ActivityDisclosure>\n );\n}\n\nfunction ToolCallRow({ item }: { item: ToolCallItem }) {\n return (\n <ActivityDisclosure\n icon={<WrenchIcon className=\"size-3.5\" />}\n title={toolDisplayName(item.name)}\n running={item.status === \"running\"}\n preview={compactPayloadPreview(item.arguments)}\n >\n <PayloadBlock label=\"Arguments\" value={item.arguments} />\n {item.status === \"complete\" ? <PayloadBlock label=\"Output\" value={item.output} /> : null}\n </ActivityDisclosure>\n );\n}\n\nfunction SandboxRow({ item }: { item: SandboxItem }) {\n return (\n <ActivityDisclosure\n icon={<SquareTerminalIcon className=\"size-3.5\" />}\n title={toolDisplayName(item.name)}\n running={item.status === \"running\"}\n failed={item.status === \"failed\"}\n preview={item.command ?? undefined}\n >\n {item.command ? <PayloadBlock label=\"Command\" value={item.command} /> : null}\n {item.output ? <PayloadBlock label=\"Output\" value={item.output} /> : null}\n </ActivityDisclosure>\n );\n}\n\n/** Spawned/messaged worker sessions get a first-class card, not a tool row. */\nfunction WorkerRow({ item, onOpenSession }: { item: WorkerItem; onOpenSession?: ((sessionId: string) => void) | undefined }) {\n const running = item.status === \"running\";\n const title = item.action === \"spawn\" ? (running ? \"Spawning worker\" : \"Worker spawned\") : running ? \"Messaging worker\" : \"Worker messaged\";\n return (\n <div className=\"my-0.5 flex items-start gap-3 rounded-og-md border border-og-border bg-og-surface-1 p-3 shadow-og-sm\">\n <span\n className={cn(\n \"mt-0.5 inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm\",\n \"bg-og-accent-soft text-og-accent\",\n )}\n >\n <BotIcon className=\"size-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className={cn(\"text-[13px] font-medium\", running ? \"og-shimmer-text\" : \"text-og-fg\")}>{title}</span>\n {running ? <span className=\"size-1.5 animate-og-pulse rounded-full bg-og-status-running\" /> : null}\n </div>\n {item.prompt ? <p className=\"mt-0.5 truncate text-xs text-og-fg-muted\">{truncate(item.prompt, 140)}</p> : null}\n {item.workerSessionId ? (\n <p className=\"mt-1 font-og-mono text-[11px] text-og-fg-subtle\">{item.workerSessionId.slice(0, 8)}</p>\n ) : null}\n </div>\n {item.workerSessionId && onOpenSession ? (\n <button\n type=\"button\"\n onClick={() => item.workerSessionId && onOpenSession(item.workerSessionId)}\n className={cn(\n \"shrink-0 self-center rounded-og-sm border border-og-border px-2.5 py-1 text-xs font-medium text-og-fg-muted\",\n \"transition-colors duration-150 hover:border-og-border-strong hover:text-og-fg\",\n )}\n >\n Open session\n </button>\n ) : null}\n </div>\n );\n}\n","import { memo } from \"react\";\nimport ReactMarkdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { cn } from \"../lib/cn\";\n\n/**\n * The default renderer for chat message bodies in {@link MessageTimeline}.\n *\n * Agent (and user) messages arrive as GitHub-flavored markdown. This turns the\n * raw text into styled HTML using `react-markdown` + `remark-gfm`, themed to the\n * package's `og-*` design tokens so it reads as one cohesive dark surface — no\n * stock Tailwind colors leak in.\n *\n * It re-parses on every render, which is exactly right for streaming: a body\n * that is still arriving (an unterminated `**`, a half-open code fence, a table\n * mid-row) renders as best-effort markdown and resolves cleanly as the rest of\n * the tokens land. Consumers who want a different renderer can still pass\n * `renderMessageText` to `MessageTimeline` to override this entirely.\n */\nexport type MarkdownProps = {\n children: string;\n className?: string | undefined;\n};\n\n/* --- element renderers (themed to og-* tokens) ------------------------------ */\n\nconst components: Components = {\n h1: ({ children, ...props }) => (\n <h1 className=\"mt-5 mb-2.5 text-xl font-semibold tracking-tight text-og-fg first:mt-0\" {...props}>\n {children}\n </h1>\n ),\n h2: ({ children, ...props }) => (\n <h2 className=\"mt-5 mb-2 text-lg font-semibold tracking-tight text-og-fg first:mt-0\" {...props}>\n {children}\n </h2>\n ),\n h3: ({ children, ...props }) => (\n <h3 className=\"mt-4 mb-1.5 text-[15px] font-semibold tracking-tight text-og-fg first:mt-0\" {...props}>\n {children}\n </h3>\n ),\n h4: ({ children, ...props }) => (\n <h4 className=\"mt-4 mb-1.5 text-sm font-semibold uppercase tracking-[0.04em] text-og-fg-muted first:mt-0\" {...props}>\n {children}\n </h4>\n ),\n p: ({ children, ...props }) => (\n <p className=\"my-2.5 leading-7 first:mt-0 last:mb-0\" {...props}>\n {children}\n </p>\n ),\n strong: ({ children, ...props }) => (\n <strong className=\"font-semibold text-og-fg\" {...props}>\n {children}\n </strong>\n ),\n em: ({ children, ...props }) => (\n <em className=\"italic\" {...props}>\n {children}\n </em>\n ),\n a: ({ children, ...props }) => (\n <a\n className=\"break-words font-medium text-og-accent underline-offset-2 hover:underline\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n {...props}\n >\n {children}\n </a>\n ),\n ul: ({ children, ...props }) => (\n <ul className=\"my-2.5 ml-5 flex list-disc flex-col gap-1 marker:text-og-fg-subtle first:mt-0 last:mb-0\" {...props}>\n {children}\n </ul>\n ),\n ol: ({ children, ...props }) => (\n <ol className=\"my-2.5 ml-5 flex list-decimal flex-col gap-1 marker:text-og-fg-subtle first:mt-0 last:mb-0\" {...props}>\n {children}\n </ol>\n ),\n // GFM task-list items carry a leading checkbox <input>; `list-none` + a\n // negative margin pull the checkbox back to the bullet column so it aligns\n // with the text.\n li: ({ children, ...props }) => (\n <li className=\"leading-7 marker:text-og-fg-subtle [&>ul]:my-1 [&>ol]:my-1 [&:has(>input)]:list-none [&:has(>input)]:-ml-5\" {...props}>\n {children}\n </li>\n ),\n input: ({ type, ...props }) =>\n type === \"checkbox\" ? (\n <input\n {...props}\n type=\"checkbox\"\n disabled\n className=\"mr-2 size-3.5 translate-y-[2px] cursor-default appearance-none rounded-[3px] border border-og-border bg-og-surface-1 align-baseline checked:border-og-accent checked:bg-og-accent checked:[background-image:url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012%2012%22%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22white%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20d%3D%22M2.5%206.2l2.2%202.2%204.6-4.8%22%2F%3E%3C%2Fsvg%3E')] checked:bg-[length:11px_11px] checked:bg-center checked:bg-no-repeat\"\n />\n ) : (\n <input type={type} {...props} />\n ),\n blockquote: ({ children, ...props }) => (\n <blockquote\n className=\"my-3 border-l-2 border-og-border-strong pl-3.5 text-og-fg-muted [&>p]:my-1.5 first:mt-0 last:mb-0\"\n {...props}\n >\n {children}\n </blockquote>\n ),\n hr: (props) => <hr className=\"my-4 border-0 border-t border-og-border\" {...props} />,\n // Inline `code` vs fenced code blocks. react-markdown v10 no longer passes an\n // `inline` flag; a fenced block is a <code> whose parent is <pre> (styled by\n // the `pre` renderer), so a `code` reaching here is treated as inline.\n code: ({ children, className: _className, ...props }) => (\n <code\n className=\"rounded-og-xs border border-og-border bg-og-surface-1 px-1 py-0.5 font-og-mono text-[0.85em] text-og-fg\"\n {...props}\n >\n {children}\n </code>\n ),\n // Fenced code blocks — mirror the timeline's PayloadBlock <pre> styling for\n // visual consistency (bordered, scrollable, mono, surface background).\n pre: ({ children, ...props }) => (\n <pre\n className=\"my-3 max-h-96 overflow-auto rounded-og-md border border-og-border bg-og-bg/60 p-3 font-og-mono text-[12.5px] leading-5 text-og-fg-muted [&>code]:border-0 [&>code]:bg-transparent [&>code]:p-0 [&>code]:text-inherit first:mt-0 last:mb-0\"\n {...props}\n >\n {children}\n </pre>\n ),\n table: ({ children, ...props }) => (\n <div className=\"my-3 max-w-full overflow-x-auto rounded-og-md border border-og-border first:mt-0 last:mb-0\">\n <table className=\"w-full border-collapse text-[13px]\" {...props}>\n {children}\n </table>\n </div>\n ),\n thead: ({ children, ...props }) => (\n <thead className=\"bg-og-surface-1\" {...props}>\n {children}\n </thead>\n ),\n th: ({ children, ...props }) => (\n <th className=\"border-b border-og-border px-3 py-1.5 text-left font-medium text-og-fg\" {...props}>\n {children}\n </th>\n ),\n td: ({ children, ...props }) => (\n <td className=\"border-b border-og-border px-3 py-1.5 align-top text-og-fg-muted [tr:last-child>&]:border-b-0\" {...props}>\n {children}\n </td>\n ),\n img: ({ alt, ...props }) => <img alt={alt ?? \"\"} className=\"my-3 max-w-full rounded-og-md border border-og-border\" {...props} />,\n};\n\nfunction MarkdownImpl({ children, className }: MarkdownProps) {\n return (\n // `min-w-0` lets the prose shrink inside flex parents (message bubbles) so\n // long links and code blocks wrap/scroll instead of forcing overflow.\n <div className={cn(\"min-w-0 break-words\", className)}>\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>\n {children}\n </ReactMarkdown>\n </div>\n );\n}\n\n/** Memoized so streaming re-renders of the parent don't re-parse settled bodies. */\nexport const Markdown = memo(MarkdownImpl);\n","import type { SessionStatus as SessionStatusValue } from \"@opengeni/sdk\";\nimport { cn } from \"../lib/cn\";\n\nexport type SessionStatusMeta = {\n label: string;\n /** Token-backed color classes for the dot and tinted badge. */\n dotClassName: string;\n badgeClassName: string;\n /** Live states breathe; terminal states hold still. */\n pulse: boolean;\n};\n\nexport const SESSION_STATUS_META: Record<SessionStatusValue, SessionStatusMeta> = {\n queued: {\n label: \"Queued\",\n dotClassName: \"bg-og-status-queued\",\n badgeClassName: \"text-og-fg-muted border-og-border bg-og-status-queued/10\",\n pulse: true,\n },\n running: {\n label: \"Running\",\n dotClassName: \"bg-og-status-running\",\n badgeClassName: \"text-og-status-running border-og-status-running/30 bg-og-status-running/10\",\n pulse: true,\n },\n idle: {\n label: \"Idle\",\n dotClassName: \"bg-og-status-idle\",\n badgeClassName: \"text-og-status-idle border-og-status-idle/30 bg-og-status-idle/10\",\n pulse: false,\n },\n requires_action: {\n label: \"Needs you\",\n dotClassName: \"bg-og-status-waiting\",\n badgeClassName: \"text-og-status-waiting border-og-status-waiting/35 bg-og-status-waiting/10\",\n pulse: true,\n },\n failed: {\n label: \"Failed\",\n dotClassName: \"bg-og-status-failed\",\n badgeClassName: \"text-og-status-failed border-og-status-failed/35 bg-og-status-failed/10\",\n pulse: false,\n },\n cancelled: {\n label: \"Cancelled\",\n dotClassName: \"bg-og-status-cancelled\",\n badgeClassName: \"text-og-fg-subtle border-og-border bg-og-status-cancelled/10\",\n pulse: false,\n },\n};\n\nexport type SessionStatusProps = {\n status: SessionStatusValue;\n /** Override the label (\"Running\" -> \"Deploying\", ...). */\n label?: string | undefined;\n size?: \"sm\" | \"md\" | undefined;\n className?: string | undefined;\n};\n\n/** Status badge with a breathing dot for live states. */\nexport function SessionStatus({ status, label, size = \"md\", className }: SessionStatusProps) {\n const meta = SESSION_STATUS_META[status];\n return (\n <span\n data-status={status}\n className={cn(\n \"og-root inline-flex shrink-0 items-center rounded-full border font-medium\",\n size === \"sm\" ? \"gap-1 px-1.5 py-px text-[10px]\" : \"gap-1.5 px-2 py-0.5 text-xs\",\n meta.badgeClassName,\n className,\n )}\n >\n <StatusDot status={status} className={size === \"sm\" ? \"size-1\" : \"size-1.5\"} />\n {label ?? meta.label}\n </span>\n );\n}\n\nexport type StatusDotProps = {\n status: SessionStatusValue;\n className?: string | undefined;\n};\n\n/** Just the dot — for dense rows and tiles. */\nexport function StatusDot({ status, className }: StatusDotProps) {\n const meta = SESSION_STATUS_META[status];\n return (\n <span className={cn(\"relative inline-flex size-1.5 shrink-0 rounded-full\", meta.dotClassName, className)}>\n {meta.pulse ? <span className={cn(\"absolute inset-0 animate-og-pulse rounded-full\", meta.dotClassName)} /> : null}\n </span>\n );\n}\n","import type { Session } from \"@opengeni/sdk\";\nimport { cn } from \"../lib/cn\";\nimport { formatRelativeTime, truncate } from \"../lib/format\";\nimport { SessionStatus } from \"./session-status\";\n\nexport type FleetTileProps = {\n session: Session;\n /** Overrides the derived title (metadata.title/name, else the initial message). */\n title?: string | undefined;\n /** Extra line under the title — e.g. \"drift check\" or the worker's task. */\n subtitle?: string | undefined;\n onOpen?: ((session: Session) => void) | undefined;\n className?: string | undefined;\n};\n\n/** Best-effort display title for a session. */\nexport function sessionDisplayTitle(session: Session): string {\n for (const key of [\"title\", \"name\"] as const) {\n const value = session.metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return truncate(session.initialMessage, 100) || session.id.slice(0, 8);\n}\n\n/**\n * One session in the fleet/manager view: title, live status, model, and\n * recency — dense but calm. Running sessions carry a breathing status dot\n * and a faint accent edge so the live ones read at a glance.\n */\nexport function FleetTile({ session, title, subtitle, onOpen, className }: FleetTileProps) {\n const running = session.status === \"running\" || session.status === \"queued\";\n const needsYou = session.status === \"requires_action\";\n return (\n <button\n type=\"button\"\n data-status={session.status}\n onClick={onOpen ? () => onOpen(session) : undefined}\n disabled={!onOpen}\n className={cn(\n \"og-root group relative flex w-full flex-col gap-2.5 overflow-hidden rounded-og-lg border border-og-border\",\n \"bg-og-surface-1 p-4 text-left shadow-og-sm\",\n \"transition-[border-color,background-color,box-shadow,transform] duration-200 ease-og-out\",\n onOpen && \"hover:-translate-y-px hover:border-og-border-strong hover:bg-og-surface-2 hover:shadow-og-md\",\n \"disabled:cursor-default\",\n className,\n )}\n >\n <span\n aria-hidden\n className={cn(\n \"absolute inset-y-0 left-0 w-0.5 transition-opacity duration-300\",\n running ? \"bg-og-accent opacity-100\" : needsYou ? \"bg-og-status-waiting opacity-100\" : \"opacity-0\",\n )}\n />\n <span className=\"flex w-full items-start justify-between gap-3\">\n <span className=\"line-clamp-2 min-w-0 text-sm font-medium leading-snug text-og-fg\">{title ?? sessionDisplayTitle(session)}</span>\n <SessionStatus status={session.status} size=\"sm\" className=\"mt-px\" />\n </span>\n {subtitle ? <span className=\"line-clamp-1 text-xs text-og-fg-muted\">{subtitle}</span> : null}\n <span className=\"mt-auto flex w-full items-center gap-2 text-[11px] text-og-fg-subtle\">\n <span className=\"font-og-mono\">{session.id.slice(0, 8)}</span>\n <span aria-hidden>·</span>\n <span className=\"truncate\">{session.model}</span>\n <span className=\"ml-auto shrink-0\" title={session.updatedAt}>\n {formatRelativeTime(session.updatedAt)}\n </span>\n </span>\n </button>\n );\n}\n"],"mappings":"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","names":["useCallback","useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useEffect","useMemo","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","useCallback","useState","useState","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useMemo","useRef","useState","useState","useRef","useMemo","useCallback","errorMessage","options","jsx","AnimatePresence","motion","useCallback","useEffect","useId","useMemo","useRef","useState","useMemo","jsx","jsxs","useMemo","jsx","jsxs","useRef","useState","useCallback","useId","useEffect","useMemo","AnimatePresence","motion","AnimatePresence","motion","useEffect","useMemo","useRef","useState","jsx","jsx","jsxs","Fragment","jsx","jsxs","useMemo","useRef","useState","useEffect","AnimatePresence","motion","jsx","jsxs"]}