@agent-native/core 0.178.0 → 0.178.1-nightly-20260909221943

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 (88) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/.agents/skills/dictate/SKILL.md +1 -0
  3. package/corpus/templates/clips/DESIGN.md +10 -7
  4. package/corpus/templates/clips/actions/list-organization-state.ts +56 -3
  5. package/corpus/templates/clips/actions/list-recordings.ts +2 -0
  6. package/corpus/templates/clips/actions/search-dictations.ts +81 -0
  7. package/corpus/templates/clips/app/components/agent-destination-logos.tsx +50 -0
  8. package/corpus/templates/clips/app/components/bug-report/bug-report-dialog.tsx +60 -0
  9. package/corpus/templates/clips/app/components/bug-report/bug-report-form.tsx +206 -0
  10. package/corpus/templates/clips/app/components/clips-command-menu.tsx +653 -0
  11. package/corpus/templates/clips/app/components/library/empty-state.tsx +52 -17
  12. package/corpus/templates/clips/app/components/library/folder-card.tsx +34 -0
  13. package/corpus/templates/clips/app/components/library/folder-tree.tsx +109 -64
  14. package/corpus/templates/clips/app/components/library/library-action-hrefs.ts +27 -0
  15. package/corpus/templates/clips/app/components/library/library-grid.tsx +295 -103
  16. package/corpus/templates/clips/app/components/library/library-layout.tsx +381 -203
  17. package/corpus/templates/clips/app/components/library/library-primary-actions.tsx +48 -0
  18. package/corpus/templates/clips/app/components/library/page-header.tsx +48 -8
  19. package/corpus/templates/clips/app/components/library/recording-card.tsx +58 -55
  20. package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -19
  21. package/corpus/templates/clips/app/components/library/sidebar-feedback-button.tsx +48 -0
  22. package/corpus/templates/clips/app/components/player/comments-panel.tsx +2 -2
  23. package/corpus/templates/clips/app/components/player/share-dialog.tsx +344 -260
  24. package/corpus/templates/clips/app/components/player/viewer-controls.tsx +2 -2
  25. package/corpus/templates/clips/app/components/recorder/camera-visualizer.tsx +0 -33
  26. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -1
  27. package/corpus/templates/clips/app/components/ui/tabs.tsx +1 -1
  28. package/corpus/templates/clips/app/hooks/use-command-search.ts +53 -0
  29. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +32 -13
  30. package/corpus/templates/clips/app/hooks/use-upload-video-picker.tsx +1 -0
  31. package/corpus/templates/clips/app/i18n/en-US.ts +7 -0
  32. package/corpus/templates/clips/app/lib/agent-share.ts +16 -0
  33. package/corpus/templates/clips/app/lib/command-events.ts +7 -0
  34. package/corpus/templates/clips/app/root.tsx +6 -82
  35. package/corpus/templates/clips/app/routes/_app.dictate.tsx +25 -5
  36. package/corpus/templates/clips/app/routes/_app.library._index.tsx +2 -30
  37. package/corpus/templates/clips/app/routes/_app.library.folder.$folderId.tsx +13 -2
  38. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +4 -17
  39. package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +111 -114
  40. package/corpus/templates/clips/app/routes/_app.spaces.$spaceId.folder.$folderId.tsx +25 -2
  41. package/corpus/templates/clips/app/routes/_app.spaces.$spaceId.tsx +14 -61
  42. package/corpus/templates/clips/app/routes/_app.spaces._index.tsx +34 -24
  43. package/corpus/templates/clips/app/routes/_app.trash.tsx +1 -1
  44. package/corpus/templates/clips/app/routes/_app.tsx +2 -4
  45. package/corpus/templates/clips/app/routes/bug-report.tsx +11 -189
  46. package/corpus/templates/clips/app/routes/share.$shareId.tsx +148 -123
  47. package/corpus/templates/clips/changelog/2026-09-08-comments-and-desktop-window-controls.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-09-08-global-command-search.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-09-09-agent-sidebar-fits-below-toolbar.md +6 -0
  50. package/corpus/templates/clips/changelog/2026-09-09-desktop-switches-stay-clear-in-dark-mode.md +6 -0
  51. package/corpus/templates/clips/changelog/2026-09-09-recording-agent-uses-global-panel.md +6 -0
  52. package/corpus/templates/clips/desktop/src/app.tsx +2 -2
  53. package/corpus/templates/clips/desktop/src/components/MediaDeviceRow.tsx +5 -3
  54. package/corpus/templates/clips/desktop/src/components/SourceRow.tsx +1 -0
  55. package/corpus/templates/clips/desktop/src/components/Switch.tsx +2 -5
  56. package/corpus/templates/clips/desktop/src/components/ui/switch.tsx +21 -3
  57. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +72 -52
  58. package/corpus/templates/clips/desktop/src/styles.css +18 -19
  59. package/corpus/templates/clips/desktop/src/tailwind.css +3 -0
  60. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +18 -10
  61. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +3 -5
  62. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +14 -3
  63. package/corpus/templates/design/AGENTS.md +2 -1
  64. package/corpus/templates/design/actions/export-png.ts +119 -0
  65. package/corpus/templates/design/actions/take-design-screenshot.ts +47 -13
  66. package/corpus/templates/design/server/plugins/agent-chat.ts +3 -1
  67. package/corpus/templates/factory/actions/dispatch-factory-item.ts +51 -22
  68. package/corpus/templates/factory/actions/list-triage-items.ts +21 -11
  69. package/corpus/templates/factory/actions/poll-slack-channel.ts +7 -2
  70. package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-keeps-claimed-markers-after-poll.md +6 -0
  71. package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-preserves-started-claimed-threads.md +6 -0
  72. package/corpus/templates/factory/changelog/2026-09-09-slack-feedback-skips-claimed-parents.md +6 -0
  73. package/corpus/templates/factory/server/lib/factory-automation-config.ts +1 -1
  74. package/corpus/templates/factory/server/lib/slack-feedback-prompt.ts +47 -0
  75. package/corpus/templates/factory/server/plugins/agent-chat.ts +5 -2
  76. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +5 -4
  77. package/corpus/templates/factory/server/triage/review-skill-alignment.ts +12 -7
  78. package/corpus/templates/factory/server/triage/slack-review-window.ts +39 -0
  79. package/dist/client/CommandMenu.js +13 -1
  80. package/dist/client/analytics.js +10 -0
  81. package/dist/collab/routes.d.ts +1 -1
  82. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  83. package/dist/notifications/routes.d.ts +2 -2
  84. package/dist/observability/routes.d.ts +5 -5
  85. package/dist/vite/client.js +25 -7
  86. package/dist/vite/sentry-source-maps.d.ts +12 -0
  87. package/dist/vite/sentry-source-maps.js +105 -0
  88. package/package.json +2 -1
