@opengeni/react 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/{chunk-6TROCOEK.js → chunk-4OTO7KBK.js} +774 -731
  2. package/dist/chunk-4OTO7KBK.js.map +1 -0
  3. package/dist/{chunk-RLUSC2WA.js → chunk-5F4WR7X7.js} +2 -1
  4. package/dist/chunk-5F4WR7X7.js.map +1 -0
  5. package/dist/{chunk-EN3YTHKR.js → chunk-CY7WK5FD.js} +2 -2
  6. package/dist/{chunk-26ZNDDLZ.js → chunk-LNIRAOA3.js} +27 -8
  7. package/dist/chunk-LNIRAOA3.js.map +1 -0
  8. package/dist/{chunk-DO544OSV.js → chunk-RC6BZ44Q.js} +4 -3
  9. package/dist/chunk-RC6BZ44Q.js.map +1 -0
  10. package/dist/{chunk-WGXVEJO5.js → chunk-SGKD2OCN.js} +5 -5
  11. package/dist/chunk-SGKD2OCN.js.map +1 -0
  12. package/dist/{chunk-JIQYUGVL.js → chunk-X34BSY2R.js} +3 -3
  13. package/dist/components/model-mark.d.ts +3 -3
  14. package/dist/composer.js +4 -4
  15. package/dist/index.js +7 -7
  16. package/dist/{latest-question-HTRIS4KJ.js → latest-question-YTOBHCWR.js} +2 -2
  17. package/dist/{model-policy-picker-menu-M54ISBMN.js → model-policy-picker-menu-DXHUL73H.js} +4 -4
  18. package/dist/model-policy.d.ts +1 -0
  19. package/dist/model-policy.js +1 -1
  20. package/dist/realtime.js +2 -2
  21. package/dist/session-ui.js +6 -6
  22. package/dist/session.js +2 -2
  23. package/dist/timeline/genie-loading.d.ts +3 -1
  24. package/dist/timeline/startup-dispatch-details.d.ts +5 -0
  25. package/dist/timeline/types.d.ts +5 -1
  26. package/package.json +3 -3
  27. package/src/components/model-mark.tsx +16 -5
  28. package/src/components/model-policy-picker-menu.tsx +2 -2
  29. package/src/components/model-policy-picker.tsx +11 -3
  30. package/src/components/session-conversation.tsx +3 -0
  31. package/src/model-policy.ts +9 -0
  32. package/src/timeline/activity-rail.tsx +14 -4
  33. package/src/timeline/genie-loading.tsx +27 -16
  34. package/src/timeline/projection.ts +7 -3
  35. package/src/timeline/startup-dispatch-details.tsx +36 -0
  36. package/src/timeline/types.ts +5 -0
  37. package/dist/chunk-26ZNDDLZ.js.map +0 -1
  38. package/dist/chunk-6TROCOEK.js.map +0 -1
  39. package/dist/chunk-DO544OSV.js.map +0 -1
  40. package/dist/chunk-RLUSC2WA.js.map +0 -1
  41. package/dist/chunk-WGXVEJO5.js.map +0 -1
  42. /package/dist/{chunk-EN3YTHKR.js.map → chunk-CY7WK5FD.js.map} +0 -0
  43. /package/dist/{chunk-JIQYUGVL.js.map → chunk-X34BSY2R.js.map} +0 -0
  44. /package/dist/{latest-question-HTRIS4KJ.js.map → latest-question-YTOBHCWR.js.map} +0 -0
  45. /package/dist/{model-policy-picker-menu-M54ISBMN.js.map → model-policy-picker-menu-DXHUL73H.js.map} +0 -0
