@opengeni/react 0.42.1 → 0.44.1

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 (49) hide show
  1. package/dist/{chunk-SJKT4TKW.js → chunk-23EJ676W.js} +3 -1
  2. package/dist/chunk-23EJ676W.js.map +1 -0
  3. package/dist/{chunk-UWYTCQWW.js → chunk-KC27K42G.js} +92 -21
  4. package/dist/{chunk-UWYTCQWW.js.map → chunk-KC27K42G.js.map} +1 -1
  5. package/dist/{chunk-KR2SK5GJ.js → chunk-KG5F2OKE.js} +260 -93
  6. package/dist/chunk-KG5F2OKE.js.map +1 -0
  7. package/dist/{chunk-4IJCL7YO.js → chunk-LWR4MXSS.js} +4 -1
  8. package/dist/chunk-LWR4MXSS.js.map +1 -0
  9. package/dist/{chunk-JALF5FI3.js → chunk-SRFUT2ZU.js} +2 -2
  10. package/dist/{chunk-WZT5G5OR.js → chunk-U6K24XQD.js} +5 -4
  11. package/dist/{chunk-WZT5G5OR.js.map → chunk-U6K24XQD.js.map} +1 -1
  12. package/dist/components/chat-composer.d.ts +5 -1
  13. package/dist/components/composer-transcription-control.d.ts +3 -1
  14. package/dist/components/composer.d.ts +6 -4
  15. package/dist/components/session-chrome.d.ts +1 -1
  16. package/dist/composer.js +3 -3
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +69 -20
  19. package/dist/index.js.map +1 -1
  20. package/dist/model-policy.d.ts +2 -0
  21. package/dist/model-policy.js +1 -1
  22. package/dist/realtime/realtime-control.d.ts +29 -1
  23. package/dist/realtime.d.ts +1 -1
  24. package/dist/realtime.js +269 -151
  25. package/dist/realtime.js.map +1 -1
  26. package/dist/session-ui.js +2 -2
  27. package/dist/session.js +2 -2
  28. package/dist/timeline/index.d.ts +1 -1
  29. package/dist/timeline/parsers.d.ts +13 -8
  30. package/package.json +2 -2
  31. package/src/components/chat-composer.tsx +58 -19
  32. package/src/components/composer-transcription-control.tsx +194 -165
  33. package/src/components/composer.tsx +78 -14
  34. package/src/components/model-policy-picker.tsx +7 -2
  35. package/src/components/session-chrome.tsx +89 -78
  36. package/src/index.ts +2 -0
  37. package/src/model-policy.ts +4 -0
  38. package/src/realtime/realtime-control.tsx +307 -137
  39. package/src/realtime.ts +1 -0
  40. package/src/timeline/index.ts +2 -0
  41. package/src/timeline/parsers.ts +201 -19
  42. package/src/timeline/projection.ts +11 -0
  43. package/src/timeline/tool-renderers.tsx +7 -5
  44. package/src/timeline/turn-summary.tsx +7 -2
  45. package/styles/tokens.css +8 -5
  46. package/dist/chunk-4IJCL7YO.js.map +0 -1
  47. package/dist/chunk-KR2SK5GJ.js.map +0 -1
  48. package/dist/chunk-SJKT4TKW.js.map +0 -1
  49. /package/dist/{chunk-JALF5FI3.js.map → chunk-SRFUT2ZU.js.map} +0 -0
