@opengeni/react-native 4.2.1-canary.39593846423001 → 4.3.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 (41) hide show
  1. package/android/build.gradle +15 -0
  2. package/android/src/main/AndroidManifest.xml +1 -0
  3. package/android/src/main/java/dev/opengeni/textselection/OpenGeniTextSelectionModule.kt +274 -0
  4. package/dist/{chunk-D3MFBDVR.js → chunk-2RNMGRTB.js} +3 -3
  5. package/dist/{chunk-D3MFBDVR.js.map → chunk-2RNMGRTB.js.map} +1 -1
  6. package/dist/{chunk-2W74OY6I.js → chunk-FHPMRXIG.js} +16 -2
  7. package/dist/chunk-FHPMRXIG.js.map +1 -0
  8. package/dist/{chunk-63PZ52YJ.js → chunk-QFV5DISV.js} +38 -5
  9. package/dist/chunk-QFV5DISV.js.map +1 -0
  10. package/dist/{chunk-U5L2CUMJ.js → chunk-ZZNZBZWV.js} +3 -3
  11. package/dist/{chunk-U5L2CUMJ.js.map → chunk-ZZNZBZWV.js.map} +1 -1
  12. package/dist/index.js +2 -2
  13. package/dist/timeline/activity.d.ts +3 -1
  14. package/dist/timeline/annotations.d.ts +81 -0
  15. package/dist/timeline/icon-nodes.generated.d.ts +5 -0
  16. package/dist/timeline/index.d.ts +2 -0
  17. package/dist/timeline/index.js +1223 -203
  18. package/dist/timeline/index.js.map +1 -1
  19. package/dist/timeline/markdown.js +5 -2
  20. package/dist/timeline/markdown.js.map +1 -1
  21. package/dist/timeline/message-timeline.d.ts +20 -2
  22. package/dist/timeline/previews.js +2 -2
  23. package/dist/timeline/primitives.d.ts +7 -1
  24. package/dist/timeline/queue-dock.d.ts +4 -1
  25. package/dist/timeline/text-selection.d.ts +44 -0
  26. package/expo-module.config.json +5 -2
  27. package/ios/OpenGeniTextSelectionModule.swift +560 -0
  28. package/package.json +6 -4
  29. package/src/timeline/activity.tsx +76 -21
  30. package/src/timeline/annotations.tsx +877 -0
  31. package/src/timeline/icon-nodes.generated.ts +14 -0
  32. package/src/timeline/index.ts +2 -0
  33. package/src/timeline/markdown.tsx +7 -0
  34. package/src/timeline/message-timeline.tsx +340 -174
  35. package/src/timeline/primitives.tsx +50 -1
  36. package/src/timeline/queue-dock.tsx +36 -0
  37. package/src/timeline/session-screen.tsx +122 -4
  38. package/src/timeline/sheet.tsx +3 -2
  39. package/src/timeline/text-selection.ts +115 -0
  40. package/dist/chunk-2W74OY6I.js.map +0 -1
  41. package/dist/chunk-63PZ52YJ.js.map +0 -1
