@agent-native/toolkit 0.13.8 → 0.13.10

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 (34) hide show
  1. package/dist/chat-history/ChatHistoryList.js +1 -1
  2. package/dist/chat-history/ChatHistoryList.js.map +1 -1
  3. package/dist/chat-history.css +46 -1
  4. package/dist/collab-ui/PresenceBar.d.ts +4 -1
  5. package/dist/collab-ui/PresenceBar.d.ts.map +1 -1
  6. package/dist/collab-ui/PresenceBar.js +19 -12
  7. package/dist/collab-ui/PresenceBar.js.map +1 -1
  8. package/dist/composer/PromptComposer.d.ts +1 -1
  9. package/dist/composer/PromptComposer.d.ts.map +1 -1
  10. package/dist/composer/PromptComposer.js +1 -1
  11. package/dist/composer/PromptComposer.js.map +1 -1
  12. package/dist/composer/TiptapComposer.d.ts +3 -3
  13. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  14. package/dist/composer/TiptapComposer.js +14 -7
  15. package/dist/composer/TiptapComposer.js.map +1 -1
  16. package/dist/composer/TiptapComposer.spec.js +1 -1
  17. package/dist/composer/TiptapComposer.spec.js.map +1 -1
  18. package/dist/composer/runtime-adapters.d.ts.map +1 -1
  19. package/dist/composer/runtime-adapters.js +2 -2
  20. package/dist/composer/runtime-adapters.js.map +1 -1
  21. package/dist/editor.css +2 -0
  22. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  23. package/dist/ui/dropdown-menu.js +8 -2
  24. package/dist/ui/dropdown-menu.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/chat-history/ChatHistoryList.tsx +2 -0
  27. package/src/chat-history.css +46 -1
  28. package/src/collab-ui/PresenceBar.tsx +44 -17
  29. package/src/composer/PromptComposer.tsx +2 -2
  30. package/src/composer/TiptapComposer.spec.ts +1 -1
  31. package/src/composer/TiptapComposer.tsx +21 -15
  32. package/src/composer/runtime-adapters.tsx +2 -2
  33. package/src/editor.css +2 -0
  34. package/src/ui/dropdown-menu.tsx +4 -0
@@ -358,6 +358,8 @@ const ChatHistoryRow = React.memo(function ChatHistoryRow({
358
358
  "an-chat-history-row",
359
359
  active && "an-chat-history-row--active",
360
360
  item.pinned && "an-chat-history-row--pinned",
361
+ hasMenu && "an-chat-history-row--has-menu",
362
+ menuOpen && "an-chat-history-row--menu-open",
361
363
  isRenaming && "an-chat-history-row--renaming",
362
364
  item.disabled && "an-chat-history-row--disabled",
363
365
  )}
@@ -234,7 +234,7 @@
234
234
  .an-chat-history--rail .an-chat-history-row__button {
235
235
  min-height: 32px;
236
236
  padding-block: 6px;
237
- padding-inline: 10px 36px;
237
+ padding-inline: 10px;
238
238
  border-radius: inherit;
239
239
  color: hsl(var(--muted-foreground));
240
240
  }
@@ -290,6 +290,15 @@
290
290
  .an-chat-history--rail .an-chat-history-row__timestamp {
291
291
  font-size: 11px;
292
292
  color: hsl(var(--muted-foreground) / 0.62);
293
+ transition: opacity 100ms ease;
294
+ }
295
+
296
+ .an-chat-history--rail
297
+ .an-chat-history-row--has-menu
298
+ .an-chat-history-row__timestamp {
299
+ display: inline-flex;
300
+ min-width: 24px;
301
+ justify-content: flex-end;
293
302
  }
294
303
 
295
304
  .an-chat-history--rail
@@ -298,6 +307,23 @@
298
307
  color: hsl(var(--accent-foreground));
299
308
  }
300
309
 
310
+ /* The menu overlays this fixed trailing slot so its hover state never changes
311
+ the title's available width or moves the rest of the rail. */
312
+ .an-chat-history--rail
313
+ .an-chat-history-row--has-menu:hover
314
+ .an-chat-history-row__timestamp,
315
+ .an-chat-history--rail
316
+ .an-chat-history-row--has-menu:focus-within
317
+ .an-chat-history-row__timestamp,
318
+ .an-chat-history--rail
319
+ .an-chat-history-row--has-menu.an-chat-history-row--menu-open
320
+ .an-chat-history-row__timestamp,
321
+ .an-chat-history--rail
322
+ .an-chat-history-row--has-menu.an-chat-history-row--pinned
323
+ .an-chat-history-row__timestamp {
324
+ opacity: 0;
325
+ }
326
+
301
327
  .an-chat-history-row__subtitle {
302
328
  margin-top: 2px;
303
329
  overflow: hidden;
@@ -351,6 +377,10 @@
351
377
  inset-inline-end: 4px;
352
378
  }