@@ -131,6 +131,7 @@ function projectPickerRows(models) {
131
131
  return {
132
132
  id: catalog.id,
133
133
  label: catalog.label,
134
+ ...catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {},
134
135
  billingClass,
135
136
  billingClassLabel: billingClassLabel(billingClass),
136
137
  selectable: catalog.availability.selectable,
@@ -147,6 +148,7 @@ function projectClientModelRows(models) {
147
148
  return {
148
149
  id: catalog.id,
149
150
  label: catalog.label,
151
+ ...catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {},
150
152
  billingClass,
151
153
  billingClassLabel: billingClassLabel(billingClass),
152
154
  selectable: true,
@@ -208,4 +210,4 @@ export {
208
210
  findPickerRow,
209
211
  groupPickerRowsByBillingClass
210
212
  };
211
- //# sourceMappingURL=chunk-SJKT4TKW.js.map
213
+ //# sourceMappingURL=chunk-23EJ676W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model-policy.ts"],"sourcesContent":["import type { ClientModel, ReasoningEffort, WorkspaceModelCatalogModel } from \"@opengeni/sdk\";\n\nexport type PickerBillingClass = \"opengeni_credits\" | \"codex_subscription\" | \"byok\";\n\nexport type PickerModelRow<TCatalog extends ClientModel = WorkspaceModelCatalogModel> = {\n id: string;\n label: string;\n /** Catalog-curated compact label for dense UI; fall back to `label` when absent. */\n shortLabel?: string | undefined;\n billingClass: PickerBillingClass;\n billingClassLabel: string;\n selectable: boolean;\n unavailableReason: string | null;\n provider: string;\n providerLabel: string;\n catalog: TCatalog;\n};\n\nexport type LatencyModeId = \"standard\" | \"priority\" | \"fast\";\n\nconst BILLING_CLASS_ORDER: PickerBillingClass[] = [\n \"opengeni_credits\",\n \"codex_subscription\",\n \"byok\",\n];\n\nconst BILLING_CLASS_LABELS: Record<PickerBillingClass, string> = {\n opengeni_credits: \"OpenGeni\",\n codex_subscription: \"Codex\",\n byok: \"Your Gateway\",\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.source === \"codex\") {\n return \"codex_subscription\";\n }\n if (model.source === \"workspace_gateway\") {\n return \"byok\";\n }\n if (model.credentialSource?.kind === \"connected_subscription\") {\n return \"codex_subscription\";\n }\n if (model.credentialSource?.kind === \"workspace_connection\") {\n return \"byok\";\n }\n if (model.billing?.upstreamPayer === \"connected_subscription\") {\n return \"codex_subscription\";\n }\n if (model.billing?.upstreamPayer === \"workspace\") {\n return \"byok\";\n }\n return \"opengeni_credits\";\n}\n\nexport function billingClassLabel(billingClass: PickerBillingClass): string {\n return BILLING_CLASS_LABELS[billingClass];\n}\n\nexport function availabilityReasonLabel(\n reason: WorkspaceModelCatalogModel[\"availability\"][\"reason\"],\n): string | null {\n if (!reason) {\n return null;\n }\n return AVAILABILITY_REASON_LABELS[reason] ?? \"Unavailable\";\n}\n\nexport function effortOptionsForModel(model: ClientModel): ReasoningEffort[] {\n const efforts = model.capabilities?.reasoning.efforts;\n if (!efforts || efforts.length === 0) {\n return [\"low\"];\n }\n const order: ReasoningEffort[] = [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n return order.filter((effort) => efforts.includes(effort));\n}\n\nexport function defaultEffortForModel(model: ClientModel): ReasoningEffort {\n const options = effortOptionsForModel(model);\n const configured = model.capabilities?.reasoning.defaultEffort;\n if (configured && options.includes(configured)) {\n return configured;\n }\n return options[0] ?? \"low\";\n}\n\nexport function coerceReasoningEffortForModel(\n model: ClientModel,\n effort: ReasoningEffort,\n): ReasoningEffort {\n const options = effortOptionsForModel(model);\n if (options.includes(effort)) {\n return effort;\n }\n return defaultEffortForModel(model);\n}\n\nexport function runnableLatencyModesForModel(model: ClientModel): LatencyModeId[] {\n const modes = model.capabilities?.latencyModes ?? [];\n return modes.filter((mode) => mode.runnable).map((mode) => mode.id);\n}\n\nexport function labelLatencyMode(mode: LatencyModeId): string {\n if (mode === \"fast\") {\n return \"Fast\";\n }\n if (mode === \"priority\") {\n return \"Priority\";\n }\n return \"Standard\";\n}\n\nexport function labelReasoningEffort(effort: ReasoningEffort): string {\n if (effort === \"xhigh\") {\n return \"Extra high\";\n }\n return effort.slice(0, 1).toUpperCase() + effort.slice(1);\n}\n\nexport function payerSummaryForModel(model: ClientModel): string {\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 \"Codex subscription · external billing\";\n }\n if (billing.upstreamPayer === \"workspace\") {\n return \"Billed to your AI Gateway\";\n }\n return \"Deployment route · external billing\";\n}\n\nexport function advancedSourceSummary(model: ClientModel): string | null {\n const source = model.credentialSource;\n if (!source) {\n return null;\n }\n if (source.kind === \"connected_subscription\") {\n return \"Connected Codex subscription\";\n }\n if (source.kind === \"workspace_connection\") {\n return \"Workspace AI Gateway\";\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\nexport function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerModelRow[] {\n return models\n .filter((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return billingClass === \"opengeni_credits\" || catalog.credentialReadiness.status === \"ready\";\n })\n .map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: catalog.availability.selectable,\n unavailableReason: catalog.availability.selectable\n ? null\n : availabilityReasonLabel(catalog.availability.reason),\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\n/** Project the lightweight client-config model list into the same picker contract. */\nexport function projectClientModelRows(models: ClientModel[]): PickerModelRow<ClientModel>[] {\n return models.map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: true,\n unavailableReason: null,\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\nexport function sortPickerRows<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): PickerModelRow<TCatalog>[] {\n return [...rows].sort((left, right) => {\n const classDelta =\n BILLING_CLASS_ORDER.indexOf(left.billingClass) -\n BILLING_CLASS_ORDER.indexOf(right.billingClass);\n if (classDelta !== 0) {\n return classDelta;\n }\n if (left.selectable !== right.selectable) {\n return left.selectable ? -1 : 1;\n }\n return left.label.localeCompare(right.label);\n });\n}\n\nexport function findPickerRow<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n modelId: string,\n): PickerModelRow<TCatalog> | null {\n return rows.find((row) => row.id === modelId) ?? null;\n}\n\nexport function groupPickerRowsByBillingClass(\n rows: PickerModelRow[],\n): Array<{ billingClass: PickerBillingClass; label: string; rows: PickerModelRow[] }>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}> {\n const sorted = sortPickerRows(rows);\n const groups: Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n }> = [];\n for (const row of sorted) {\n const existing = groups.find((group) => group.billingClass === row.billingClass);\n if (existing) {\n existing.rows.push(row);\n continue;\n }\n groups.push({\n billingClass: row.billingClass,\n label: row.billingClassLabel,\n rows: [row],\n });\n }\n return groups;\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-Q2NCKWTK.js";
5
5
  import {
6
6
  groupPickerRowsByBillingClass
7
- } from "./chunk-SJKT4TKW.js";
7
+ } from "./chunk-23EJ676W.js";
8
8
  import {
9
9
  Tooltip,
10
10
  TooltipContent,
@@ -2613,16 +2613,60 @@ var defaultChatComposerMessages = {
2613
2613
  formatBytes,
2614
2614
  formatRelativeTime
2615
2615
  };
2616
- function applyComposerTextareaHeight(textarea, maxPx = 220) {
2617
- if (textarea.scrollHeight > textarea.clientHeight + 1) {
2618
- textarea.style.height = `${Math.min(textarea.scrollHeight, maxPx)}px`;
2619
- return;
2616
+ var composerHeightMirror = null;
2617
+ function measureComposerContentHeight(textarea) {
2618
+ if (typeof document === "undefined") {
2619
+ return textarea.scrollHeight;
2620
+ }
2621
+ const width = textarea.clientWidth;
2622
+ if (width <= 0) {
2623
+ return textarea.offsetHeight;
2624
+ }
2625
+ let mirror = composerHeightMirror;
2626
+ if (!mirror) {
2627
+ mirror = document.createElement("textarea");
2628
+ mirror.setAttribute("aria-hidden", "true");
2629
+ mirror.tabIndex = -1;
2630
+ mirror.rows = 1;
2631
+ mirror.style.cssText = "position:absolute;top:0;left:0;visibility:hidden;pointer-events:none;height:auto;min-height:0;max-height:none;overflow:hidden;z-index:-1;";
2632
+ composerHeightMirror = mirror;
2620
2633
  }
2634
+ const style = getComputedStyle(textarea);
2635
+ mirror.style.width = `${width}px`;
2636
+ mirror.style.boxSizing = style.boxSizing;
2637
+ mirror.style.font = style.font;
2638
+ mirror.style.fontSize = style.fontSize;
2639
+ mirror.style.fontFamily = style.fontFamily;
2640
+ mirror.style.fontWeight = style.fontWeight;
2641
+ mirror.style.fontStyle = style.fontStyle;
2642
+ mirror.style.letterSpacing = style.letterSpacing;
2643
+ mirror.style.lineHeight = style.lineHeight;
2644
+ mirror.style.textTransform = style.textTransform;
2645
+ mirror.style.paddingTop = style.paddingTop;
2646
+ mirror.style.paddingRight = style.paddingRight;
2647
+ mirror.style.paddingBottom = style.paddingBottom;
2648
+ mirror.style.paddingLeft = style.paddingLeft;
2649
+ mirror.style.borderTopWidth = style.borderTopWidth;
2650
+ mirror.style.borderRightWidth = style.borderRightWidth;
2651
+ mirror.style.borderBottomWidth = style.borderBottomWidth;
2652
+ mirror.style.borderLeftWidth = style.borderLeftWidth;
2653
+ mirror.style.borderStyle = style.borderStyle;
2654
+ mirror.style.whiteSpace = style.whiteSpace;
2655
+ mirror.style.wordBreak = style.wordBreak;
2656
+ mirror.style.overflowWrap = style.overflowWrap;
2657
+ mirror.value = textarea.value;
2658
+ if (!mirror.isConnected) {
2659
+ document.documentElement.appendChild(mirror);
2660
+ }
2661
+ return mirror.scrollHeight;
2662
+ }
2663
+ function applyComposerTextareaHeight(textarea, maxPx = 220, measure = measureComposerContentHeight) {
2621
2664
  const before = textarea.offsetHeight;
2622
- textarea.style.height = "auto";
2623
- const nextPx = Math.min(textarea.scrollHeight, maxPx);
2665
+ const nextPx = Math.min(
2666
+ textarea.scrollHeight > textarea.clientHeight + 1 ? textarea.scrollHeight : measure(textarea),
2667
+ maxPx
2668
+ );
2624
2669
  if (Math.abs(nextPx - before) < 1) {
2625
- textarea.style.height = `${before}px`;
2626
2670
  return;
2627
2671
  }
2628
2672
  textarea.style.height = `${nextPx}px`;
@@ -3150,7 +3194,8 @@ var Footer = forwardRef(function ComposerFooter({ className, ...props }, ref) {
3150
3194
  ref,
3151
3195
  className: cn(
3152
3196
  "flex items-end gap-1.5 px-2 pb-2 pt-0.5 sm:px-2.5 sm:pb-2.5",
3153
- "max-sm:items-center max-sm:gap-1",
3197
+ // Mobile: one control row — never wrap into a second toolbar line.
3198
+ "max-sm:flex-nowrap max-sm:items-center max-sm:gap-1",
3154
3199
  className
3155
3200
  )
3156
3201
  }
@@ -3190,7 +3235,11 @@ var Actions = forwardRef(function ComposerActions({ className, ...props }, ref)
3190
3235
  {
3191
3236
  ...props,
3192
3237
  ref,
3193
- className: cn("ml-auto flex shrink-0 items-center gap-1.5", className)
3238
+ className: cn(
3239
+ "ml-auto flex shrink-0 items-center gap-1.5",
3240
+ "max-sm:flex-nowrap max-sm:gap-1",
3241
+ className
3242
+ )
3194
3243
  }
3195
3244
  );
3196
3245
  });
@@ -3743,7 +3792,8 @@ function ComposerTranscriptionControl({
3743
3792
  messages: overrides,
3744
3793
  className,
3745
3794
  createRecordingStore,
3746
- createOwnerId
3795
+ createOwnerId,
3796
+ suppressed = false
3747
3797
  }) {
3748
3798
  const composer = useChatComposer();
3749
3799
  const messages = { ...defaultMessages, ...overrides };
@@ -3751,7 +3801,7 @@ function ComposerTranscriptionControl({
3751
3801
  client,
3752
3802
  workspaceId,
3753
3803
  capability,
3754
- enabled: workspaceEnabled,
3804
+ enabled: workspaceEnabled && !suppressed,
3755
3805
  value: composer.value,
3756
3806
  setValue: composer.setValue,
3757
3807
  focusInput: composer.focusInput,
@@ -3760,6 +3810,13 @@ function ComposerTranscriptionControl({
3760
3810
  createOwnerId
3761
3811
  });
3762
3812
  const { status } = transcription;
3813
+ const cancelTranscription = transcription.cancel;
3814
+ useEffect4(() => {
3815
+ if (!suppressed) return;
3816
+ if (status === "recording" || status === "requesting-permission") {
3817
+ cancelTranscription();
3818
+ }
3819
+ }, [cancelTranscription, status, suppressed]);
3763
3820
  const active = status === "requesting-permission" || status === "recording" || status === "saving" || status === "transcribing";
3764
3821
  const recoverable = transcription.hasRecoverableRecording && (status === "recovered" || status === "transcript-ready" || status === "error");
3765
3822
  const savedTranscript = status === "transcript-ready" && transcription.savedTranscript !== null;
@@ -3774,12 +3831,16 @@ function ComposerTranscriptionControl({
3774
3831
  }
3775
3832
  void transcription.start();
3776
3833
  }
3777
- return /* @__PURE__ */ jsxs4(
3778
- "span",
3834
+ return /* @__PURE__ */ jsx4(AnimatePresence3, { initial: false, children: suppressed ? null : /* @__PURE__ */ jsx4(
3835
+ motion3.span,
3779
3836
  {
3780
- className: cn("inline-flex min-w-0 items-center gap-1.5", className),
3837
+ initial: { opacity: 0, width: 0 },
3838
+ animate: { opacity: 1, width: "auto" },
3839
+ exit: { opacity: 0, width: 0 },
3840
+ transition: { duration: 0.36, ease: [0.22, 1, 0.36, 1] },
3841
+ className: cn("inline-flex min-w-0 overflow-hidden", className),
3781
3842
  "data-transcription-status": status,
3782
- children: [
3843
+ children: /* @__PURE__ */ jsxs4("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
3783
3844
  /* @__PURE__ */ jsx4(AnimatePresence3, { mode: "popLayout", initial: false, children: recoverable ? /* @__PURE__ */ jsxs4(
3784
3845
  motion3.span,
3785
3846
  {
@@ -3896,6 +3957,7 @@ function ComposerTranscriptionControl({
3896
3957
  motion3.button,
3897
3958
  {
3898
3959
  type: "button",
3960
+ "data-og-composer-dictate": true,
3899
3961
  initial: { opacity: 0, scale: 0.96 },
3900
3962
  animate: { opacity: 1, scale: 1 },
3901
3963
  exit: { opacity: 0, scale: 0.96 },
@@ -3920,10 +3982,19 @@ function ComposerTranscriptionControl({
3920
3982
  children: errorMessage3
3921
3983
  }
3922
3984
  ) }) : null,
3923
- /* @__PURE__ */ jsx4("span", { className: "sr-only", role: status === "error" ? "alert" : "status", "aria-live": "polite", children: announcement })
3924
- ]
3925
- }
3926
- );
3985
+ /* @__PURE__ */ jsx4(
3986
+ "span",
3987
+ {
3988
+ className: "sr-only",
3989
+ role: status === "error" ? "alert" : "status",
3990
+ "aria-live": "polite",
3991
+ children: announcement
3992
+ }
3993
+ )
3994
+ ] })
3995
+ },
3996
+ "composer-dictate"
3997
+ ) });
3927
3998
  }
3928
3999
  function VoiceWaveform({
3929
4000
  stream,
@@ -4091,4 +4162,4 @@ export {
4091
4162
  Status,
4092
4163
  ComposerTranscriptionControl
4093
4164
  };
4094
- //# sourceMappingURL=chunk-UWYTCQWW.js.map
4165
+ //# sourceMappingURL=chunk-KC27K42G.js.map