@@ -0,0 +1,48 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
2
+ import { IconVideoPlus } from "@tabler/icons-react";
3
+ import { NavLink } from "react-router";
4
+
5
+ import { ImportMenu } from "@/components/import-menu";
6
+
7
+ import {
8
+ buildLibraryActionHrefs,
9
+ type LibraryActionScope,
10
+ } from "./library-action-hrefs";
11
+ import { PageHeaderActionGroup, PageHeaderPrimaryAction } from "./page-header";
12
+
13
+ type LibraryPrimaryActionsProps = LibraryActionScope;
14
+
15
+ export function LibraryPrimaryActions({
16
+ folderId,
17
+ spaceId,
18
+ }: LibraryPrimaryActionsProps) {
19
+ const t = useT();
20
+ const { recordHref, uploadHref, importLoomHref } = buildLibraryActionHrefs({
21
+ folderId,
22
+ spaceId,
23
+ });
24
+
25
+ return (
26
+ <PageHeaderActionGroup>
27
+ <PageHeaderPrimaryAction asChild>
28
+ <NavLink to={recordHref} aria-label={t("navigation.newRecording")}>
29
+ <IconVideoPlus />
30
+ <span className="hidden sm:inline">
31
+ {t("navigation.newRecording")}
32
+ </span>
33
+ </NavLink>
34
+ </PageHeaderPrimaryAction>
35
+ <ImportMenu
36
+ uploadHref={uploadHref}
37
+ importLoomHref={importLoomHref}
38
+ iconOnly
39
+ triggerIcon="chevron"
40
+ size="sm"
41
+ variant="default"
42
+ className="w-8 self-stretch border-s border-primary-foreground/20 px-0 shadow-none"
43
+ menuSide="bottom"
44
+ menuAlign="end"
45
+ />
46
+ </PageHeaderActionGroup>
47
+ );
48
+ }
@@ -2,18 +2,22 @@ import {
2
2
  type ComponentProps,
3
3
  createContext,
4
4
  forwardRef,
5
+ Fragment,
5
6
  ReactNode,
6
7
  useContext,
7
8
  useEffect,
8
9
  useState,
9
10
  } from "react";