@@ -9,6 +9,7 @@ import type {
9
9
  import {
10
10
  pathBasename,
11
11
  pathDirname,
12
+ presentsToolOutputPreview,
12
13
  sandboxRowTitle,
13
14
  startupDuration,
14
15
  startupPhaseTitle,
@@ -24,7 +25,7 @@ import {
24
25
  type WebSearchResult,
25
26
  } from "@opengeni/react/timeline-model";
26
27
  import { useOpenGeniText } from "@opengeni/react/messages";
27
- import { createContext, useContext, type ReactNode } from "react";
28
+ import { createContext, useContext, useEffect, type ReactNode } from "react";
28
29
  import { Pressable, Text, View } from "react-native";
29
30
  import { Icon, type NativeIconName } from "./icon";
30
31
  import {
@@ -39,6 +40,7 @@ import {
39
40
  } from "./primitives";
40
41
  import { fontStyle, useNativeTimelineTheme } from "./theme";
41
42
  import { useNativeTimelineMessages } from "./messages";
43
+ import { annotationSourceTestId } from "./text-selection";
42
44
 
43
45
  /* ----------------------------------------------------------------------------
44
46
  Native activity rows. Tool rows draw from the shared presentation model
@@ -388,9 +390,12 @@ function PatchView({
388
390
  export function PresentedToolRow({
389
391
  presentation: p,
390
392
  compact = false,
393
+ outputPreview,
391
394
  }: {
392
395
  presentation: ToolRowPresentation;
393
396
  compact?: boolean;
397
+ /** The row's output preview, when its output is not exact. */
398
+ outputPreview?: ToolCallItem["outputPreview"];
394
399
  }) {
395
400
  return (
396
401
  <ActivityDisclosure
@@ -405,6 +410,7 @@ export function PresentedToolRow({
405
410
  compact={compact}
406
411
  preview={p.preview ? previewContent(p.preview, compact) : undefined}
407
412
  expandable={p.body.kind !== "none"}
413
+ outputPreview={outputPreview}
408
414
  >
409
415
  <ToolBodyView body={p.body} />
410
416
  </ActivityDisclosure>
@@ -422,12 +428,53 @@ function ToolCallRow({ item, compact }: { item: ToolCallItem; compact: boolean }
422
428
  ? item.name.slice(item.name.lastIndexOf("__") + 2)
423
429
  : item.name;
424
430
  const custom = options.toolRenderers?.[item.name] ?? options.toolRenderers?.[leaf];
425
- for (const renderer of [custom, options.renderTool]) {
426
- if (!renderer) continue;
427
- const node = renderer({ item, presentation, compact });
428
- if (node != null) return <>{node}</>;
431
+ const outputPreview = item.outputPreview ?? null;
432
+ // Custom renderers and presentations that parse their result need the
433
+ // exact output first; a failed read falls back to the built-in row, which
434
+ // says it is a preview.
435
+ const exactFirst =
436
+ outputPreview !== null &&
437
+ (custom !== undefined || options.renderTool !== undefined || !presentsToolOutputPreview(item));
438
+ if (exactFirst && outputPreview.load && outputPreview.state !== "error") {
439
+ return <ToolOutputExactRow item={item} preview={outputPreview} compact={compact} />;
429
440
  }
430
- return <PresentedToolRow presentation={presentation} compact={compact} />;
441
+ if (!exactFirst) {
442
+ for (const renderer of [custom, options.renderTool]) {
443
+ if (!renderer) continue;
444
+ const node = renderer({ item, presentation, compact });
445
+ if (node != null) return <>{node}</>;
446
+ }
447
+ }
448
+ return (
449
+ <PresentedToolRow presentation={presentation} compact={compact} outputPreview={outputPreview} />
450
+ );
451
+ }
452
+
453
+ /** A tool row reading its exact output before it renders. */
454
+ function ToolOutputExactRow({
455
+ item,
456
+ preview,
457
+ compact,
458
+ }: {
459
+ item: ToolCallItem;
460
+ preview: NonNullable<ToolCallItem["outputPreview"]>;
461
+ compact: boolean;
462
+ }) {
463
+ const t = useOpenGeniText();
464
+ const pending = preview.state === "preview";
465
+ const load = preview.load;
466
+ useEffect(() => {
467
+ if (pending) load?.();
468
+ }, [pending, load]);
469
+ return (
470
+ <ActivityDisclosure
471
+ icon="wrench"
472
+ title={toolDisplayName(t, item.name)}
473
+ preview={t("timeline.toolRenderers.loadingOutput")}
474
+ compact={compact}
475
+ expandable={false}
476
+ />
477
+ );
431
478
  }
432
479
 
433
480
  function ReasoningRow({ item, compact }: { item: ReasoningItem; compact: boolean }) {
@@ -473,20 +520,23 @@ function ReasoningRow({ item, compact }: { item: ReasoningItem; compact: boolean
473
520
  accessibilityLabel={item.streaming ? m.thinking : m.thought}
474
521
  preview={plain || undefined}
475
522
  >
476
- {options.renderMarkdown ? (
477
- options.renderMarkdown(item.text, { tone: "muted", streaming: item.streaming })
478
- ) : (
479
- <Text
480
- style={{
481
- ...fontStyle(theme),
482
- fontSize: theme.size.base,
483
- lineHeight: 24,
484
- color: theme.colors["fg-muted"],
485
- }}
486
- >
487
- {item.text}
488
- </Text>
489
- )}
523
+ <View testID={annotationSourceTestId(undefined)} collapsable={false}>
524
+ {options.renderMarkdown ? (
525
+ options.renderMarkdown(item.text, { tone: "muted", streaming: item.streaming })
526
+ ) : (
527
+ <Text
528
+ selectable
529
+ style={{
530
+ ...fontStyle(theme),
531
+ fontSize: theme.size.base,
532
+ lineHeight: 24,
533
+ color: theme.colors["fg-muted"],
534
+ }}
535
+ >
536
+ {item.text}
537
+ </Text>
538
+ )}
539
+ </View>
490
540
  </ActivityDisclosure>
491
541
  );
492
542
  }
@@ -671,11 +721,16 @@ function ActivityNoteRow({ item }: { item: AgentMessageItem }) {
671
721
  <View style={{ marginTop: 4 }}>
672
722
  <Icon name="message-square-text" size={14} color={theme.colors["fg-subtle"]} />
673
723
  </View>
674
- <View style={{ flex: 1, minWidth: 0 }}>
724
+ <View
725
+ testID={annotationSourceTestId(item.annotationSource?.eventId)}
726
+ collapsable={false}
727
+ style={{ flex: 1, minWidth: 0 }}
728
+ >
675
729
  {options.renderMarkdown ? (
676
730
  options.renderMarkdown(item.text, { tone: "muted", streaming: item.streaming })
677
731
  ) : (
678
732
  <Text
733
+ selectable
679
734
  style={{
680
735
  ...fontStyle(theme),
681
736
  fontSize: theme.size.sm,