353
379
 
380
+ .an-chat-history--rail .an-chat-history-row__menu {
381
+ inset-inline-end: 10px;
382
+ }
383
+
354
384
  .an-chat-history-row__menu-trigger {
355
385
  display: inline-flex;
356
386
  align-items: center;
@@ -369,6 +399,10 @@
369
399
  opacity 100ms ease;
370
400
  }
371
401
 
402
+ .an-chat-history--rail .an-chat-history-row__menu-trigger {
403
+ pointer-events: none;
404
+ }
405
+
372
406
  .an-chat-history-row:hover .an-chat-history-row__menu-trigger,
373
407
  .an-chat-history-row:focus-within .an-chat-history-row__menu-trigger,
374
408
  .an-chat-history-row__menu-trigger[aria-expanded="true"],
@@ -376,6 +410,17 @@
376
410
  opacity: 1;
377
411
  }
378
412
 
413
+ .an-chat-history--rail
414
+ .an-chat-history-row:hover
415
+ .an-chat-history-row__menu-trigger,
416
+ .an-chat-history--rail
417
+ .an-chat-history-row:focus-within
418
+ .an-chat-history-row__menu-trigger,
419
+ .an-chat-history--rail .an-chat-history-row__menu-trigger[aria-expanded="true"],
420
+ .an-chat-history--rail .an-chat-history-row__menu-trigger--pinned {
421
+ pointer-events: auto;
422
+ }
423
+
379
424
  .an-chat-history-row__menu-trigger:hover,
