@agent-native/toolkit 0.13.7 → 0.13.9

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/dist/chat-history/ChatHistoryList.d.ts.map +1 -1
  2. package/dist/chat-history/ChatHistoryList.js +12 -5
  3. package/dist/chat-history/ChatHistoryList.js.map +1 -1
  4. package/dist/chat-history.css +7 -1
  5. package/dist/collab-ui/PresenceBar.d.ts +4 -1
  6. package/dist/collab-ui/PresenceBar.d.ts.map +1 -1
  7. package/dist/collab-ui/PresenceBar.js +19 -12
  8. package/dist/collab-ui/PresenceBar.js.map +1 -1
  9. package/dist/collab-ui/RecentEditHighlights.d.ts +3 -1
  10. package/dist/collab-ui/RecentEditHighlights.d.ts.map +1 -1
  11. package/dist/collab-ui/RecentEditHighlights.js +17 -9
  12. package/dist/collab-ui/RecentEditHighlights.js.map +1 -1
  13. package/dist/composer/PromptComposer.d.ts +3 -1
  14. package/dist/composer/PromptComposer.d.ts.map +1 -1
  15. package/dist/composer/PromptComposer.js +3 -3
  16. package/dist/composer/PromptComposer.js.map +1 -1
  17. package/dist/composer/TiptapComposer.d.ts +8 -4
  18. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  19. package/dist/composer/TiptapComposer.js +35 -19
  20. package/dist/composer/TiptapComposer.js.map +1 -1
  21. package/dist/composer/TiptapComposer.spec.js +2 -1
  22. package/dist/composer/TiptapComposer.spec.js.map +1 -1
  23. package/dist/composer/runtime-adapters.d.ts +4 -0
  24. package/dist/composer/runtime-adapters.d.ts.map +1 -1
  25. package/dist/composer/runtime-adapters.js +2 -2
  26. package/dist/composer/runtime-adapters.js.map +1 -1
  27. package/dist/editor.css +2 -0
  28. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  29. package/dist/ui/dropdown-menu.js +8 -2
  30. package/dist/ui/dropdown-menu.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/chat-history/ChatHistoryList.tsx +36 -24
  33. package/src/chat-history.css +7 -1
  34. package/src/collab-ui/PresenceBar.tsx +44 -17
  35. package/src/collab-ui/RecentEditHighlights.tsx +22 -8
  36. package/src/composer/PromptComposer.tsx +6 -2
  37. package/src/composer/TiptapComposer.spec.ts +2 -1
  38. package/src/composer/TiptapComposer.tsx +61 -28
  39. package/src/composer/runtime-adapters.tsx +6 -2
  40. package/src/editor.css +2 -0
  41. package/src/ui/dropdown-menu.tsx +4 -0
@@ -580,7 +580,7 @@ export interface TiptapComposerProps {
580
580
  references: Reference[],
581
581
  attachments?: ReadonlyArray<unknown>,
582
582
  options?: TiptapComposerSubmitOptions,
583
- ) => void;
583
+ ) => void | Promise<void>;
584
584
  /** Return false to stop a submit before it enters the chat runtime. */
585
585
  onBeforeSubmit?: () => boolean | Promise<boolean>;
586
586
  /**
@@ -631,20 +631,24 @@ export interface TiptapComposerProps {
631
631
  voiceEnabled?: boolean;
632
632
  /** Selected model override for this conversation */
633
633
  selectedModel?: string;
634
- /** Selected reasoning effort override for this conversation */
634
+ /** Selected effort override for this conversation */
635
635
  selectedEffort?: ReasoningEffort;
636
+ /** Show the legacy provider-level Auto model option (default: true). */
637
+ showAutoModelOption?: boolean;
636
638
  /** Available models grouped by provider */
637
639
  availableModels?: Array<{
638
640
  engine: string;
639
641
  label: string;
640
642
  models: string[];
641
643
  configured: boolean;
644
+ statusLabel?: string;
645
+ isSubscription?: boolean;
642
646
  }>;
643
647
  /** Whether the model list is still being resolved. */
644
648
  modelListLoading?: boolean;
645
649
  /** Callback when user picks a model */
646
650
  onModelChange?: (model: string, engine: string) => void;
647
- /** Callback when user picks a reasoning effort */
651
+ /** Callback when user picks an effort */
648
652
  onEffortChange?: (effort: ReasoningEffort) => void;