@@ -196,6 +196,7 @@ function projectPickerRows(models) {
196
196
  billingClass,
197
197
  billingClassLabel: billingClassLabel(billingClass),
198
198
  selectable: catalog.availability.selectable,
199
+ fundingHint: catalog.creditFunding === "promotional" ? "Free credits" : catalog.creditFunding === "general" ? "Uses credits" : catalog.creditFunding === "unavailable" ? "Needs credits" : void 0,
199
200
  unavailableReason: catalog.availability.selectable ? null : availabilityReasonLabel(catalog.availability.reason),
200
201
  provider: catalog.provider,
201
202
  providerLabel: catalog.providerLabel,
@@ -296,4 +297,4 @@ export {
296
297
  modelDisplayName2 as modelDisplayName,
297
298
  modelVendor
298
299
  };
299
- //# sourceMappingURL=chunk-RLUSC2WA.js.map
300
+ //# sourceMappingURL=chunk-5F4WR7X7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model-policy.ts"],"sourcesContent":["import {\n compareModelPickerOrder,\n modelPickerBillingClassFor,\n type ModelPickerBillingClass,\n} from \"@opengeni/sdk/model-picker-order\";\nimport { modelDisplayName } from \"@opengeni/sdk/model-display\";\nimport type { ClientModel, ReasoningEffort, WorkspaceModelCatalogModel } from \"@opengeni/sdk\";\n\nexport type PickerBillingClass = ModelPickerBillingClass;\n\nexport type PickerModelRow<TCatalog extends ClientModel = WorkspaceModelCatalogModel> = {\n id: string;\n label: string;\n /** Catalog-curated compact label for dense UI; fall back to `label` when absent. */\n shortLabel?: string | undefined;\n billingClass: PickerBillingClass;\n billingClassLabel: string;\n selectable: boolean;\n unavailableReason: string | null;\n fundingHint?: string | undefined;\n provider: string;\n providerLabel: string;\n catalog: TCatalog;\n};\n\nexport type LatencyModeId = \"standard\" | \"priority\" | \"fast\";\n\nconst BILLING_CLASS_LABELS: Record<PickerBillingClass, string> = {\n opengeni_credits: \"Models\",\n external: \"External\",\n codex_subscription: \"Codex\",\n supergrok_subscription: \"SuperGrok\",\n claude_subscription: \"Claude subscription\",\n // Who connected the key (organization or workspace) is a settings fact, not\n // a model choice: both scopes share one label and one picker group.\n byok: \"API keys\",\n organization_byok: \"API keys\",\n};\n\n/** Models settings keeps naming who connected the key. */\nconst SCOPED_BILLING_CLASS_LABELS: Record<PickerBillingClass, string> = {\n ...BILLING_CLASS_LABELS,\n byok: \"Workspace providers\",\n organization_byok: \"Organization providers\",\n};\n\nconst AVAILABILITY_REASON_LABELS: Record<string, string> = {\n missing_credential: \"Credentials required\",\n needs_reauth: \"Reconnect required\",\n credential_not_ready: \"Credential not ready\",\n not_entitled: \"Not entitled\",\n provider_unhealthy: \"Provider unavailable\",\n policy_blocked: \"Blocked by workspace policy\",\n unsupported: \"Unsupported\",\n};\n\nexport function billingClassForModel(model: ClientModel): PickerBillingClass {\n if (model.provider === \"organization-gateway\" || model.provider === \"organization-openrouter\") {\n return \"organization_byok\";\n }\n if (\n model.provider?.startsWith(\"workspace-openai-\") ||\n model.provider?.startsWith(\"workspace-azure-openai-\")\n )\n return \"byok\";\n if (model.provider === \"workspace-gateway\" || model.provider === \"workspace-openrouter\") {\n return \"byok\";\n }\n return modelPickerBillingClassFor(model);\n}\n\nexport function billingClassLabel(billingClass: PickerBillingClass): string {\n return BILLING_CLASS_LABELS[billingClass];\n}\n\n/** The group label that names the connection scope, for Models settings only. */\nexport function scopedBillingClassLabel(billingClass: PickerBillingClass): string {\n return SCOPED_BILLING_CLASS_LABELS[billingClass];\n}\n\nexport function availabilityReasonLabel(\n reason: WorkspaceModelCatalogModel[\"availability\"][\"reason\"],\n): string | null {\n if (!reason) {\n return null;\n }\n return AVAILABILITY_REASON_LABELS[reason] ?? \"Unavailable\";\n}\n\nexport function effortOptionsForModel(model: ClientModel): ReasoningEffort[] {\n const efforts = model.capabilities?.reasoning.efforts;\n if (!efforts || efforts.length === 0) {\n return [\"low\"];\n }\n const order: ReasoningEffort[] = [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n return order.filter((effort) => efforts.includes(effort));\n}\n\nexport function defaultEffortForModel(model: ClientModel): ReasoningEffort {\n const options = effortOptionsForModel(model);\n const configured = model.capabilities?.reasoning.defaultEffort;\n if (configured && options.includes(configured)) {\n return configured;\n }\n return options[0] ?? \"low\";\n}\n\nexport function coerceReasoningEffortForModel(\n model: ClientModel,\n effort: ReasoningEffort,\n): ReasoningEffort {\n const options = effortOptionsForModel(model);\n if (options.includes(effort)) {\n return effort;\n }\n return defaultEffortForModel(model);\n}\n\nexport function runnableLatencyModesForModel(model: ClientModel): LatencyModeId[] {\n const modes = model.capabilities?.latencyModes ?? [];\n return modes.filter((mode) => mode.runnable).map((mode) => mode.id);\n}\n\nexport function labelLatencyMode(mode: LatencyModeId): string {\n if (mode === \"fast\") {\n return \"Fast\";\n }\n if (mode === \"priority\") {\n return \"Priority\";\n }\n return \"Standard\";\n}\n\nexport function labelReasoningEffort(effort: ReasoningEffort): string {\n if (effort === \"xhigh\") {\n return \"Extra high\";\n }\n return effort.slice(0, 1).toUpperCase() + effort.slice(1);\n}\n\n/** Payment prompts must use cost policy, never the presentation group. */\nexport function modelUsesCredits(model: ClientModel | undefined): boolean {\n if (model?.cost !== undefined) return model.cost === \"credits\";\n return model?.billing?.metering === \"opengeni_credits\";\n}\n\nexport function payerSummaryForModel(model: ClientModel): string {\n if (model.cost === \"free\") {\n return \"Free in this deployment\";\n }\n if (model.cost === \"credits\") {\n return \"Opengeni credits\";\n }\n if (model.cost === \"subscription\") {\n return model.credentialSource?.kind === \"connected_subscription\" &&\n model.credentialSource.provider === \"claude\"\n ? \"Claude subscription · external billing\"\n : model.source === \"supergrok\"\n ? \"SuperGrok subscription · external billing\"\n : \"Codex subscription · external billing\";\n }\n if (model.cost === \"workspace\") {\n return workspaceProviderPayerSummary(model);\n }\n if (model.cost === \"organization\") {\n return organizationProviderPayerSummary(model);\n }\n\n // Older client-config payloads do not carry `cost`; preserve their existing\n // settlement-derived label until every deployment has rolled forward.\n const billing = model.billing;\n if (!billing) {\n return \"Route unknown\";\n }\n if (billing.metering === \"opengeni_credits\") {\n return \"Opengeni credits · automatic managed route\";\n }\n if (billing.upstreamPayer === \"connected_subscription\") {\n return model.credentialSource?.kind === \"connected_subscription\" &&\n model.credentialSource.provider === \"claude\"\n ? \"Claude subscription · external billing\"\n : model.source === \"supergrok\"\n ? \"SuperGrok subscription · external billing\"\n : \"Codex subscription · external billing\";\n }\n if (billing.upstreamPayer === \"workspace\") {\n return workspaceProviderPayerSummary(model);\n }\n if (billing.upstreamPayer === \"organization\") {\n return organizationProviderPayerSummary(model);\n }\n return billing.upstreamPayer === \"deployment\"\n ? \"Opengeni · no model credits\"\n : \"External provider · no Opengeni credits\";\n}\n\nexport function advancedSourceSummary(model: ClientModel): string | null {\n const source = model.credentialSource;\n if (!source) {\n return model.billing?.metering === \"external\" && model.billing.upstreamPayer === \"deployment\"\n ? \"Deployment-provided connection\"\n : null;\n }\n if (source.kind === \"connected_subscription\") {\n return source.provider === \"claude\"\n ? \"Connected Claude subscription\"\n : source.provider === \"xai\"\n ? \"Connected SuperGrok subscription\"\n : \"Connected Codex subscription\";\n }\n if (source.kind === \"workspace_connection\") {\n if (model.provider === \"workspace-openrouter\") {\n return \"Workspace OpenRouter connection\";\n }\n if (model.provider === \"workspace-gateway\" || model.source === \"workspace_gateway\") {\n return \"Workspace Vercel AI Gateway\";\n }\n return \"Workspace provider connection\";\n }\n if (source.kind === \"deployment\") {\n return source.mechanism === \"azure_ad_bearer\"\n ? \"Deployment Azure identity\"\n : \"Deployment API key\";\n }\n return null;\n}\n\nfunction workspaceProviderPayerSummary(model: ClientModel): string {\n if (model.provider === \"workspace-anthropic\")\n return \"Billed to the workspace Anthropic API account\";\n if (model.provider === \"workspace-claude-subscription\")\n return \"Uses the workspace Claude subscription · no Opengeni credits\";\n if (model.provider === \"workspace-openrouter\") {\n return \"Billed to the workspace OpenRouter account\";\n }\n if (model.provider === \"workspace-gateway\" || model.source === \"workspace_gateway\") {\n return \"Billed to the workspace Vercel account\";\n }\n return \"Billed to the workspace provider account\";\n}\n\nfunction organizationProviderPayerSummary(model: ClientModel): string {\n if (model.provider === \"organization-anthropic\")\n return \"Billed to the organization Anthropic API account\";\n if (model.provider === \"organization-claude-subscription\")\n return \"Uses the connected Claude subscription · no Opengeni credits\";\n if (model.provider === \"organization-openrouter\") {\n return \"Billed to the organization OpenRouter account\";\n }\n if (model.provider === \"organization-gateway\") {\n return \"Billed to the organization Vercel account\";\n }\n return \"Billed to the organization provider account\";\n}\n\n/**\n * The curated compact label, else the family-free name for Claude models\n * (\"Opus 5.5\"): the maker's mark beside it already says Claude.\n */\nfunction compactLabel(catalog: ClientModel): { shortLabel?: string } {\n if (catalog.shortLabel) return { shortLabel: catalog.shortLabel };\n const name = modelDisplayName(catalog);\n return name.startsWith(\"Claude \") ? { shortLabel: name.slice(\"Claude \".length) } : {};\n}\n\nexport function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerModelRow[] {\n return models\n .filter((catalog) => catalog.credentialReadiness.status === \"ready\")\n .map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: modelDisplayName(catalog),\n ...compactLabel(catalog),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: catalog.availability.selectable,\n fundingHint:\n catalog.creditFunding === \"promotional\"\n ? \"Free credits\"\n : catalog.creditFunding === \"general\"\n ? \"Uses credits\"\n : catalog.creditFunding === \"unavailable\"\n ? \"Needs credits\"\n : undefined,\n unavailableReason: catalog.availability.selectable\n ? null\n : availabilityReasonLabel(catalog.availability.reason),\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\n/** Project the lightweight client-config model list into the same picker contract. */\nexport function projectClientModelRows(models: ClientModel[]): PickerModelRow<ClientModel>[] {\n return models.map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: modelDisplayName(catalog),\n ...compactLabel(catalog),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: true,\n unavailableReason: null,\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\nexport function sortPickerRows<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): PickerModelRow<TCatalog>[] {\n return [...rows].sort(compareModelPickerOrder);\n}\n\nexport function findPickerRow<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n modelId: string,\n): PickerModelRow<TCatalog> | null {\n return rows.find((row) => row.id === modelId) ?? null;\n}\n\nexport type GroupPickerRowsOptions = {\n codexOnly?: boolean;\n /**\n * Default true: organization- and workspace-connected keys share one group\n * and identical copies show once. Models settings passes false.\n */\n collapseScopes?: boolean | undefined;\n /** Kept visible when it has an identical twin (see below). */\n selectedId?: string | undefined;\n};\n\n/**\n * Organization- and workspace-connected API keys are one choice for the person\n * picking a model, so they share one group.\n */\nfunction displayGroupFor(billingClass: PickerBillingClass): PickerBillingClass {\n return billingClass === \"organization_byok\" ? \"byok\" : billingClass;\n}\n\n/**\n * The same model through the same provider kind, whichever scope connected it:\n * `organization-anthropic/claude-opus-5-5` and `workspace-anthropic/claude-opus-5-5`\n * share a key, while OpenRouter and the Anthropic API never do (different\n * accounts and bills).\n */\nfunction scopeFreeIdentity(row: PickerModelRow<ClientModel>): string | null {\n const provider = row.provider.replace(/^(?:organization|workspace)-/, \"\");\n if (provider === row.provider) return null;\n const upstream =\n row.catalog.deployment?.upstreamModelId ??\n (row.id.startsWith(`${row.provider}/`) ? row.id.slice(row.provider.length + 1) : row.id);\n return `${provider}\\u0000${upstream}`;\n}\n\n/**\n * Two rows that are the same model through the same provider kind, connected\n * by the organization and by the workspace, are one choice: show one. Keep the\n * current selection, else a selectable row, else the first in picker order.\n */\nfunction prefersTwin<TCatalog extends ClientModel>(\n candidate: PickerModelRow<TCatalog>,\n current: PickerModelRow<TCatalog>,\n selectedId: string | undefined,\n): boolean {\n if (selectedId !== undefined && current.id === selectedId) return false;\n if (selectedId !== undefined && candidate.id === selectedId) return true;\n return candidate.selectable && !current.selectable;\n}\n\nexport function groupPickerRowsByBillingClass(\n rows: PickerModelRow[],\n options?: GroupPickerRowsOptions,\n): Array<{ billingClass: PickerBillingClass; label: string; rows: PickerModelRow[] }>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n options?: GroupPickerRowsOptions,\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n options?: GroupPickerRowsOptions,\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}> {\n const sorted = sortPickerRows(rows);\n const groups: Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n }> = [];\n for (const row of sorted) {\n const collapse = options?.collapseScopes !== false;\n const billingClass = collapse ? displayGroupFor(row.billingClass) : row.billingClass;\n const existing = groups.find((group) => group.billingClass === billingClass);\n if (existing) {\n const identity = collapse ? scopeFreeIdentity(row) : null;\n const twin =\n identity === null\n ? -1\n : existing.rows.findIndex((candidate) => scopeFreeIdentity(candidate) === identity);\n if (twin < 0) {\n existing.rows.push(row);\n } else if (prefersTwin(row, existing.rows[twin]!, options?.selectedId)) {\n existing.rows[twin] = row;\n }\n continue;\n }\n groups.push({\n billingClass,\n label:\n billingClass === row.billingClass ? row.billingClassLabel : billingClassLabel(billingClass),\n rows: [row],\n });\n }\n const codexIndex = groups.findIndex((group) => group.billingClass === \"codex_subscription\");\n const codex = groups[codexIndex];\n const selectableOpenGeni = groups\n .find((group) => group.billingClass === \"opengeni_credits\")\n ?.rows.filter((row) => row.selectable);\n // Presentation only: never change the catalog/default model ordering or selection.\n const onlyFreeOpenGeni =\n selectableOpenGeni !== undefined &&\n selectableOpenGeni.length > 0 &&\n selectableOpenGeni.every((row) => row.catalog.cost === \"free\");\n if (\n codex &&\n codex.rows.some((row) => row.selectable) &&\n (options?.codexOnly || onlyFreeOpenGeni)\n ) {\n groups.splice(codexIndex, 1);\n groups.unshift(codex);\n }\n return groups;\n}\nexport { modelDisplayName, modelVendor } from \"@opengeni/sdk/model-display\";\n"],"mappings":"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","names":["modelDisplayName"]}
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-BRM6FVZA.js";
12
12
  import {
13
13
  groupPickerRowsByBillingClass
14
- } from "./chunk-RLUSC2WA.js";
14
+ } from "./chunk-5F4WR7X7.js";
15
15
  import {
16
16
  ComposerResponsiveContext
17
17
  } from "./chunk-VZTQ73XT.js";
