@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
@@ -11,7 +11,7 @@
11
11
  * | --- | --- |
12
12
  * | `--og-session-chrome-surface` / `-open` | Dock fill (collapsed / expanded) |
13
13
  * | `--og-session-chrome-border` / `-open` | Dock edge |
14
- * | `--og-session-chrome-highlight` | Sliding chip selection pill |
14
+ * | `--og-session-chrome-highlight` / `-ring` | Sliding chip selection fill + edge |
15
15
  * | `--og-session-chrome-shadow` / `-open` | Elevation |
16
16
  * | `--og-session-chrome-radius` | Dock corner radius |
17
17
  * | `--og-session-chrome-chip-min-height` | Signal chip height |
@@ -394,7 +394,7 @@ export function SessionChrome({
394
394
  const chipRefs = useRef<Partial<Record<SessionChromeSignalId, HTMLButtonElement | null>>>({});
395
395
  const railRef = useRef<HTMLDivElement | null>(null);
396
396
  const panelBodyRef = useRef<HTMLDivElement | null>(null);
397
- const [pill, setPill] = useState({ left: 0, width: 0, opacity: 0 });
397
+ const [pill, setPill] = useState({ left: 0, top: 0, width: 0, height: 0, opacity: 0 });
398
398
  const [panelHeight, setPanelHeight] = useState(0);
399
399
 
400
400
  const signalIds = signals.map((signal) => signal.id).join(",");
@@ -421,11 +421,15 @@ export function SessionChrome({
421
421
  }
422
422
  const chip = chipRefs.current[active];
423
423
  if (!chip) return;
424
+ // Measure against the chip's own box so a wrapped multi-row rail never
425
+ // stretches the highlight into a tall stripe across every signal.
424
426
  const railBox = rail.getBoundingClientRect();
425
427
  const chipBox = chip.getBoundingClientRect();
426
428
  setPill({
427
429
  left: chipBox.left - railBox.left,
430
+ top: chipBox.top - railBox.top,
428
431
  width: chipBox.width,
432
+ height: chipBox.height,
429
433
  opacity: 1,
430
434
  });
431
435
  };
@@ -433,6 +437,9 @@ export function SessionChrome({
433
437
  if (!rail) return;
434
438
  const observer = new ResizeObserver(measure);
435
439
  observer.observe(rail);
440
+ for (const chip of Object.values(chipRefs.current)) {
441
+ if (chip) observer.observe(chip);
442
+ }
436
443
  window.addEventListener("resize", measure);
437
444
  return () => {
438
445
  observer.disconnect();
@@ -568,88 +575,92 @@ export function SessionChrome({
568
575
  }}
569
576
  >
570
577
  <div
571
- ref={railRef}
572
- className="relative flex flex-wrap items-stretch"
578
+ className="relative"
573
579
  style={{
574
- gap: "var(--og-session-chrome-chip-gap)",
575
- padding: "var(--og-session-chrome-rail-pad)",
580
+ paddingTop: "var(--og-session-chrome-rail-pad)",
581
+ paddingBottom: "var(--og-session-chrome-rail-pad)",
582
+ paddingLeft: "var(--og-session-chrome-rail-pad)",
583
+ paddingRight: "var(--og-session-chrome-rail-pad)",
576
584
  }}
577
585
  >
578
- <motion.div
579
- aria-hidden
580
- className="pointer-events-none absolute rounded-og-md ring-1 ring-og-border/50"
586
+ <div
587
+ ref={railRef}
588
+ className="relative flex flex-wrap items-center"
581
589
  style={{
582
- top: "var(--og-session-chrome-rail-pad)",
583
- bottom: "var(--og-session-chrome-rail-pad)",
584
- background: "var(--og-session-chrome-highlight)",
590
+ gap: "var(--og-session-chrome-chip-gap)",
585
591
  }}
586
- initial={false}
587
- animate={{
588
- x: pill.left,
589
- width: pill.width,
590
- opacity: pill.opacity,
591
- }}
592
- transition={{ duration: shellDuration, ease }}
593
- />
594
- {signals.map((signal) => {
595
- const selected = active === signal.id;
596
- return (
597
- <button
598
- key={signal.id}
599
- type="button"
600
- ref={(node) => {
601
- chipRefs.current[signal.id] = node;
602
- }}
603
- aria-expanded={selected}
604
- aria-controls={panelId}
605
- data-testid={`session-chrome-${signal.id}`}
606
- data-og-session-chrome-signal={signal.id}
607
- onClick={() => setActive(selected ? null : signal.id)}
608
- className={cn(
609
- "group relative z-[1] inline-flex min-h-[var(--og-session-chrome-chip-min-height)] max-w-full items-center gap-1 rounded-og-md text-left text-og-xs outline-none",
610
- "transition-colors duration-150 motion-reduce:transition-none",
611
- "hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40",
612
- "pointer-coarse:min-h-11",
613
- selected ? "text-og-fg" : "text-og-fg-muted",
614
- )}
615
- style={{
616
- paddingInline: "var(--og-session-chrome-chip-pad-x)",
617
- }}
618
- >
619
- <span className={cn("shrink-0", toneClass(signal.tone, selected))}>
620
- {signal.icon}
621
- </span>
622
- <span className="shrink-0 font-medium text-og-fg">{signal.label}</span>
623
- {signal.detail ? (
624
- <>
625
- <span aria-hidden className="shrink-0 text-og-fg-subtle/60">
626
- ·
627
- </span>
628
- <span className="min-w-0 max-w-[8.5rem] truncate text-og-fg sm:max-w-[12rem]">
629
- {signal.detail}
592
+ >
593
+ <motion.div
594
+ aria-hidden
595
+ className="pointer-events-none absolute left-0 top-0 rounded-og-md"
596
+ style={{
597
+ background: "var(--og-session-chrome-highlight)",
598
+ boxShadow: "inset 0 0 0 1px var(--og-session-chrome-highlight-ring)",
599
+ }}
600
+ initial={false}
601
+ animate={{
602
+ x: pill.left,
603
+ y: pill.top,
604
+ width: pill.width,
605
+ height: pill.height,
606
+ opacity: pill.opacity,
607
+ }}
608
+ transition={{ duration: shellDuration, ease }}
609
+ />
610
+ {signals.map((signal) => {
611
+ const selected = active === signal.id;
612
+ return (
613
+ <button
614
+ key={signal.id}
615
+ type="button"
616
+ ref={(node) => {
617
+ chipRefs.current[signal.id] = node;
618
+ }}
619
+ aria-expanded={selected}
620
+ aria-controls={panelId}
621
+ aria-label={selected ? `Close ${signal.label}` : undefined}
622
+ data-testid={`session-chrome-${signal.id}`}
623
+ data-og-session-chrome-signal={signal.id}
624
+ onClick={() => setActive(selected ? null : signal.id)}
625
+ className={cn(
626
+ "group relative z-[1] inline-flex min-h-[var(--og-session-chrome-chip-min-height)] max-w-full items-center gap-1 rounded-og-md py-1 text-left text-og-xs outline-none",
627
+ // Coarse pointers keep a 44px target (session-pins acceptance).
628
+ "pointer-coarse:min-h-11",
629
+ "transition-colors duration-150 motion-reduce:transition-none",
630
+ "hover:text-og-fg focus-visible:bg-og-surface-3/50",
631
+ selected ? "text-og-fg" : "text-og-fg-muted",
632
+ )}
633
+ style={{
634
+ paddingInline: "var(--og-session-chrome-chip-pad-x)",
635
+ }}
636
+ >
637
+ <span className={cn("shrink-0", toneClass(signal.tone, selected))}>
638
+ {signal.icon}
639
+ </span>
640
+ <span className="shrink-0 font-medium text-og-fg">{signal.label}</span>
641
+ {signal.detail ? (
642
+ <>
643
+ <span aria-hidden className="shrink-0 text-og-fg-subtle/60">
644
+ ·
645
+ </span>
646
+ <span className="min-w-0 max-w-[8.5rem] truncate text-og-fg sm:max-w-[12rem]">
647
+ {signal.detail}
648
+ </span>
649
+ </>
650
+ ) : null}
651
+ {selected ? (
652
+ <span
653
+ data-testid="session-chrome-close"
654
+ className="ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-og-sm text-og-fg-subtle transition-colors group-hover:text-og-fg pointer-coarse:size-5"
655
+ aria-hidden
656
+ >
657
+ <XIcon className="size-3" />
630
658
  </span>
631
- </>
632
- ) : null}
633
- </button>
634
- );
635
- })}
636
- <AnimatePresence initial={false}>
637
- {open ? (
638
- <motion.button
639
- key="close"
640
- type="button"
641
- aria-label="Close session chrome panel"
642
- onClick={() => setActive(null)}
643
- initial={reduceMotion ? false : { opacity: 0 }}
644
- animate={{ opacity: 1 }}
645
- exit={reduceMotion ? { opacity: 1 } : { opacity: 0 }}
646
- transition={{ duration: crossfadeDuration, ease }}
647
- className="relative z-[1] ml-auto inline-flex size-7 shrink-0 items-center justify-center rounded-og-md text-og-fg-subtle outline-none transition-colors hover:bg-og-surface-3/60 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 pointer-coarse:size-11"
648
- >
649
- <XIcon className="size-3" />
650
- </motion.button>
651
- ) : null}
652
- </AnimatePresence>
659
+ ) : null}
660
+ </button>
661
+ );
662
+ })}
663
+ </div>
653
664
  </div>
654
665
 
655
666
  <motion.div
package/src/index.ts CHANGED
@@ -367,12 +367,14 @@ export type {
367
367
  // Pure provider-shape parsers (exec banner, V4A diff, secret redaction, …)
368
368
  export {
369
369
  applyPatchOps,
370
+ applyPatchOpsFromToolItem,
370
371
  controlCaret,
371
372
  execTruncated,
372
373
  isApplyPatch,
373
374
  isExecSessionLostBanner,
374
375
  looksBinary,
375
376
  parseExecBannerSessionId,
377
+ parseFreeformApplyPatch,
376
378
  parseToolArgs,
377
379
  redactSecrets,
378
380
  sandboxCommandExitCode,
@@ -5,6 +5,8 @@ export type PickerBillingClass = "opengeni_credits" | "codex_subscription" | "by
5
5
  export type PickerModelRow<TCatalog extends ClientModel = WorkspaceModelCatalogModel> = {
6
6
  id: string;
7
7
  label: string;
8
+ /** Catalog-curated compact label for dense UI; fall back to `label` when absent. */
9
+ shortLabel?: string | undefined;
8
10
  billingClass: PickerBillingClass;
9
11
  billingClassLabel: string;
10
12
  selectable: boolean;
@@ -171,6 +173,7 @@ export function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerM
171
173
  return {
172
174
  id: catalog.id,
173
175
  label: catalog.label,
176
+ ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),
174
177
  billingClass,
175
178
  billingClassLabel: billingClassLabel(billingClass),
176
179
  selectable: catalog.availability.selectable,
@@ -191,6 +194,7 @@ export function projectClientModelRows(models: ClientModel[]): PickerModelRow<Cl
191
194
  return {
192
195
  id: catalog.id,
193
196
  label: catalog.label,
197
+ ...(catalog.shortLabel ? { shortLabel: catalog.shortLabel } : {}),
194
198
  billingClass,
195
199
  billingClassLabel: billingClassLabel(billingClass),
196
200
  selectable: true,