649
653
  /**
650
654
  * Disable Builder/provider status polling for hosts that supply provider
@@ -844,7 +848,7 @@ function ModeSelector({
844
848
 
845
849
  const FRIENDLY_MODEL_NAMES: Record<string, string> = {
846
850
  auto: "Default model",
847
- "codex-cli": "ChatGPT subscription",
851
+ "codex-cli": "Codex",
848
852
  "claude-fable-5": "Fable 5",
849
853
  "kimi-k2-5": "Kimi K2.5",
850
854
  "deepseek-v3-1": "DeepSeek v3.1",
@@ -959,7 +963,7 @@ function latestModelsOnly(models: string[]): string[] {
959
963
  return true;
960
964
  }
961
965
  // GPT: family = gpt-{major} (e.g. gpt-5.6-sol and gpt-5.6-luna are different)
962
- // OpenAI reasoning: each is its own family
966
+ // OpenAI effort: each is its own family
963
967
  // Gemini: family = gemini-{major} + variant
964
968
  const gemini = m.match(/^gemini-(\d+(?:\.\d+)?)-(.+?)(?:-preview)?$/);
965
969
  if (gemini) {
@@ -1046,6 +1050,7 @@ function ModelSelector({
1046
1050
  model,
1047
1051
  effort,
1048
1052
  engines,
1053
+ showAutoModelOption = true,
1049
1054
  modelListLoading = false,
1050
1055
  onChange,
1051
1056
  onEffortChange,
@@ -1061,7 +1066,10 @@ function ModelSelector({
1061
1066
  label: string;
1062
1067
  models: string[];
1063
1068
  configured: boolean;
1069
+ statusLabel?: string;
1070
+ isSubscription?: boolean;
1064
1071
  }>;
1072
+ showAutoModelOption?: boolean;
1065
1073
  modelListLoading?: boolean;
1066
1074
  onChange: (model: string, engine: string) => void;
1067
1075
  onEffortChange?: (effort: ReasoningEffort) => void;
@@ -1075,7 +1083,9 @@ function ModelSelector({
1075
1083
  const reasoning = adapters.models?.reasoning;
1076
1084
  const defaultEffort = reasoning?.defaultEffort ?? DEFAULT_REASONING_EFFORT;
1077
1085
  const [open, setOpen] = useState(false);
1078
- const autoModelGroup = engines.find((group) => group.models.includes("auto"));
1086
+ const autoModelGroup = showAutoModelOption
1087
+ ? engines.find((group) => group.models.includes("auto"))
1088
+ : undefined;
1079
1089
  const providerGroups = useMemo(
1080
1090
  () =>
1081
1091
  engines
@@ -1123,12 +1133,12 @@ function ModelSelector({
1123
1133
  });
1124
1134
  }, []);
1125
1135
 
1126
- // The reasoning effort list is collapsed by default — it's a secondary
1136
+ // The effort list is collapsed by default — it's a secondary
1127
1137
  // control most users don't touch, so it stays tucked behind a header that
1128
1138
  // reveals the current effort at a glance. Reset to collapsed on each open.
1129
- const [reasoningExpanded, setReasoningExpanded] = useState(false);
1139
+ const [effortExpanded, setEffortExpanded] = useState(false);
1130
1140
  useEffect(() => {
1131
- if (open) setReasoningExpanded(false);
1141
+ if (open) setEffortExpanded(false);
1132
1142
  }, [open]);
1133
1143
 
1134
1144
  // The optional image-model section follows the same collapsed-by-default
@@ -1155,12 +1165,16 @@ function ModelSelector({
1155
1165
  const hasConfiguredBuilderModels = providerGroups.some(
1156
1166
  (group) => group.engine === "builder" && group.configured,
1157
1167
  );
1168
+ const hasConnectedSubscription = providerGroups.some(
1169
+ (group) => group.configured && group.isSubscription,
1170
+ );
1158
1171
  const showBuilderCta =
1159
1172
  (builderFlow.hasFetchedStatus ||
1160
1173
  (!providerConnectStatusEnabled && !!onConnectProvider)) &&
1161
1174
  !builderFlow.configured &&
1162
1175
  !builderFlow.envManaged &&
1163
- !hasConfiguredBuilderModels;
1176
+ !hasConfiguredBuilderModels &&
1177
+ !hasConnectedSubscription;
1164
1178
  const onlyConnectPathAvailable = shouldShowOnlyConnectPath(
1165
1179
  showBuilderCta,
1166
1180
  providerGroups,
@@ -1188,7 +1202,7 @@ function ModelSelector({
1188
1202
  data-agent-composer-slot="model-button"
1189
1203
  aria-label={`Model: ${friendlyModelName(model)}${
1190
1204
  effortOptions.length > 0
1191
- ? `. Reasoning: ${effortLabel(selectedEffort)}`
1205
+ ? `. Effort: ${effortLabel(selectedEffort)}`
1192
1206
  : ""
1193
1207
  }`}
1194
1208
  className="agent-composer-model-button flex min-w-0 max-w-[10.5rem] shrink items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground"
@@ -1352,6 +1366,17 @@ function ModelSelector({
1352
1366
  const groupKey = `${group.engine}:${group.label}`;
1353
1367
  const isExpanded = expandedGroups.has(groupKey);
1354
1368
  const ChevronIcon = isExpanded ? IconChevronDown : IconChevronRight;
1369
+ const isLocalRuntime =
1370
+ group.engine === "codex-cli" || group.engine === "claude-cli";
1371
+ const canConnectLocalRuntime =
1372
+ isLocalRuntime && Boolean(onConnectLocalRuntime);
1373
+ const statusLabel =
1374
+ group.statusLabel ??
1375
+ (!group.configured
1376
+ ? canConnectLocalRuntime
1377
+ ? "sign in"
1378
+ : "needs API key"
1379
+ : undefined);
1355
1380
  return (
1356
1381
  <div key={groupKey}>
1357
1382
  <div className="flex items-center hover:bg-accent/30">
@@ -1371,21 +1396,24 @@ function ModelSelector({
1371
1396
  </span>
1372
1397
  )}
1373
1398
  </button>
1374
- {!group.configured && (
1399
+ {!group.configured && statusLabel && (
1375
1400
  <button
1376
1401
  type="button"
1377
- className="text-[10px] text-muted-foreground/60 hover:text-foreground cursor-pointer pe-3 py-1.5"
1402
+ className="ms-auto max-w-[9rem] shrink-0 text-end text-[10px] text-muted-foreground/60 hover:text-foreground cursor-pointer pe-3 py-1.5"
1378
1403
  onClick={() =>
1379
- group.engine === "codex-cli" && onConnectLocalRuntime
1404
+ canConnectLocalRuntime
1380
1405
  ? connectLocalRuntime(group.engine)
1381
1406
  : openLlmSettings()
1382
1407
  }
1383
1408
  >
1384
- {group.engine === "codex-cli" && onConnectLocalRuntime
1385
- ? "sign in"
1386
- : "needs API key"}
1409
+ {statusLabel}
1387
1410
  </button>
1388
1411
  )}
1412
+ {group.configured && statusLabel && (
1413
+ <span className="ms-auto max-w-[9rem] shrink-0 pe-3 text-end text-[10px] text-muted-foreground/70">
1414
+ {statusLabel}
1415
+ </span>
1416
+ )}
1389
1417
  </div>
1390
1418
  {isExpanded &&
1391
1419
  models.map((m) => (
@@ -1394,10 +1422,7 @@ function ModelSelector({
1394
1422
  type="button"
1395
1423
  onClick={() => {
1396
1424
  if (!group.configured) {
1397
- if (
1398
- group.engine === "codex-cli" &&
1399
- onConnectLocalRuntime
1400
- ) {
1425
+ if (canConnectLocalRuntime) {
1401
1426
  connectLocalRuntime(group.engine);
1402
1427
  } else {
1403
1428
  openLlmSettings();
@@ -1441,26 +1466,26 @@ function ModelSelector({
1441
1466
  <div className="flex items-center hover:bg-accent/30">
1442
1467
  <button
1443
1468
  type="button"
1444
- aria-expanded={reasoningExpanded}
1445
- onClick={() => setReasoningExpanded((prev) => !prev)}
1469
+ aria-expanded={effortExpanded}
1470
+ onClick={() => setEffortExpanded((prev) => !prev)}
1446
1471
  className="flex flex-1 min-w-0 items-center gap-1.5 px-2 py-1.5 cursor-pointer text-start"
1447
1472
  >
1448
- {reasoningExpanded ? (
1473
+ {effortExpanded ? (
1449
1474
  <IconChevronDown className="h-3 w-3 shrink-0 text-muted-foreground" />
1450
1475
  ) : (
1451
1476
  <IconChevronRight className="h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" />
1452
1477
  )}
1453
1478
  <span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0">
1454
- Reasoning
1479
+ Effort
1455
1480
  </span>
1456
- {!reasoningExpanded && (
1481
+ {!effortExpanded && (
1457
1482
  <span className="text-[11px] text-muted-foreground/80 truncate">
1458
1483
  {effortLabel(selectedEffort)}
1459
1484
  </span>
1460
1485
  )}
1461
1486
  </button>
1462
1487
  </div>
1463
- {reasoningExpanded &&
1488
+ {effortExpanded &&
1464
1489
  effortOptions.map((option) => (
1465
1490
  <button
1466
1491
  key={option}
@@ -1540,6 +1565,7 @@ export function TiptapComposer({
1540
1565
  voiceEnabled = DEFAULT_VOICE_DICTATION_ENABLED,
1541
1566
  selectedModel,
1542
1567
  selectedEffort,
1568
+ showAutoModelOption = true,
1543
1569
  availableModels,
1544
1570
  modelListLoading,
1545
1571
  onModelChange,
@@ -2625,7 +2651,13 @@ export function TiptapComposer({
2625
2651
  }
2626
2652
 
2627
2653
  if (onSubmit) {
2628
- onSubmit(text, references, attachments, { intent });
2654
+ try {
2655
+ await onSubmit(text, references, attachments, { intent });
2656
+ } catch {
2657
+ // Hosts own their submit errors. Keep the draft and attachments
2658
+ // available for recovery when a host rejects the submission.
2659
+ return;
2660
+ }
2629
2661
  // Clear any pending attachments now that the host has them.
2630
2662
  void composerRuntime.clearAttachments().catch(() => {});
2631
2663
  if (!clearOnSubmit) {
@@ -2985,6 +3017,7 @@ export function TiptapComposer({
2985
3017
  model={selectedModel}
2986
3018
  effort={selectedEffort}
2987
3019
  engines={availableModels}
3020
+ showAutoModelOption={showAutoModelOption}
2988
3021
  modelListLoading={modelListLoading}
2989
3022
  onChange={onModelChange}
2990
3023
  onEffortChange={onEffortChange}
@@ -26,6 +26,10 @@ export interface EngineModelGroup {
26
26
  label: string;
27
27
  models: string[];
28
28
  configured: boolean;
29
+ /** Provider-owned connection state shown at the far edge of the row. */
30
+ statusLabel?: string;
31
+ /** Marks a configured local subscription so setup CTAs can stay hidden. */
32
+ isSubscription?: boolean;
29
33
  }
