@rizom/brain 0.2.0-alpha.383 → 0.2.0-alpha.384
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/brain.js +36 -36
- package/dist/chunks/{app-7z5e3c7s.js → app-zn0wshdg.js} +2 -2
- package/dist/chunks/{index-ymrghn05.js → index-fe19h0ey.js} +3 -3
- package/dist/chunks/{index-ymrghn05.js.map → index-fe19h0ey.js.map} +1 -1
- package/dist/chunks/{index-ccy24bdp.js → index-q8rrvgdf.js} +2 -2
- package/dist/chunks/{index-3dz3sh65.js → index-y41e244y.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/model.js +37 -37
- package/dist/model.js.map +2 -2
- package/dist/ui/studio-app.css +32 -18
- package/dist/ui/studio-app.js +3 -3
- package/dist/ui/studio-app.js.map +1 -1
- package/dist/ui/studio-asset-manifest.json +16 -16
- package/dist/ui/studio-chunks/account-view-811dnmr7.js +3 -0
- package/dist/ui/studio-chunks/{account-view-4544h367.js.map → account-view-811dnmr7.js.map} +2 -2
- package/dist/ui/studio-chunks/{highlighted-body-OFNGDK62-1w01z27m.js → highlighted-body-OFNGDK62-kw57xp1t.js} +2 -2
- package/dist/ui/studio-chunks/{highlighted-body-OFNGDK62-1w01z27m.js.map → highlighted-body-OFNGDK62-kw57xp1t.js.map} +1 -1
- package/dist/ui/studio-chunks/{main-1gqf08r8.js → main-53ha0ekw.js} +18 -18
- package/dist/ui/studio-chunks/{main-1gqf08r8.js.map → main-53ha0ekw.js.map} +4 -7
- package/dist/ui/studio-chunks/{main-b34wmcw1.js → main-g0bad58x.js} +4 -4
- package/dist/ui/studio-chunks/{main-b34wmcw1.js.map → main-g0bad58x.js.map} +1 -1
- package/dist/ui/studio-chunks/main-g6b89p15.js +7 -0
- package/dist/ui/studio-chunks/{main-ptks77cs.js.map → main-g6b89p15.js.map} +3 -3
- package/dist/ui/studio-chunks/main-me847330.js +50 -0
- package/dist/ui/studio-chunks/{main-vzjqx8f9.js.map → main-me847330.js.map} +6 -3
- package/dist/ui/studio-chunks/mermaid-GHXKKRXX-hqacyqmt.js +3 -0
- package/dist/ui/studio-chunks/{mermaid-GHXKKRXX-ftrk50mv.js.map → mermaid-GHXKKRXX-hqacyqmt.js.map} +1 -1
- package/dist/ui/studio-chunks/studio-chat-workspace-hmkhk808.js +5 -0
- package/dist/ui/studio-chunks/studio-chat-workspace-hmkhk808.js.map +20 -0
- package/package.json +1 -1
- package/dist/ui/studio-chunks/account-view-4544h367.js +0 -3
- package/dist/ui/studio-chunks/main-ptks77cs.js +0 -7
- package/dist/ui/studio-chunks/main-vzjqx8f9.js +0 -50
- package/dist/ui/studio-chunks/mermaid-GHXKKRXX-ftrk50mv.js +0 -3
- package/dist/ui/studio-chunks/studio-chat-workspace-kpfmp85b.js +0 -5
- package/dist/ui/studio-chunks/studio-chat-workspace-kpfmp85b.js.map +0 -21
- /package/dist/chunks/{app-7z5e3c7s.js.map → app-zn0wshdg.js.map} +0 -0
- /package/dist/chunks/{index-ccy24bdp.js.map → index-q8rrvgdf.js.map} +0 -0
- /package/dist/chunks/{index-3dz3sh65.js.map → index-y41e244y.js.map} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../ui-react/src/studio-chat-attachment.tsx", "../../../../shared/contracts/src/agent-action.ts", "../../../../shared/contracts/src/entity-read.ts", "../../../../shared/contracts/src/guest-execution.ts", "../../../../shared/contracts/src/chat.ts", "../../../../shell/plugins/src/message-interface/artifact-display.ts", "../../ui-react/src/studio-chat-layout.styles.ts", "../../ui-react/src/studio-chat-session-rename.tsx", "../../../../shell/plugins/src/message-interface/upload-policy.ts", "../../ui-react/src/studio-chat-workspace.tsx", "../../ui-react/src/chat-workspace-model.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { useRef, useState, type ReactElement } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport {\n ChatApiError,\n type ChatCard,\n type ChatClient,\n} from \"@brains/contracts/chat\";\nimport {\n getArtifactCardState,\n narrowArtifactJobStatus,\n} from \"@brains/plugins/message-interface/artifact-display\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogTitle,\n} from \"@brains/app-ui-react\";\nimport { chatClass, chatLayout } from \"./studio-chat-layout.styles\";\n\nexport function StudioChatAttachment(props: {\n card: Extract<ChatCard, { kind: \"attachment\" }>;\n client: ChatClient;\n}): ReactElement {\n const { card, client } = props;\n const job = useQuery({\n queryKey: [\n \"studio\",\n \"chat\",\n \"attachment-job\",\n client.paths.jobStatus,\n card.jobId,\n ],\n queryFn: () => client.getJobStatus(card.jobId ?? \"\"),\n enabled: Boolean(card.jobId),\n retry: false,\n refetchInterval: (query) =>\n query.state.data?.status === \"pending\" ||\n query.state.data?.status === \"processing\"\n ? 2000\n : false,\n });\n const missingJob =\n job.error instanceof ChatApiError && job.error.status === 404;\n const statusUnavailable = job.isError && !missingJob;\n const state = getArtifactCardState(\n card.jobId ? narrowArtifactJobStatus(job.data?.status) : null,\n );\n // A missing historical job must not hide a durable file. Its own GET still\n // enforces access and the preview has an explicit loading-error fallback.\n const available =\n !card.jobId ||\n missingJob ||\n (!job.isError &&\n job.data !== undefined &&\n (state.status === \"completed\" || state.status === \"unknown\"));\n const previewUrl = card.attachment.previewUrl ?? card.attachment.url;\n const [failedPreview, setFailedPreview] = useState<string | null>(null);\n const [imageOpen, setImageOpen] = useState(false);\n const [failedFullImage, setFailedFullImage] = useState<string | null>(null);\n const previewTrigger = useRef<HTMLButtonElement>(null);\n const label = statusUnavailable\n ? \"Status unavailable\"\n : card.jobId && job.isPending\n ? \"Checking generation status\"\n : state.label;\n\n return (\n <section\n className={chatClass(\"studio-chat-card\", chatLayout.card)}\n aria-label={card.title}\n >\n <span className={chatClass(\"studio-chat-card-kicker\", chatLayout.kicker)}>\n Artifact\n </span>\n <strong>{card.title}</strong>\n <span\n role=\"status\"\n className={chatClass(\n \"studio-chat-card-description\",\n chatLayout.cardText,\n )}\n >\n {label}\n </span>\n {card.description ? (\n <p\n className={chatClass(\n \"studio-chat-card-description\",\n chatLayout.cardText,\n )}\n >\n {card.description}\n </p>\n ) : null}\n {available && card.attachment.mediaType.startsWith(\"image/\") ? (\n failedPreview === previewUrl ? (\n <p role=\"status\">\n Image preview unavailable. You can still open or download the file.\n </p>\n ) : (\n <button\n ref={previewTrigger}\n type=\"button\"\n aria-label={`Enlarge ${card.title}`}\n className={chatClass(\n \"studio-chat-image-trigger\",\n chatLayout.imageTrigger,\n )}\n onClick={() => setImageOpen(true)}\n >\n <img\n className={chatClass(\n \"studio-chat-attachment-preview\",\n chatLayout.attachmentPreview,\n )}\n src={previewUrl}\n alt={card.title}\n loading=\"lazy\"\n onError={() => setFailedPreview(previewUrl)}\n />\n </button>\n )\n ) : null}\n {available ? (\n <div\n className={chatClass(\"studio-chat-card-actions\", chatLayout.actions)}\n >\n <a\n className={chatClass(\"studio-chat-card-action\", chatLayout.button)}\n href={card.attachment.url}\n >\n Open\n </a>\n <a\n className={chatClass(\"studio-chat-card-action\", chatLayout.button)}\n href={card.attachment.downloadUrl ?? card.attachment.url}\n download={card.attachment.filename ?? true}\n >\n Download\n </a>\n </div>\n ) : null}\n <Dialog open={imageOpen && available} onOpenChange={setImageOpen}>\n <DialogContent\n aria-describedby={undefined}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n previewTrigger.current?.focus();\n }}\n >\n <DialogTitle>{card.title}</DialogTitle>\n {failedFullImage === card.attachment.url ? (\n <p role=\"status\">\n Image unavailable. You can still try opening or downloading the\n file.\n </p>\n ) : (\n <img\n className={chatClass(\n \"studio-chat-full-image\",\n chatLayout.fullImage,\n )}\n src={card.attachment.url}\n alt={card.title}\n onError={() => setFailedFullImage(card.attachment.url)}\n />\n )}\n <a\n href={card.attachment.downloadUrl ?? card.attachment.url}\n download={card.attachment.filename ?? true}\n >\n Download image\n </a>\n </DialogContent>\n </Dialog>\n {statusUnavailable ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void job.refetch()}\n >\n Check status\n </Button>\n ) : null}\n </section>\n );\n}\n",
|
|
6
|
+
"import { z } from \"@brains/utils/zod\";\n\nexport const AGENT_ACTION_REQUEST_CHANNEL = \"agent:action:request\";\n\ntype AgentEventActionSchema = z.ZodObject<{\n type: z.ZodLiteral<\"event\">;\n event: z.ZodString;\n fromState: z.ZodOptional<z.ZodString>;\n}>;\n\nexport const agentEventActionSchema: AgentEventActionSchema = z.object({\n type: z.literal(\"event\"),\n event: z.string().min(1),\n /** State id the action was rendered for; lets handlers reject stale events. */\n fromState: z.string().min(1).optional(),\n});\n\nexport type AgentEventAction = z.output<typeof agentEventActionSchema>;\n\ntype AgentActionRequestSchema = z.ZodObject<{\n conversationId: z.ZodString;\n interfaceType: z.ZodString;\n channelId: z.ZodOptional<z.ZodString>;\n channelName: z.ZodString;\n userPermissionLevel: z.ZodEnum<{\n admin: \"admin\";\n trusted: \"trusted\";\n public: \"public\";\n }>;\n isAnchor: z.ZodBoolean;\n action: AgentEventActionSchema;\n}>;\n\nexport const agentActionRequestSchema: AgentActionRequestSchema = z.object({\n conversationId: z.string().min(1),\n interfaceType: z.string().min(1),\n channelId: z.string().min(1).optional(),\n channelName: z.string().min(1),\n userPermissionLevel: z.enum([\"admin\", \"trusted\", \"public\"]),\n isAnchor: z.boolean(),\n action: agentEventActionSchema,\n});\n\nexport type AgentActionRequest = z.output<typeof agentActionRequestSchema>;\n",
|
|
7
|
+
"import { z } from \"@brains/utils/zod\";\n\n/** Per-query transfer bounds. These do not promise a database execution deadline\n * or bound plugin parser work; callers must separately account for those costs.\n */\nexport const entityReadBudgetSchema: z.ZodObject<\n {\n rows: z.ZodNumber;\n rowBytes: z.ZodNumber;\n queryCharacters: z.ZodNumber;\n },\n z.core.$strict\n> = z.strictObject({\n rows: z.number().int().positive(),\n rowBytes: z.number().int().positive(),\n queryCharacters: z.number().int().positive(),\n});\nexport type EntityReadBudget = z.output<typeof entityReadBudgetSchema>;\n\n/** Server-owned query embedding capability; never accepted from JSON tool input. */\nexport type QueryEmbedding = (\n query: string,\n signal: AbortSignal,\n) => Promise<Float32Array>;\n",
|
|
8
|
+
"import { z } from \"@brains/utils/zod\";\nimport { entityReadBudgetSchema } from \"./entity-read\";\n\ntype Strict<Shape extends z.ZodRawShape> = z.ZodObject<Shape, z.core.$strict>;\n\n/** Server-owned limits, not a browser's requested model settings. */\nexport const guestExecutionLimitsSchema: Strict<{\n messageCharacters: z.ZodNumber;\n outputTokens: z.ZodNumber;\n contextTokens: z.ZodNumber;\n contextBytes: z.ZodNumber;\n toolSteps: z.ZodNumber;\n toolCalls: z.ZodNumber;\n toolResultCharacters: z.ZodNumber;\n retrieval: typeof entityReadBudgetSchema;\n requestTimeoutSeconds: z.ZodNumber;\n}> = z.strictObject({\n messageCharacters: z.number().int().positive(),\n outputTokens: z.number().int().positive(),\n contextTokens: z.number().int().positive(),\n contextBytes: z.number().int().positive(),\n toolSteps: z.number().int().positive(),\n toolCalls: z.number().int().positive(),\n toolResultCharacters: z.number().int().positive(),\n retrieval: entityReadBudgetSchema,\n requestTimeoutSeconds: z.number().int().positive().max(2_147_483),\n});\n\nexport const guestExecutionPolicySchema: Strict<{\n limits: typeof guestExecutionLimitsSchema;\n maxCostMicroUsd: z.ZodNumber;\n}> = z.strictObject({\n limits: guestExecutionLimitsSchema,\n maxCostMicroUsd: z.number().int().positive(),\n});\nexport type GuestExecutionPolicy = z.output<typeof guestExecutionPolicySchema>;\n",
|
|
9
|
+
"import { z } from \"@brains/utils/zod\";\nimport { agentEventActionSchema, type AgentEventAction } from \"./agent-action\";\n\nexport {\n guestExecutionLimitsSchema,\n guestExecutionPolicySchema,\n type GuestExecutionPolicy,\n} from \"./guest-execution\";\n\nexport const CHAT_API_VERSION = 1 as const;\nexport const DEFAULT_CHAT_API_PATH = \"/api/chat\" as const;\n/** Server-owned conversation scope; never derive it from browser role claims. */\nexport const guestInterfaceType = \"web-chat-guest\";\n\ntype Loose<Shape extends z.ZodRawShape> = z.ZodObject<Shape, z.core.$loose>;\ntype Strict<Shape extends z.ZodRawShape> = z.ZodObject<Shape, z.core.$strict>;\n\n/** Pinned when a guest conversation is created; reads cannot renew retention. */\nexport const guestRetentionSchema: Strict<{\n idleSeconds: z.ZodNumber;\n maxAgeSeconds: z.ZodNumber;\n}> = z\n .strictObject({\n idleSeconds: z\n .number()\n .int()\n .positive()\n .max(Math.floor(Number.MAX_SAFE_INTEGER / 1000)),\n maxAgeSeconds: z\n .number()\n .int()\n .positive()\n .max(Math.floor(Number.MAX_SAFE_INTEGER / 1000)),\n })\n .refine(\n (retention) => retention.idleSeconds <= retention.maxAgeSeconds,\n \"Guest idle expiry must not exceed maximum age\",\n );\n\nexport const guestConversationOwnershipSchema: Strict<{\n visitorId: z.ZodString;\n retention: typeof guestRetentionSchema;\n}> = z.strictObject({\n visitorId: z.string().uuid(),\n retention: guestRetentionSchema,\n});\nexport type GuestConversationOwnership = z.output<\n typeof guestConversationOwnershipSchema\n>;\n\nconst chatIdSchema: z.ZodString = z.string().trim().min(1).max(256);\n/** Present on guest send/status responses; it is a locator, never authority. */\nexport const CHAT_CONVERSATION_ID_HEADER = \"x-brain-conversation-id\";\n\nexport const guestChatSessionResponseSchema: Strict<{\n expiresAt: z.ZodNumber;\n provider: z.ZodString;\n notice: z.ZodString;\n deletionLimitations: z.ZodString;\n retention: typeof guestRetentionSchema;\n messageCharacters: z.ZodNumber;\n canSend: z.ZodBoolean;\n}> = z.strictObject({\n expiresAt: z.number().int().positive(),\n provider: z.string().min(1),\n notice: z.string().min(1),\n deletionLimitations: z.string().min(1),\n retention: guestRetentionSchema,\n messageCharacters: z.number().int().positive(),\n canSend: z.boolean(),\n});\nexport type GuestChatSessionResponse = z.output<\n typeof guestChatSessionResponseSchema\n>;\n\nexport const guestChatSubmissionStatusSchema: Strict<{\n conversationId: z.ZodString;\n state: z.ZodEnum<{\n active: \"active\";\n completed: \"completed\";\n failed: \"failed\";\n interrupted: \"interrupted\";\n uncertain: \"uncertain\";\n }>;\n}> = z.strictObject({\n conversationId: chatIdSchema,\n state: z.enum([\"active\", \"completed\", \"failed\", \"interrupted\", \"uncertain\"]),\n});\nexport type GuestChatSubmissionStatus = z.output<\n typeof guestChatSubmissionStatusSchema\n>;\n\nconst chatUploadIdSchema: z.ZodString = z\n .string()\n .regex(\n /^upload-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n );\nconst chatTitleSchema: z.ZodString = z.string().trim().min(1).max(48);\nconst chatTimestampSchema: z.ZodString = z.string().datetime();\nconst chatRelativeUrlSchema: z.ZodString = z\n .string()\n .regex(/^\\/(?!\\/)/)\n .max(2_048);\nconst chatLinkUrlSchema: z.ZodString = z\n .string()\n .regex(/^(?:\\/(?!\\/)|https?:\\/\\/)/)\n .max(2_048);\n\nconst chatToolApprovalCardSchema: Loose<{\n kind: z.ZodLiteral<\"tool-approval\">;\n id: z.ZodString;\n toolCallId: z.ZodOptional<z.ZodString>;\n toolName: z.ZodString;\n input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n summary: z.ZodString;\n completionSummary: z.ZodOptional<z.ZodString>;\n preview: z.ZodOptional<z.ZodString>;\n state: z.ZodEnum<{\n \"approval-requested\": \"approval-requested\";\n \"approval-responded\": \"approval-responded\";\n \"output-available\": \"output-available\";\n \"output-denied\": \"output-denied\";\n \"output-error\": \"output-error\";\n }>;\n output: z.ZodOptional<z.ZodUnknown>;\n error: z.ZodOptional<z.ZodString>;\n}> = z.looseObject({\n kind: z.literal(\"tool-approval\"),\n id: chatIdSchema,\n toolCallId: chatIdSchema.optional(),\n toolName: z.string().trim().min(1).max(256),\n input: z.record(z.string(), z.unknown()).optional(),\n summary: z.string().max(4_096),\n completionSummary: z.string().max(4_096).optional(),\n preview: z.string().max(100_000).optional(),\n state: z.enum([\n \"approval-requested\",\n \"approval-responded\",\n \"output-available\",\n \"output-denied\",\n \"output-error\",\n ]),\n output: z.unknown().optional(),\n error: z.string().max(4_096).optional(),\n});\n\nconst chatAttachmentCardSourceSchema: Loose<{\n entityType: z.ZodOptional<z.ZodString>;\n entityId: z.ZodOptional<z.ZodString>;\n attachmentType: z.ZodOptional<z.ZodString>;\n}> = z.looseObject({\n entityType: z.string().trim().min(1).max(128).optional(),\n entityId: chatIdSchema.optional(),\n attachmentType: z.string().trim().min(1).max(128).optional(),\n});\n\nconst chatAttachmentCardDataSchema: Loose<{\n mediaType: z.ZodString;\n url: z.ZodString;\n downloadUrl: z.ZodOptional<z.ZodString>;\n previewUrl: z.ZodOptional<z.ZodString>;\n filename: z.ZodOptional<z.ZodString>;\n sizeBytes: z.ZodOptional<z.ZodNumber>;\n source: z.ZodOptional<typeof chatAttachmentCardSourceSchema>;\n}> = z.looseObject({\n mediaType: z.string().trim().min(1).max(255),\n url: chatLinkUrlSchema,\n downloadUrl: chatLinkUrlSchema.optional(),\n previewUrl: chatLinkUrlSchema.optional(),\n filename: z.string().trim().min(1).max(255).optional(),\n sizeBytes: z.number().int().nonnegative().optional(),\n source: chatAttachmentCardSourceSchema.optional(),\n});\n\nconst chatAttachmentCardSchema: Loose<{\n kind: z.ZodLiteral<\"attachment\">;\n id: z.ZodString;\n jobId: z.ZodOptional<z.ZodString>;\n title: z.ZodString;\n description: z.ZodOptional<z.ZodString>;\n attachment: typeof chatAttachmentCardDataSchema;\n}> = z.looseObject({\n kind: z.literal(\"attachment\"),\n id: chatIdSchema,\n jobId: chatIdSchema.optional(),\n title: z.string().max(4_096),\n description: z.string().max(20_000).optional(),\n attachment: chatAttachmentCardDataSchema,\n});\n\nconst chatSourceCitationSchema: Loose<{\n id: z.ZodString;\n title: z.ZodOptional<z.ZodString>;\n source: z.ZodString;\n url: z.ZodOptional<z.ZodString>;\n entityType: z.ZodOptional<z.ZodString>;\n entityId: z.ZodOptional<z.ZodString>;\n excerpt: z.ZodOptional<z.ZodString>;\n provenance: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n}> = z.looseObject({\n id: chatIdSchema,\n title: z.string().max(4_096).optional(),\n source: z.string().trim().min(1).max(512),\n url: chatLinkUrlSchema.optional(),\n entityType: z.string().trim().min(1).max(128).optional(),\n entityId: chatIdSchema.optional(),\n excerpt: z.string().max(20_000).optional(),\n provenance: z.record(z.string(), z.unknown()).optional(),\n});\n\nconst chatSourcesCardSchema: Loose<{\n kind: z.ZodLiteral<\"sources\">;\n id: z.ZodString;\n title: z.ZodOptional<z.ZodString>;\n sources: z.ZodArray<typeof chatSourceCitationSchema>;\n}> = z.looseObject({\n kind: z.literal(\"sources\"),\n id: chatIdSchema,\n title: z.string().max(4_096).optional(),\n sources: z.array(chatSourceCitationSchema).min(1).max(100),\n});\n\nconst chatSuggestedActionSchema: z.ZodDiscriminatedUnion<\n [\n z.ZodObject<{\n type: z.ZodLiteral<\"prompt\">;\n id: z.ZodString;\n label: z.ZodString;\n prompt: z.ZodString;\n description: z.ZodOptional<z.ZodString>;\n }>,\n z.ZodObject<{\n type: z.ZodLiteral<\"event\">;\n id: z.ZodString;\n label: z.ZodString;\n event: z.ZodString;\n fromState: z.ZodOptional<z.ZodString>;\n description: z.ZodOptional<z.ZodString>;\n }>,\n ],\n \"type\"\n> = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"prompt\"),\n id: chatIdSchema,\n label: z.string().trim().min(1).max(256),\n prompt: z.string().min(1).max(100_000),\n description: z.string().max(4_096).optional(),\n }),\n z.object({\n type: z.literal(\"event\"),\n id: chatIdSchema,\n label: z.string().trim().min(1).max(256),\n event: z.string().trim().min(1).max(256),\n fromState: z.string().trim().min(1).max(256).optional(),\n description: z.string().max(4_096).optional(),\n }),\n]);\n\nconst chatActionsCardSchema: Loose<{\n kind: z.ZodLiteral<\"actions\">;\n id: z.ZodString;\n title: z.ZodOptional<z.ZodString>;\n actions: z.ZodArray<typeof chatSuggestedActionSchema>;\n}> = z.looseObject({\n kind: z.literal(\"actions\"),\n id: chatIdSchema,\n title: z.string().max(4_096).optional(),\n actions: z.array(chatSuggestedActionSchema).min(1).max(100),\n});\n\nexport const chatCardSchema: z.ZodDiscriminatedUnion<\n [\n typeof chatToolApprovalCardSchema,\n typeof chatAttachmentCardSchema,\n typeof chatSourcesCardSchema,\n typeof chatActionsCardSchema,\n ],\n \"kind\"\n> = z.discriminatedUnion(\"kind\", [\n chatToolApprovalCardSchema,\n chatAttachmentCardSchema,\n chatSourcesCardSchema,\n chatActionsCardSchema,\n]);\n\nexport type ChatCard = z.output<typeof chatCardSchema>;\n\n/** Presentation projection, not authorization: callers must use guest-scoped\n * runtime results or owned guest history. Never pass arbitrary operator cards. */\nexport function getGuestSourceCards(\n value: unknown,\n): Extract<ChatCard, { kind: \"sources\" }>[] {\n if (!Array.isArray(value)) return [];\n const sources: Extract<ChatCard, { kind: \"sources\" }>[\"sources\"] = [];\n const seen = new Set<string>();\n for (const candidate of value.slice(0, 10)) {\n const parsed = chatSourcesCardSchema.safeParse(candidate);\n if (!parsed.success || parsed.data.id !== \"sources:tool-results\") continue;\n for (const source of parsed.data.sources) {\n if (sources.length >= 15) break;\n if (\n !source.entityType ||\n !source.entityId ||\n source.entityId.length > 256 ||\n source.source !== source.entityType ||\n source.id !== `${source.entityType}:${source.entityId}` ||\n seen.has(source.id)\n )\n continue;\n seen.add(source.id);\n let url: string | undefined;\n if (source.url && source.url.length <= 512) {\n try {\n const parsedUrl = new URL(source.url);\n if (\n parsedUrl.protocol === \"https:\" &&\n !parsedUrl.username &&\n !parsedUrl.password &&\n parsedUrl.href.length <= 512\n )\n url = parsedUrl.href;\n } catch {\n // An untrusted URL must not turn a citation into navigation authority.\n }\n }\n sources.push({\n id: source.id,\n source: source.entityType,\n entityType: source.entityType,\n entityId: source.entityId,\n title: (source.title ?? source.entityId).slice(0, 160),\n ...(source.excerpt ? { excerpt: source.excerpt.slice(0, 280) } : {}),\n ...(url ? { url } : {}),\n });\n }\n }\n return sources.length\n ? [\n {\n kind: \"sources\",\n id: \"sources:tool-results\",\n title: \"Retrieved sources\",\n sources,\n },\n ]\n : [];\n}\n\nexport type ChatEventAction = AgentEventAction;\nexport const chatEventActionSchema: typeof agentEventActionSchema =\n agentEventActionSchema;\n\nconst chatPendingConfirmationSchema: z.ZodObject<{\n id: z.ZodString;\n toolCallId: z.ZodOptional<z.ZodString>;\n toolName: z.ZodString;\n summary: z.ZodString;\n completionSummary: z.ZodOptional<z.ZodString>;\n preview: z.ZodOptional<z.ZodString>;\n args: z.ZodUnknown;\n}> = z.object({\n id: chatIdSchema,\n toolCallId: chatIdSchema.optional(),\n toolName: z.string().trim().min(1).max(256),\n summary: z.string().max(4_096),\n completionSummary: z.string().max(4_096).optional(),\n preview: z.string().max(100_000).optional(),\n args: z.unknown(),\n});\n\nconst chatToolResultSchema: z.ZodObject<{\n toolName: z.ZodString;\n args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n jobId: z.ZodOptional<z.ZodString>;\n data: z.ZodOptional<z.ZodUnknown>;\n error: z.ZodOptional<\n z.ZodObject<{\n message: z.ZodString;\n code: z.ZodOptional<z.ZodString>;\n }>\n >;\n}> = z.object({\n toolName: z.string().trim().min(1).max(256),\n args: z.record(z.string(), z.unknown()).optional(),\n jobId: chatIdSchema.optional(),\n data: z.unknown().optional(),\n error: z\n .object({\n message: z.string().max(4_096),\n code: z.string().trim().min(1).max(256).optional(),\n })\n .optional(),\n});\n\nexport const chatActionResponseSchema: Loose<{\n text: z.ZodString;\n toolResults: z.ZodOptional<z.ZodArray<typeof chatToolResultSchema>>;\n cards: z.ZodOptional<z.ZodArray<typeof chatCardSchema>>;\n pendingConfirmations: z.ZodOptional<\n z.ZodArray<typeof chatPendingConfirmationSchema>\n >;\n usage: z.ZodObject<{\n promptTokens: z.ZodNumber;\n completionTokens: z.ZodNumber;\n totalTokens: z.ZodNumber;\n }>;\n}> = z.looseObject({\n text: z.string().max(1_000_000),\n toolResults: z.array(chatToolResultSchema).max(100).optional(),\n cards: z.array(chatCardSchema).max(100).optional(),\n pendingConfirmations: z\n .array(chatPendingConfirmationSchema)\n .max(100)\n .optional(),\n usage: z.object({\n promptTokens: z.number().int().nonnegative(),\n completionTokens: z.number().int().nonnegative(),\n totalTokens: z.number().int().nonnegative(),\n }),\n});\n\nexport type ChatActionResponse = z.output<typeof chatActionResponseSchema>;\n\nexport interface ChatApiPaths {\n stream: string;\n actions: string;\n sessions: string;\n sessionArchive: string;\n messages: string;\n uploads: string;\n contextSessions: string;\n documentAttachments: string;\n imageAttachments: string;\n jobStatus: string;\n}\n\nexport function createChatApiPaths(\n apiPath: string = DEFAULT_CHAT_API_PATH,\n): ChatApiPaths {\n const normalized = normalizeChatApiPath(apiPath);\n return {\n stream: normalized,\n actions: `${normalized}/actions`,\n sessions: `${normalized}/sessions`,\n sessionArchive: `${normalized}/sessions/archive`,\n messages: `${normalized}/messages`,\n uploads: `${normalized}/uploads`,\n contextSessions: `${normalized}/context-sessions`,\n documentAttachments: `${normalized}/attachments/document`,\n imageAttachments: `${normalized}/attachments/image`,\n jobStatus: `${normalized}/jobs/status`,\n };\n}\n\nfunction normalizeChatApiPath(apiPath: string): string {\n const trimmed = apiPath.trim();\n if (\n !trimmed.startsWith(\"/\") ||\n trimmed.startsWith(\"//\") ||\n trimmed.length > 512 ||\n /[\\s\"'<>\\\\]/u.test(trimmed) ||\n trimmed.includes(\"?\") ||\n trimmed.includes(\"#\")\n ) {\n throw new Error(\n \"Chat API path must be a same-origin absolute path without query or fragment\",\n );\n }\n const normalized = trimmed.replace(/\\/+$/, \"\");\n if (normalized.length === 0) {\n throw new Error(\"Chat API path must not be the site root\");\n }\n return normalized;\n}\n\nexport const chatContextHandoffRequestSchema: Strict<{\n version: z.ZodLiteral<1>;\n sourceId: z.ZodString;\n itemId: z.ZodString;\n titleSeed: z.ZodString;\n}> = z.strictObject({\n version: z.literal(1),\n sourceId: z\n .string()\n .trim()\n .regex(/^[a-z][a-z0-9-]*$/)\n .max(64),\n itemId: z.string().trim().min(1).max(300),\n titleSeed: z\n .string()\n .trim()\n .min(1)\n .max(160)\n .refine((value) => !/[\\p{Cc}\\p{Cf}]/u.test(value)),\n});\n\nexport type ChatContextHandoffRequest = z.output<\n typeof chatContextHandoffRequestSchema\n>;\n\nexport const chatSessionListQuerySchema: z.ZodObject<{\n query: z.ZodDefault<z.ZodString>;\n archived: z.ZodDefault<z.ZodBoolean>;\n offset: z.ZodDefault<z.ZodNumber>;\n limit: z.ZodDefault<z.ZodNumber>;\n}> = z.object({\n query: z.string().trim().max(200).default(\"\"),\n archived: z.boolean().default(false),\n offset: z\n .number()\n .int()\n .nonnegative()\n .max(Number.MAX_SAFE_INTEGER)\n .default(0),\n limit: z.number().int().min(1).max(100).default(25),\n});\nexport type ChatSessionListQuery = z.input<typeof chatSessionListQuerySchema>;\n\nexport const chatSessionSchema: Loose<{\n id: z.ZodString;\n title: z.ZodString;\n lastActiveAt: z.ZodString;\n archived: z.ZodOptional<z.ZodBoolean>;\n contextHandoff: z.ZodOptional<typeof chatContextHandoffRequestSchema>;\n}> = z.looseObject({\n id: chatIdSchema,\n title: chatTitleSchema,\n lastActiveAt: chatTimestampSchema,\n archived: z.boolean().optional(),\n contextHandoff: chatContextHandoffRequestSchema.optional(),\n});\n\nexport type ChatSession = z.output<typeof chatSessionSchema>;\n\nexport const chatSessionsResponseSchema: Loose<{\n sessions: z.ZodArray<typeof chatSessionSchema>;\n}> = z.looseObject({\n sessions: z.array(chatSessionSchema).max(100),\n});\n\nexport type ChatSessionsResponse = z.output<typeof chatSessionsResponseSchema>;\n\nexport const chatHistoryAttachmentSourceSchema: Loose<{\n kind: z.ZodString;\n id: z.ZodString;\n}> = z.looseObject({\n kind: z.string().trim().min(1).max(64),\n id: chatIdSchema,\n});\n\nexport type ChatHistoryAttachmentSource = z.output<\n typeof chatHistoryAttachmentSourceSchema\n>;\n\nexport const chatHistoryAttachmentSchema: Loose<{\n kind: z.ZodLiteral<\"text\">;\n filename: z.ZodString;\n mediaType: z.ZodString;\n sizeBytes: z.ZodNumber;\n createdAt: z.ZodString;\n source: z.ZodOptional<typeof chatHistoryAttachmentSourceSchema>;\n}> = z.looseObject({\n kind: z.literal(\"text\"),\n filename: z.string().trim().min(1).max(255),\n mediaType: z.string().trim().min(1).max(255),\n sizeBytes: z.number().int().nonnegative(),\n createdAt: chatTimestampSchema,\n source: chatHistoryAttachmentSourceSchema.optional(),\n});\n\nexport type ChatHistoryAttachment = z.output<\n typeof chatHistoryAttachmentSchema\n>;\n\nexport const chatHistoryMessageSchema: Loose<{\n id: z.ZodString;\n role: z.ZodEnum<{ user: \"user\"; assistant: \"assistant\" }>;\n content: z.ZodString;\n attachments: z.ZodOptional<z.ZodArray<typeof chatHistoryAttachmentSchema>>;\n cards: z.ZodOptional<z.ZodArray<typeof chatCardSchema>>;\n}> = z.looseObject({\n id: chatIdSchema,\n role: z.enum([\"user\", \"assistant\"]),\n content: z.string().max(1_000_000),\n attachments: z.array(chatHistoryAttachmentSchema).max(100).optional(),\n cards: z.array(chatCardSchema).max(100).optional(),\n});\n\nexport type ChatHistoryMessage = z.output<typeof chatHistoryMessageSchema>;\n\nexport const chatMessagesResponseSchema: Loose<{\n messages: z.ZodArray<typeof chatHistoryMessageSchema>;\n}> = z.looseObject({\n messages: z.array(chatHistoryMessageSchema).max(100),\n});\n\nexport type ChatMessagesResponse = z.output<typeof chatMessagesResponseSchema>;\n\n/** Read-only guest history plus the exact submission's existing receipt. */\nexport const guestChatSubmissionIdSchema: z.ZodString = z\n .string()\n .min(1)\n .max(256)\n .refine((value) => value.trim().length > 0);\nexport const guestChatHistoryResponseSchema: Strict<{\n messages: z.ZodArray<typeof chatHistoryMessageSchema>;\n submission: z.ZodNullable<typeof guestChatSubmissionStatusSchema>;\n}> = z.strictObject({\n messages: z.array(chatHistoryMessageSchema).max(100),\n submission: guestChatSubmissionStatusSchema.nullable(),\n});\nexport type GuestChatHistoryResponse = z.output<\n typeof guestChatHistoryResponseSchema\n>;\n\nexport const chatTextPartSchema: z.ZodObject<{\n type: z.ZodLiteral<\"text\">;\n text: z.ZodString;\n}> = z.object({\n type: z.literal(\"text\"),\n text: z.string().max(1_000_000),\n});\n\nexport type ChatTextPart = z.output<typeof chatTextPartSchema>;\n\nexport const chatFilePartSchema: z.ZodObject<{\n type: z.ZodLiteral<\"file\">;\n mediaType: z.ZodOptional<z.ZodString>;\n filename: z.ZodOptional<z.ZodString>;\n url: z.ZodString;\n}> = z.object({\n type: z.literal(\"file\"),\n mediaType: z.string().trim().min(1).max(255).optional(),\n filename: z.string().trim().min(1).max(255).optional(),\n url: z.string().min(1).max(2_000_000),\n});\n\nexport type ChatFilePart = z.output<typeof chatFilePartSchema>;\n\nexport const chatUploadRefSchema: z.ZodObject<{\n kind: z.ZodLiteral<\"upload\">;\n id: z.ZodString;\n}> = z.object({\n kind: z.literal(\"upload\"),\n id: chatUploadIdSchema,\n});\n\nexport type ChatUploadRef = z.output<typeof chatUploadRefSchema>;\n\nexport const chatUploadPartSchema: z.ZodObject<{\n type: z.ZodLiteral<\"data-upload\">;\n data: Loose<{ ref: typeof chatUploadRefSchema }>;\n}> = z.object({\n type: z.literal(\"data-upload\"),\n data: z.looseObject({ ref: chatUploadRefSchema }),\n});\n\nexport type ChatUploadPart = z.output<typeof chatUploadPartSchema>;\nexport type ChatUploadPartData = ChatUploadPart[\"data\"];\n\nexport const chatApprovalResponseSchema: z.ZodObject<{\n id: z.ZodString;\n approved: z.ZodBoolean;\n toolCallId: z.ZodOptional<z.ZodString>;\n toolName: z.ZodOptional<z.ZodString>;\n input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n title: z.ZodOptional<z.ZodString>;\n}> = z.object({\n id: chatIdSchema,\n approved: z.boolean(),\n toolCallId: chatIdSchema.optional(),\n toolName: z.string().trim().min(1).max(256).optional(),\n input: z.record(z.string(), z.unknown()).optional(),\n title: z.string().max(4_096).optional(),\n});\n\nexport type ChatApprovalResponse = z.output<typeof chatApprovalResponseSchema>;\n\nexport const chatApprovalResponsePartSchema: Loose<{\n state: z.ZodLiteral<\"approval-responded\">;\n toolCallId: z.ZodOptional<z.ZodString>;\n toolName: z.ZodOptional<z.ZodString>;\n input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n title: z.ZodOptional<z.ZodString>;\n approval: typeof chatApprovalResponseSchema;\n}> = z.looseObject({\n state: z.literal(\"approval-responded\"),\n toolCallId: chatIdSchema.optional(),\n toolName: z.string().trim().min(1).max(256).optional(),\n input: z.record(z.string(), z.unknown()).optional(),\n title: z.string().max(4_096).optional(),\n approval: chatApprovalResponseSchema,\n});\n\nexport type ChatApprovalResponsePart = z.output<\n typeof chatApprovalResponsePartSchema\n>;\n\nexport const chatMessageSchema: z.ZodObject<{\n id: z.ZodOptional<z.ZodString>;\n role: z.ZodEnum<{ user: \"user\"; assistant: \"assistant\"; system: \"system\" }>;\n parts: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;\n content: z.ZodOptional<z.ZodString>;\n}> = z.object({\n id: chatIdSchema.optional(),\n role: z.enum([\"user\", \"assistant\", \"system\"]),\n parts: z.array(z.unknown()).max(1_000).optional(),\n content: z.string().max(1_000_000).optional(),\n});\n\nexport type ChatMessage = z.output<typeof chatMessageSchema>;\nexport type ChatMessageRole = ChatMessage[\"role\"];\n\nconst chatSafeText = (max: number): z.ZodString =>\n z\n .string()\n .trim()\n .min(1)\n .max(max)\n .refine((value) => !/[\\p{Cc}\\p{Cf}]/u.test(value));\n\nexport const chatSourceContextSchema: Strict<{\n sourceId: z.ZodString;\n itemId: z.ZodString;\n label: z.ZodString;\n}> = z.strictObject({\n sourceId: z\n .string()\n .trim()\n .regex(/^[a-z][a-z0-9-]*$/)\n .max(64),\n itemId: z.string().trim().min(1).max(300),\n label: chatSafeText(160),\n});\n\nexport type ChatSourceContext = z.output<typeof chatSourceContextSchema>;\n\nexport const chatMessageRequestSchema: Strict<{\n id: z.ZodOptional<z.ZodString>;\n messages: z.ZodArray<typeof chatMessageSchema>;\n trigger: z.ZodOptional<z.ZodString>;\n inboxContext: z.ZodOptional<typeof chatSourceContextSchema>;\n}> = z\n .object({\n id: chatIdSchema.optional(),\n messages: z.array(chatMessageSchema).min(1).max(200),\n trigger: z.string().trim().min(1).max(64).optional(),\n inboxContext: chatSourceContextSchema.optional(),\n })\n .strict();\n\nexport type ChatMessageRequest = z.output<typeof chatMessageRequestSchema>;\n\n/** Guest history is loaded by the server, not replayed as browser authority. */\nexport const guestChatMessageRequestSchema: Strict<{\n id: z.ZodOptional<z.ZodString>;\n messages: z.ZodArray<\n Strict<{\n id: z.ZodString;\n role: z.ZodLiteral<\"user\">;\n parts: z.ZodArray<\n Strict<{ type: z.ZodLiteral<\"text\">; text: z.ZodString }>\n >;\n }>\n >;\n}> = z.strictObject({\n id: chatIdSchema.optional(),\n messages: z\n .array(\n z.strictObject({\n id: chatIdSchema,\n role: z.literal(\"user\"),\n parts: z\n .array(z.strictObject({ type: z.literal(\"text\"), text: z.string() }))\n .min(1)\n .max(16),\n }),\n )\n .length(1),\n});\n\nconst chatJobStatusValueSchema: z.ZodEnum<{\n pending: \"pending\";\n processing: \"processing\";\n completed: \"completed\";\n failed: \"failed\";\n}> = z.enum([\"pending\", \"processing\", \"completed\", \"failed\"]);\n\nexport type ChatJobStatusValue = z.output<typeof chatJobStatusValueSchema>;\n\nexport const chatProgressEventSchema: Loose<{\n type: z.ZodEnum<{ job: \"job\"; batch: \"batch\" }>;\n status: typeof chatJobStatusValueSchema;\n operationType: z.ZodEnum<{\n file_operations: \"file_operations\";\n content_operations: \"content_operations\";\n data_processing: \"data_processing\";\n batch_processing: \"batch_processing\";\n }>;\n operationTarget: z.ZodOptional<z.ZodString>;\n message: z.ZodOptional<z.ZodString>;\n progress: z.ZodOptional<\n z.ZodObject<{\n current: z.ZodNumber;\n total: z.ZodNumber;\n percentage: z.ZodNumber;\n }>\n >;\n}> = z.looseObject({\n type: z.enum([\"job\", \"batch\"]),\n status: chatJobStatusValueSchema,\n operationType: z.enum([\n \"file_operations\",\n \"content_operations\",\n \"data_processing\",\n \"batch_processing\",\n ]),\n operationTarget: z.string().max(1_024).optional(),\n message: z.string().max(4_096).optional(),\n progress: z\n .object({\n current: z.number().nonnegative(),\n total: z.number().nonnegative(),\n percentage: z.number().min(0).max(100),\n })\n .optional(),\n});\n\nexport type ChatProgressEvent = z.output<typeof chatProgressEventSchema>;\n\nexport const chatToolStatusEventSchema: Loose<{\n status: z.ZodEnum<{\n \"tool-running\": \"tool-running\";\n \"tool-completed\": \"tool-completed\";\n \"tool-awaiting-approval\": \"tool-awaiting-approval\";\n \"tool-failed\": \"tool-failed\";\n }>;\n toolName: z.ZodString;\n error: z.ZodOptional<z.ZodString>;\n}> = z.looseObject({\n status: z.enum([\n \"tool-running\",\n \"tool-completed\",\n \"tool-awaiting-approval\",\n \"tool-failed\",\n ]),\n toolName: z.string().trim().min(1).max(256),\n error: z.string().max(4_096).optional(),\n});\n\nexport type ChatToolStatusEvent = z.output<typeof chatToolStatusEventSchema>;\nexport type ChatToolStatusValue = ChatToolStatusEvent[\"status\"];\n\n/**\n * Version-1 wire events emitted by the Chat stream. These are transport and\n * server-owned lifecycle facts, not assembled UI messages or host view state.\n */\nexport const chatProtocolEventSchema: z.ZodDiscriminatedUnion<\n [\n Loose<{\n type: z.ZodLiteral<\"start\">;\n messageId: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{ type: z.ZodLiteral<\"start-step\"> }>,\n Loose<{ type: z.ZodLiteral<\"finish-step\"> }>,\n Loose<{\n type: z.ZodLiteral<\"finish\">;\n finishReason: z.ZodOptional<\n z.ZodEnum<{\n length: \"length\";\n error: \"error\";\n stop: \"stop\";\n \"content-filter\": \"content-filter\";\n \"tool-calls\": \"tool-calls\";\n other: \"other\";\n }>\n >;\n }>,\n Loose<{\n type: z.ZodLiteral<\"abort\">;\n reason: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{ type: z.ZodLiteral<\"error\">; errorText: z.ZodString }>,\n Loose<{ type: z.ZodLiteral<\"text-start\">; id: z.ZodString }>,\n Loose<{\n type: z.ZodLiteral<\"text-delta\">;\n id: z.ZodString;\n delta: z.ZodString;\n }>,\n Loose<{ type: z.ZodLiteral<\"text-end\">; id: z.ZodString }>,\n Loose<{ type: z.ZodLiteral<\"reasoning-start\">; id: z.ZodString }>,\n Loose<{\n type: z.ZodLiteral<\"reasoning-delta\">;\n id: z.ZodString;\n delta: z.ZodString;\n }>,\n Loose<{ type: z.ZodLiteral<\"reasoning-end\">; id: z.ZodString }>,\n Loose<{\n type: z.ZodLiteral<\"tool-input-start\">;\n toolCallId: z.ZodString;\n toolName: z.ZodString;\n title: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-input-delta\">;\n toolCallId: z.ZodString;\n inputTextDelta: z.ZodString;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-input-available\">;\n toolCallId: z.ZodString;\n toolName: z.ZodString;\n input: z.ZodUnknown;\n title: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-input-error\">;\n toolCallId: z.ZodString;\n toolName: z.ZodString;\n input: z.ZodUnknown;\n errorText: z.ZodString;\n title: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-approval-request\">;\n approvalId: z.ZodString;\n toolCallId: z.ZodString;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-output-available\">;\n toolCallId: z.ZodString;\n output: z.ZodUnknown;\n preliminary: z.ZodOptional<z.ZodBoolean>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-output-error\">;\n toolCallId: z.ZodString;\n errorText: z.ZodString;\n }>,\n Loose<{\n type: z.ZodLiteral<\"tool-output-denied\">;\n toolCallId: z.ZodString;\n }>,\n Loose<{\n type: z.ZodLiteral<\"source-url\">;\n sourceId: z.ZodString;\n url: z.ZodString;\n title: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"source-document\">;\n sourceId: z.ZodString;\n mediaType: z.ZodString;\n title: z.ZodString;\n filename: z.ZodOptional<z.ZodString>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"file\">;\n url: z.ZodString;\n mediaType: z.ZodString;\n }>,\n Loose<{\n type: z.ZodLiteral<\"data-progress\">;\n id: z.ZodOptional<z.ZodString>;\n data: typeof chatProgressEventSchema;\n transient: z.ZodOptional<z.ZodBoolean>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"data-status\">;\n id: z.ZodOptional<z.ZodString>;\n data: typeof chatToolStatusEventSchema;\n transient: z.ZodOptional<z.ZodBoolean>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"data-tool-result\">;\n id: z.ZodOptional<z.ZodString>;\n data: typeof chatToolResultSchema;\n transient: z.ZodOptional<z.ZodBoolean>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"data-actions\">;\n id: z.ZodOptional<z.ZodString>;\n data: typeof chatActionsCardSchema;\n transient: z.ZodOptional<z.ZodBoolean>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"data-sources\">;\n id: z.ZodOptional<z.ZodString>;\n data: typeof chatSourcesCardSchema;\n transient: z.ZodOptional<z.ZodBoolean>;\n }>,\n Loose<{\n type: z.ZodLiteral<\"data-attachment\">;\n id: z.ZodOptional<z.ZodString>;\n data: typeof chatAttachmentCardSchema;\n transient: z.ZodOptional<z.ZodBoolean>;\n }>,\n ],\n \"type\"\n> = z.discriminatedUnion(\"type\", [\n z.looseObject({\n type: z.literal(\"start\"),\n messageId: chatIdSchema.optional(),\n }),\n z.looseObject({ type: z.literal(\"start-step\") }),\n z.looseObject({ type: z.literal(\"finish-step\") }),\n z.looseObject({\n type: z.literal(\"finish\"),\n finishReason: z\n .enum([\n \"length\",\n \"error\",\n \"stop\",\n \"content-filter\",\n \"tool-calls\",\n \"other\",\n ])\n .optional(),\n }),\n z.looseObject({\n type: z.literal(\"abort\"),\n reason: z.string().max(4_096).optional(),\n }),\n z.looseObject({\n type: z.literal(\"error\"),\n errorText: z.string().max(20_000),\n }),\n z.looseObject({ type: z.literal(\"text-start\"), id: chatIdSchema }),\n z.looseObject({\n type: z.literal(\"text-delta\"),\n id: chatIdSchema,\n delta: z.string().max(1_000_000),\n }),\n z.looseObject({ type: z.literal(\"text-end\"), id: chatIdSchema }),\n z.looseObject({\n type: z.literal(\"reasoning-start\"),\n id: chatIdSchema,\n }),\n z.looseObject({\n type: z.literal(\"reasoning-delta\"),\n id: chatIdSchema,\n delta: z.string().max(1_000_000),\n }),\n z.looseObject({\n type: z.literal(\"reasoning-end\"),\n id: chatIdSchema,\n }),\n z.looseObject({\n type: z.literal(\"tool-input-start\"),\n toolCallId: chatIdSchema,\n toolName: z.string().trim().min(1).max(256),\n title: z.string().max(4_096).optional(),\n }),\n z.looseObject({\n type: z.literal(\"tool-input-delta\"),\n toolCallId: chatIdSchema,\n inputTextDelta: z.string().max(1_000_000),\n }),\n z.looseObject({\n type: z.literal(\"tool-input-available\"),\n toolCallId: chatIdSchema,\n toolName: z.string().trim().min(1).max(256),\n input: z.unknown(),\n title: z.string().max(4_096).optional(),\n }),\n z.looseObject({\n type: z.literal(\"tool-input-error\"),\n toolCallId: chatIdSchema,\n toolName: z.string().trim().min(1).max(256),\n input: z.unknown(),\n errorText: z.string().max(20_000),\n title: z.string().max(4_096).optional(),\n }),\n z.looseObject({\n type: z.literal(\"tool-approval-request\"),\n approvalId: chatIdSchema,\n toolCallId: chatIdSchema,\n }),\n z.looseObject({\n type: z.literal(\"tool-output-available\"),\n toolCallId: chatIdSchema,\n output: z.unknown(),\n preliminary: z.boolean().optional(),\n }),\n z.looseObject({\n type: z.literal(\"tool-output-error\"),\n toolCallId: chatIdSchema,\n errorText: z.string().max(20_000),\n }),\n z.looseObject({\n type: z.literal(\"tool-output-denied\"),\n toolCallId: chatIdSchema,\n }),\n z.looseObject({\n type: z.literal(\"source-url\"),\n sourceId: chatIdSchema,\n url: chatLinkUrlSchema,\n title: z.string().max(4_096).optional(),\n }),\n z.looseObject({\n type: z.literal(\"source-document\"),\n sourceId: chatIdSchema,\n mediaType: z.string().trim().min(1).max(255),\n title: z.string().max(4_096),\n filename: z.string().trim().min(1).max(255).optional(),\n }),\n z.looseObject({\n type: z.literal(\"file\"),\n url: chatLinkUrlSchema,\n mediaType: z.string().trim().min(1).max(255),\n }),\n z.looseObject({\n type: z.literal(\"data-progress\"),\n id: chatIdSchema.optional(),\n data: chatProgressEventSchema,\n transient: z.boolean().optional(),\n }),\n z.looseObject({\n type: z.literal(\"data-status\"),\n id: chatIdSchema.optional(),\n data: chatToolStatusEventSchema,\n transient: z.boolean().optional(),\n }),\n z.looseObject({\n type: z.literal(\"data-tool-result\"),\n id: chatIdSchema.optional(),\n data: chatToolResultSchema,\n transient: z.boolean().optional(),\n }),\n z.looseObject({\n type: z.literal(\"data-actions\"),\n id: chatIdSchema.optional(),\n data: chatActionsCardSchema,\n transient: z.boolean().optional(),\n }),\n z.looseObject({\n type: z.literal(\"data-sources\"),\n id: chatIdSchema.optional(),\n data: chatSourcesCardSchema,\n transient: z.boolean().optional(),\n }),\n z.looseObject({\n type: z.literal(\"data-attachment\"),\n id: chatIdSchema.optional(),\n data: chatAttachmentCardSchema,\n transient: z.boolean().optional(),\n }),\n]);\n\nexport type ChatProtocolEvent = z.output<typeof chatProtocolEventSchema>;\n\nexport const chatContextHandoffResponseSchema: Strict<{\n conversationId: z.ZodString;\n}> = z.strictObject({\n conversationId: chatIdSchema,\n});\n\nexport type ChatContextHandoffResponse = z.output<\n typeof chatContextHandoffResponseSchema\n>;\n\nexport const renameChatSessionRequestSchema: Strict<{\n title: z.ZodString;\n}> = z\n .object({\n title: chatTitleSchema,\n })\n .strict();\n\nexport type RenameChatSessionRequest = z.output<\n typeof renameChatSessionRequestSchema\n>;\n\nexport const renameChatSessionResponseSchema: z.ZodObject<{\n renamed: z.ZodBoolean;\n title: z.ZodString;\n}> = z.object({\n renamed: z.boolean(),\n title: chatTitleSchema,\n});\n\nexport type RenameChatSessionResponse = z.output<\n typeof renameChatSessionResponseSchema\n>;\n\nexport const archiveChatSessionResponseSchema: z.ZodObject<{\n archived: z.ZodBoolean;\n}> = z.object({\n archived: z.boolean(),\n});\n\nexport type ArchiveChatSessionResponse = z.output<\n typeof archiveChatSessionResponseSchema\n>;\n\nexport const deleteChatSessionResponseSchema: z.ZodObject<{\n deleted: z.ZodBoolean;\n}> = z.object({\n deleted: z.boolean(),\n});\n\nexport type DeleteChatSessionResponse = z.output<\n typeof deleteChatSessionResponseSchema\n>;\n\nexport const chatActionRequestSchema: Strict<{\n conversationId: z.ZodString;\n action: typeof agentEventActionSchema;\n}> = z\n .object({\n conversationId: chatIdSchema,\n action: agentEventActionSchema,\n })\n .strict();\n\nexport type ChatActionRequest = z.output<typeof chatActionRequestSchema>;\n\nexport const chatJobStatusSchema: Loose<{\n id: z.ZodString;\n status: typeof chatJobStatusValueSchema;\n message: z.ZodOptional<z.ZodString>;\n}> = z.looseObject({\n id: chatIdSchema,\n status: chatJobStatusValueSchema,\n message: z.string().max(4_096).optional(),\n});\n\nexport type ChatJobStatus = z.output<typeof chatJobStatusSchema>;\n\nexport const chatUploadResponseSchema: Loose<{\n id: z.ZodString;\n ref: typeof chatUploadRefSchema;\n filename: z.ZodString;\n mediaType: z.ZodString;\n sizeBytes: z.ZodNumber;\n createdAt: z.ZodString;\n url: z.ZodString;\n downloadUrl: z.ZodString;\n}> = z\n .looseObject({\n id: chatUploadIdSchema,\n ref: chatUploadRefSchema,\n filename: z.string().trim().min(1).max(255),\n mediaType: z.string().trim().min(1).max(255),\n sizeBytes: z.number().int().nonnegative(),\n createdAt: chatTimestampSchema,\n url: chatRelativeUrlSchema,\n downloadUrl: chatRelativeUrlSchema,\n })\n .refine((upload) => upload.id === upload.ref.id, {\n path: [\"ref\", \"id\"],\n message: \"Upload response ids must match\",\n });\n\nexport type ChatUploadResponse = z.output<typeof chatUploadResponseSchema>;\n\nexport type ChatFetch = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport interface ChatClientOptions {\n apiPath?: string | undefined;\n fetch?: ChatFetch | undefined;\n credentials?: RequestCredentials | undefined;\n}\n\nexport interface ChatClient {\n readonly version: typeof CHAT_API_VERSION;\n readonly paths: ChatApiPaths;\n /** Use a guest API base path. Establishes a credential, not a conversation. */\n openGuestSession(): Promise<GuestChatSessionResponse>;\n streamMessages(\n request: ChatMessageRequest,\n options?: { signal?: AbortSignal | undefined },\n ): Promise<Response>;\n listSessions(query?: ChatSessionListQuery): Promise<ChatSession[]>;\n getMessages(conversationId: string): Promise<ChatHistoryMessage[]>;\n getGuestHistory(\n conversationId: string,\n submissionId: string,\n ): Promise<GuestChatHistoryResponse>;\n renameSession(\n conversationId: string,\n title: string,\n ): Promise<RenameChatSessionResponse>;\n archiveSession(conversationId: string): Promise<ArchiveChatSessionResponse>;\n deleteSession(conversationId: string): Promise<DeleteChatSessionResponse>;\n getJobStatus(jobId: string): Promise<ChatJobStatus>;\n openContextSession(\n request: ChatContextHandoffRequest,\n ): Promise<ChatContextHandoffResponse>;\n runAction(request: ChatActionRequest): Promise<ChatActionResponse>;\n upload(file: Blob, filename: string): Promise<ChatUploadResponse>;\n getUploadUrl(uploadId: string, download?: boolean): string;\n getDocumentAttachmentUrl(documentId: string, download?: boolean): string;\n getImageAttachmentUrl(imageId: string, download?: boolean): string;\n}\n\nexport type ChatApiErrorKind = \"http\" | \"invalid-response\";\n\nexport class ChatApiError extends Error {\n public readonly operation: string;\n public readonly status: number;\n public readonly kind: ChatApiErrorKind;\n /** Validated duplicate-send status, so a lost first response can recover its locator. */\n public readonly guestSubmission: GuestChatSubmissionStatus | undefined;\n\n public constructor(\n operation: string,\n status: number,\n kind: ChatApiErrorKind = \"http\",\n guestSubmission?: GuestChatSubmissionStatus,\n ) {\n super(`Chat API could not ${operation} (${status})`);\n this.name = \"ChatApiError\";\n this.operation = operation;\n this.status = status;\n this.kind = kind;\n // Recovery data is not routine error telemetry; keep its locator out of\n // ordinary error serialization while allowing explicit client recovery.\n Object.defineProperty(this, \"guestSubmission\", {\n value: guestSubmission,\n enumerable: false,\n writable: false,\n });\n }\n}\n\nfunction parseChatProtocolLine(line: string): ChatProtocolEvent | undefined {\n const normalized = line.endsWith(\"\\r\") ? line.slice(0, -1) : line;\n if (!normalized.startsWith(\"data:\")) return undefined;\n const payload = normalized.slice(5).trimStart();\n if (payload.length === 0 || payload === \"[DONE]\") return undefined;\n\n let value: unknown;\n try {\n value = JSON.parse(payload);\n } catch {\n throw new ChatApiError(\"read stream\", 502, \"invalid-response\");\n }\n const parsed = chatProtocolEventSchema.safeParse(value);\n if (!parsed.success) {\n throw new ChatApiError(\"read stream\", 502, \"invalid-response\");\n }\n return parsed.data;\n}\n\n/** Decode the versioned SSE protocol without assembling host-owned UI state. */\nexport async function* readChatProtocolEvents(\n response: Response,\n): AsyncGenerator<ChatProtocolEvent> {\n if (!response.ok) {\n throw new ChatApiError(\"read stream\", response.status);\n }\n if (!response.body) {\n throw new ChatApiError(\"read stream\", 502, \"invalid-response\");\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffered = \"\";\n try {\n for (;;) {\n const { value, done } = await reader.read();\n buffered += decoder.decode(value, { stream: !done });\n let newline = buffered.indexOf(\"\\n\");\n while (newline >= 0) {\n const line = buffered.slice(0, newline);\n buffered = buffered.slice(newline + 1);\n const event = parseChatProtocolLine(line);\n if (event) yield event;\n newline = buffered.indexOf(\"\\n\");\n }\n if (done) break;\n }\n if (buffered.length > 0) {\n const event = parseChatProtocolLine(buffered);\n if (event) yield event;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function createChatClient(options: ChatClientOptions = {}): ChatClient {\n const paths = createChatApiPaths(options.apiPath);\n const fetchFn = options.fetch ?? globalThis.fetch;\n const credentials = options.credentials ?? \"include\";\n\n async function requestJson<T>(\n operation: string,\n url: string,\n schema: z.ZodType<T>,\n init?: RequestInit,\n ): Promise<T> {\n const response = await fetchFn(url, {\n ...init,\n credentials,\n });\n if (!response.ok) {\n throw new ChatApiError(operation, response.status);\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n throw new ChatApiError(operation, 502, \"invalid-response\");\n }\n const parsed = schema.safeParse(body);\n if (!parsed.success) {\n throw new ChatApiError(operation, 502, \"invalid-response\");\n }\n return parsed.data;\n }\n\n function withId(path: string, id: string): string {\n const parsedId = chatIdSchema.parse(id);\n return `${path}?id=${encodeURIComponent(parsedId)}`;\n }\n\n function withDownload(path: string, id: string, download: boolean): string {\n const base = withId(path, id);\n return download ? `${base}&download=1` : base;\n }\n\n return {\n version: CHAT_API_VERSION,\n paths,\n async openGuestSession(): Promise<GuestChatSessionResponse> {\n return requestJson(\n \"open guest session\",\n `${paths.stream}/session`,\n guestChatSessionResponseSchema,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: \"{}\",\n },\n );\n },\n async streamMessages(\n request: ChatMessageRequest,\n streamOptions: { signal?: AbortSignal | undefined } = {},\n ): Promise<Response> {\n const body = chatMessageRequestSchema.parse(request);\n const response = await fetchFn(paths.stream, {\n method: \"POST\",\n credentials,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n ...(streamOptions.signal ? { signal: streamOptions.signal } : {}),\n });\n if (!response.ok) {\n let submission: GuestChatSubmissionStatus | undefined;\n if (response.status === 409) {\n try {\n const status = guestChatSubmissionStatusSchema.safeParse(\n await response.json(),\n );\n if (status.success) submission = status.data;\n } catch {\n // Non-JSON conflicts remain ordinary HTTP errors; never expose raw bodies.\n }\n }\n throw new ChatApiError(\n \"send messages\",\n response.status,\n \"http\",\n submission,\n );\n }\n return response;\n },\n async listSessions(\n options: ChatSessionListQuery = {},\n ): Promise<ChatSession[]> {\n const query = chatSessionListQuerySchema.parse(options);\n const params = new URLSearchParams();\n if (query.query) params.set(\"q\", query.query);\n if (query.archived) params.set(\"archived\", \"true\");\n if (query.offset) params.set(\"offset\", String(query.offset));\n if (query.limit !== 25) params.set(\"limit\", String(query.limit));\n const suffix = params.size ? `?${params.toString()}` : \"\";\n const response = await requestJson(\n \"list sessions\",\n `${paths.sessions}${suffix}`,\n chatSessionsResponseSchema,\n );\n return response.sessions;\n },\n async getMessages(conversationId: string): Promise<ChatHistoryMessage[]> {\n const response = await requestJson(\n \"load messages\",\n withId(paths.messages, conversationId),\n chatMessagesResponseSchema,\n );\n return response.messages;\n },\n async getGuestHistory(\n conversationId: string,\n submissionId: string,\n ): Promise<GuestChatHistoryResponse> {\n return requestJson(\n \"check guest history\",\n `${withId(paths.messages, conversationId)}&submissionId=${encodeURIComponent(guestChatSubmissionIdSchema.parse(submissionId))}`,\n guestChatHistoryResponseSchema,\n );\n },\n async renameSession(\n conversationId: string,\n title: string,\n ): Promise<RenameChatSessionResponse> {\n const body = renameChatSessionRequestSchema.parse({ title });\n return requestJson(\n \"rename session\",\n withId(paths.sessions, conversationId),\n renameChatSessionResponseSchema,\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n },\n async archiveSession(\n conversationId: string,\n ): Promise<ArchiveChatSessionResponse> {\n return requestJson(\n \"archive session\",\n withId(paths.sessionArchive, conversationId),\n archiveChatSessionResponseSchema,\n { method: \"PUT\" },\n );\n },\n async deleteSession(\n conversationId: string,\n ): Promise<DeleteChatSessionResponse> {\n return requestJson(\n \"delete session\",\n withId(paths.sessions, conversationId),\n deleteChatSessionResponseSchema,\n { method: \"DELETE\" },\n );\n },\n getJobStatus(jobId: string): Promise<ChatJobStatus> {\n return requestJson(\n \"load job status\",\n withId(paths.jobStatus, jobId),\n chatJobStatusSchema,\n );\n },\n openContextSession(\n request: ChatContextHandoffRequest,\n ): Promise<ChatContextHandoffResponse> {\n return requestJson(\n \"open context session\",\n paths.contextSessions,\n chatContextHandoffResponseSchema,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(chatContextHandoffRequestSchema.parse(request)),\n },\n );\n },\n runAction(request: ChatActionRequest): Promise<ChatActionResponse> {\n const body = chatActionRequestSchema.parse(request);\n return requestJson(\n \"run action\",\n paths.actions,\n chatActionResponseSchema,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n },\n async upload(file: Blob, filename: string): Promise<ChatUploadResponse> {\n const normalizedFilename = z\n .string()\n .trim()\n .min(1)\n .max(255)\n .parse(filename);\n const form = new FormData();\n form.set(\"file\", file, normalizedFilename);\n return requestJson(\n \"upload file\",\n paths.uploads,\n chatUploadResponseSchema,\n {\n method: \"POST\",\n body: form,\n },\n );\n },\n getUploadUrl(uploadId: string, download = false): string {\n return withDownload(paths.uploads, uploadId, download);\n },\n getDocumentAttachmentUrl(documentId: string, download = false): string {\n return withDownload(paths.documentAttachments, documentId, download);\n },\n getImageAttachmentUrl(imageId: string, download = false): string {\n return withDownload(paths.imageAttachments, imageId, download);\n },\n };\n}\n",
|
|
10
|
+
"import { z } from \"@brains/utils/zod\";\nimport { definedFields } from \"@brains/utils/strip-undefined\";\n\nexport interface ArtifactDisplay {\n jobId?: string;\n title: string;\n description?: string;\n mediaType?: string;\n filename?: string;\n sizeLabel?: string;\n url?: string;\n downloadUrl?: string;\n previewUrl?: string;\n}\n\nexport type ArtifactJobStatus =\n \"pending\" | \"processing\" | \"completed\" | \"failed\" | \"unknown\";\n\nexport interface ArtifactCardState {\n status: ArtifactJobStatus | \"ready\";\n label: string;\n isPending: boolean;\n}\n\nexport function formatArtifactDisplay(data: unknown): ArtifactDisplay | null {\n const attachment = parseRecord(getRecordValue(data, \"attachment\"));\n if (!attachment) return null;\n\n const jobId = getStringValue(data, \"jobId\");\n const description = getStringValue(data, \"description\");\n const mediaType = getStringValue(attachment, \"mediaType\");\n const filename = getStringValue(attachment, \"filename\");\n const sizeLabel = formatByteSize(getNumberValue(attachment, \"sizeBytes\"));\n const url = getStringValue(attachment, \"url\");\n const downloadUrl = getStringValue(attachment, \"downloadUrl\");\n const previewUrl = getStringValue(attachment, \"previewUrl\");\n\n return {\n ...definedFields({ jobId }),\n title: getStringValue(data, \"title\") ?? \"Generated artifact\",\n ...definedFields({\n description,\n mediaType,\n filename,\n sizeLabel,\n url,\n downloadUrl,\n previewUrl,\n }),\n };\n}\n\nexport function formatByteSize(\n sizeBytes: number | undefined,\n): string | undefined {\n if (sizeBytes === undefined) return undefined;\n if (!Number.isFinite(sizeBytes) || sizeBytes < 0) return undefined;\n if (sizeBytes < 1024) return `${sizeBytes} B`;\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = sizeBytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value >= 10 ? 0 : 1)} ${unit}`;\n }\n value /= 1024;\n }\n return undefined;\n}\n\nexport function narrowArtifactJobStatus(\n status: string | undefined,\n): ArtifactJobStatus {\n switch (status) {\n case \"pending\":\n case \"processing\":\n case \"completed\":\n case \"failed\":\n return status;\n default:\n return \"unknown\";\n }\n}\n\nexport function artifactStatusLabel(status: ArtifactJobStatus | null): string {\n switch (status) {\n case \"pending\":\n return \"queued\";\n case \"processing\":\n return \"generating\";\n case \"completed\":\n return \"ready\";\n case \"failed\":\n return \"failed\";\n case \"unknown\":\n return \"status unknown\";\n default:\n return \"ready\";\n }\n}\n\nexport function getArtifactCardState(\n jobStatus: ArtifactJobStatus | null,\n): ArtifactCardState {\n return {\n status: jobStatus ?? \"ready\",\n label: artifactStatusLabel(jobStatus),\n isPending: jobStatus === \"pending\" || jobStatus === \"processing\",\n };\n}\n\nconst recordSchema = z.record(z.string(), z.unknown());\n\nfunction parseRecord(data: unknown): Record<string, unknown> | null {\n const parsed = recordSchema.safeParse(data);\n return parsed.success ? parsed.data : null;\n}\n\nfunction getRecordValue(data: unknown, key: string): unknown {\n return parseRecord(data)?.[key];\n}\n\nfunction getStringValue(data: unknown, key: string): string | undefined {\n const value = getRecordValue(data, key);\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction getNumberValue(data: unknown, key: string): number | undefined {\n const value = getRecordValue(data, key);\n return typeof value === \"number\" ? value : undefined;\n}\n",
|
|
11
|
+
"import * as stylex from \"@stylexjs/stylex\";\nexport const chatLayout: Record<\"imageTrigger\" | \"fullImage\" | \"toolbar\" | \"toolbarButton\" | \"details\" | \"composerBar\" | \"userTurn\" | \"source\" | \"uploadStrip\" | \"uploadPreview\" | \"uploadName\" | \"root\" | \"shell\" | \"frame\" | \"room\" | \"emptyConversation\" | \"picker\" | \"thread\" | \"threadHead\" | \"sessionList\" | \"session\" | \"activeSession\" | \"sessionTitle\" | \"sessionControls\" | \"sessionFilterSelect\" | \"timestamp\" | \"actions\" | \"title\" | \"context\" | \"contextBody\" | \"contextItem\" | \"threadScroll\" | \"manuscript\" | \"turn\" | \"speaker\" | \"turnBody\" | \"userBody\" | \"paragraph\" | \"cards\" | \"card\" | \"attachmentPreview\" | \"kicker\" | \"empty\" | \"error\" | \"form\" | \"composer\" | \"composerHint\" | \"input\" | \"uploadInput\" | \"attachButton\" | \"uploadList\" | \"upload\" | \"headCopy\" | \"subheading\" | \"button\" | \"primaryButton\" | \"cardHeading\" | \"cardText\", stylex.StyleXStyles> = {\n imageTrigger: {\n k1xSpc: \"x1lliihq\",\n kzqmXN: \"xh8yej3\",\n kmVPX3: \"x1717udv\",\n kMzoRj: \"xc342km\",\n kWkggS: \"xjbqb8w\",\n kkrTdU: \"x1huxd7x\",\n kAzted: \"x1gg8mnh\",\n k3Woio: \"x16dl9wz\",\n kiEn40: \"x7s97pk\",\n $$css: true\n },\n fullImage: {\n kzqmXN: \"xh8yej3\",\n kZKoxP: \"xt7dq6l\",\n kskxy: \"x6kd6ug\",\n kVIFPx: \"x19kjcj4\",\n $$css: true\n },\n toolbar: {\n k1xSpc: \"x78zum5\",\n kGNEyG: \"x6s0dn4\",\n kOIVth: \"x195vfkc\",\n kmuXW: \"x2lah0s\",\n $$css: true\n },\n toolbarButton: {\n kAzted: \"x1gg8mnh\",\n k7Eaqz: \"x1nb6za0\",\n kmVPX3: \"x1160tuk\",\n kGuDYH: \"xfifm61\",\n $$css: true\n },\n details: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"xou54vl\",\n k7Eaqz: \"xeuugli\",\n $$css: true\n },\n composerBar: {\n k1xSpc: \"x78zum5\",\n kjj79g: \"x1qughib\",\n kGNEyG: \"x6s0dn4\",\n kOIVth: \"x167g77z\",\n $$css: true\n },\n userTurn: {\n koQZXg: \"x8x9d4c\",\n ks0D6T: \"x1v8xovm\",\n kWkggS: \"xbslqsl\",\n kaIpWk: \"x1cxwkf3\",\n kmVPX3: \"x1j671cp\",\n $$css: true\n },\n source: {\n khDVqt: \"x126k92a\",\n kHjlTd: \"xj0a0fe\",\n kVQacm: \"xysyzu8\",\n kskxy: \"x8ln6o7\",\n kmVPX3: \"xc7ga6q\",\n kogj98: \"x1ghz6dp\",\n kMv6JI: \"xa9opjo\",\n kGuDYH: \"xfifm61\",\n kLWn49: \"x1dbl2gt\",\n kWkggS: \"xbslqsl\",\n $$css: true\n },\n uploadStrip: {\n k1xSpc: \"x78zum5\",\n kXHlph: \"xw2csxc\",\n kskxy: \"x569fbc\",\n kOIVth: \"x167g77z\",\n k7Eaqz: \"xeuugli\",\n k5wCbM: \"x1597r2g\",\n k1K539: \"xzueoph\",\n $$css: true\n },\n uploadPreview: {\n kzqmXN: \"x100vrsf\",\n kZKoxP: \"x1vqgdyp\",\n kVIFPx: \"xl1xv1r\",\n kaIpWk: \"x12oqio5\",\n $$css: true\n },\n uploadName: {\n k7Eaqz: \"xeuugli\",\n kUk6DE: \"x98rzlu\",\n kHjlTd: \"xj0a0fe\",\n kGuDYH: \"xfifm61\",\n $$css: true\n },\n sessionControls: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x167g77z\",\n k7Eaqz: \"xeuugli\",\n k1K539: \"xod5an3\",\n kGuDYH: \"xfifm61\",\n kMwMTN: \"x1ar3pfp\",\n $$css: true\n },\n sessionFilterSelect: {\n kzqmXN: \"xh8yej3\",\n k7Eaqz: \"xeuugli\",\n kAzted: \"x141feeh x1c4ya5t\",\n kGuDYH: \"x4z9k3i xf2x79s\",\n $$css: true\n },\n composerHint: {\n k1xSpc: \"x1lliihq xkaaz9w\",\n keoZOQ: \"x1xmf6yo\",\n kGuDYH: \"x1j6dyjg\",\n kLWn49: \"x37zpob\",\n kMwMTN: \"x1ar3pfp\",\n $$css: true\n },\n shell: {\n k1xSpc: \"xrvj5dj\",\n kUk6DE: \"x98rzlu\",\n kAzted: \"x2lwn1j\",\n k7Eaqz: \"xeuugli\",\n kVQacm: \"xb3r6kr\",\n $$css: true\n },\n root: {\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kZKoxP: \"xtdtrs8\",\n kskxy: \"x1wj9ous\",\n kAzted: \"x2lwn1j\",\n k7Eaqz: \"xeuugli\",\n kVQacm: \"xb3r6kr\",\n $$css: true\n },\n frame: {\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n k7Eaqz: \"xeuugli\",\n kAzted: \"x2lwn1j\",\n kVQacm: \"xb3r6kr\",\n kmVPX3: \"x1717udv\",\n kOIVth: \"xxhr3t\",\n $$css: true\n },\n room: {\n k1xSpc: \"xrvj5dj\",\n kumcoG: \"x1mkdm3x\",\n kOIVth: \"xxhr3t\",\n kUk6DE: \"x98rzlu\",\n kAzted: \"x2lwn1j\",\n k7Eaqz: \"xeuugli\",\n kVQacm: \"xb3r6kr\",\n $$css: true\n },\n emptyConversation: {\n kogj98: \"x1ghz6dp\",\n $$css: true\n },\n picker: {\n \"--console-text-muted\": \"x1phc7po\",\n k1xSpc: \"xrvj5dj\",\n k9llMU: \"x1yn14it\",\n kskxy: \"x1j65ot3\",\n kAzted: \"x2lwn1j\",\n kVQacm: \"xb3r6kr\",\n $$css: true\n },\n thread: {\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n k7Eaqz: \"xeuugli\",\n kAzted: \"x2lwn1j\",\n kVQacm: \"xb3r6kr\",\n $$css: true\n },\n threadHead: {\n k1xSpc: \"x78zum5\",\n kGNEyG: \"x6s0dn4\",\n kjj79g: \"x1qughib\",\n kOIVth: \"x167g77z\",\n k7Eaqz: \"xeuugli\",\n kmuXW: \"x2lah0s\",\n kAzted: \"xt55aet\",\n kmVPX3: \"xsoouyo xbqoc8e\",\n kt9PQ7: \"xso031l\",\n kfdmCh: \"x1q0q8m5\",\n kL6WhQ: \"xpqg30t\",\n k1K539: \"xat24cr\",\n $$css: true\n },\n title: {\n kogj98: \"x1ghz6dp\",\n kVQacm: \"xb3r6kr\",\n kg5iWk: \"xlyipyv\",\n khDVqt: \"xuxw1ft\",\n k7Eaqz: \"xeuugli\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"x4z9k3i\",\n k63SB2: \"xo1l8bm\",\n kLWn49: \"x1evy7pa\",\n kMwMTN: \"xqvuw85\",\n $$css: true\n },\n headCopy: {\n k7Eaqz: \"xeuugli\",\n kUk6DE: \"x98rzlu\",\n $$css: true\n },\n actions: {\n k1xSpc: \"x78zum5\",\n kwnvtZ: \"x1a02dak\",\n kGNEyG: \"x6s0dn4\",\n kOIVth: \"x883omv\",\n $$css: true\n },\n sessionList: {\n k1xSpc: \"xrvj5dj\",\n kfiyM8: \"x10ukxgv\",\n kAzted: \"x2lwn1j\",\n k7Eaqz: \"xeuugli\",\n kORKVm: \"x1odjw0f\",\n $$css: true\n },\n session: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x17d4w8g\",\n kzqmXN: \"xh8yej3\",\n k7Eaqz: \"xeuugli\",\n kmVPX3: \"x1g8o3q3\",\n kMzoRj: \"xc342km\",\n kt9PQ7: \"xso031l\",\n ksu8eU: \"x1y0btm7\",\n kVAM5u: \"xy1lt07\",\n kWkggS: \"xjbqb8w\",\n kMwMTN: \"xqvuw85\",\n k9WMMc: \"xdpxx8g\",\n kkrTdU: \"x1ypdohk\",\n kDPRdz: \"x1711cle\",\n k3Woio: \"x16dl9wz\",\n kiEn40: \"x1bqaal\",\n $$css: true\n },\n activeSession: {\n kMwMTN: \"x1myn341\",\n $$css: true\n },\n sessionTitle: {\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xif65rj\",\n k63SB2: \"xo1l8bm\",\n kLWn49: \"xfrs9s4\",\n kHjlTd: \"xj0a0fe\",\n k1xSpc: \"x104kibb\",\n kgKLqz: \"x1ua5tub\",\n kJFfOR: \"x1h7i4cw\",\n kVQacm: \"xb3r6kr\",\n $$css: true\n },\n timestamp: {\n kMv6JI: \"xa9opjo\",\n kGuDYH: \"x1j6dyjg\",\n kLWn49: \"xa7kkou\",\n kMwMTN: \"x1ar3pfp\",\n kHjlTd: \"xj0a0fe\",\n $$css: true\n },\n context: {\n k7Eaqz: \"xeuugli\",\n kt9PQ7: \"xso031l\",\n kfdmCh: \"x1q0q8m5\",\n kL6WhQ: \"xpqg30t\",\n $$css: true\n },\n contextBody: {\n k1xSpc: \"xrvj5dj\",\n kI3sdo: \"x16dl9wz\",\n kInvED: \"x2ssjo2\",\n kOIVth: \"xou54vl\",\n kskxy: \"xtgemb3\",\n kORKVm: \"x1odjw0f\",\n kGO01o: \"x1l90r2v\",\n kg3NbH: \"xfn1xvj\",\n k7Eaqz: \"xeuugli\",\n $$css: true\n },\n contextItem: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x17d4w8g\",\n k7Eaqz: \"xeuugli\",\n kmVPX3: \"x1b4vry6\",\n kt9PQ7: \"xso031l\",\n kfdmCh: \"x1q0q8m5\",\n kL6WhQ: \"xpqg30t\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xfifm61\",\n kLWn49: \"x1dbl2gt\",\n $$css: true\n },\n threadScroll: {\n kUk6DE: \"x98rzlu\",\n kI3sdo: \"x16dl9wz\",\n kInvED: \"x2ssjo2\",\n kAzted: \"x2lwn1j\",\n k7Eaqz: \"xeuugli\",\n kORKVm: \"x1odjw0f\",\n kZeWKH: \"xish69e\",\n k5wCbM: \"x1597r2g\",\n k6w4Gs: \"xgwpcrc\",\n $$css: true\n },\n manuscript: {\n k7Eaqz: \"xeuugli\",\n ks0D6T: \"x1ac2792\",\n kUOVxO: \"xvueqy4\",\n kmVPX3: \"x12mnf9l xvc418b\",\n $$css: true\n },\n turn: {\n k1xSpc: \"xrvj5dj\",\n kumcoG: \"x1mkdm3x\",\n kOIVth: \"x167g77z\",\n kmVPX3: \"x1717udv\",\n k1K539: \"x1xka2u1\",\n k7Eaqz: \"xeuugli\",\n $$css: true\n },\n speaker: {\n kLKAdn: \"xexx8yu\",\n kMv6JI: \"xa9opjo\",\n kGuDYH: \"x1j6dyjg\",\n kLWn49: \"x1dbl2gt\",\n kMwMTN: \"x1ar3pfp\",\n $$css: true\n },\n turnBody: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x1v2ro7d\",\n k7Eaqz: \"xeuugli\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"x1j61zf2 x1sgj8az\",\n k63SB2: \"xo1l8bm\",\n kLWn49: \"x11m8ghp\",\n kMwMTN: \"xqvuw85\",\n kHjlTd: \"xj0a0fe\",\n $$css: true\n },\n userBody: {\n k63SB2: \"xo1l8bm\",\n $$css: true\n },\n paragraph: {\n kogj98: \"x1ghz6dp\",\n khDVqt: \"x126k92a\",\n kHjlTd: \"xj0a0fe\",\n $$css: true\n },\n cards: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x1v2ro7d\",\n k7Eaqz: \"xeuugli\",\n $$css: true\n },\n attachmentPreview: {\n k1xSpc: \"x1lliihq\",\n kzqmXN: \"xh8yej3\",\n ks0D6T: \"x193iq5w\",\n kZKoxP: \"xt7dq6l\",\n kskxy: \"x1iuus0c\",\n kVIFPx: \"x19kjcj4\",\n kWkggS: \"x18s3upu\",\n $$css: true\n },\n card: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x883omv\",\n k7Eaqz: \"xeuugli\",\n kmVPX3: \"x1tamke2\",\n kMzoRj: \"xmkeg23\",\n ksu8eU: \"x1y0btm7\",\n kVAM5u: \"xy1lt07\",\n kaIpWk: \"x1sxf85j\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xfifm61\",\n k63SB2: \"xo1l8bm\",\n kLWn49: \"x1dbl2gt\",\n kHjlTd: \"xj0a0fe\",\n kXHlph: \"xw2csxc\",\n $$css: true\n },\n kicker: {\n kMv6JI: \"xa9opjo\",\n kGuDYH: \"x1j6dyjg\",\n kMwMTN: \"x1ar3pfp\",\n $$css: true\n },\n cardHeading: {\n kogj98: \"x1ghz6dp\",\n $$css: true\n },\n cardText: {\n kogj98: \"x1ghz6dp\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xfifm61\",\n kLWn49: \"x1dbl2gt\",\n $$css: true\n },\n empty: {\n kogj98: \"xhv1u6h\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xfifm61\",\n kLWn49: \"x1dbl2gt\",\n kMwMTN: \"x1ar3pfp\",\n kHjlTd: \"xj0a0fe\",\n $$css: true\n },\n error: {\n kMwMTN: \"x1mel2pz\",\n $$css: true\n },\n form: {\n k1xSpc: \"xrvj5dj\",\n kOIVth: \"x1jnr06f\",\n k7Eaqz: \"xeuugli\",\n kMzoRj: \"xmkeg23\",\n ksu8eU: \"x1y0btm7\",\n kVAM5u: \"x8tuc8h\",\n kaIpWk: \"x4pepcl\",\n kmVPX3: \"x1160tuk\",\n kWkggS: \"x18s3upu\",\n $$css: true\n },\n composer: {\n kmuXW: \"x2lah0s\",\n k7Eaqz: \"xeuugli\",\n kzqmXN: \"xh8yej3\",\n ks0D6T: \"x1ac2792\",\n kSGwAc: \"xamitd3\",\n kmVPX3: \"x17udgi5 x1lbfznl\",\n $$css: true\n },\n input: {\n kzqmXN: \"xh8yej3\",\n kB7OPa: \"x9f619\",\n k7Eaqz: \"xeuugli\",\n kZKoxP: \"xn3w4p2\",\n kAzted: \"x1gg8mnh\",\n kskxy: \"x1hyak1l\",\n kHenm0: \"xtt52l0\",\n kmVPX3: \"x14odnwx\",\n kMzoRj: \"xc342km\",\n ksu8eU: \"x1y0btm7\",\n kVAM5u: \"xy1lt07\",\n kaIpWk: \"x1sxf85j\",\n kWkggS: \"xjbqb8w\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"x1j61zf2\",\n kLWn49: \"x1evy7pa\",\n kMwMTN: \"xqvuw85\",\n k3Woio: \"x16dl9wz\",\n kiEn40: \"x7s97pk\",\n $$css: true\n },\n attachButton: {\n k1xSpc: \"x3nfvp2\",\n kGNEyG: \"x6s0dn4\",\n kAzted: \"x1ba4aug x126n28w\",\n kmVPX3: \"x153ncpu\",\n kB7OPa: \"x9f619\",\n kMzoRj: \"xmkeg23\",\n ksu8eU: \"x1y0btm7\",\n kVAM5u: \"xy1lt07\",\n kaIpWk: \"x1sxf85j\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xfifm61\",\n kMwMTN: \"xqvuw85\",\n kkrTdU: \"x1ypdohk\",\n k8PahR: \"xt2bx3g\",\n kfQpEX: \"x1fanpfn\",\n $$css: true\n },\n uploadInput: {\n kVAEAm: \"x10l6tqk\",\n kzqmXN: \"x1i1rx1s\",\n kZKoxP: \"xjm9jq1\",\n kz4h6p: \"x1hyvwdk\",\n kVQacm: \"xb3r6kr\",\n khDVqt: \"xuxw1ft\",\n $$css: true\n },\n uploadList: {\n k1xSpc: \"x78zum5\",\n kwnvtZ: \"xozqiw3\",\n kmuXW: \"x2lah0s\",\n kOIVth: \"x167g77z\",\n kogj98: \"x1ghz6dp\",\n kmVPX3: \"x1717udv\",\n kH6xsr: \"x3ct3a4\",\n $$css: true\n },\n upload: {\n k1xSpc: \"x78zum5\",\n kGNEyG: \"x6s0dn4\",\n kOIVth: \"x17d4w8g\",\n kmuXW: \"x2lah0s\",\n kogj98: \"x1ghz6dp\",\n ks0D6T: \"x1jkqq1h\",\n kMv6JI: \"xa9opjo\",\n kGuDYH: \"x1j6dyjg\",\n k63SB2: \"xo1l8bm\",\n kMwMTN: \"x1ar3pfp\",\n kHjlTd: \"xj0a0fe\",\n $$css: true\n },\n button: {\n kAzted: \"x1gg8mnh\",\n kmVPX3: \"x153ncpu\",\n kMzoRj: \"xmkeg23\",\n ksu8eU: \"x1y0btm7\",\n kVAM5u: \"xy1lt07\",\n kaIpWk: \"x1sxf85j\",\n kWkggS: \"xjbqb8w\",\n kMwMTN: \"xqvuw85\",\n kMv6JI: \"x5ddh9m\",\n kGuDYH: \"xfifm61\",\n kkrTdU: \"x1ypdohk\",\n k3Woio: \"x16dl9wz\",\n kiEn40: \"x7s97pk\",\n kWCcOm: \"xijokvz\",\n kYPGJ8: \"xtgyt42\",\n $$css: true\n },\n primaryButton: {\n kWkggS: \"x15vqgvx\",\n kVAM5u: \"xawfzfr\",\n kMwMTN: \"xb8ja0n\",\n $$css: true\n },\n subheading: {\n kogj98: \"x1ghz6dp\",\n kLWn49: \"x1evy7pa\",\n $$css: true\n }\n};\nexport function chatClass(name: string, ...styles: stylex.StyleXStyles[]): string {\n return `${name} ${stylex.props(...styles).className ?? \"\"}`;\n}",
|
|
12
|
+
"/** @jsxImportSource react */\nimport { useEffect, useRef, useState, type ReactElement } from \"react\";\nimport { Button, Input } from \"@brains/app-ui-react\";\nimport { getErrorMessage } from \"@brains/utils/error\";\nimport { chatClass, chatLayout } from \"./studio-chat-layout.styles\";\n\nexport function StudioChatSessionRename(props: {\n title: string;\n onRename: (title: string) => Promise<void>;\n}): ReactElement {\n const [editing, setEditing] = useState(false);\n const [title, setTitle] = useState(props.title);\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const mounted = useRef(false);\n const pendingRequest = useRef(false);\n const input = useRef<HTMLInputElement | null>(null);\n useEffect(() => {\n if (editing) input.current?.focus();\n }, [editing]);\n const trigger = useRef<HTMLSpanElement | null>(null);\n useEffect(() => {\n mounted.current = true;\n return (): void => {\n mounted.current = false;\n };\n }, []);\n const finish = (): void => {\n setEditing(false);\n setError(null);\n requestAnimationFrame(() =>\n trigger.current?.querySelector(\"button\")?.focus(),\n );\n };\n const rename = async (): Promise<void> => {\n if (pendingRequest.current || !title.trim()) return;\n pendingRequest.current = true;\n setPending(true);\n setError(null);\n try {\n await props.onRename(title.trim());\n if (mounted.current) finish();\n } catch (cause) {\n if (mounted.current)\n setError(\n getErrorMessage(\n cause,\n \"Rename failed. Your proposed title is kept.\",\n ) || \"Rename failed. Your proposed title is kept.\",\n );\n } finally {\n pendingRequest.current = false;\n if (mounted.current) setPending(false);\n }\n };\n return (\n <>\n <span ref={trigger}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-expanded={editing}\n disabled={editing}\n onClick={() => {\n setTitle(props.title);\n setEditing(true);\n }}\n >\n Rename\n </Button>\n </span>\n {editing && (\n <form\n className={chatClass(\n \"studio-chat-rename\",\n chatLayout.sessionControls,\n )}\n onSubmit={(event) => {\n event.preventDefault();\n void rename();\n }}\n >\n <label>\n Conversation title\n <Input\n ref={input}\n xstyle={chatLayout.sessionFilterSelect}\n value={title}\n onChange={(event) => setTitle(event.target.value)}\n required\n maxLength={48}\n disabled={pending}\n />\n </label>\n <div className={chatClass(\"\", chatLayout.actions)}>\n <Button type=\"submit\" disabled={pending || !title.trim()}>\n {pending ? \"Renaming…\" : \"Save title\"}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={pending}\n onClick={finish}\n >\n Cancel\n </Button>\n </div>\n {error && <p role=\"alert\">{error}</p>}\n </form>\n )}\n </>\n );\n}\n",
|
|
13
|
+
"export const defaultMessageUploadFilename = \"upload.txt\";\nexport const messageTextUploadAccept =\n \".md,.txt,.markdown,text/plain,text/markdown,text/x-markdown\";\nexport const messageBinaryUploadAccept =\n \".png,.jpg,.jpeg,.webp,.gif,.pdf,image/png,image/jpeg,image/webp,image/gif,application/pdf\";\nexport const messageUploadAccept =\n \".md,.txt,.markdown,.png,.jpg,.jpeg,.webp,.gif,.pdf,text/plain,text/markdown,text/x-markdown,image/png,image/jpeg,image/webp,image/gif,application/pdf\";\nexport const messageTextUploadMaxBytes = 100_000;\nexport const messageUploadMaxBytes = 5_000_000;\n\nconst textFileExtensions = [\".md\", \".txt\", \".markdown\"];\nconst textMimeTypes = [\"text/plain\", \"text/markdown\", \"text/x-markdown\"];\nconst binaryFileExtensionMediaTypes = new Map([\n [\".png\", \"image/png\"],\n [\".jpg\", \"image/jpeg\"],\n [\".jpeg\", \"image/jpeg\"],\n [\".webp\", \"image/webp\"],\n [\".gif\", \"image/gif\"],\n [\".pdf\", \"application/pdf\"],\n]);\nconst binaryMimeTypes = new Set(binaryFileExtensionMediaTypes.values());\n\nexport type MessageUploadPolicyErrorCode =\n \"unsupported_type\" | \"file_too_large\" | \"binary_content\";\n\nexport interface ValidatedTextUpload {\n ok: true;\n filename: string;\n mediaType: string;\n sizeBytes: number;\n text: string;\n}\n\nexport interface ValidatedFileUpload {\n ok: true;\n kind: \"file\";\n filename: string;\n mediaType: string;\n sizeBytes: number;\n}\n\nexport interface InvalidUpload {\n ok: false;\n code: MessageUploadPolicyErrorCode;\n message: string;\n}\n\nexport type TextUploadValidationResult = ValidatedTextUpload | InvalidUpload;\n\nexport type ValidatedMessageUpload =\n (ValidatedTextUpload & { kind: \"text\" }) | ValidatedFileUpload;\n\nexport type MessageUploadValidationResult =\n ValidatedMessageUpload | InvalidUpload;\n\nexport interface ValidateUploadInput {\n filename: string;\n mediaType: string | undefined;\n content: Uint8Array;\n fallbackFilename?: string | undefined;\n}\n\nexport function sanitizeUploadFilename(\n filename: string,\n fallbackFilename: string = defaultMessageUploadFilename,\n): string {\n const leaf = filename.split(/[\\\\/]/).at(-1)?.trim() ?? \"\";\n const cleaned = Array.from(leaf)\n .filter((char: string) => {\n const code = char.charCodeAt(0);\n return code > 31 && code !== 127;\n })\n .join(\"\")\n .slice(0, 160);\n return cleaned.length > 0 ? cleaned : fallbackFilename;\n}\n\nexport function normalizeTextUploadMediaType(\n filename: string,\n mediaType: string | undefined,\n): string {\n const trimmed = mediaType?.trim() ?? \"\";\n if (trimmed.length > 0) return trimmed;\n\n const lowerFilename = filename.toLowerCase();\n if (lowerFilename.endsWith(\".md\") || lowerFilename.endsWith(\".markdown\")) {\n return \"text/markdown\";\n }\n if (lowerFilename.endsWith(\".txt\")) {\n return \"text/plain\";\n }\n return \"application/octet-stream\";\n}\n\nexport function normalizeMessageUploadMediaType(\n filename: string,\n mediaType: string | undefined,\n): string {\n const trimmed = mediaType?.trim() ?? \"\";\n const explicitMediaType = trimmed.split(\";\", 1)[0]?.toLowerCase() ?? trimmed;\n if (\n explicitMediaType.length > 0 &&\n explicitMediaType !== \"application/octet-stream\"\n ) {\n return explicitMediaType;\n }\n\n const textMediaType = normalizeTextUploadMediaType(filename, undefined);\n if (textMediaType !== \"application/octet-stream\") return textMediaType;\n\n const lowerFilename = filename.toLowerCase();\n for (const [extension, extensionMediaType] of binaryFileExtensionMediaTypes) {\n if (lowerFilename.endsWith(extension)) return extensionMediaType;\n }\n return \"application/octet-stream\";\n}\n\nexport function isUploadableTextFile(\n filename: string,\n mediaType: string | undefined,\n): boolean {\n if (\n mediaType &&\n textMimeTypes.some((type) => mediaType.toLowerCase().startsWith(type))\n ) {\n return true;\n }\n return textFileExtensions.some((extension) =>\n filename.toLowerCase().endsWith(extension),\n );\n}\n\nexport function isTextUploadSizeAllowed(sizeBytes: number): boolean {\n return sizeBytes <= messageTextUploadMaxBytes;\n}\n\nexport function isMessageUploadSizeAllowed(sizeBytes: number): boolean {\n return sizeBytes <= messageUploadMaxBytes;\n}\n\nexport function isUploadableBinaryFile(\n filename: string,\n mediaType: string | undefined,\n): boolean {\n const normalizedMediaType = normalizeMessageUploadMediaType(\n filename,\n mediaType,\n );\n if (binaryMimeTypes.has(normalizedMediaType)) return true;\n\n return binaryFileExtensionMediaTypes.has(getLowercaseExtension(filename));\n}\n\nexport function getMessageUploadKind(\n filename: string,\n mediaType: string | undefined,\n): \"text\" | \"file\" | undefined {\n const normalizedMediaType = normalizeMessageUploadMediaType(\n filename,\n mediaType,\n );\n if (isUploadableTextFile(filename, normalizedMediaType)) return \"text\";\n if (isUploadableBinaryFile(filename, normalizedMediaType)) return \"file\";\n return undefined;\n}\n\nexport function isMessageUploadDeclaredSizeAllowed(\n uploadKind: \"text\" | \"file\",\n sizeBytes: number,\n): boolean {\n if (sizeBytes <= 0) return true;\n return uploadKind === \"text\"\n ? isTextUploadSizeAllowed(sizeBytes)\n : isMessageUploadSizeAllowed(sizeBytes);\n}\n\nexport function isLikelyUtf8Text(bytes: Uint8Array): boolean {\n if (bytes.includes(0)) return false;\n try {\n new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function validateTextUpload(\n input: ValidateUploadInput,\n): TextUploadValidationResult {\n const filename = sanitizeUploadFilename(\n input.filename,\n input.fallbackFilename,\n );\n const mediaType = normalizeTextUploadMediaType(filename, input.mediaType);\n if (!isUploadableTextFile(filename, mediaType)) {\n return {\n ok: false,\n code: \"unsupported_type\",\n message: `Unsupported file upload type: ${filename}`,\n };\n }\n\n if (!isTextUploadSizeAllowed(input.content.byteLength)) {\n return {\n ok: false,\n code: \"file_too_large\",\n message: `File upload too large: ${filename}`,\n };\n }\n\n if (!isLikelyUtf8Text(input.content)) {\n return {\n ok: false,\n code: \"binary_content\",\n message: `Unsupported file upload type: ${filename}`,\n };\n }\n\n return {\n ok: true,\n filename,\n mediaType,\n sizeBytes: input.content.byteLength,\n text: new TextDecoder(\"utf-8\").decode(input.content).replace(/^\\uFEFF/, \"\"),\n };\n}\n\nexport function validateMessageUpload(\n input: ValidateUploadInput,\n): MessageUploadValidationResult {\n const filename = sanitizeUploadFilename(\n input.filename,\n input.fallbackFilename,\n );\n const mediaType = normalizeMessageUploadMediaType(filename, input.mediaType);\n\n if (isUploadableTextFile(filename, mediaType)) {\n const textUpload = validateTextUpload({\n filename,\n mediaType,\n content: input.content,\n ...(input.fallbackFilename !== undefined && {\n fallbackFilename: input.fallbackFilename,\n }),\n });\n return textUpload.ok ? { ...textUpload, kind: \"text\" } : textUpload;\n }\n\n if (!isUploadableBinaryFile(filename, mediaType)) {\n return {\n ok: false,\n code: \"unsupported_type\",\n message: `Unsupported file upload type: ${filename}`,\n };\n }\n\n if (!isMessageUploadSizeAllowed(input.content.byteLength)) {\n return {\n ok: false,\n code: \"file_too_large\",\n message: `File upload too large: ${filename}`,\n };\n }\n\n if (!hasExpectedBinarySignature(input.content, mediaType)) {\n return {\n ok: false,\n code: \"unsupported_type\",\n message: `Unsupported file upload type: ${filename}`,\n };\n }\n\n return {\n ok: true,\n kind: \"file\",\n filename,\n mediaType,\n sizeBytes: input.content.byteLength,\n };\n}\n\nfunction getLowercaseExtension(filename: string): string {\n const dotIndex = filename.lastIndexOf(\".\");\n return dotIndex >= 0 ? filename.slice(dotIndex).toLowerCase() : \"\";\n}\n\nfunction hasExpectedBinarySignature(\n bytes: Uint8Array,\n mediaType: string,\n): boolean {\n switch (mediaType) {\n case \"image/png\":\n return startsWithBytes(bytes, [0x89, 0x50, 0x4e, 0x47]);\n case \"image/jpeg\":\n return startsWithBytes(bytes, [0xff, 0xd8, 0xff]);\n case \"image/gif\":\n return (\n startsWithAscii(bytes, \"GIF87a\") || startsWithAscii(bytes, \"GIF89a\")\n );\n case \"image/webp\":\n return startsWithAscii(bytes, \"RIFF\") && hasAsciiAt(bytes, \"WEBP\", 8);\n case \"application/pdf\":\n return startsWithAscii(bytes, \"%PDF-\");\n default:\n return false;\n }\n}\n\nfunction startsWithBytes(bytes: Uint8Array, expected: number[]): boolean {\n return expected.every((byte, index) => bytes[index] === byte);\n}\n\nfunction startsWithAscii(bytes: Uint8Array, expected: string): boolean {\n return hasAsciiAt(bytes, expected, 0);\n}\n\nfunction hasAsciiAt(\n bytes: Uint8Array,\n expected: string,\n offset: number,\n): boolean {\n return Array.from(expected).every(\n (char, index) => bytes[offset + index] === char.charCodeAt(0),\n );\n}\n",
|
|
14
|
+
"/** @jsxImportSource react */\nimport { libraryStyles as library } from \"./studio-library.styles\";\nimport { StudioChatAttachment } from \"./studio-chat-attachment\";\nimport { StudioChatSessionRename } from \"./studio-chat-session-rename\";\nimport {\n messageUploadAccept,\n messageTextUploadMaxBytes,\n messageUploadMaxBytes,\n} from \"@brains/plugins/message-interface/upload-policy\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogTitle,\n NativeSelect,\n} from \"@brains/app-ui-react\";\nimport { chatClass, chatLayout } from \"./studio-chat-layout.styles\";\nimport {\n StudioChatDraftStore,\n studioChatDraftKey,\n type StudioChatNavigationState,\n} from \"./studio-chat-drafts\";\nimport { typographyStyles } from \"./studio-typography.styles\";\nimport {\n createChatClient,\n readChatProtocolEvents,\n type ChatCard,\n type ChatClient,\n type ChatHistoryMessage,\n type ChatMessage,\n type ChatSession,\n type ChatUploadResponse,\n} from \"@brains/contracts/chat\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ChangeEvent,\n type FormEvent,\n type KeyboardEvent,\n type ReactElement,\n} from \"react\";\nimport {\n STUDIO_CHAT_WORKSPACE_ID,\n studioChatWorkspacePath,\n} from \"../../src/chat-workspace\";\nimport type { EntityTypeInfo, StudioWorkspaceInfo } from \"./api\";\nimport type { StudioChatHandoff } from \"./operator-launch\";\nimport {\n approvalResponseMessage,\n createStudioChatStreamState,\n reduceStudioChatStream,\n streamAssistantMessage,\n type StudioChatApproval,\n type StudioChatStreamState,\n} from \"./chat-workspace-model\";\nimport { TypeSwitcher } from \"./entity-fields\";\nimport { useStudioNavigationCollapsed } from \"./studio-navigation-state\";\nimport { StudioChrome } from \"./studio-chrome\";\nimport { StudioSearchField } from \"./studio-search-field\";\nimport { StudioMarkdown } from \"./studio-markdown\";\nimport {\n navigationClassName as navClass,\n navigationStyles as nav,\n} from \"./studio-navigation.styles\";\n\nconst CHAT_UPLOAD_GUIDANCE = `Text/Markdown up to ${messageTextUploadMaxBytes / 1000} KB; PNG, JPEG, WebP, GIF or PDF up to ${messageUploadMaxBytes / 1000000} MB.`;\n\nconst studioChatKeys = {\n sessions: [\"studio\", \"chat\", \"sessions\"] as const,\n messages: (conversationId: string) =>\n [\"studio\", \"chat\", \"messages\", conversationId] as const,\n};\n\ntype ChatActionCard = Extract<ChatCard, { kind: \"actions\" }>;\ntype ChatSuggestedAction = ChatActionCard[\"actions\"][number];\n\ninterface SessionView {\n query: string;\n archived: boolean;\n offset: number;\n}\n\ninterface ChatUploadAttempt {\n id: string;\n file: File;\n status: \"uploading\" | \"failed\";\n error?: string;\n}\n\ninterface InterruptedResponse {\n kind: \"stopped\" | \"disconnected\" | \"failed\";\n detail?: string;\n retry?: { text: string; uploads: ChatUploadResponse[] };\n}\n\nexport interface StudioChatWorkspaceProps {\n apiPath?: string | undefined;\n draftStore?: StudioChatDraftStore | undefined;\n onNavigationStateChange?:\n ((state: StudioChatNavigationState) => void) | undefined;\n studioBasePath: string;\n sessionId: string | null;\n types: EntityTypeInfo[];\n workspaces: StudioWorkspaceInfo[];\n handoff: StudioChatHandoff | null;\n navigate: (href: string, options?: { preserveWork?: boolean }) => void;\n selectEntityType: (entityType: string) => void;\n selectWorkspace: (workspaceId: string) => void;\n}\n\nexport function StudioChatWorkspace(\n props: StudioChatWorkspaceProps,\n): ReactElement {\n const queryClient = useQueryClient();\n const chatClient = useMemo(\n () =>\n createChatClient({\n apiPath: props.apiPath,\n fetch: (input, init) => globalThis.fetch(input, init),\n }),\n [props.apiPath],\n );\n const [localDraftStore] = useState(() => new StudioChatDraftStore());\n const draftStore = props.draftStore ?? localDraftStore;\n const draftKey = studioChatDraftKey(props.apiPath, props.sessionId);\n const currentDraftKey = useRef(draftKey);\n currentDraftKey.current = draftKey;\n const { text: draft, uploads } = useSyncExternalStore(\n draftStore.subscribe,\n () => draftStore.read(draftKey),\n () => draftStore.read(draftKey),\n );\n const setDraft = useCallback(\n (text: string) => draftStore.update(draftKey, { text }),\n [draftStore, draftKey],\n );\n const setUploads = useCallback(\n (\n value:\n | ChatUploadResponse[]\n | ((current: ChatUploadResponse[]) => ChatUploadResponse[]),\n ) =>\n draftStore.update(draftKey, {\n uploads:\n typeof value === \"function\"\n ? value(draftStore.read(draftKey).uploads)\n : value,\n }),\n [draftStore, draftKey],\n );\n const [pendingMessages, setPendingMessages] = useState<ChatHistoryMessage[]>(\n [],\n );\n const [stream, setStream] = useState<StudioChatStreamState | null>(null);\n const [sending, setSending] = useState(false);\n const [archiving, setArchiving] = useState(false);\n const [uploading, setUploading] = useState(false);\n const [uploadAttempts, setUploadAttempts] = useState<ChatUploadAttempt[]>([]);\n const uploadBatchRef = useRef<symbol | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [interrupted, setInterrupted] = useState<InterruptedResponse | null>(\n null,\n );\n useEffect(() => {\n props.onNavigationStateChange?.({\n hasDraft: Boolean(draft || uploads.length || uploadAttempts.length),\n busy: sending || uploading,\n });\n }, [\n draft,\n uploads,\n uploadAttempts,\n sending,\n uploading,\n props.onNavigationStateChange,\n ]);\n useEffect(\n () => (): void =>\n props.onNavigationStateChange?.({ hasDraft: false, busy: false }),\n [props.onNavigationStateChange],\n );\n const navigationCollapsed = useStudioNavigationCollapsed();\n const [sessionPickerOpen, setSessionPickerOpen] = useState(false);\n const [detailsOpen, setDetailsOpen] = useState(false);\n const detailsTrigger = useRef<HTMLSpanElement>(null);\n const sessionPickerTrigger = useRef<HTMLSpanElement>(null);\n const threadEndRef = useRef<HTMLDivElement | null>(null);\n const threadScrollRef = useRef<HTMLDivElement | null>(null);\n const followLatestRef = useRef(true);\n const [showJumpToLatest, setShowJumpToLatest] = useState(false);\n const activeStreamRef = useRef<AbortController | null>(null);\n const mountedRef = useRef(false);\n useEffect(() => {\n mountedRef.current = true;\n return (): void => {\n mountedRef.current = false;\n uploadBatchRef.current = null;\n const active = activeStreamRef.current;\n activeStreamRef.current = null;\n active?.abort();\n };\n }, []);\n const handledHandoffRef = useRef<string | null>(null);\n const adoptedSessionRef = useRef<string | null>(null);\n\n const [sessionSearch, setSessionSearch] = useState(\"\");\n const [sessionView, setSessionView] = useState<SessionView>({\n query: \"\",\n archived: false,\n offset: 0,\n });\n useEffect(() => {\n const timer = window.setTimeout(\n () =>\n setSessionView((current) =>\n current.query === sessionSearch.trim()\n ? current\n : { ...current, query: sessionSearch.trim(), offset: 0 },\n ),\n 250,\n );\n return (): void => window.clearTimeout(timer);\n }, [sessionSearch]);\n const sessionsQuery = useQuery({\n queryKey: [...studioChatKeys.sessions, sessionView],\n queryFn: () => chatClient.listSessions(sessionView),\n });\n const messagesQuery = useQuery({\n queryKey: studioChatKeys.messages(props.sessionId ?? \"\"),\n queryFn: () => chatClient.getMessages(props.sessionId ?? \"\"),\n // A newly accepted session already has an optimistic copy of its first\n // turn. Wait for the completed stream to replace that copy atomically.\n enabled:\n props.sessionId !== null && !sending && pendingMessages.length === 0,\n });\n const sessions = sessionsQuery.data ?? [];\n const storedMessages = messagesQuery.data ?? [];\n const currentSession =\n sessions.find((session) => session.id === props.sessionId) ??\n queryClient\n .getQueriesData<ChatSession[]>({ queryKey: studioChatKeys.sessions })\n .flatMap(([, items]) => items ?? [])\n .find((session) => session.id === props.sessionId);\n const archivedSession = currentSession?.archived === true;\n const sessionControls = {\n search: sessionSearch,\n view: sessionView,\n error: sessionsQuery.error ? \"Sessions could not be loaded.\" : null,\n onRetry: (): void => {\n void sessionsQuery.refetch();\n },\n onSearch: setSessionSearch,\n onView: setSessionView,\n };\n const visibleMessages = useMemo(() => {\n const next = [...storedMessages, ...pendingMessages];\n if (stream && (stream.text || stream.cards.length > 0)) {\n next.push(streamAssistantMessage(stream));\n }\n return next;\n }, [pendingMessages, storedMessages, stream]);\n const contextCards = useMemo(\n () =>\n visibleMessages.flatMap((message) =>\n (message.cards ?? []).filter(\n (card) => card.kind === \"sources\" || card.kind === \"attachment\",\n ),\n ),\n [visibleMessages],\n );\n\n useEffect(() => {\n setDetailsOpen(false);\n setSessionPickerOpen(false);\n if (props.sessionId && adoptedSessionRef.current === props.sessionId) {\n adoptedSessionRef.current = null;\n return;\n }\n const active = activeStreamRef.current;\n activeStreamRef.current = null;\n active?.abort();\n setSending(false);\n setPendingMessages([]);\n setStream(null);\n setUploading(false);\n uploadBatchRef.current = null;\n setUploadAttempts([]);\n setArchiving(false);\n setError(null);\n setInterrupted(null);\n }, [props.sessionId]);\n\n useEffect(() => {\n followLatestRef.current = true;\n setShowJumpToLatest(false);\n }, [props.sessionId]);\n\n useEffect(() => {\n const scroll = threadScrollRef.current;\n const manuscript = scroll?.firstElementChild;\n if (!scroll || !manuscript) return;\n const follow = (): void => {\n if (followLatestRef.current) scroll.scrollTop = scroll.scrollHeight;\n };\n follow();\n const observer = new ResizeObserver(follow);\n observer.observe(manuscript);\n return (): void => observer.disconnect();\n }, []);\n\n useEffect(() => {\n if (followLatestRef.current) {\n const scroll = threadScrollRef.current;\n if (scroll) scroll.scrollTop = scroll.scrollHeight;\n }\n }, [stream, visibleMessages.length]);\n\n const navigateToSession = useCallback(\n (conversationId?: string, preserveWork = false): void => {\n props.navigate(\n studioChatWorkspacePath(props.studioBasePath, conversationId),\n { preserveWork },\n );\n setSessionPickerOpen(false);\n setDetailsOpen(false);\n },\n [props.navigate, props.studioBasePath],\n );\n\n useEffect(() => {\n if (!props.handoff || props.sessionId) return;\n const handoffKey = `${props.handoff.sourceId}\\u0000${props.handoff.itemId}`;\n if (handledHandoffRef.current === handoffKey) return;\n handledHandoffRef.current = handoffKey;\n setDraft(props.handoff.prompt);\n setError(null);\n void chatClient\n .openContextSession({\n version: 1,\n sourceId: props.handoff.sourceId,\n itemId: props.handoff.itemId,\n titleSeed: props.handoff.label,\n })\n .then(({ conversationId }) => {\n if (\n !mountedRef.current ||\n currentDraftKey.current !== draftKey ||\n handledHandoffRef.current !== handoffKey\n )\n return;\n draftStore.adopt(\n draftKey,\n studioChatDraftKey(props.apiPath, conversationId),\n );\n navigateToSession(conversationId, true);\n })\n .catch((cause: unknown) => {\n if (\n !mountedRef.current ||\n currentDraftKey.current !== draftKey ||\n handledHandoffRef.current !== handoffKey\n )\n return;\n handledHandoffRef.current = null;\n setError(errorMessage(cause, \"Context could not be attached\"));\n });\n }, [\n chatClient,\n navigateToSession,\n props.handoff,\n props.sessionId,\n props.apiPath,\n draftStore,\n draftKey,\n setDraft,\n ]);\n\n const runStream = useCallback(\n async (\n conversationId: string,\n messages: ChatMessage[],\n onAccepted?: () => void,\n retry?: InterruptedResponse[\"retry\"],\n ): Promise<boolean> => {\n activeStreamRef.current?.abort();\n const controller = new AbortController();\n activeStreamRef.current = controller;\n setSending(true);\n setError(null);\n setInterrupted(null);\n let stoppedByServer = false;\n let next: StudioChatStreamState = {\n ...createStudioChatStreamState(),\n messageId: crypto.randomUUID(),\n };\n setStream(next);\n let accepted = false;\n let retained = false;\n const retainResponse = (): void => {\n if (retained || (!next.text && next.cards.length === 0)) return;\n retained = true;\n const message = streamAssistantMessage(next);\n setPendingMessages((current) => [...current, message]);\n setStream({ ...next, text: \"\", cards: [] });\n };\n try {\n const response = await chatClient.streamMessages(\n {\n id: conversationId,\n messages,\n trigger: \"submit-message\",\n },\n { signal: controller.signal },\n );\n accepted = true;\n onAccepted?.();\n for await (const event of readChatProtocolEvents(response)) {\n if (activeStreamRef.current !== controller) return accepted;\n if (event.type === \"abort\") stoppedByServer = true;\n next = reduceStudioChatStream(next, event);\n setStream(next);\n }\n if (activeStreamRef.current !== controller) return accepted;\n retainResponse();\n if (\n controller.signal.aborted ||\n stoppedByServer ||\n next.error !== null ||\n !next.finished\n ) {\n setInterrupted({\n kind:\n controller.signal.aborted || stoppedByServer\n ? \"stopped\"\n : next.error !== null\n ? \"failed\"\n : \"disconnected\",\n ...(next.error ? { detail: next.error } : {}),\n ...(retry ? { retry } : {}),\n });\n return accepted;\n }\n try {\n const authoritativeMessages =\n await chatClient.getMessages(conversationId);\n if (activeStreamRef.current !== controller) return accepted;\n queryClient.setQueryData(\n studioChatKeys.messages(conversationId),\n authoritativeMessages,\n );\n setPendingMessages([]);\n // History now owns the completed turn, including its approvals.\n // Keep the live state only when this read fails.\n setStream(null);\n } catch {\n // The completed response remains visible from the optimistic state;\n // a later session visit can retry the authoritative history read.\n }\n await queryClient.invalidateQueries({\n queryKey: studioChatKeys.sessions,\n });\n } catch (cause) {\n if (activeStreamRef.current !== controller) return accepted;\n retainResponse();\n setInterrupted({\n kind: controller.signal.aborted\n ? \"stopped\"\n : accepted\n ? \"disconnected\"\n : \"failed\",\n ...(!controller.signal.aborted\n ? {\n detail: errorMessage(\n cause,\n \"Chat could not complete the response\",\n ),\n }\n : {}),\n ...(retry ? { retry } : {}),\n });\n } finally {\n if (activeStreamRef.current === controller) {\n activeStreamRef.current = null;\n setSending(false);\n }\n }\n return accepted;\n },\n [chatClient, queryClient],\n );\n\n const submitPrompt = useCallback(\n async (prompt: string): Promise<void> => {\n const text = prompt.trim();\n if (\n (!text && uploads.length === 0) ||\n sending ||\n uploading ||\n uploadAttempts.length > 0\n )\n return;\n const conversationId = props.sessionId ?? `web-${crypto.randomUUID()}`;\n const sentKey = studioChatDraftKey(props.apiPath, conversationId);\n const messageId = crypto.randomUUID();\n const uploadParts = uploads.map((upload) => ({\n type: \"data-upload\" as const,\n data: { ref: upload.ref },\n }));\n const parts = [\n ...(text ? [{ type: \"text\" as const, text }] : []),\n ...uploadParts,\n ];\n setPendingMessages((current) => [\n ...current,\n {\n id: messageId,\n role: \"user\",\n content: text,\n cards: uploads.map((upload): ChatCard => ({\n kind: \"attachment\",\n id: upload.id,\n title: upload.filename,\n attachment: {\n mediaType: upload.mediaType,\n filename: upload.filename,\n sizeBytes: upload.sizeBytes,\n url: upload.url,\n downloadUrl: upload.downloadUrl,\n },\n })),\n },\n ]);\n // The transcript owns the message from here, so the composer empties now\n // rather than when the server answers; a refusal puts the draft back. A\n // suggested action carries its own prompt and never empties the composer.\n const sentUploads = [...uploads];\n const held = draftStore.read(draftKey);\n const sentFromComposer = held.text === prompt;\n if (sentFromComposer || sentUploads.length > 0)\n draftStore.update(draftKey, {\n text: sentFromComposer ? \"\" : held.text,\n uploads: held.uploads.filter(\n (upload) => !sentUploads.some((sent) => sent.id === upload.id),\n ),\n });\n const accepted = await runStream(\n conversationId,\n [{ id: messageId, role: \"user\", parts }],\n () => {\n if (\n !props.sessionId &&\n mountedRef.current &&\n currentDraftKey.current === draftKey\n ) {\n draftStore.adopt(draftKey, sentKey);\n adoptedSessionRef.current = conversationId;\n navigateToSession(conversationId, true);\n }\n },\n { text: prompt, uploads: [...uploads] },\n );\n if (\n !accepted &&\n (currentDraftKey.current === sentKey ||\n (!props.sessionId && currentDraftKey.current === draftKey))\n ) {\n setPendingMessages((current) =>\n current.filter((message) => message.id !== messageId),\n );\n // Restore into whichever conversation the composer now shows, keeping\n // anything typed while the request was in flight.\n const key = currentDraftKey.current;\n const current = draftStore.read(key);\n draftStore.update(key, {\n ...(sentFromComposer && !current.text ? { text: prompt } : {}),\n uploads: [\n ...sentUploads.filter(\n (upload) =>\n !current.uploads.some((kept) => kept.id === upload.id),\n ),\n ...current.uploads,\n ],\n });\n }\n },\n [\n navigateToSession,\n props.sessionId,\n props.apiPath,\n draftStore,\n draftKey,\n runStream,\n sending,\n uploading,\n uploads,\n uploadAttempts.length,\n ],\n );\n\n const submit = (event: FormEvent<HTMLFormElement>): void => {\n event.preventDefault();\n void submitPrompt(draft);\n };\n\n const respondToApproval = useCallback(\n async (approval: StudioChatApproval, approved: boolean): Promise<void> => {\n if (!props.sessionId || sending) return;\n await runStream(props.sessionId, [\n approvalResponseMessage(approval, approved),\n ]);\n },\n [props.sessionId, runStream, sending],\n );\n\n const runSuggestedAction = useCallback(\n async (action: ChatSuggestedAction): Promise<void> => {\n if (action.type === \"prompt\") {\n await submitPrompt(action.prompt);\n return;\n }\n if (!props.sessionId || sending) return;\n setSending(true);\n setError(null);\n try {\n const result = await chatClient.runAction({\n conversationId: props.sessionId,\n action: {\n type: \"event\",\n event: action.event,\n ...(action.fromState ? { fromState: action.fromState } : {}),\n },\n });\n if (!mountedRef.current || currentDraftKey.current !== draftKey) return;\n setPendingMessages((current) => [\n ...current,\n {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: result.text,\n ...(result.cards ? { cards: result.cards } : {}),\n },\n ]);\n } catch (cause) {\n if (mountedRef.current && currentDraftKey.current === draftKey)\n setError(errorMessage(cause, \"Chat action failed\"));\n } finally {\n if (mountedRef.current && currentDraftKey.current === draftKey)\n setSending(false);\n }\n },\n [chatClient, props.sessionId, sending, submitPrompt, draftKey],\n );\n\n const runUploads = useCallback(\n async (attempts: ChatUploadAttempt[]): Promise<void> => {\n if (uploadBatchRef.current || attempts.length === 0) return;\n const batch = Symbol();\n uploadBatchRef.current = batch;\n setUploading(true);\n setUploadAttempts((current) => [\n ...current.filter(\n (item) => !attempts.some((attempt) => attempt.id === item.id),\n ),\n ...attempts.map((attempt): ChatUploadAttempt => ({\n id: attempt.id,\n file: attempt.file,\n status: \"uploading\",\n })),\n ]);\n await Promise.all(\n attempts.map(async (attempt): Promise<void> => {\n try {\n const upload = await chatClient.upload(\n attempt.file,\n attempt.file.name,\n );\n if (\n uploadBatchRef.current !== batch ||\n currentDraftKey.current !== draftKey\n )\n return;\n setUploads((current) => [...current, upload]);\n setUploadAttempts((current) =>\n current.filter((item) => item.id !== attempt.id),\n );\n } catch (cause) {\n if (\n uploadBatchRef.current !== batch ||\n currentDraftKey.current !== draftKey\n )\n return;\n setUploadAttempts((current) =>\n current.map((item) =>\n item.id === attempt.id\n ? {\n ...item,\n status: \"failed\",\n error: errorMessage(cause, \"Upload failed\"),\n }\n : item,\n ),\n );\n }\n }),\n );\n if (uploadBatchRef.current === batch) {\n uploadBatchRef.current = null;\n setUploading(false);\n }\n },\n [chatClient, draftKey, setUploads],\n );\n\n const uploadFiles = useCallback(\n async (event: ChangeEvent<HTMLInputElement>): Promise<void> => {\n const files = Array.from(event.target.files ?? []);\n event.target.value = \"\";\n await runUploads(\n files.map((file) => ({\n id: crypto.randomUUID(),\n file,\n status: \"uploading\",\n })),\n );\n },\n [runUploads],\n );\n\n const archiveCurrent = useCallback(async (): Promise<void> => {\n if (\n !props.sessionId ||\n sending ||\n uploading ||\n draft ||\n uploads.length ||\n uploadAttempts.length\n )\n return;\n setSending(true);\n setArchiving(true);\n try {\n await chatClient.archiveSession(props.sessionId);\n await queryClient.invalidateQueries({\n queryKey: studioChatKeys.sessions,\n });\n if (mountedRef.current && currentDraftKey.current === draftKey)\n navigateToSession(undefined, true);\n } catch (cause) {\n if (mountedRef.current && currentDraftKey.current === draftKey)\n setError(errorMessage(cause, \"Conversation could not be archived\"));\n } finally {\n if (mountedRef.current && currentDraftKey.current === draftKey) {\n setSending(false);\n setArchiving(false);\n }\n }\n }, [\n chatClient,\n navigateToSession,\n props.sessionId,\n queryClient,\n sending,\n uploading,\n draft,\n uploads.length,\n uploadAttempts.length,\n draftKey,\n ]);\n\n const workspaceBadges = Object.fromEntries(\n props.workspaces.flatMap((workspace) =>\n workspace.badge === undefined ? [] : [[workspace.id, workspace.badge]],\n ),\n );\n\n return (\n <div\n className={chatClass(\"studio\", library.frame, chatLayout.root)}\n data-view=\"chat\"\n data-studio-shell=\"\"\n >\n <StudioChrome\n contextLabel=\"Chat\"\n navigation={{\n types: props.types,\n workspaces: props.workspaces,\n activeEntityType: null,\n activeWorkspaceId: STUDIO_CHAT_WORKSPACE_ID,\n workspaceBadges,\n selectEntityType: props.selectEntityType,\n selectWorkspace: props.selectWorkspace,\n }}\n />\n <div\n className={navClass(\n \"studio-chat-shell\",\n chatLayout.shell,\n nav.shell,\n navigationCollapsed && nav.shellCollapsed,\n )}\n >\n <aside className={navClass(\"rail studio-chat-studio-rail\", nav.rail)}>\n <TypeSwitcher\n renderMode=\"desktop\"\n types={props.types}\n active={null}\n onSelect={props.selectEntityType}\n workspaces={props.workspaces}\n activeWorkspace={STUDIO_CHAT_WORKSPACE_ID}\n workspaceBadges={workspaceBadges}\n onSelectWorkspace={props.selectWorkspace}\n />\n </aside>\n <main className={chatClass(\"studio-chat-workspace\", chatLayout.frame)}>\n <div className={chatClass(\"studio-chat-room\", chatLayout.room)}>\n <section\n className={chatClass(\"studio-chat-thread\", chatLayout.thread)}\n aria-label=\"Conversation\"\n >\n <header\n className={chatClass(\n \"studio-chat-thread-head\",\n chatLayout.threadHead,\n )}\n >\n <h1\n className={chatClass(\n \"studio-chat-session-heading\",\n chatLayout.title,\n )}\n title={currentSession?.title}\n >\n {currentSession?.title ??\n (props.sessionId ? \"Conversation\" : \"New conversation\")}\n </h1>\n <div\n className={chatClass(\n \"studio-chat-head-actions\",\n chatLayout.toolbar,\n )}\n >\n <span\n ref={sessionPickerTrigger}\n className=\"studio-chat-session-picker-trigger\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n xstyle={chatLayout.toolbarButton}\n aria-haspopup=\"dialog\"\n aria-expanded={sessionPickerOpen}\n onClick={() => setSessionPickerOpen(true)}\n >\n History\n </Button>\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n xstyle={chatLayout.toolbarButton}\n aria-label=\"New conversation\"\n title=\"New conversation\"\n onClick={() => navigateToSession()}\n >\n +\n </Button>\n <span ref={detailsTrigger}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n xstyle={chatLayout.toolbarButton}\n aria-label=\"Conversation details and options\"\n aria-haspopup=\"dialog\"\n aria-expanded={detailsOpen}\n onClick={() => setDetailsOpen(true)}\n >\n •••\n </Button>\n </span>\n </div>\n </header>\n <Dialog\n open={sessionPickerOpen}\n onOpenChange={setSessionPickerOpen}\n >\n <DialogContent\n aria-describedby={undefined}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n sessionPickerTrigger.current\n ?.querySelector(\"button\")\n ?.focus();\n }}\n >\n <DialogTitle>Conversations</DialogTitle>\n <SessionRail\n {...sessionControls}\n activeSessionId={props.sessionId}\n loading={sessionsQuery.isPending}\n sessions={sessions}\n onNew={() => navigateToSession()}\n onSelect={navigateToSession}\n />\n </DialogContent>\n </Dialog>\n <Dialog open={detailsOpen} onOpenChange={setDetailsOpen}>\n <DialogContent\n aria-describedby={undefined}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n detailsTrigger.current?.querySelector(\"button\")?.focus();\n }}\n >\n <DialogTitle>Conversation details</DialogTitle>\n <div\n className={chatClass(\n \"studio-chat-details\",\n chatLayout.details,\n )}\n >\n <p>{currentSession?.title ?? \"New conversation\"}</p>\n <div\n className={chatClass(\n \"studio-chat-session-actions\",\n chatLayout.actions,\n )}\n >\n {currentSession && (\n <StudioChatSessionRename\n key={currentSession.id}\n title={currentSession.title}\n onRename={async (title): Promise<void> => {\n const result = await chatClient.renameSession(\n currentSession.id,\n title,\n );\n if (!result.renamed)\n throw new Error(\n \"The conversation could not be renamed.\",\n );\n queryClient.setQueriesData<ChatSession[]>(\n { queryKey: studioChatKeys.sessions },\n (items) =>\n items?.map((session) =>\n session.id === currentSession.id\n ? { ...session, title: result.title }\n : session,\n ),\n );\n void queryClient.invalidateQueries({\n queryKey: studioChatKeys.sessions,\n });\n }}\n />\n )}\n {archivedSession && (\n <p role=\"status\">\n Archived conversation. New messages here remain\n archived.\n </p>\n )}\n {props.sessionId && !archivedSession ? (\n <Button\n className=\"studio-chat-header-action\"\n variant=\"ghost\"\n type=\"button\"\n onClick={() => void archiveCurrent()}\n disabled={\n sending ||\n uploading ||\n Boolean(draft) ||\n uploads.length > 0 ||\n uploadAttempts.length > 0\n }\n title={\n draft || uploads.length || uploadAttempts.length\n ? \"Send or clear the draft before archiving\"\n : undefined\n }\n >\n {archiving ? \"Archiving…\" : \"Archive\"}\n </Button>\n ) : null}\n </div>\n <details>\n <summary>Sources and attachments</summary>\n <ConversationContext\n cards={contextCards}\n progress={stream?.progress ?? []}\n session={currentSession}\n />\n </details>\n <details>\n <summary>File types and limits</summary>\n <p id=\"studio-chat-upload-guidance\">\n {CHAT_UPLOAD_GUIDANCE}\n </p>\n </details>\n </div>\n </DialogContent>\n </Dialog>\n <div\n ref={threadScrollRef}\n tabIndex={0}\n role=\"region\"\n aria-label=\"Conversation messages\"\n onScroll={(event) => {\n const scroll = event.currentTarget;\n const nearBottom =\n scroll.scrollHeight -\n scroll.clientHeight -\n scroll.scrollTop <=\n 48;\n followLatestRef.current = nearBottom;\n setShowJumpToLatest(!nearBottom);\n }}\n className={chatClass(\n \"studio-chat-thread-scroll\",\n chatLayout.threadScroll,\n )}\n >\n <div\n className={chatClass(\n \"studio-chat-manuscript\",\n chatLayout.manuscript,\n )}\n >\n {messagesQuery.error && (\n <section role=\"alert\">\n <p>\n {storedMessages.length > 0\n ? \"Showing previously loaded messages. \"\n : \"\"}\n Conversation could not be loaded.\n </p>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={messagesQuery.isFetching}\n onClick={() => void messagesQuery.refetch()}\n >\n Retry conversation\n </Button>\n </section>\n )}\n {messagesQuery.isPending &&\n props.sessionId &&\n visibleMessages.length === 0 ? (\n <p\n className={chatClass(\n \"studio-chat-empty\",\n chatLayout.empty,\n )}\n >\n Opening conversation…\n </p>\n ) : null}\n {!messagesQuery.error &&\n (!props.sessionId || !messagesQuery.isPending) &&\n visibleMessages.length === 0 ? (\n <ChatEmptyState />\n ) : null}\n {visibleMessages.map((message) => (\n <ChatTurn\n key={message.id}\n message={message}\n client={chatClient}\n disabled={sending}\n onAction={runSuggestedAction}\n onApproval={respondToApproval}\n />\n ))}\n {stream?.approvals.map((approval) => (\n <ApprovalCard\n key={approval.approvalId}\n approval={approval}\n disabled={sending}\n onDecision={respondToApproval}\n />\n ))}\n {stream && stream.progress.length > 0 && (\n <details\n className={chatClass(\n \"studio-chat-progress\",\n chatLayout.card,\n )}\n >\n <summary>\n Activity · {stream.progress.length} updates\n </summary>\n <pre className={chatClass(\"\", chatLayout.source)}>\n {JSON.stringify(stream.progress, null, 2)}\n </pre>\n </details>\n )}\n {sending ? (\n <p\n className={chatClass(\n \"studio-chat-stream-status\",\n chatLayout.empty,\n )}\n role=\"status\"\n >\n Responding…\n </p>\n ) : null}\n {interrupted && (\n <section\n className={chatClass(\n \"studio-chat-interruption\",\n chatLayout.empty,\n )}\n role={interrupted.kind === \"stopped\" ? \"status\" : \"alert\"}\n aria-atomic=\"true\"\n >\n <strong>\n {interrupted.kind === \"stopped\"\n ? \"Stopped\"\n : interrupted.kind === \"disconnected\"\n ? \"Connection lost\"\n : \"Response failed\"}\n </strong>\n <p>\n Any received text is kept here. Stopping the response\n does not undo completed actions; the server may still be\n working.\n </p>\n {interrupted.detail && <p>{interrupted.detail}</p>}\n {interrupted.retry && (\n <>\n <p>\n Sending again may repeat completed actions. Review\n the request before sending.\n </p>\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={\n sending ||\n uploading ||\n Boolean(draft) ||\n uploads.length > 0\n }\n onClick={() => {\n if (\n !interrupted.retry ||\n draft ||\n uploads.length > 0\n )\n return;\n setDraft(interrupted.retry.text);\n setUploads([...interrupted.retry.uploads]);\n threadScrollRef.current\n ?.closest(\".studio-chat-thread\")\n ?.querySelector<HTMLTextAreaElement>(\"textarea\")\n ?.focus();\n }}\n >\n Review retry in composer\n </Button>\n {(draft || uploads.length > 0) && (\n <p>\n Your composer draft is unchanged. Send or clear it\n before restoring this request.\n </p>\n )}\n </>\n )}\n </section>\n )}\n {error ? (\n <p\n className={chatClass(\n \"studio-chat-error\",\n chatLayout.empty,\n chatLayout.error,\n )}\n role=\"alert\"\n >\n {error}\n </p>\n ) : null}\n <div ref={threadEndRef} />\n </div>\n </div>\n <Composer\n onJumpToLatest={\n showJumpToLatest\n ? (): void => {\n followLatestRef.current = true;\n setShowJumpToLatest(false);\n const scroll = threadScrollRef.current;\n if (scroll) {\n scroll.focus({ preventScroll: true });\n scroll.scrollTop = scroll.scrollHeight;\n }\n }\n : undefined\n }\n draft={draft}\n sending={sending}\n uploading={uploading}\n uploads={uploads}\n uploadAttempts={uploadAttempts}\n onRetryUpload={(attempt) => void runUploads([attempt])}\n onDismissUpload={(id) =>\n setUploadAttempts((current) =>\n current.filter((attempt) => attempt.id !== id),\n )\n }\n onDraft={setDraft}\n locked={archiving}\n onRemoveUpload={(id) =>\n setUploads((current) =>\n current.filter((upload) => upload.id !== id),\n )\n }\n onFiles={uploadFiles}\n onSubmit={submit}\n onStop={\n activeStreamRef.current\n ? (): void => activeStreamRef.current?.abort()\n : undefined\n }\n />\n </section>\n </div>\n </main>\n </div>\n </div>\n );\n}\n\nfunction SessionRail(props: {\n sessions: ChatSession[];\n activeSessionId: string | null;\n loading: boolean;\n search: string;\n view: SessionView;\n error: string | null;\n onRetry: () => void;\n onSearch: (search: string) => void;\n onView: (view: SessionView) => void;\n onNew: () => void;\n onSelect: (id: string) => void;\n}): ReactElement {\n return (\n <aside\n className={chatClass(\"studio-chat-session-picker\", chatLayout.picker)}\n aria-label=\"Chat sessions\"\n >\n {\n <header\n className={chatClass(\n \"studio-chat-sessions-head\",\n chatLayout.threadHead,\n )}\n >\n <div\n className={chatClass(\"studio-chat-head-copy\", chatLayout.headCopy)}\n >\n <h2\n className={chatClass(\n \"studio-chat-sessions-title\",\n chatLayout.subheading,\n typographyStyles.section,\n )}\n >\n History\n </h2>\n </div>\n <button\n className={chatClass(\"studio-chat-new\", chatLayout.button)}\n type=\"button\"\n aria-label=\"New conversation\"\n onClick={props.onNew}\n >\n +\n </button>\n </header>\n }\n <div\n className={chatClass(\n \"studio-chat-session-controls\",\n chatLayout.sessionControls,\n )}\n >\n <StudioSearchField\n label=\"Search conversations\"\n placeholder=\"Search conversations\"\n value={props.search}\n onChange={props.onSearch}\n />\n <NativeSelect\n xstyle={chatLayout.sessionFilterSelect}\n aria-label=\"Show conversations\"\n value={props.view.archived ? \"archived\" : \"active\"}\n onChange={(event) =>\n props.onView({\n ...props.view,\n archived: event.target.value === \"archived\",\n offset: 0,\n })\n }\n >\n <option value=\"active\">Active conversations</option>\n <option value=\"archived\">Archived conversations</option>\n </NativeSelect>\n {(props.view.offset > 0 || props.sessions.length >= 25) && (\n <div\n className={chatClass(\"\", chatLayout.actions)}\n aria-label=\"Conversation pages\"\n role=\"group\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={props.loading || props.view.offset === 0}\n onClick={() =>\n props.onView({\n ...props.view,\n offset: Math.max(0, props.view.offset - 25),\n })\n }\n >\n Previous\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={props.loading || props.sessions.length < 25}\n onClick={() =>\n props.onView({ ...props.view, offset: props.view.offset + 25 })\n }\n >\n Next\n </Button>\n </div>\n )}\n {props.error && (\n <p role=\"alert\">\n {props.error}{\" \"}\n <Button type=\"button\" variant=\"ghost\" onClick={props.onRetry}>\n Retry sessions\n </Button>\n </p>\n )}\n </div>\n <div\n className={chatClass(\n \"studio-chat-session-list\",\n chatLayout.sessionList,\n )}\n >\n {props.loading ? (\n <p className={chatClass(\"studio-chat-empty\", chatLayout.empty)}>\n Loading sessions…\n </p>\n ) : null}\n {!props.loading && !props.error && props.sessions.length === 0 ? (\n <p className={chatClass(\"studio-chat-empty\", chatLayout.empty)}>\n {props.view.query\n ? \"No conversations match this search.\"\n : props.view.offset > 0\n ? \"No more conversations.\"\n : props.view.archived\n ? \"No archived conversations.\"\n : \"No conversations yet.\"}\n </p>\n ) : null}\n {props.sessions.map((session) => (\n <button\n className={chatClass(\n \"studio-chat-session\",\n chatLayout.session,\n session.id === props.activeSessionId && chatLayout.activeSession,\n )}\n data-active={\n session.id === props.activeSessionId ? \"true\" : \"false\"\n }\n type=\"button\"\n key={session.id}\n onClick={() => props.onSelect(session.id)}\n >\n <strong\n className={chatClass(\n \"studio-chat-session-title\",\n chatLayout.sessionTitle,\n )}\n >\n {session.title}\n </strong>\n <time\n className={chatClass(\n \"studio-chat-session-time\",\n chatLayout.timestamp,\n )}\n dateTime={session.lastActiveAt}\n title={session.lastActiveAt}\n >\n {formatSessionTime(session.lastActiveAt)}\n </time>\n </button>\n ))}\n </div>\n </aside>\n );\n}\n\nfunction ChatEmptyState(): ReactElement {\n return (\n <section\n className={chatClass(\n \"studio-chat-empty\",\n chatLayout.empty,\n chatLayout.emptyConversation,\n )}\n aria-label=\"New conversation\"\n >\n <p className={chatClass(\"\", chatLayout.cardText)}>\n No messages yet. Your draft stays in the composer until you send it.\n </p>\n </section>\n );\n}\n\nfunction ChatTurn(props: {\n disabled: boolean;\n message: ChatHistoryMessage;\n client: ChatClient;\n onAction: (action: ChatSuggestedAction) => Promise<void>;\n onApproval: (\n approval: StudioChatApproval,\n approved: boolean,\n ) => Promise<void>;\n}): ReactElement {\n return (\n <article\n className={chatClass(\n \"studio-chat-turn\",\n chatLayout.turn,\n props.message.role === \"user\" && chatLayout.userTurn,\n )}\n data-role={props.message.role}\n >\n <span className={chatClass(\"studio-chat-turn-label\", chatLayout.speaker)}>\n {props.message.role === \"user\" ? \"You\" : \"Brain\"}\n </span>\n <div\n className={chatClass(\n \"studio-chat-turn-body\",\n chatLayout.turnBody,\n props.message.role === \"user\" && chatLayout.userBody,\n )}\n >\n {props.message.content ? (\n props.message.role === \"assistant\" ? (\n <StudioMarkdown\n className={chatClass(\"studio-chat-prose\", chatLayout.cards)}\n presentation=\"chat\"\n >\n {props.message.content}\n </StudioMarkdown>\n ) : (\n <p className={chatClass(\"studio-chat-text\", chatLayout.paragraph)}>\n {props.message.content}\n </p>\n )\n ) : null}\n {props.message.attachments?.map((attachment) => (\n <p\n className={chatClass(\"studio-chat-upload\", chatLayout.upload)}\n key={`${attachment.filename}-${attachment.createdAt}`}\n >\n {attachment.filename}\n </p>\n ))}\n {props.message.cards?.length ? (\n <div className={chatClass(\"studio-chat-cards\", chatLayout.cards)}>\n {props.message.cards.map((card) => (\n <MessageCard\n card={card}\n client={props.client}\n disabled={props.disabled}\n key={`${card.kind}-${card.id}`}\n onAction={props.onAction}\n onApproval={props.onApproval}\n />\n ))}\n </div>\n ) : null}\n </div>\n </article>\n );\n}\n\nfunction MessageCard(props: {\n disabled: boolean;\n card: ChatCard;\n client: ChatClient;\n onAction: (action: ChatSuggestedAction) => Promise<void>;\n onApproval: (\n approval: StudioChatApproval,\n approved: boolean,\n ) => Promise<void>;\n}): ReactElement {\n const { card } = props;\n if (card.kind === \"actions\") {\n return (\n <section className={chatClass(\"studio-chat-card\", chatLayout.card)}>\n <span\n className={chatClass(\"studio-chat-card-kicker\", chatLayout.kicker)}\n >\n Actions\n </span>\n {card.title ? <strong>{card.title}</strong> : null}\n <div\n className={chatClass(\"studio-chat-card-actions\", chatLayout.actions)}\n >\n {card.actions.map((action) => (\n <button\n className={chatClass(\n \"studio-chat-card-action\",\n chatLayout.button,\n )}\n type=\"button\"\n key={action.id}\n disabled={props.disabled}\n onClick={() => void props.onAction(action)}\n >\n {action.label}\n </button>\n ))}\n </div>\n </section>\n );\n }\n if (card.kind === \"sources\") {\n return (\n <details className={chatClass(\"studio-chat-sources\", chatLayout.card)}>\n <summary>{card.title ?? `${card.sources.length} sources`}</summary>\n <ul>\n {card.sources.map((source) => (\n <li key={source.id}>\n {source.url ? (\n <a href={source.url}>{source.title ?? source.source}</a>\n ) : (\n (source.title ?? source.source)\n )}\n {source.excerpt && (\n <p className={chatClass(\"\", chatLayout.paragraph)}>\n {source.excerpt}\n </p>\n )}\n <details>\n <summary>Source details</summary>\n <pre className={chatClass(\"\", chatLayout.source)}>\n {JSON.stringify(source, null, 2)}\n </pre>\n </details>\n </li>\n ))}\n </ul>\n </details>\n );\n }\n if (card.kind === \"attachment\") {\n return <StudioChatAttachment card={card} client={props.client} />;\n }\n const pending = card.state === \"approval-requested\";\n const approval: StudioChatApproval = {\n approvalId: card.id,\n toolCallId: card.toolCallId ?? card.id,\n toolName: card.toolName,\n ...(card.input ? { input: card.input } : {}),\n ...(card.summary ? { title: card.summary } : {}),\n };\n return (\n <section className={chatClass(\"studio-chat-card\", chatLayout.card)}>\n <span className={chatClass(\"studio-chat-card-kicker\", chatLayout.kicker)}>\n {pending\n ? \"Approval required\"\n : card.state === \"approval-responded\"\n ? \"Decision received · awaiting result\"\n : card.state === \"output-available\"\n ? \"Completed\"\n : card.state === \"output-denied\"\n ? \"Declined\"\n : \"Action failed\"}\n </span>\n <strong>{card.summary}</strong>\n {card.completionSummary && <p>{card.completionSummary}</p>}\n {card.error !== undefined && <p role=\"alert\">{card.error}</p>}\n {(card.preview !== undefined || card.input !== undefined) && (\n <details>\n <summary>Review exact action</summary>\n <pre\n className={chatClass(\"studio-chat-card-preview\", chatLayout.source)}\n >\n {card.preview ?? JSON.stringify(card.input, null, 2)}\n </pre>\n {card.preview !== undefined && card.input !== undefined && (\n <details>\n <summary>Tool input</summary>\n <pre className={chatClass(\"\", chatLayout.source)}>\n {JSON.stringify(card.input, null, 2)}\n </pre>\n </details>\n )}\n <p className={chatClass(\"\", chatLayout.cardText)}>\n Tool: {card.toolName}\n </p>\n </details>\n )}\n {card.output !== undefined && (\n <details>\n <summary>Action result</summary>\n <pre className={chatClass(\"\", chatLayout.source)}>\n {typeof card.output === \"string\"\n ? card.output\n : JSON.stringify(card.output, null, 2)}\n </pre>\n </details>\n )}\n {pending ? (\n <div\n className={chatClass(\n \"studio-chat-approval-actions\",\n chatLayout.actions,\n )}\n >\n <button\n className={chatClass(\n \"studio-chat-approval-action\",\n chatLayout.button,\n )}\n type=\"button\"\n disabled={props.disabled}\n onClick={() => void props.onApproval(approval, false)}\n >\n Decline\n </button>\n <button\n className={chatClass(\n \"studio-chat-approval-action\",\n chatLayout.button,\n chatLayout.primaryButton,\n )}\n data-primary=\"true\"\n type=\"button\"\n disabled={props.disabled}\n onClick={() => void props.onApproval(approval, true)}\n >\n Approve\n </button>\n </div>\n ) : null}\n </section>\n );\n}\n\nfunction ApprovalCard(props: {\n approval: StudioChatApproval;\n disabled: boolean;\n onDecision: (\n approval: StudioChatApproval,\n approved: boolean,\n ) => Promise<void>;\n}): ReactElement {\n return (\n <section className={chatClass(\"studio-chat-approval\", chatLayout.card)}>\n <span className={chatClass(\"studio-chat-card-kicker\", chatLayout.kicker)}>\n Approval required\n </span>\n <strong>{props.approval.title ?? props.approval.toolName}</strong>\n {props.approval.input !== undefined && (\n <details>\n <summary>Review exact action</summary>\n <pre className={chatClass(\"\", chatLayout.source)}>\n {JSON.stringify(props.approval.input, null, 2)}\n </pre>\n <p>Tool: {props.approval.toolName}</p>\n </details>\n )}\n <div\n className={chatClass(\n \"studio-chat-approval-actions\",\n chatLayout.actions,\n )}\n >\n <button\n className={chatClass(\n \"studio-chat-approval-action\",\n chatLayout.button,\n )}\n type=\"button\"\n disabled={props.disabled}\n onClick={() => void props.onDecision(props.approval, false)}\n >\n Decline\n </button>\n <button\n className={chatClass(\n \"studio-chat-approval-action\",\n chatLayout.button,\n chatLayout.primaryButton,\n )}\n data-primary=\"true\"\n type=\"button\"\n disabled={props.disabled}\n onClick={() => void props.onDecision(props.approval, true)}\n >\n Approve\n </button>\n </div>\n </section>\n );\n}\n\nfunction Composer(props: {\n locked: boolean;\n onRemoveUpload: (id: string) => void;\n draft: string;\n uploads: ChatUploadResponse[];\n uploadAttempts: ChatUploadAttempt[];\n onRetryUpload: (attempt: ChatUploadAttempt) => void;\n onDismissUpload: (id: string) => void;\n sending: boolean;\n uploading: boolean;\n onDraft: (value: string) => void;\n onFiles: (event: ChangeEvent<HTMLInputElement>) => Promise<void>;\n onSubmit: (event: FormEvent<HTMLFormElement>) => void;\n onStop?: (() => void) | undefined;\n onJumpToLatest?: (() => void) | undefined;\n}): ReactElement {\n const keyDown = (event: KeyboardEvent<HTMLTextAreaElement>): void => {\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.nativeEvent.isComposing\n ) {\n event.preventDefault();\n event.currentTarget.form?.requestSubmit();\n }\n };\n return (\n <footer className={chatClass(\"studio-chat-composer\", chatLayout.composer)}>\n {props.onJumpToLatest && (\n <Button type=\"button\" variant=\"ghost\" onClick={props.onJumpToLatest}>\n Jump to latest ↓\n </Button>\n )}\n <form\n className={chatClass(\"studio-chat-composer-form\", chatLayout.form)}\n onSubmit={props.onSubmit}\n >\n {(props.uploadAttempts.length > 0 || props.uploads.length > 0) && (\n <div\n className={chatClass(\n \"studio-chat-upload-strip\",\n chatLayout.uploadStrip,\n )}\n role=\"region\"\n aria-label=\"Draft attachments\"\n tabIndex={0}\n >\n <ul\n className={chatClass(\n \"studio-chat-upload-list\",\n chatLayout.uploadList,\n )}\n aria-label={\n props.uploadAttempts.length > 0\n ? \"File upload progress\"\n : \"Attached files\"\n }\n >\n {props.uploadAttempts.map((attempt) => (\n <li\n key={attempt.id}\n className={chatClass(\"studio-chat-upload\", chatLayout.upload)}\n >\n <div className={chatClass(\"\", chatLayout.uploadName)}>\n <span\n role={attempt.status === \"failed\" ? \"alert\" : \"status\"}\n >\n {attempt.file.name}:{\" \"}\n {attempt.status === \"uploading\"\n ? \"Uploading…\"\n : (attempt.error ?? \"Upload failed\")}\n </span>\n {attempt.status === \"uploading\" && (\n <progress aria-label={`Uploading ${attempt.file.name}`} />\n )}\n </div>\n {attempt.status === \"failed\" && (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n xstyle={chatLayout.toolbarButton}\n aria-label={`Retry uploading ${attempt.file.name}`}\n disabled={\n props.uploading || props.sending || props.locked\n }\n onClick={() => props.onRetryUpload(attempt)}\n >\n Retry\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n xstyle={chatLayout.toolbarButton}\n aria-label={`Dismiss failed upload ${attempt.file.name}`}\n onClick={() => props.onDismissUpload(attempt.id)}\n >\n ×\n </Button>\n </>\n )}\n </li>\n ))}\n {props.uploads.map((upload) => (\n <li\n className={chatClass(\"studio-chat-upload\", chatLayout.upload)}\n key={upload.id}\n >\n <DraftUploadPreview upload={upload} />\n <span className={chatClass(\"\", chatLayout.uploadName)}>\n {upload.filename}\n <br />\n Ready · draft only\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n xstyle={chatLayout.toolbarButton}\n aria-label={`Remove ${upload.filename} from message`}\n disabled={props.locked}\n onClick={() => props.onRemoveUpload(upload.id)}\n >\n ×\n </Button>\n </li>\n ))}\n </ul>\n </div>\n )}\n <textarea\n className={chatClass(\"studio-chat-message\", chatLayout.input)}\n aria-label=\"Message\"\n aria-describedby=\"studio-chat-composer-hint\"\n placeholder=\"Message…\"\n value={props.draft}\n disabled={props.locked}\n onChange={(event) => props.onDraft(event.target.value)}\n onKeyDown={keyDown}\n />\n <div\n className={chatClass(\n \"studio-chat-composer-actions\",\n chatLayout.composerBar,\n )}\n >\n <label\n className={chatClass(\n \"studio-chat-composer-action\",\n chatLayout.attachButton,\n )}\n title={CHAT_UPLOAD_GUIDANCE}\n >\n <span aria-hidden=\"true\">+</span>\n <input\n className={chatClass(\n \"studio-chat-upload-input\",\n chatLayout.uploadInput,\n )}\n aria-label=\"Attach files\"\n type=\"file\"\n accept={messageUploadAccept}\n multiple\n disabled={props.locked || props.sending || props.uploading}\n onChange={(event) => void props.onFiles(event)}\n />\n </label>\n {props.uploadAttempts.length > 0 && (\n <span className={chatClass(\"\", chatLayout.kicker)}>\n Resolve uploads before sending\n </span>\n )}\n {props.locked ? (\n <Button type=\"button\" disabled>\n Archiving…\n </Button>\n ) : props.sending ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n xstyle={chatLayout.toolbarButton}\n onClick={props.onStop}\n disabled={!props.onStop}\n title=\"Stop receiving the response. Completed actions are not undone.\"\n >\n Stop\n </Button>\n ) : (\n <Button\n className=\"studio-chat-composer-action\"\n type=\"submit\"\n xstyle={chatLayout.toolbarButton}\n aria-label=\"Send message\"\n disabled={\n props.uploading ||\n props.uploadAttempts.length > 0 ||\n (!props.draft.trim() && props.uploads.length === 0)\n }\n >\n ↑\n </Button>\n )}\n </div>\n </form>\n <small\n id=\"studio-chat-composer-hint\"\n className={chatClass(\n \"studio-chat-composer-hint\",\n chatLayout.composerHint,\n )}\n >\n Enter to send · Shift+Enter for a new line\n </small>\n </footer>\n );\n}\n\nfunction DraftUploadPreview({\n upload,\n}: {\n upload: ChatUploadResponse;\n}): ReactElement | null {\n const [failed, setFailed] = useState(false);\n if (failed || !upload.mediaType.startsWith(\"image/\")) return null;\n return (\n <img\n className={chatClass(\n \"studio-chat-draft-preview\",\n chatLayout.uploadPreview,\n )}\n src={upload.url}\n alt={upload.filename}\n onError={() => setFailed(true)}\n />\n );\n}\n\nfunction ConversationContext(props: {\n cards: ChatCard[];\n progress: StudioChatStreamState[\"progress\"];\n session: ChatSession | undefined;\n}): ReactElement {\n return (\n <aside\n className={chatClass(\"studio-chat-context\", chatLayout.contextBody)}\n tabIndex={0}\n aria-label=\"Conversation sources and attachments\"\n >\n <div className={chatClass(\"studio-chat-context-list\", chatLayout.cards)}>\n {props.session?.contextHandoff ? (\n <section\n className={chatClass(\n \"studio-chat-context-card\",\n chatLayout.contextItem,\n )}\n >\n <span\n className={chatClass(\n \"studio-chat-context-kicker\",\n chatLayout.kicker,\n )}\n >\n Linked context\n </span>\n <h3\n className={chatClass(\n \"studio-chat-context-card-title\",\n chatLayout.cardHeading,\n typographyStyles.section,\n )}\n >\n {props.session.contextHandoff.titleSeed}\n </h3>\n <p\n className={chatClass(\n \"studio-chat-context-card-text\",\n chatLayout.cardText,\n )}\n >\n {props.session.contextHandoff.sourceId} ·{\" \"}\n {props.session.contextHandoff.itemId}\n </p>\n </section>\n ) : null}\n {props.cards.length === 0 && props.progress.length === 0 ? (\n <p className={chatClass(\"studio-chat-empty\", chatLayout.empty)}>\n No sources or attachments in this conversation yet.\n </p>\n ) : null}\n {props.cards.map((card, index) => (\n <section\n className={chatClass(\n \"studio-chat-context-card\",\n chatLayout.contextItem,\n )}\n key={`${card.kind}-${card.id}-${index}`}\n >\n <span\n className={chatClass(\n \"studio-chat-context-kicker\",\n chatLayout.kicker,\n )}\n >\n {card.kind === \"sources\" ? \"Sources\" : \"Artifact\"}\n </span>\n <h3\n className={chatClass(\n \"studio-chat-context-card-title\",\n chatLayout.cardHeading,\n typographyStyles.section,\n )}\n >\n {card.kind === \"sources\"\n ? (card.title ?? `${card.sources.length} consulted`)\n : card.kind === \"attachment\"\n ? card.title\n : \"Conversation context\"}\n </h3>\n {card.kind === \"sources\" ? (\n <>\n <ul>\n {card.sources.slice(0, 5).map((source) => (\n <li key={source.id}>{source.title ?? source.source}</li>\n ))}\n </ul>\n {card.sources.length > 5 ? (\n <p\n className={chatClass(\n \"studio-chat-context-card-text\",\n chatLayout.cardText,\n )}\n >\n {card.sources.length - 5} more sources in the conversation.\n </p>\n ) : null}\n </>\n ) : card.kind === \"attachment\" && card.description ? (\n <p\n className={chatClass(\n \"studio-chat-context-card-text\",\n chatLayout.cardText,\n )}\n >\n {card.description}\n </p>\n ) : null}\n </section>\n ))}\n {props.progress.map((item, index) => (\n <section\n className={chatClass(\n \"studio-chat-context-card\",\n chatLayout.contextItem,\n )}\n key={`${item.type}-${index}`}\n >\n <span\n className={chatClass(\n \"studio-chat-context-kicker\",\n chatLayout.kicker,\n )}\n >\n Durable job\n </span>\n <h3\n className={chatClass(\n \"studio-chat-context-card-title\",\n chatLayout.cardHeading,\n typographyStyles.section,\n )}\n >\n {item.operationTarget ?? item.operationType}\n </h3>\n <p\n className={chatClass(\n \"studio-chat-context-card-text\",\n chatLayout.cardText,\n )}\n >\n {item.message ?? item.status}\n </p>\n </section>\n ))}\n </div>\n </aside>\n );\n}\n\nfunction formatSessionTime(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"\";\n return new Intl.DateTimeFormat(undefined, {\n day: \"numeric\",\n year:\n date.getFullYear() === new Date().getFullYear() ? undefined : \"numeric\",\n month: \"short\",\n timeZoneName: \"short\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n }).format(date);\n}\n\nfunction errorMessage(cause: unknown, fallback: string): string {\n return cause instanceof Error && cause.message ? cause.message : fallback;\n}\n",
|
|
15
|
+
"import {\n chatMessageSchema,\n type ChatCard,\n type ChatHistoryMessage,\n type ChatMessage,\n type ChatProgressEvent,\n type ChatProtocolEvent,\n type ChatToolStatusEvent,\n} from \"@brains/contracts/chat\";\n\ninterface StudioChatToolInput {\n toolCallId: string;\n toolName: string;\n input: unknown;\n title?: string | undefined;\n}\n\nexport interface StudioChatApproval {\n approvalId: string;\n toolCallId: string;\n toolName: string;\n input?: Record<string, unknown> | undefined;\n title?: string | undefined;\n}\n\nexport interface StudioChatStreamState {\n messageId: string;\n text: string;\n cards: ChatCard[];\n approvals: StudioChatApproval[];\n progress: ChatProgressEvent[];\n statuses: ChatToolStatusEvent[];\n toolInputs: Readonly<Record<string, StudioChatToolInput>>;\n finished: boolean;\n error: string | null;\n}\n\nexport function createStudioChatStreamState(): StudioChatStreamState {\n return {\n messageId: \"assistant-stream\",\n text: \"\",\n cards: [],\n approvals: [],\n progress: [],\n statuses: [],\n toolInputs: {},\n finished: false,\n error: null,\n };\n}\n\n/** Studio-owned assembly of raw server protocol facts into one visible turn. */\nexport function reduceStudioChatStream(\n state: StudioChatStreamState,\n event: ChatProtocolEvent,\n): StudioChatStreamState {\n switch (event.type) {\n case \"start\":\n return event.messageId ? { ...state, messageId: event.messageId } : state;\n case \"text-delta\":\n return { ...state, text: `${state.text}${event.delta}` };\n case \"tool-input-available\":\n return {\n ...state,\n toolInputs: {\n ...state.toolInputs,\n [event.toolCallId]: {\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n input: event.input,\n ...(event.title ? { title: event.title } : {}),\n },\n },\n };\n case \"tool-approval-request\": {\n const tool = state.toolInputs[event.toolCallId];\n const approval: StudioChatApproval = {\n approvalId: event.approvalId,\n toolCallId: event.toolCallId,\n toolName: tool?.toolName ?? \"tool\",\n ...(isRecord(tool?.input) ? { input: tool.input } : {}),\n ...(tool?.title ? { title: tool.title } : {}),\n };\n return {\n ...state,\n approvals: [\n ...state.approvals.filter(\n (item) => item.approvalId !== event.approvalId,\n ),\n approval,\n ],\n };\n }\n case \"tool-output-available\":\n case \"tool-output-error\":\n case \"tool-output-denied\":\n return {\n ...state,\n approvals: state.approvals.filter(\n (approval) => approval.toolCallId !== event.toolCallId,\n ),\n };\n case \"data-progress\":\n return { ...state, progress: [...state.progress, event.data] };\n case \"data-status\":\n return { ...state, statuses: [...state.statuses, event.data] };\n case \"data-actions\":\n case \"data-sources\":\n case \"data-attachment\":\n return { ...state, cards: [...state.cards, event.data] };\n case \"finish\":\n return { ...state, finished: true };\n case \"abort\":\n return {\n ...state,\n finished: true,\n error: event.reason ?? \"Response stopped\",\n };\n case \"error\":\n return { ...state, finished: true, error: event.errorText };\n default:\n return state;\n }\n}\n\nexport function streamAssistantMessage(\n state: StudioChatStreamState,\n): ChatHistoryMessage {\n return {\n id: state.messageId,\n role: \"assistant\",\n content: state.text,\n ...(state.cards.length > 0 ? { cards: state.cards } : {}),\n };\n}\n\nexport function approvalResponseMessage(\n approval: StudioChatApproval,\n approved: boolean,\n): ChatMessage {\n const response = {\n id: approval.approvalId,\n approved,\n toolCallId: approval.toolCallId,\n toolName: approval.toolName,\n ...(approval.input ? { input: approval.input } : {}),\n ...(approval.title ? { title: approval.title } : {}),\n };\n return chatMessageSchema.parse({\n role: \"assistant\",\n parts: [\n {\n state: \"approval-responded\",\n toolCallId: approval.toolCallId,\n toolName: approval.toolName,\n ...(approval.input ? { input: approval.input } : {}),\n ...(approval.title ? { title: approval.title } : {}),\n approval: response,\n },\n ],\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"
|
|
16
|
+
],
|
|
17
|
+
"mappings": "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",
|
|
18
|
+
"debugId": "F23241A26A6A034464756E2164756E21",
|
|
19
|
+
"names": []
|
|
20
|
+
}
|