@@ -4752,4 +4752,4 @@ export {
4752
4752
  useVoiceInput,
4753
4753
  ComposerTranscriptionControl
4754
4754
  };
4755
- //# sourceMappingURL=chunk-EN3YTHKR.js.map
4755
+ //# sourceMappingURL=chunk-CY7WK5FD.js.map
@@ -7,7 +7,7 @@ import {
7
7
  labelReasoningEffort,
8
8
  projectClientModelRows,
9
9
  scopedBillingClassLabel
10
- } from "./chunk-RLUSC2WA.js";
10
+ } from "./chunk-5F4WR7X7.js";
11
11
  import {
12
12
  usePortalTokenSource,
13
13
  usePortalTokenStyle
@@ -31,9 +31,11 @@ function GrokMark(props) {
31
31
  // src/components/model-mark.tsx
32
32
  import {
33
33
  modelDisplayName,
34
+ modelLogoUrl,
34
35
  modelVendor
35
36
  } from "@opengeni/sdk/model-display";
36
37
  import { SparklesIcon } from "lucide-react";
38
+ import { useState } from "react";
37
39
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
38
40
  function ChatGptMark(props) {
39
41
  return /* @__PURE__ */ jsx3("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx3("path", { d: "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3653-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8414 3.3698-2.02 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.783-2.7622a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" }) });
@@ -41,14 +43,25 @@ function ChatGptMark(props) {
41
43
  var MARKED_VENDORS = /* @__PURE__ */ new Set(["openai", "anthropic", "xai"]);
42
44
  function modelHasMark(model) {
43
45
  const vendor = modelVendor(model);
44
- return vendor !== null && MARKED_VENDORS.has(vendor);
46
+ return modelLogoUrl(model) !== null || vendor !== null && MARKED_VENDORS.has(vendor);
45
47
  }
46
48
  function ModelMark(props) {
49
+ const logoUrl = modelLogoUrl(props.model);
50
+ const [failedUrl, setFailedUrl] = useState(null);
47
51
  const vendor = modelVendor(props.model);
48
52
  const className = cn("size-3.5 shrink-0", props.className);
49
53
  const label = props["aria-label"];
50
54
  const a11y = label ? { role: "img", "aria-label": label } : { "aria-hidden": true };
51
- const mark = vendor === "openai" ? /* @__PURE__ */ jsx3(ChatGptMark, { className: "size-full" }) : vendor === "anthropic" ? /* @__PURE__ */ jsx3(ClaudeMark, { className: "size-full" }) : vendor === "xai" ? /* @__PURE__ */ jsx3(GrokMark, { className: "size-full" }) : props.fallback !== void 0 ? props.fallback : /* @__PURE__ */ jsx3(SparklesIcon, { className: "size-full", "aria-hidden": true });
55
+ const mark = logoUrl && logoUrl !== failedUrl ? /* @__PURE__ */ jsx3(
56
+ "img",
57
+ {
58
+ src: logoUrl,
59
+ alt: "",
60
+ className: "size-full object-contain",
61
+ referrerPolicy: "no-referrer",
62
+ onError: () => setFailedUrl(logoUrl)
63
+ }
64
+ ) : vendor === "openai" ? /* @__PURE__ */ jsx3(ChatGptMark, { className: "size-full" }) : vendor === "anthropic" ? /* @__PURE__ */ jsx3(ClaudeMark, { className: "size-full" }) : vendor === "xai" ? /* @__PURE__ */ jsx3(GrokMark, { className: "size-full" }) : props.fallback !== void 0 ? props.fallback : /* @__PURE__ */ jsx3(SparklesIcon, { className: "size-full", "aria-hidden": true });
52
65
  if (mark === null) return null;
53
66
  return /* @__PURE__ */ jsx3(
54
67
  "span",
@@ -69,7 +82,7 @@ function ModelName(props) {
69
82
  }
70
83
 
71
84
  // src/components/model-policy-picker.tsx
72
- import { modelDisplayName as modelDisplayName2 } from "@opengeni/sdk/model-display";
85
+ import { modelDisplayName as modelDisplayName2, modelLogoUrl as modelLogoUrl2 } from "@opengeni/sdk/model-display";
73
86
  import {
74
87
  ChevronDownIcon,
75
88
  ChevronLeftIcon,
@@ -85,11 +98,11 @@ import {
85
98
  lazy,
86
99
  useMemo,
87
100
  useId,
88
- useState
101
+ useState as useState2
89
102
  } from "react";
90
103
  import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
91
104
  var LazyModelPolicyPickerMenu = lazy(
92
- () => import("./model-policy-picker-menu-M54ISBMN.js").then(({ ModelPolicyPickerPopover }) => ({
105
+ () => import("./model-policy-picker-menu-DXHUL73H.js").then(({ ModelPolicyPickerPopover }) => ({
93
106
  default: ModelPolicyPickerPopover
94
107
  }))
95
108
  );
@@ -191,6 +204,9 @@ function SelectedModelMark(input) {
191
204
  }
192
205
  );
193
206
  }
207
+ if (modelLogoUrl2(model)) {
208
+ return /* @__PURE__ */ jsx4(ModelMark, { model, className: "text-og-fg" });
209
+ }
194
210
  if (presentation?.icon !== void 0 || BRANDED_BILLING_CLASSES.has(billingClass) || !modelHasMark(model)) {
195
211
  return /* @__PURE__ */ jsx4(
196
212
  BillingClassMark,
@@ -304,7 +320,7 @@ function PickerAnimatedPage(props) {
304
320
  );
305
321
  }
306
322
  function useModelPolicyPickerState(props) {
307
- const [uncontrolledOpen, setUncontrolledOpen] = useState(props.defaultOpen ?? false);
323
+ const [uncontrolledOpen, setUncontrolledOpen] = useState2(props.defaultOpen ?? false);
308
324
  const open = props.open ?? uncontrolledOpen;
309
325
  const setOpen = (next) => {
310
326
  if (props.open === void 0) setUncontrolledOpen(next);
@@ -323,6 +339,7 @@ function ModelPolicyPicker(props) {
323
339
  const { open, setOpen, rows } = useModelPolicyPickerState(props);
324
340
  const selected = findPickerRow(rows, props.model);
325
341
  const needsModel = !rows.some((row) => row.selectable) && (rows.length > 0 || Boolean(props.connectModelsHref));
342
+ const selectedDescription = needsModel ? messages.connectTitle : [selected?.label ?? fallbackName(props), labelReasoningEffort(props.effort)].join(" \xB7 ");
326
343
  if (props.loading) {
327
344
  return /* @__PURE__ */ jsx4(
328
345
  "span",
@@ -352,6 +369,7 @@ function ModelPolicyPicker(props) {
352
369
  onClick: () => setOpen(!open),
353
370
  disabled: props.disabled,
354
371
  "aria-label": messages.label,
372
+ "aria-description": selectedDescription,
355
373
  className: cn(
356
374
  "og-root inline-flex h-8 min-w-[180px] max-w-full items-center gap-2 rounded-og-md border border-og-border bg-og-surface px-2.5 text-sm text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
357
375
  props.className
@@ -389,6 +407,7 @@ function ModelPolicyPicker(props) {
389
407
  onClick: () => setOpen(!open),
390
408
  disabled: props.disabled,
391
409
  "aria-label": messages.label,
410
+ "aria-description": selectedDescription,
392
411
  className: cn(
393
412
  "og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border px-2.5 text-og-control outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2",
394
413
  // With no usable model the pill is the one thing that unblocks the
@@ -450,4 +469,4 @@ export {
450
469
  PickerAnimatedPage,
451
470
  ModelPolicyPicker
452
471
  };
453
- //# sourceMappingURL=chunk-26ZNDDLZ.js.map
472
+ //# sourceMappingURL=chunk-LNIRAOA3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/claude-mark.tsx","../src/components/grok-mark.tsx","../src/components/model-mark.tsx","../src/components/model-policy-picker.tsx"],"sourcesContent":["import type { SVGProps } from \"react\";\n\n/** ClaudeMark: Simple Icons, CC0; https://github.com/simple-icons/simple-icons */\nexport function ClaudeMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d=\"m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z\" />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\n\n/**\n * MIT License\n *\n * Copyright (c) 2023 LobeHub\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n * Source: https://raw.githubusercontent.com/lobehub/lobe-icons/master/src/Grok/components/Mono.tsx\n */\nexport function GrokMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d=\"M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815\" />\n </svg>\n );\n}\n","import {\n modelDisplayName,\n modelLogoUrl,\n modelVendor,\n type ModelDisplayInput,\n type ModelVendor,\n} from \"@opengeni/sdk/model-display\";\nimport { SparklesIcon } from \"lucide-react\";\nimport { useState, type ReactNode, type SVGProps } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { ClaudeMark } from \"./claude-mark\";\nimport { GrokMark } from \"./grok-mark\";\n\n/** ChatGPT / OpenAI mark (Simple Icons path), currentColor like the other marks. */\nexport function ChatGptMark(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <path d=\"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3653-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8414 3.3698-2.02 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.783-2.7622a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z\" />\n </svg>\n );\n}\n\nconst MARKED_VENDORS: ReadonlySet<ModelVendor> = new Set([\"openai\", \"anthropic\", \"xai\"]);\n\n/** True when `ModelMark` has a real maker logo for this model (not the neutral fallback). */\nexport function modelHasMark(model: ModelDisplayInput): boolean {\n const vendor = modelVendor(model);\n return modelLogoUrl(model) !== null || (vendor !== null && MARKED_VENDORS.has(vendor));\n}\n\n/**\n * The catalog's maker logo, with bundled maker logos and a neutral fallback.\n * Makers without a configured or bundled logo get a neutral mark, so an org- and\n * a workspace-connected copy of one model always look the same.\n */\nexport function ModelMark(props: {\n model: ModelDisplayInput;\n className?: string | undefined;\n /** Shown when the maker has no bundled logo. Defaults to a neutral sparkle. */\n fallback?: ReactNode;\n \"aria-label\"?: string | undefined;\n}) {\n const logoUrl = modelLogoUrl(props.model);\n const [failedUrl, setFailedUrl] = useState<string | null>(null);\n const vendor = modelVendor(props.model);\n const className = cn(\"size-3.5 shrink-0\", props.className);\n const label = props[\"aria-label\"];\n const a11y = label ? { role: \"img\" as const, \"aria-label\": label } : { \"aria-hidden\": true };\n const mark =\n logoUrl && logoUrl !== failedUrl ? (\n <img\n src={logoUrl}\n alt=\"\"\n className=\"size-full object-contain\"\n referrerPolicy=\"no-referrer\"\n onError={() => setFailedUrl(logoUrl)}\n />\n ) : vendor === \"openai\" ? (\n <ChatGptMark className=\"size-full\" />\n ) : vendor === \"anthropic\" ? (\n <ClaudeMark className=\"size-full\" />\n ) : vendor === \"xai\" ? (\n <GrokMark className=\"size-full\" />\n ) : props.fallback !== undefined ? (\n props.fallback\n ) : (\n <SparklesIcon className=\"size-full\" aria-hidden />\n );\n if (mark === null) return null;\n return (\n <span\n className={cn(\"inline-flex items-center justify-center [&>svg]:size-full\", className)}\n data-model-vendor={vendor ?? \"unknown\"}\n {...a11y}\n >\n {mark}\n </span>\n );\n}\n\n/**\n * A model as people should see it outside model settings: the maker's mark and\n * the clean display name. Never a routing prefix, connection id or scope.\n */\nexport function ModelName(props: {\n model: ModelDisplayInput;\n /** Hide the maker mark for dense text-only contexts. */\n mark?: boolean | undefined;\n className?: string | undefined;\n markClassName?: string | undefined;\n}) {\n const name = modelDisplayName(props.model);\n return (\n <span className={cn(\"inline-flex min-w-0 items-center gap-1.5\", props.className)} title={name}>\n {props.mark === false ? null : (\n <ModelMark model={props.model} className={props.markClassName} />\n )}\n <span className=\"min-w-0 truncate\">{name}</span>\n </span>\n );\n}\n","import { ClaudeMark } from \"./claude-mark\";\nimport { GrokMark } from \"./grok-mark\";\nimport { ChatGptMark, ModelMark, modelHasMark } from \"./model-mark\";\nimport { modelDisplayName, modelLogoUrl } from \"@opengeni/sdk/model-display\";\nimport type { ClientModel, LatencyMode, ReasoningEffort } from \"@opengeni/sdk\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n Globe2Icon,\n KeyRoundIcon,\n SparklesIcon,\n ZapIcon,\n} from \"lucide-react\";\nimport { motion, useReducedMotion } from \"motion/react\";\nimport {\n Suspense,\n lazy,\n useMemo,\n useId,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { MENU_CHEVRON_CLASS } from \"../lib/menu-styles\";\nimport { usePortalTokenSource, usePortalTokenStyle } from \"../lib/use-portal-token-style\";\nimport {\n effortOptionsForModel,\n findPickerRow,\n labelReasoningEffort,\n projectClientModelRows,\n scopedBillingClassLabel,\n type PickerBillingClass,\n type PickerModelRow,\n} from \"../model-policy\";\n\nconst LazyModelPolicyPickerMenu = lazy(() =>\n import(\"./model-policy-picker-menu\").then(({ ModelPolicyPickerPopover }) => ({\n default: ModelPolicyPickerPopover,\n })),\n);\n\ntype ClientPickerModelRow = PickerModelRow<ClientModel>;\n\n/** Presentation only; never changes model identity, billing or availability. */\nexport type ModelPolicyPickerGroupPresentation = Partial<\n Record<\n PickerBillingClass,\n {\n label?: string | undefined;\n /** Omit to preserve the default; null hides the supporting text. */\n description?: string | null | undefined;\n /** Decorative, non-interactive content. Omit for the default; null hides it. */\n icon?: ReactNode | undefined;\n }\n >\n>;\n\nexport type ModelPolicyPickerMessages = {\n label: string;\n loading: string;\n noModels: string;\n connectTitle: string;\n connectBody: string;\n connectAction: string;\n thinking: string;\n fast: string;\n fastRateHint: string;\n codexOnly: string;\n searchLabel?: string;\n searchPlaceholder?: string;\n currentModel?: string;\n noMatches?: string;\n unsupportedAttachments?: string;\n thinkingEffort?: string;\n selected?: string;\n free?: string;\n\n billingHints: Record<PickerBillingClass, string>;\n};\n\nexport const defaultModelPolicyPickerMessages: ModelPolicyPickerMessages = {\n label: \"Model and effort\",\n loading: \"Loading model catalog…\",\n noModels: \"No models available.\",\n connectTitle: \"Connect a model\",\n connectBody: \"Use a subscription or a provider key you already have.\",\n connectAction: \"Open Models\",\n thinking: \"Thinking\",\n fast: \"Fast\",\n fastRateHint: \"2× rate\",\n codexOnly: \"Codex-only session\",\n searchLabel: \"Search models or providers\",\n searchPlaceholder: \"Search models or providers…\",\n currentModel: \"Current model\",\n noMatches: \"No matching models. Try a model or provider name.\",\n unsupportedAttachments: \"This model cannot view the attached images.\",\n thinkingEffort: \"Thinking effort\",\n selected: \"Selected\",\n free: \"Free\",\n\n billingHints: {\n opengeni_credits: \"Provided by Opengeni\",\n external: \"Provider terms and limits apply\",\n codex_subscription: \"ChatGPT / Codex plan\",\n supergrok_subscription: \"SuperGrok / xAI plan\",\n claude_subscription: \"Claude plan\",\n byok: \"Billed to the connected provider account\",\n organization_byok: \"Billed to the connected provider account\",\n },\n};\n\nexport type ModelPolicyPickerProps = {\n /** Host branding for payment-source groups, shared by menu and trigger. */\n groupPresentation?: ModelPolicyPickerGroupPresentation | undefined;\n /** Lightweight deployment models. Catalog rows take precedence when supplied. */\n models?: ClientModel[] | undefined;\n /** Warn only when the draft actually contains images this model cannot view. */\n hasImageAttachments?: boolean | undefined;\n /** Catalog-backed rows with availability and billing-class truth. */\n rows?: PickerModelRow[] | undefined;\n model: string;\n effort: ReasoningEffort;\n latencyMode: LatencyMode;\n disabled?: boolean | undefined;\n loading?: boolean | undefined;\n error?: string | null | undefined;\n /** Controlled menu state. Omit for the built-in uncontrolled behavior. */\n open?: boolean | undefined;\n /** Initial menu state when `open` is uncontrolled. */\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n /** Non-Codex models stay visible but cannot be selected. */\n codexOnly?: boolean | undefined;\n /** Identity of the current session scope. */\n sessionKey?: string | undefined;\n /** Prefer bottom on new-chat surfaces and top for bottom-docked composers. */\n menuSide?: \"top\" | \"bottom\" | undefined;\n /**\n * Default true: show models the way people choose them, with clean names,\n * maker marks, one \"API keys\" group for organization- and workspace-connected\n * keys, and one row for identical copies. Models settings passes false to\n * keep its scope-aware presentation (raw catalog labels, scoped groups).\n */\n collapseScopes?: boolean | undefined;\n /** Hide latency controls on surfaces whose saved policy does not include latency. */\n allowLatencyMode?: boolean | undefined;\n /** Settings → Models. Shown when the catalog has no model that can run. */\n connectModelsHref?: string | undefined;\n /** Classes for the portalled menu surface. Prefer --og-* tokens for theming. */\n contentClassName?: string | undefined;\n /** Inline styles for the portalled menu, applied after inherited --og-* tokens. */\n contentStyle?: CSSProperties | undefined;\n className?: string | undefined;\n /**\n * \"pill\" (default) is the composer's quiet rounded trigger with the effort.\n * \"field\" is a settings control: a bordered rectangle with the model name\n * and `triggerMeta` (for example the payer) in muted text. The effort stays\n * in the menu.\n */\n triggerStyle?: \"pill\" | \"field\" | undefined;\n /** Muted text after the model name in the \"field\" trigger. */\n triggerMeta?: ReactNode;\n messages?: Partial<ModelPolicyPickerMessages> | undefined;\n onModelChange: (modelId: string) => void;\n onEffortChange: (effort: ReasoningEffort) => void;\n onLatencyModeChange: (latencyMode: LatencyMode) => void;\n};\n\nconst SLIDE_EASE = [0.22, 1, 0.36, 1] as const;\n\nexport function BillingClassMark(props: {\n billingClass: PickerBillingClass;\n presentation?: ModelPolicyPickerGroupPresentation[PickerBillingClass] | undefined;\n className?: string | undefined;\n \"aria-label\"?: string | undefined;\n}) {\n const labels: Record<PickerBillingClass, string> = {\n opengeni_credits: \"Models\",\n external: \"External provider\",\n codex_subscription: \"Codex\",\n supergrok_subscription: \"SuperGrok\",\n claude_subscription: \"Claude\",\n byok: \"API key\",\n organization_byok: \"API key\",\n };\n if (props.presentation?.icon === null) return null;\n const label = props[\"aria-label\"] ?? props.presentation?.label ?? labels[props.billingClass];\n const accessibility =\n label.length === 0\n ? { \"aria-hidden\": true as const }\n : { role: \"img\" as const, \"aria-label\": label };\n const shell = cn(\n \"inline-flex size-3.5 shrink-0 items-center justify-center overflow-hidden text-og-fg-subtle [&>svg]:size-full [&>img]:size-full\",\n props.className,\n );\n const mark = \"size-3.5\";\n return (\n <span\n className={shell}\n data-testid={`billing-class-icon-${props.billingClass}`}\n {...accessibility}\n >\n {props.presentation?.icon !== undefined ? (\n props.presentation.icon\n ) : props.billingClass === \"opengeni_credits\" ? (\n <SparklesIcon className={mark} aria-hidden />\n ) : props.billingClass === \"external\" ? (\n <Globe2Icon className={mark} aria-hidden />\n ) : props.billingClass === \"codex_subscription\" ? (\n <ChatGptMark className={mark} />\n ) : props.billingClass === \"claude_subscription\" ? (\n <ClaudeMark className={mark} />\n ) : props.billingClass === \"supergrok_subscription\" ? (\n <GrokMark className={mark} />\n ) : (\n <KeyRoundIcon className={mark} aria-hidden />\n )}\n </span>\n );\n}\n\nfunction isCodexModel(model: ClientModel): boolean {\n return model.id.startsWith(\"codex/\") || model.source === \"codex\";\n}\n\nfunction billingClassForMissingSelection(modelId: string): PickerBillingClass {\n if (modelId.startsWith(\"workspace-claude-subscription/\")) return \"claude_subscription\";\n if (modelId.startsWith(\"workspace-anthropic/\")) return \"byok\";\n if (modelId.startsWith(\"organization-claude-subscription/\")) return \"claude_subscription\";\n if (modelId.startsWith(\"organization-anthropic/\")) return \"organization_byok\";\n if (modelId.startsWith(\"workspace-gateway/\")) return \"byok\";\n if (modelId.startsWith(\"workspace-openrouter/\")) return \"byok\";\n // A deployment OpenRouter ID does not encode its workspace-facing cost.\n // Missing rows therefore use the credits-safe rail instead of falsely\n // claiming that an unknown former selection was externally funded.\n if (modelId.startsWith(\"openrouter/\")) return \"opengeni_credits\";\n if (modelId.startsWith(\"codex/\")) return \"codex_subscription\";\n if (modelId.startsWith(\"supergrok/\")) return \"supergrok_subscription\";\n return \"opengeni_credits\";\n}\n\nfunction applyCodexOnly(\n rows: ClientPickerModelRow[],\n codexOnly: boolean,\n unavailableReason: string,\n): ClientPickerModelRow[] {\n if (!codexOnly) return rows;\n return rows.map((row) =>\n isCodexModel(row.catalog)\n ? row\n : {\n ...row,\n selectable: false,\n unavailableReason: row.unavailableReason ?? unavailableReason,\n },\n );\n}\n\n/**\n * The trigger shows who makes the chosen model. Subscription rails already\n * carry their maker's mark (ChatGPT, Claude, Grok). Configured catalog logos win\n * in collapsed model presentation; otherwise explicit host branding wins and models show\n * the maker's logo instead of a generic key, falling back to the group mark.\n */\nfunction SelectedModelMark(input: {\n props: ModelPolicyPickerProps;\n selected: ClientPickerModelRow | null;\n}) {\n const billingClass =\n input.selected?.billingClass ?? billingClassForMissingSelection(input.props.model);\n const presentation = groupPresentationFor(input.props, billingClass);\n const model = input.selected?.catalog ?? input.props.model;\n if (input.props.collapseScopes === false) {\n return (\n <BillingClassMark\n billingClass={billingClass}\n presentation={presentation}\n aria-label={presentation?.label ?? SCOPED_MARK_LABELS[billingClass]}\n className=\"text-og-fg\"\n />\n );\n }\n if (modelLogoUrl(model)) {\n return <ModelMark model={model} className=\"text-og-fg\" />;\n }\n if (\n presentation?.icon !== undefined ||\n BRANDED_BILLING_CLASSES.has(billingClass) ||\n !modelHasMark(model)\n ) {\n return (\n <BillingClassMark\n billingClass={billingClass}\n presentation={presentation}\n className=\"text-og-fg\"\n />\n );\n }\n return <ModelMark model={model} className=\"text-og-fg\" />;\n}\n\nconst SCOPED_MARK_LABELS: Partial<Record<PickerBillingClass, string>> = {\n byok: \"Workspace provider account\",\n organization_byok: \"Organization provider account\",\n};\n\n/** Models settings keeps naming who is billed for a key. */\nexport const SCOPED_BILLING_HINTS: Partial<Record<PickerBillingClass, string>> = {\n byok: \"Billed to the workspace provider account\",\n organization_byok: \"Billed to the organization provider account\",\n};\n\n/**\n * Host branding for a payment group. While scopes are collapsed, API keys are\n * one group, so either API-key presentation serves both.\n */\nexport function groupPresentationFor(\n props: Pick<ModelPolicyPickerProps, \"groupPresentation\" | \"collapseScopes\">,\n billingClass: PickerBillingClass,\n): ModelPolicyPickerGroupPresentation[PickerBillingClass] {\n const own = props.groupPresentation?.[billingClass];\n if (own !== undefined || props.collapseScopes === false) return own;\n if (billingClass === \"byok\") return props.groupPresentation?.organization_byok;\n if (billingClass === \"organization_byok\") return props.groupPresentation?.byok;\n return undefined;\n}\n\n/** A selection the catalog no longer lists: its clean name (settings keep the id). */\nfunction fallbackName(props: ModelPolicyPickerProps): string {\n return props.collapseScopes === false ? props.model : modelDisplayName(props.model);\n}\n\nconst BRANDED_BILLING_CLASSES: ReadonlySet<PickerBillingClass> = new Set([\n \"codex_subscription\",\n \"claude_subscription\",\n \"supergrok_subscription\",\n]);\n\nexport function effectiveRows(props: ModelPolicyPickerProps): ClientPickerModelRow[] {\n const rows = props.rows !== undefined ? props.rows : projectClientModelRows(props.models ?? []);\n const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };\n return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly).map((row) => {\n const scoped =\n props.collapseScopes === false\n ? {\n ...row,\n label: row.catalog.label,\n billingClassLabel: scopedBillingClassLabel(row.billingClass),\n }\n : row;\n if (props.collapseScopes === false) {\n if (row.catalog.shortLabel) scoped.shortLabel = row.catalog.shortLabel;\n else delete scoped.shortLabel;\n }\n const label = groupPresentationFor(props, row.billingClass)?.label;\n return label === undefined ? scoped : { ...scoped, billingClassLabel: label };\n });\n}\n\nexport function PickerNavRow(props: {\n label: string;\n hint?: string | undefined;\n icon?: ReactNode;\n trailing?: ReactNode;\n showChevron?: boolean | undefined;\n disabled?: boolean | undefined;\n title?: string | undefined;\n description?: string | undefined;\n active?: boolean | undefined;\n testId?: string | undefined;\n onClick: () => void;\n}) {\n return (\n <button\n type=\"button\"\n disabled={props.disabled}\n title={props.title}\n aria-description={props.description}\n onClick={props.onClick}\n data-testid={props.testId}\n className={cn(\n // The one menu row (lib/menu-styles.ts), with density tokens for embedders.\n \"flex min-h-8 w-full cursor-pointer items-center gap-2.5 rounded-og-md px-[var(--og-model-picker-row-padding-x)] py-[var(--og-model-picker-row-padding-y)] text-left text-og-fg outline-hidden transition-colors duration-[120ms] hover:bg-og-hover focus-visible:bg-og-hover focus-visible:outline-2 focus-visible:-outline-offset-2! focus-visible:outline-og-accent/55 pointer-coarse:min-h-11\",\n props.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {props.icon}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-og-menu\">{props.label}</span>\n {props.hint ? (\n <span className=\"mt-0.5 block truncate text-og-sm text-og-fg-muted\">{props.hint}</span>\n ) : null}\n </span>\n {props.trailing ? <span className=\"ml-auto shrink-0\">{props.trailing}</span> : null}\n {props.showChevron === false ? null : <ChevronRightIcon className={MENU_CHEVRON_CLASS} />}\n </button>\n );\n}\n\nexport function PickerBackHeader(props: {\n label: string;\n icon?: ReactNode;\n onBack: () => void;\n trailing?: ReactNode;\n}) {\n return (\n <div className=\"mb-1.5 flex min-h-9 items-center gap-1 border-b border-og-border pb-1.5\">\n <button\n type=\"button\"\n onClick={props.onBack}\n data-testid=\"model-picker-back\"\n className=\"flex min-h-8 min-w-0 flex-1 cursor-pointer items-center gap-1 rounded-og-md pr-2.5 text-left text-og-fg outline-hidden transition-colors duration-[120ms] hover:bg-og-hover focus-visible:outline-2 focus-visible:-outline-offset-2! focus-visible:outline-og-accent/55 pointer-coarse:min-h-11\"\n >\n <span className=\"flex size-8 shrink-0 items-center justify-center text-og-fg-muted\">\n <ChevronLeftIcon className=\"size-4\" />\n </span>\n {props.icon}\n <span className=\"min-w-0 flex-1 truncate text-og-menu font-medium\">{props.label}</span>\n </button>\n {props.trailing ? <div className=\"relative z-10 shrink-0\">{props.trailing}</div> : null}\n </div>\n );\n}\n\nexport function PickerAnimatedPage(props: {\n pageKey: string;\n direction: 1 | -1;\n children: ReactNode;\n}) {\n const reduceMotion = useReducedMotion();\n return (\n <motion.div\n key={props.pageKey}\n initial={reduceMotion ? false : { x: props.direction * 14, opacity: 0 }}\n animate={{ x: 0, opacity: 1 }}\n transition={{ duration: reduceMotion ? 0 : 0.18, ease: SLIDE_EASE }}\n className=\"w-full\"\n >\n {props.children}\n </motion.div>\n );\n}\n\n/** @internal Shared controlled/uncontrolled state seam. */\nexport function useModelPolicyPickerState(props: ModelPolicyPickerProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(props.defaultOpen ?? false);\n const open = props.open ?? uncontrolledOpen;\n const setOpen = (next: boolean) => {\n if (props.open === undefined) setUncontrolledOpen(next);\n props.onOpenChange?.(next);\n };\n return { open, setOpen, rows: effectiveRows(props) };\n}\n\nexport function ModelPolicyPicker(props: ModelPolicyPickerProps) {\n const contentId = useId();\n const trigger = usePortalTokenSource<HTMLButtonElement>();\n const portalStyle = usePortalTokenStyle(trigger.source);\n const messages = useMemo(\n () => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),\n [props.messages],\n );\n const { open, setOpen, rows } = useModelPolicyPickerState(props);\n const selected = findPickerRow(rows, props.model);\n const needsModel =\n !rows.some((row) => row.selectable) && (rows.length > 0 || Boolean(props.connectModelsHref));\n const selectedDescription = needsModel\n ? messages.connectTitle\n : [selected?.label ?? fallbackName(props), labelReasoningEffort(props.effort)].join(\" · \");\n\n if (props.loading) {\n return (\n <span\n className={cn(\n \"og-root inline-flex h-8 w-40 shrink-0 animate-pulse rounded-full bg-og-surface-2\",\n props.triggerStyle === \"field\" && \"w-[180px] rounded-og-md\",\n props.className,\n )}\n aria-label={messages.loading}\n data-testid=\"model-picker-loading\"\n />\n );\n }\n if (props.triggerStyle === \"field\") {\n return (\n <>\n <button\n ref={trigger.ref}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n data-state={open ? \"open\" : \"closed\"}\n data-trigger-style=\"field\"\n onClick={() => setOpen(!open)}\n disabled={props.disabled}\n aria-label={messages.label}\n aria-description={selectedDescription}\n className={cn(\n \"og-root inline-flex h-8 min-w-[180px] max-w-full items-center gap-2 rounded-og-md border border-og-border bg-og-surface px-2.5 text-sm text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50\",\n props.className,\n )}\n >\n {needsModel ? (\n <SparklesIcon className=\"size-3.5 shrink-0\" aria-hidden />\n ) : (\n <SelectedModelMark props={props} selected={selected} />\n )}\n <span className=\"min-w-0 truncate font-medium\">\n {needsModel ? messages.connectTitle : (selected?.label ?? fallbackName(props))}\n </span>\n {props.triggerMeta && !needsModel ? (\n <span className=\"min-w-0 shrink-[9999] truncate text-og-fg-muted\">\n {props.triggerMeta}\n </span>\n ) : null}\n <ChevronDownIcon className=\"ml-auto size-3.5 shrink-0 text-og-fg-muted\" />\n </button>\n {open ? (\n <Suspense fallback={null}>\n <LazyModelPolicyPickerMenu\n {...props}\n anchor={trigger.currentRef}\n contentId={contentId}\n portalStyle={portalStyle}\n onOpenChange={setOpen}\n />\n </Suspense>\n ) : null}\n </>\n );\n }\n return (\n <>\n <button\n ref={trigger.ref}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? contentId : undefined}\n data-state={open ? \"open\" : \"closed\"}\n onClick={() => setOpen(!open)}\n disabled={props.disabled}\n aria-label={messages.label}\n aria-description={selectedDescription}\n className={cn(\n \"og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border px-2.5 text-og-control outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2\",\n // With no usable model the pill is the one thing that unblocks the\n // composer, so it takes the primary wash.\n needsModel\n ? \"border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover\"\n : \"border-transparent text-og-fg-muted hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg\",\n props.className,\n )}\n >\n {needsModel ? (\n <SparklesIcon className=\"size-3.5 shrink-0\" aria-hidden />\n ) : (\n <SelectedModelMark props={props} selected={selected} />\n )}\n <span className=\"og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden @max-[20rem]/model-controls:hidden\">\n {needsModel ? messages.connectTitle : (selected?.label ?? fallbackName(props))}\n </span>\n <span className=\"og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden @max-[20rem]/model-controls:block\">\n {needsModel\n ? messages.connectTitle\n : (selected?.shortLabel ?? selected?.label ?? fallbackName(props))}\n </span>\n {selected &&\n !needsModel &&\n effortOptionsForModel(selected.catalog).length > 1 &&\n selected.catalog.capabilities?.reasoning.runnable !== false ? (\n <span\n className=\"og-model-policy-effort min-w-0 shrink-[9999] truncate\"\n title={labelReasoningEffort(props.effort)}\n >\n {labelReasoningEffort(props.effort)}\n </span>\n ) : null}\n {props.latencyMode === \"fast\" && !needsModel ? (\n <ZapIcon\n className=\"size-3.5 shrink-0 fill-current stroke-current text-og-fg\"\n aria-label={messages.fast}\n data-testid=\"model-picker-fast-icon\"\n />\n ) : null}\n <ChevronDownIcon className=\"size-3 shrink-0\" />\n </button>\n\n {open ? (\n <Suspense fallback={null}>\n <LazyModelPolicyPickerMenu\n {...props}\n anchor={trigger.currentRef}\n contentId={contentId}\n portalStyle={portalStyle}\n onOpenChange={setOpen}\n />\n </Suspense>\n ) : null}\n </>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","modelDisplayName","modelLogoUrl","SparklesIcon","useState","jsx","jsxs","SparklesIcon","modelLogoUrl","modelDisplayName","useState"]}
@@ -854,7 +854,7 @@ function buildTimeline(events, options = {}) {
854
854
  null,
855
855
  0,
856
856
  queuedAt,
857
- `${event.id}-queue`
857
+ `${turnId}-queue`
858
858
  );
859
859
  break;
860
860
  }
@@ -1575,7 +1575,8 @@ function groupReadableTurns(items) {
1575
1575
  let group = turns.get(key);
1576
1576
  const firstMessage = messages.get(key)?.[0];
1577
1577
  const messageStart = firstMessage?.startedAt ?? firstMessage?.occurredAt;
1578
- const startedAt = messageStart && Date.parse(messageStart) < Date.parse(item.occurredAt) ? messageStart : item.occurredAt;
1578
+ const activityStart = item.kind === "startup-phase" ? item.loadingStartedAt ?? item.occurredAt : item.occurredAt;
1579
+ const startedAt = messageStart && Date.parse(messageStart) < Date.parse(activityStart) ? messageStart : activityStart;
1579
1580
  if (!group) {
1580
1581
  const settlement = settlements.get(key);
1581
1582
  group = {
@@ -2600,4 +2601,4 @@ export {
2600
2601
  isTurnExecutionEvidence,
2601
2602
  extractSessionRef
2602
2603
  };
2603
- //# sourceMappingURL=chunk-DO544OSV.js.map
2604
+ //# sourceMappingURL=chunk-RC6BZ44Q.js.map