380
425
  .an-chat-history-row__menu-trigger[aria-expanded="true"] {
381
426
  background: hsl(var(--accent));
@@ -20,6 +20,9 @@ export interface PresenceBarProps {
20
20
  agentPresent?: boolean;
21
21
  /** Whether the agent is actively making edits right now. */
22
22
  agentActive?: boolean;
23
+ /** Whether to show the status dot beside the active agent label. When false,
24
+ * the label is integrated with the avatar pill. */
25
+ showAgentEditingDot?: boolean;
23
26
  /** Current user's email (to exclude from the list). */
24
27
  currentUserEmail?: string;
25
28
  /** Max visible avatars before "+N" overflow. Default: 5 */
@@ -151,12 +154,15 @@ function AgentAvatar({
151
154
  active,
152
155
  onClick,
153
156
  isFollowing,
157
+ showAgentEditingDot,
154
158
  }: {
155
159
  active: boolean;
156
160
  onClick?: () => void;
157
161
  isFollowing?: boolean;
162
+ showAgentEditingDot: boolean;
158
163
  }) {
159
164
  injectStyles();
165
+ const integratedEditingBadge = active && !isFollowing && !showAgentEditingDot;
160
166
 
161
167
  return (
162
168
  <div
@@ -164,6 +170,12 @@ function AgentAvatar({
164
170
  display: "flex",
165
171
  alignItems: "center",
166
172
  gap: 4,
173
+ ...(integratedEditingBadge && {
174
+ height: AVATAR_SIZE,
175
+ paddingRight: 8,
176
+ borderRadius: 9999,
177
+ backgroundColor: `${AGENT_COLOR}20`,
178
+ }),
167
179
  }}
168
180
  >
169
181
  <div
@@ -193,7 +205,12 @@ function AgentAvatar({
193
205
  >
194
206
  A
195
207
  </div>
196
- {active && !isFollowing && <AgentEditingChip />}
208
+ {active && !isFollowing && (
209
+ <AgentEditingChip
210
+ showDot={showAgentEditingDot}
211
+ integrated={integratedEditingBadge}
212
+ />
213
+ )}
197
214
  {isFollowing && (
198
215
  <span
199
216
  style={{
@@ -216,33 +233,41 @@ function AgentAvatar({
216
233
  );
217
234
  }
218
235
 
219
- function AgentEditingChip() {
236
+ function AgentEditingChip({
237
+ showDot,
238
+ integrated,
239
+ }: {
240
+ showDot: boolean;
241
+ integrated: boolean;
242
+ }) {
220
243
  return (
221
244
  <span
222
245
  style={{
223
246
  display: "inline-flex",
224
247
  alignItems: "center",
225
- gap: 4,
226
- height: 20,
227
- padding: "0 8px",
228
- borderRadius: 9999,
229
- backgroundColor: `${AGENT_COLOR}20`,
248
+ gap: showDot ? 4 : 0,
249
+ height: integrated ? "auto" : 20,
250
+ padding: integrated ? 0 : "0 8px",
251
+ borderRadius: integrated ? 0 : 9999,
252
+ backgroundColor: integrated ? "transparent" : `${AGENT_COLOR}20`,
230
253
  color: AGENT_COLOR,
231
254
  fontSize: 11,
232
255
  fontWeight: 600,
233
256
  whiteSpace: "nowrap",
234
257
  }}
235
258
  >
236
- <span
237
- style={{
238
- width: 6,
239
- height: 6,
240
- borderRadius: "50%",
241
- backgroundColor: AGENT_COLOR,
242
- animation: "_anPresencePulse 2s infinite",
243
- flexShrink: 0,
244
- }}
245
- />
259
+ {showDot && (
260
+ <span
261
+ style={{
262
+ width: 6,
263
+ height: 6,
264
+ borderRadius: "50%",
265
+ backgroundColor: AGENT_COLOR,
266
+ animation: "_anPresencePulse 2s infinite",
267
+ flexShrink: 0,
268
+ }}
269
+ />
270
+ )}
246
271
  AI editing
247
272
  </span>
248
273
  );
@@ -275,6 +300,7 @@ export function PresenceBar({
275
300
  activeUsers,
276
301
  agentPresent,
277
302
  agentActive,
303
+ showAgentEditingDot = true,
278
304
  currentUserEmail,
279
305
  maxVisible = 5,
280
306
  className,
@@ -313,6 +339,7 @@ export function PresenceBar({
313
339
  active={!!agentActive}
314
340
  onClick={onAvatarClick ? () => onAvatarClick(null) : undefined}
315
341
  isFollowing={isFollowingAgent}
342
+ showAgentEditingDot={showAgentEditingDot}
316
343
  />
317
344
  )}
318
345
  {visibleUsers.length > 0 && (
@@ -81,7 +81,7 @@ export interface PromptComposerProps {
81
81
  files: PromptComposerFile[],
82
82
  references: Reference[],
83
83
  options: PromptComposerSubmitOptions,
84
- ) => void;
84
+ ) => void | Promise<void>;
85
85
  placeholder?: string;
86
86
  disabled?: boolean;
87
87
  /** Override the generic document attachment cap for a multipart host. */
@@ -587,7 +587,7 @@ function PromptComposerInner({
587
587
  text,
588
588
  attachments,
589
589
  });
590
- onSubmit(finalText, files, references, {
590
+ await onSubmit(finalText, files, references, {
591
591
  intent: submitOptions?.intent ?? "immediate",
592
592
  model: composerModel,
593
593
  engine: composerEngine,
@@ -44,7 +44,7 @@ describe("createTiptapComposerExtensions", () => {
44
44
  }).not.toThrow();
45
45
  });
46
46
 
47
- it("offers explicit reasoning levels without legacy Auto", () => {
47
+ it("offers explicit effort levels without legacy Auto", () => {
48
48
  expect(getComposerReasoningEffortOptions("auto")).toEqual([
49
49
  "low",
50
50
  "medium",
@@ -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,7 +631,7 @@ 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
636
  /** Show the legacy provider-level Auto model option (default: true). */
637
637
  showAutoModelOption?: boolean;
@@ -648,7 +648,7 @@ export interface TiptapComposerProps {
648
648
  modelListLoading?: boolean;
649
649
  /** Callback when user picks a model */
650
650
  onModelChange?: (model: string, engine: string) => void;
651
- /** Callback when user picks a reasoning effort */
651
+ /** Callback when user picks an effort */
652
652
  onEffortChange?: (effort: ReasoningEffort) => void;
653
653
  /**
654
654
  * Disable Builder/provider status polling for hosts that supply provider
@@ -963,7 +963,7 @@ function latestModelsOnly(models: string[]): string[] {
963
963
  return true;
964
964
  }
965
965
  // GPT: family = gpt-{major} (e.g. gpt-5.6-sol and gpt-5.6-luna are different)
966
- // OpenAI reasoning: each is its own family
966
+ // OpenAI effort: each is its own family
967
967
  // Gemini: family = gemini-{major} + variant
968
968
  const gemini = m.match(/^gemini-(\d+(?:\.\d+)?)-(.+?)(?:-preview)?$/);
969
969
  if (gemini) {
@@ -1133,12 +1133,12 @@ function ModelSelector({
1133
1133
  });
1134
1134
  }, []);
1135
1135
 
1136
- // The reasoning effort list is collapsed by default — it's a secondary
1136
+ // The effort list is collapsed by default — it's a secondary
1137
1137
  // control most users don't touch, so it stays tucked behind a header that
1138
1138
  // reveals the current effort at a glance. Reset to collapsed on each open.
1139
- const [reasoningExpanded, setReasoningExpanded] = useState(false);
1139
+ const [effortExpanded, setEffortExpanded] = useState(false);
1140
1140
  useEffect(() => {
1141
- if (open) setReasoningExpanded(false);
1141
+ if (open) setEffortExpanded(false);
1142
1142
  }, [open]);
1143
1143
 
1144
1144
  // The optional image-model section follows the same collapsed-by-default
@@ -1202,7 +1202,7 @@ function ModelSelector({
1202
1202
  data-agent-composer-slot="model-button"
1203
1203
  aria-label={`Model: ${friendlyModelName(model)}${
1204
1204
  effortOptions.length > 0
1205
- ? `. Reasoning: ${effortLabel(selectedEffort)}`
1205
+ ? `. Effort: ${effortLabel(selectedEffort)}`
1206
1206
  : ""
1207
1207
  }`}
1208
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"
@@ -1466,26 +1466,26 @@ function ModelSelector({
1466
1466
  <div className="flex items-center hover:bg-accent/30">
1467
1467
  <button
1468
1468
  type="button"
1469
- aria-expanded={reasoningExpanded}
1470
- onClick={() => setReasoningExpanded((prev) => !prev)}
1469
+ aria-expanded={effortExpanded}
1470
+ onClick={() => setEffortExpanded((prev) => !prev)}
1471
1471
  className="flex flex-1 min-w-0 items-center gap-1.5 px-2 py-1.5 cursor-pointer text-start"
1472
1472
  >
1473
- {reasoningExpanded ? (
1473
+ {effortExpanded ? (
1474
1474
  <IconChevronDown className="h-3 w-3 shrink-0 text-muted-foreground" />
1475
1475
  ) : (
1476
1476
  <IconChevronRight className="h-3 w-3 shrink-0 text-muted-foreground rtl:-scale-x-100" />
1477
1477
  )}
1478
1478
  <span className="text-[11px] font-medium text-muted-foreground uppercase tracking-wide shrink-0">
1479
- Reasoning
1479
+ Effort
1480
1480
  </span>
1481
- {!reasoningExpanded && (
1481
+ {!effortExpanded && (
1482
1482
  <span className="text-[11px] text-muted-foreground/80 truncate">
1483
1483
  {effortLabel(selectedEffort)}
1484
1484
  </span>
1485
1485
  )}
1486
1486
  </button>
1487
1487
  </div>
1488
- {reasoningExpanded &&
1488
+ {effortExpanded &&
1489
1489
  effortOptions.map((option) => (
1490
1490
  <button
1491
1491
  key={option}
@@ -2651,7 +2651,13 @@ export function TiptapComposer({
2651
2651
  }
2652
2652
 
2653
2653
  if (onSubmit) {
2654
- 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
+ }
2655
2661
  // Clear any pending attachments now that the host has them.
2656
2662
  void composerRuntime.clearAttachments().catch(() => {});
2657
2663
  if (!clearOnSubmit) {
@@ -184,7 +184,7 @@ const fallbackModels = {
184
184
  useChatModels: () => ({
185
185
  selectedModel: "auto",
186
186
  selectedEngine: "auto",
187
- selectedEffort: "medium" as ReasoningEffort,
187
+ selectedEffort: "high" as ReasoningEffort,
188
188
  availableModels: [],
189
189
  isLoading: false,
190
190
  onModelChange: () => {},
@@ -281,7 +281,7 @@ export function useComposerRuntimeAdapters() {
281
281
  return useContext(ComposerRuntimeAdaptersContext);
282
282
  }
283
283
 
284
- export const DEFAULT_REASONING_EFFORT: ReasoningEffort = "medium";
284
+ export const DEFAULT_REASONING_EFFORT: ReasoningEffort = "high";
285
285
  export function getReasoningEffortOptionsForModel(
286
286
  _model?: string,
287
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
  )}