10
11
  import { createPortal } from "react-dom";
12
+ import { NavLink } from "react-router";
11
13
 
12
14
  import {
13
15
  Breadcrumb,
14
16
  BreadcrumbItem,
17
+ BreadcrumbLink,
15
18
  BreadcrumbList,
16
19
  BreadcrumbPage,
20
+ BreadcrumbSeparator,
17
21
  } from "@/components/ui/breadcrumb";
18
22
  import { Button, type ButtonProps } from "@/components/ui/button";
19
23
  import { ButtonGroup } from "@/components/ui/button-group";
@@ -76,22 +80,58 @@ export const PageHeaderActionGroup = forwardRef<
76
80
  return (
77
81
  <ButtonGroup
78
82
  ref={ref}
79
- className={cn("shrink-0 [&>*]:h-9", className)}
83
+ className={cn(
84
+ "shrink-0 [&>*]:h-9 has-[>input[data-button-group-ignore]]:[&>*:nth-last-child(2)]:!rounded-r-md",
85
+ className,
86
+ )}
80
87
  {...props}
81
88
  />
82
89
  );
83
90
  });
84
91
  PageHeaderActionGroup.displayName = "PageHeaderActionGroup";
85
92
 
86
- export function PageBreadcrumb({ label }: { label: string }) {
93
+ export interface PageBreadcrumbItem {
94
+ label: string;
95
+ to?: string;
96
+ }
97
+
98
+ export function PageBreadcrumb({
99
+ items,
100
+ }: {
101
+ items: readonly PageBreadcrumbItem[];
102
+ }) {
103
+ if (items.length === 0) return null;
104
+
87
105
  return (
88
- <Breadcrumb aria-label={label} className="min-w-0">
106
+ <Breadcrumb
107
+ aria-label={items.map((item) => item.label).join(" / ")}
108
+ className="min-w-0"
109
+ >
89
110
  <BreadcrumbList className="flex-nowrap overflow-hidden">
90
- <BreadcrumbItem className="min-w-0">
91
- <BreadcrumbPage className="truncate font-medium">
92
- {label}
93
- </BreadcrumbPage>
94
- </BreadcrumbItem>
111
+ {items.map((item, index) => {
112
+ const current = index === items.length - 1;
113
+
114
+ return (
115
+ <Fragment key={`${item.to ?? "current"}:${item.label}:${index}`}>
116
+ {index > 0 ? <BreadcrumbSeparator className="shrink-0" /> : null}
117
+ <BreadcrumbItem className={current ? "min-w-0" : "shrink-0"}>
118
+ {current ? (
119
+ <BreadcrumbPage className="truncate font-medium">
120
+ {item.label}
121
+ </BreadcrumbPage>
122
+ ) : item.to ? (
123
+ <BreadcrumbLink asChild>
124
+ <NavLink to={item.to} className="block max-w-48 truncate">
125
+ {item.label}
126
+ </NavLink>
127
+ </BreadcrumbLink>
128
+ ) : (
129
+ <span className="block max-w-48 truncate">{item.label}</span>
130
+ )}
131
+ </BreadcrumbItem>
132
+ </Fragment>
133
+ );
134
+ })}
95
135
  </BreadcrumbList>
96
136
  </Breadcrumb>
97
137
  );
@@ -461,7 +461,7 @@ export function RecordingCard({
461
461
 
462
462
  {/* Body */}
463
463
  <div className="relative z-10 flex flex-1 flex-col gap-2 p-4 pointer-events-none">
464
- <div className="flex items-start gap-3">
464
+ <div className="flex items-center gap-3">
465
465
  <div className="min-w-0 flex-1">
466
466
  {hasDefaultTitle ? (
467
467
  <Skeleton
@@ -473,60 +473,6 @@ export function RecordingCard({
473
473
  {displayTitle}
474
474
  </div>
475
475
  )}
476
- <div className="mt-1.5 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground">
477
- <span className="inline-flex min-w-0 items-center gap-1.5">
478
- <ClipsAvatar
479
- email={recording.ownerEmail}
480
- alt={displayOwnerName}
481
- fallback={ownerInitials}
482
- className="h-4 w-4 shrink-0"
483
- fallbackClassName="bg-primary/15 text-[8px] text-primary"
484
- />
485
- <span className="min-w-0 truncate">{displayOwnerName}</span>
486
- </span>
487
- <span aria-hidden className="text-muted-foreground/60">
488
- •
489
- </span>
490
- <time dateTime={recording.createdAt} className="shrink-0">
491
- {relative}
492
- </time>
493
- </div>
494
- <div className="mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground">
495
- <span className="inline-flex items-center gap-1.5">
496
- <PrivacyIcon
497
- visibility={recording.visibility}
498
- className="shrink-0"
499
- />
500
- <span>{visibilityLabel}</span>
501
- </span>
502
- <span aria-hidden className="text-muted-foreground/60">
503
- •
504
- </span>
505
- {recording.viewCount > 0 && !readOnly ? (
506
- <ViewedByPopover
507
- recordingId={recording.id}
508
- className="pointer-events-auto underline-offset-2 hover:underline hover:text-foreground"
509
- >
510
- {t("clipsFinalRaw.viewsCount", {
511
- count: recording.viewCount,
512
- })}
513
- </ViewedByPopover>
514
- ) : (
515
- <span>
516
- {t("clipsFinalRaw.viewsCount", {
517
- count: recording.viewCount,
518
- })}
519
- </span>
520
- )}
521
- {recording.agentViewCount > 0 ? (
522
- <AgentViewCount
523
- count={recording.agentViewCount}
524
- label={t("recordingInsights.agentViewsCount", {
525
- count: recording.agentViewCount,
526
- })}
527
- />
528
- ) : null}
529
- </div>
530
476
  </div>
531
477
 
532
478
  {showActions && (
@@ -630,6 +576,63 @@ export function RecordingCard({
630
576
  )}
631
577
  </div>
632
578
 
579
+ <div className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 gap-y-1.5 text-xs text-muted-foreground">
580
+ <div className="flex min-w-0 items-center gap-1.5">
581
+ <ClipsAvatar
582
+ email={recording.ownerEmail}
583
+ alt={displayOwnerName}
584
+ fallback={ownerInitials}
585
+ className="h-4 w-4 shrink-0"
586
+ fallbackClassName="bg-primary/15 text-[8px] text-primary"
587
+ />
588
+ <span className="min-w-0 truncate">{displayOwnerName}</span>
589
+ </div>
590
+
591
+ <div className="flex items-center justify-self-end gap-x-2 whitespace-nowrap">
592
+ {recording.viewCount > 0 && !readOnly ? (
593
+ <ViewedByPopover
594
+ recordingId={recording.id}
595
+ className="pointer-events-auto underline-offset-2 hover:text-foreground hover:underline"
596
+ >
597
+ {t("clipsFinalRaw.viewsCount", {
598
+ count: recording.viewCount,
599
+ })}
600
+ </ViewedByPopover>
601
+ ) : (
602
+ <span>
603
+ {t("clipsFinalRaw.viewsCount", {
604
+ count: recording.viewCount,
605
+ })}
606
+ </span>
607
+ )}
608
+ {recording.agentViewCount > 0 ? (
609
+ <AgentViewCount
610
+ count={recording.agentViewCount}
611
+ label={t("recordingInsights.agentViewsCount", {
612
+ count: recording.agentViewCount,
613
+ })}
614
+ />
615
+ ) : null}
616
+ </div>
617
+
618
+ <time
619
+ dateTime={recording.createdAt}
620
+ className="whitespace-nowrap"
621
+ >
622
+ {relative}
623
+ </time>
624
+
625
+ <div className="flex items-center justify-self-end gap-1.5 whitespace-nowrap">
626
+ <span className="inline-flex items-center gap-1.5">
627
+ <PrivacyIcon
628
+ visibility={recording.visibility}
629
+ className="shrink-0"
630
+ />
631
+ <span>{visibilityLabel}</span>
632
+ </span>
633
+ </div>
634
+ </div>
635
+
633
636
  {recording.tags.length > 0 && (
634
637
  <div className="flex items-center gap-1 truncate">
635
638
  {recording.tags.slice(0, 2).map((t) => (
@@ -108,29 +108,15 @@ export function SearchBar({ className, side = "right" }: SearchBarProps) {
108
108
  return () => cancelAnimationFrame(frame);
109
109
  }, [focusSearchInput, routeRequestsFocus, setSearchParams]);
110
110
 
111
- // "/" is the inline search shortcut. Cmd+K belongs to the app command menu.
112
111
  useEffect(() => {
113
112
  const onKey = (e: KeyboardEvent) => {
114
- if (
115
- e.key === "/" &&
116
- !e.metaKey &&
117
- !e.ctrlKey &&
118
- !e.altKey &&
119
- (e.target as HTMLElement)?.tagName?.toLowerCase() !== "input" &&
120
- (e.target as HTMLElement)?.tagName?.toLowerCase() !== "textarea" &&
121
- !(e.target as HTMLElement)?.isContentEditable
122
- ) {
123
- e.preventDefault();
124
- focusSearchInput();
125
- }
126
- if (e.key === "Escape") {
127
- setOpen(false);
128
- inputRef.current?.blur();
129
- }
113
+ if (e.key !== "Escape") return;
114
+ setOpen(false);
115
+ inputRef.current?.blur();
130
116
  };
131
117
  window.addEventListener("keydown", onKey);
132
118
  return () => window.removeEventListener("keydown", onKey);
133
- }, [focusSearchInput]);
119
+ }, []);
134
120
 
135
121
  function pickResult(hit: SearchHit) {
136
122
  setOpen(false);
@@ -184,7 +170,7 @@ export function SearchBar({ className, side = "right" }: SearchBarProps) {
184
170
  aria-hidden="true"
185
171
  className="absolute end-1.5 top-1/2 h-5 -translate-y-1/2 px-1 font-mono text-[10px]"
186
172
  >
187
- {shortcutLabel("/")}
173
+ {shortcutLabel("cmd+k")}
188
174
  </Kbd>
189
175
  )}
190
176
  </div>
@@ -0,0 +1,48 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
2
+ import { IconMessageCircle } from "@tabler/icons-react";
3
+
4
+ import { Button } from "@/components/ui/button";
5
+ import {
6
+ Tooltip,
7
+ TooltipContent,
8
+ TooltipTrigger,
9
+ } from "@/components/ui/tooltip";
10
+ import { openBugReportDialog } from "@/lib/command-events";
11
+
12
+ interface SidebarFeedbackButtonProps {
13
+ collapsed: boolean;
14
+ }
15
+
16
+ export function SidebarFeedbackButton({
17
+ collapsed,
18
+ }: SidebarFeedbackButtonProps) {
19
+ const t = useT();
20
+ const label = t("bugReportRoute.sidebarCta");
21
+
22
+ const button = (
23
+ <Button
24
+ type="button"
25
+ size={collapsed ? "icon" : "sm"}
26
+ variant="ghost"
27
+ aria-label={collapsed ? label : undefined}
28
+ onClick={openBugReportDialog}
29
+ className={
30
+ collapsed
31
+ ? "size-9 bg-transparent text-primary hover:bg-accent/60 hover:text-primary"
32
+ : "h-auto w-full justify-start gap-2 bg-transparent px-2 py-1.5 text-xs font-normal text-primary hover:bg-accent/60 hover:text-primary"
33
+ }
34
+ >
35
+ <IconMessageCircle className="size-4 shrink-0 text-primary" />
36
+ {!collapsed && <span>{label}</span>}
37
+ </Button>
38
+ );
39
+
40
+ if (!collapsed) return button;
41
+
42
+ return (
43
+ <Tooltip>
44
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
45
+ <TooltipContent side="right">{label}</TooltipContent>
46
+ </Tooltip>
47
+ );
48
+ }
@@ -506,7 +506,7 @@ export function CommentsPanel(props: CommentsPanelProps) {
506
506
  )}
507
507
  >
508
508
  {isInlinePresentation && enableComments ? (
509
- <div className="mb-5 shrink-0">{composer}</div>
509
+ <div className="mb-3 shrink-0">{composer}</div>
510
510
  ) : null}
511
511
  <div
512
512
  className={cn(
@@ -524,7 +524,7 @@ export function CommentsPanel(props: CommentsPanelProps) {
524
524
  isInlinePresentation={isInlinePresentation}
525
525
  />
526
526
  ) : (
527
- <ul className="space-y-5">
527
+ <ul className="space-y-3">
528
528
  {sortedThreads.map((thread) => {
529
529
  const root = thread[0];
530
530
  const replies = thread.slice(1);