30
34
 
31
35
  export interface ComposerModelState {
@@ -180,7 +184,7 @@ const fallbackModels = {
180
184
  useChatModels: () => ({
181
185
  selectedModel: "auto",
182
186
  selectedEngine: "auto",
183
- selectedEffort: "medium" as ReasoningEffort,
187
+ selectedEffort: "high" as ReasoningEffort,
184
188
  availableModels: [],
185
189
  isLoading: false,
186
190
  onModelChange: () => {},
@@ -277,7 +281,7 @@ export function useComposerRuntimeAdapters() {
277
281
  return useContext(ComposerRuntimeAdaptersContext);
278
282
  }
279
283
 
280
- export const DEFAULT_REASONING_EFFORT: ReasoningEffort = "medium";
284
+ export const DEFAULT_REASONING_EFFORT: ReasoningEffort = "high";
281
285
  export function getReasoningEffortOptionsForModel(
282
286
  _model?: string,
283
287
  ): ReasoningEffort[] {
package/src/editor.css CHANGED
@@ -57,6 +57,8 @@
57
57
  box-shadow: none;
58
58
  opacity: 0.55;
59
59
  pointer-events: none;
60
+ /* compositing-ok: .notion-drag-preview exists only during a drag and is
61
+ transformed every frame of it; the layer is retired with the element. */
60
62
  will-change: transform;
61
63
  }
62
64
 
@@ -54,6 +54,8 @@ const DropdownMenuSubContent = React.forwardRef<
54
54
  <DropdownMenuPrimitive.SubContent
55
55
  ref={ref}
56
56
  className={cn(
57
+ // compositing-ok: Radix content mounts on open and unmounts on close,
58
+ // so the promoted layer is retired with it.
57
59
  "z-[290] min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg will-change-[transform,opacity] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:duration-100 data-[state=open]:duration-150 data-[state=closed]:ease-out data-[state=open]:ease-out data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1 motion-reduce:data-[state=open]:zoom-in-100 motion-reduce:data-[state=closed]:zoom-out-100 motion-reduce:data-[side=bottom]:slide-in-from-top-0 motion-reduce:data-[side=left]:slide-in-from-right-0 motion-reduce:data-[side=right]:slide-in-from-left-0 motion-reduce:data-[side=top]:slide-in-from-bottom-0",
58
60
  className,
59
61
  )}
@@ -83,6 +85,8 @@ const DropdownMenuContent = React.forwardRef<
83
85
  ref={ref}
84
86
  sideOffset={sideOffset}
85
87
  className={cn(
88
+ // compositing-ok: Radix content mounts on open and unmounts on close,
89
+ // so the promoted layer is retired with it.
86
90
  "z-[290] min-w-[8rem] origin-[var(--radix-dropdown-menu-content-transform-origin)] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md will-change-[transform,opacity] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:duration-100 data-[state=open]:duration-150 data-[state=closed]:ease-out data-[state=open]:ease-out data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1 motion-reduce:data-[state=open]:zoom-in-100 motion-reduce:data-[state=closed]:zoom-out-100 motion-reduce:data-[side=bottom]:slide-in-from-top-0 motion-reduce:data-[side=left]:slide-in-from-right-0 motion-reduce:data-[side=right]:slide-in-from-left-0 motion-reduce:data-[side=top]:slide-in-from-bottom-0",
87
91
  className,
88
92
  )}