@agent-native/core 0.153.1 → 0.153.4

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/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +21 -19
  3. package/corpus/templates/analytics/AGENTS.md +4 -0
  4. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  5. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +0 -11
  6. package/corpus/templates/clips/app/components/player/share-dialog.tsx +32 -33
  7. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +29 -39
  8. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +0 -1
  9. package/corpus/templates/clips/desktop/src/app.tsx +817 -441
  10. package/corpus/templates/clips/desktop/src/styles.css +234 -0
  11. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
  12. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +593 -7
  13. package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +95 -10
  14. package/corpus/templates/forms/AGENTS.md +6 -0
  15. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  16. package/corpus/templates/mail/AGENTS.md +5 -4
  17. package/corpus/templates/mail/actions/get-automation-settings.ts +17 -6
  18. package/corpus/templates/mail/actions/send-email.ts +17 -9
  19. package/corpus/templates/mail/actions/send-queued-drafts.ts +21 -11
  20. package/corpus/templates/mail/actions/update-automation-settings.ts +20 -6
  21. package/corpus/templates/mail/app/i18n/en-US.ts +5 -0
  22. package/corpus/templates/mail/app/pages/SettingsPage.tsx +68 -7
  23. package/corpus/templates/mail/server/lib/automation-settings.ts +27 -0
  24. package/corpus/templates/mail/server/plugins/agent-chat.ts +2 -0
  25. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +3 -3
  26. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +17 -4
  27. package/corpus/templates/slides/app/context/DeckContext.tsx +3 -2
  28. package/corpus/templates/slides/app/pages/DeckEditor.tsx +44 -0
  29. package/corpus/templates/slides/changelog/2026-08-12-arrow-key-navigation-in-the-slide-film-strip-now-scrolls-sli.md +6 -0
  30. package/corpus/templates/slides/changelog/2026-08-12-duplicate-a-slide-from-the-film-strip-with-cmd-ctrl-c-then-c.md +6 -0
  31. package/corpus/templates/slides/changelog/2026-08-12-presenting-a-deck-now-returns-you-to-the-slide-you-were-view.md +6 -0
  32. package/dist/client/resources/mcp-integration-catalog.d.ts +7 -0
  33. package/dist/client/resources/mcp-integration-catalog.js +14 -1
  34. package/dist/client/settings/AgentsSection.js +46 -30
  35. package/dist/client/sharing/ShareDialog.js +4 -2
  36. package/dist/collab/awareness.d.ts +2 -2
  37. package/dist/observability/routes.d.ts +5 -5
  38. package/dist/secrets/routes.d.ts +9 -9
  39. package/dist/server/agent-chat-plugin.js +1 -0
  40. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  41. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -31,4 +31,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
31
31
 
32
32
  ## Generated Counts
33
33
 
34
- - template files: 8185
34
+ - template files: 8189
@@ -101,25 +101,27 @@ Don't just dump raw data. Synthesize findings:
101
101
 
102
102
  ### Step 4: Generate Charts (when useful)
103
103
 
104
- When the analysis benefits from a visual — trends over time, distributions, comparisons between categories — call `generate-chart` before formatting the report. The action returns a `url` you embed directly in the markdown.
105
-
106
- ```
107
- generate-chart
108
- --title "Closed-lost deals by month"
109
- --type bar
110
- --labels '["Jan","Feb","Mar"]'
111
- --data '[18, 22, 14]'
112
- ```
113
-
114
- Embed the returned URL in `resultMarkdown` using standard markdown image syntax:
115
-
116
- ```markdown
117
- ![Closed-lost deals by month](/api/media/closed-lost-deals-by-month-1234567890.png?v=1234567890)
118
- ```
119
-
120
- You can include multiple charts in one analysis. Reach for a chart when it communicates the finding faster than a table — don't force visuals on every analysis.
121
-
122
- Include the re-generation step in your saved `instructions` so re-runs produce fresh charts.
104
+ When the analysis benefits from a visual — trends over time, distributions, or
105
+ comparisons between categories — query the data first, then use the live
106
+ `/chart` embed described in `data-querying` for an in-chat answer. Do not call
107
+ `generate-chart` for a one-off chat result: it produces a static image for
108
+ saved artifacts, requires pre-stringified JSON, and does not count as a real
109
+ data query for the final response guard.
110
+
111
+ For a stacked multi-series bar chart, keep the query in long form and emit a
112
+ panel with `chartType: "bar"`, `config.pivot` containing `xKey`, `seriesKey`,
113
+ and `valueKey`, plus `config.stacked: true`. The live chart route pivots the
114
+ rows and renders one stack per x-axis category. See `data-querying`'s
115
+ "Inline Charts In Chat" section for the exact `embed` fence and encoding.
116
+
117
+ Only use `generate-chart` when a saved analysis artifact explicitly needs a
118
+ static image. If it returns an error while answering in chat, switch to the
119
+ live embed instead of retrying reformatted `labels` or `data` parameters.
120
+
121
+ You can include multiple live charts in one analysis. Reach for a chart when it
122
+ communicates the finding faster than a table - don't force visuals on every
123
+ analysis. Include the query and embed configuration in saved `instructions` so
124
+ re-runs produce fresh charts.
123
125
 
124
126
  ### Step 5: Format Results as Markdown
125
127
 
@@ -48,6 +48,10 @@ Read the relevant skill before deeper work:
48
48
  sibling-invocable because this app owns schema, source selection, and tools.
49
49
  Prefer natural-language delegation; shaped reads are stable contracts, not
50
50
  delegation workarounds.
51
+ - Analytics owns first-party product usage, app/template events, agent-native
52
+ signups, conversions, and other curated product metrics. Answer sibling-app
53
+ delegations with the built-in source and query catalog; sibling agents should
54
+ send a natural-language question, never SQL.
51
55
  - For open-ended delegated requests, choose a safe default and label partial.
52
56
  - Data integrity first. Never invent numbers, dimensions, filters, or source
53
57
  semantics; only present values you actually retrieved, and state uncertainty.
@@ -105,6 +105,7 @@ export const ANALYTICS_OBSERVABILITY_INCIDENT_GUIDANCE =
105
105
  "OBSERVABILITY INCIDENT WORKFLOW — For a named user's session or error question, resolve the user's email from context, then use list-session-recordings with userId over a bounded recent window to discover the relevant sessions. Do not require hasErrors=true for this initial lookup: replay/network/stuck-run evidence can exist while the recording's JavaScript errorCount is zero. Use hasErrors=true only when the user specifically asks for recordings with captured JavaScript errors or the recording metadata confirms that filter is appropriate. Use list-error-issues with userId or sessionRecordingId to identify a grouped issue, then get-error-issue for stack, breadcrumbs, occurrences, and linked recordings. For console diagnostics or failed network requests, create-session-replay-agent-link first and use its scoped diagnostics endpoint for detailed error text, stacks, request metadata, and bounded 5xx snippets; enumerate with kind/limit and fromMs/toMs or offset when needed. Use get-session-replay-summary and get-session-replay-timeline for the page-navigation and click sequence, and use get-session-replay-events only for additional bounded replay-event details. If no grouped error exists, correlate first-party observability events such as agent_chat_stuck_detected with query-agent-native-analytics. This and other read-only investigation tools remain available in Plan mode; run the query instead of deferring it to execution mode. Prefer these first-party actions over generic SQL. Report the matching evidence and do not claim a root cause without a corroborating error, event, or replay signal. ";
106
106
 
107
107
  export const ANALYTICS_CROSS_APP_ROUTING_GUIDANCE =
108
+ "WORKSPACE APP ROUTING — Analytics is the sibling app for first-party product usage, app/template events, agent-native signups, conversions, and other curated product metrics. When another app delegates one of these questions with `call-agent`, answer it here using the built-in first-party source and query catalog; do not send the user back to another app or ask the caller to invent SQL. " +
108
109
  "WORKSPACE APP ROUTING — Brain is the sibling app that owns company knowledge and indexed Slack context. Brain is not an Analytics extension and will not appear in `list-extensions`. When the user asks about company knowledge, decisions, meeting context, or Slack messages/context such as a named channel or thread, use `call-agent` with agent `brain` and a narrow natural-language question. Use `describe-workspace-apps` only when you need to confirm the sibling capability. Do not use `list-extensions` to find Brain, and do not use `provider-api-request` to call Brain. If Brain reports an access or source error, preserve that exact error; do not infer that the Slack bot is absent from a channel or tell the user to re-invite it. Stay in Analytics for metrics and aggregates over a named provider. ";
109
110
 
110
111
  export const NON_ANALYTICS_REQUEST_GUIDANCE =
@@ -12,7 +12,6 @@ import {
12
12
  CopyField,
13
13
  GeneralAccessSelect,
14
14
  MakePublicCard,
15
- ShareCardHeader,
16
15
  SharePeopleTab,
17
16
  copyToClipboard,
18
17
  useResourceVisibilityMutation,
@@ -30,7 +29,6 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
30
29
 
31
30
  export interface ShareMeetingPopoverProps {
32
31
  meetingId: string;
33
- meetingTitle?: string;
34
32
  shareTranscript: boolean;
35
33
  transcriptReady: boolean;
36
34
  children: ReactNode;
@@ -38,7 +36,6 @@ export interface ShareMeetingPopoverProps {
38
36
 
39
37
  export function ShareMeetingPopover({
40
38
  meetingId,
41
- meetingTitle,
42
39
  shareTranscript,
43
40
  transcriptReady,
44
41
  children,
@@ -52,7 +49,6 @@ export function ShareMeetingPopover({
52
49
  >
53
50
  <ShareMeetingContent
54
51
  meetingId={meetingId}
55
- meetingTitle={meetingTitle}
56
52
  shareTranscript={shareTranscript}
57
53
  transcriptReady={transcriptReady}
58
54
  />
@@ -63,12 +59,10 @@ export function ShareMeetingPopover({
63
59
 
64
60
  function ShareMeetingContent({
65
61
  meetingId,
66
- meetingTitle,
67
62
  shareTranscript,
68
63
  transcriptReady,
69
64
  }: {
70
65
  meetingId: string;
71
- meetingTitle?: string;
72
66
  shareTranscript: boolean;
73
67
  transcriptReady: boolean;
74
68
  }) {
@@ -85,14 +79,9 @@ function ShareMeetingContent({
85
79
 
86
80
  const data = sharesQuery.data;
87
81
  const canManage = data?.role === "owner" || data?.role === "admin";
88
- const titleText = meetingTitle
89
- ? t("clipsFinalRaw.shareNamedMeeting", { title: meetingTitle })
90
- : t("clipsFinalRaw.shareMeeting");
91
82
 
92
83
  return (
93
84
  <>
94
- <ShareCardHeader title={titleText} ownerEmail={data?.ownerEmail} />
95
-
96
85
  <Tabs defaultValue="link" className="min-w-0 px-4 py-3">
97
86
  <TabsList className="grid w-full grid-cols-2">
98
87
  <TabsTrigger value="link" className="gap-1.5">
@@ -27,7 +27,6 @@ import {
27
27
  CopyField,
28
28
  GeneralAccessSelect,
29
29
  MakePublicCard,
30
- ShareCardHeader,
31
30
  SharePeopleTab,
32
31
  copyToClipboard,
33
32
  useResourceVisibilityMutation,
@@ -51,6 +50,7 @@ import {
51
50
  } from "@/components/ui/popover";
52
51
  import { Switch } from "@/components/ui/switch";
53
52
  import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
53
+ import { cn } from "@/lib/utils";
54
54
 
55
55
  import { buildEmailPreviewMarkup } from "../../../shared/email-preview";
56
56
  import { isLoomEmbedUrl } from "../../../shared/loom";
@@ -228,19 +228,12 @@ function ShareRecordingContent({
228
228
  absoluteAppUrl(`/share/${recordingId}`),
229
229
  ownerViaId,
230
230
  );
231
- const titleText = recordingTitle
232
- ? t("shareDialog.shareTitle", { title: recordingTitle })
233
- : t("shareDialog.shareRecording");
234
-
235
231
  return (
236
232
  <>
237
- <ShareCardHeader
238
- title={titleText}
239
- ownerEmail={data?.ownerEmail}
240
- reserveCloseButton={reserveCloseButton}
241
- />
242
-
243
- <Tabs defaultValue="link" className="min-w-0 px-4 py-3">
233
+ <Tabs
234
+ defaultValue="link"
235
+ className={cn("min-w-0 px-4 py-3", reserveCloseButton && "pe-12")}
236
+ >
244
237
  <TabsList className="grid w-full grid-cols-3">
245
238
  <TabsTrigger value="link" className="gap-1.5">
246
239
  <IconLink size={14} />
@@ -441,6 +434,25 @@ function LinkTab({
441
434
  ? t("shareDialog.agentPrompt", { agentContextUrl: agentLink })
442
435
  : "";
443
436
  const [agentDetailsOpen, setAgentDetailsOpen] = useState(false);
437
+ const showMakePublic = sharesLoaded && !isPublic && canManage;
438
+ const downloadButton = videoUrl ? (
439
+ <Button
440
+ variant="outline"
441
+ size="sm"
442
+ className={isLoomRecording ? "gap-1.5" : undefined}
443
+ onClick={() => window.open(videoUrl, "_blank", "noopener,noreferrer")}
444
+ >
445
+ {isLoomRecording ? (
446
+ <>
447
+ <IconExternalLink className="h-4 w-4" />
448
+ {t("shareDialog.openPlayer")}
449
+ </>
450
+ ) : (
451
+ t("recordRoute.downloadRecording")
452
+ )}
453
+ </Button>
454
+ ) : null;
455
+ const moveDownloadIntoMakePublicRow = showMakePublic && Boolean(videoUrl);
444
456
 
445
457
  useEffect(() => {
446
458
  if (isPublic) setAgentDetailsOpen(false);
@@ -540,9 +552,12 @@ function LinkTab({
540
552
  </Collapsible>
541
553
  ) : null}
542
554
 
543
- {sharesLoaded && !isPublic && canManage ? (
555
+ {showMakePublic ? (
544
556
  <MakePublicCard
545
557
  isPending={isPending}
558
+ secondaryAction={
559
+ moveDownloadIntoMakePublicRow ? downloadButton : undefined
560
+ }
546
561
  onMakePublic={() =>
547
562
  setResourceVisibility("public", {
548
563
  onSuccess: () => copyToClipboard(shareUrl),
@@ -551,7 +566,9 @@ function LinkTab({
551
566
  />
552
567
  ) : null}
553
568
 
554
- {emailPreviewThumbnailUrl || videoUrl || animatedThumbnailUrl ? (
569
+ {emailPreviewThumbnailUrl ||
570
+ animatedThumbnailUrl ||
571
+ (videoUrl && !moveDownloadIntoMakePublicRow) ? (
555
572
  <div className="flex flex-wrap gap-2">
556
573
  {emailPreviewThumbnailUrl ? (
557
574
  <Button
@@ -571,25 +588,7 @@ function LinkTab({
571
588
  {t("shareDialog.gifPreview")}
572
589
  </Button>
573
590
  ) : null}
574
- {videoUrl ? (
575
- <Button
576
- variant="outline"
577
- size="sm"
578
- className={isLoomRecording ? "gap-1.5" : undefined}
579
- onClick={() =>
580
- window.open(videoUrl, "_blank", "noopener,noreferrer")
581
- }
582
- >
583
- {isLoomRecording ? (
584
- <>
585
- <IconExternalLink className="h-4 w-4" />
586
- {t("shareDialog.openPlayer")}
587
- </>
588
- ) : (
589
- t("recordRoute.downloadRecording")
590
- )}
591
- </Button>
592
- ) : null}
591
+ {!moveDownloadIntoMakePublicRow ? downloadButton : null}
593
592
  </div>
594
593
  ) : null}
595
594
  </div>
@@ -14,7 +14,7 @@ import {
14
14
  IconWorld,
15
15
  } from "@tabler/icons-react";
16
16
  import { useQueryClient } from "@tanstack/react-query";
17
- import { useMemo, useState } from "react";
17
+ import { useMemo, useState, type ReactNode } from "react";
18
18
 
19
19
  import {
20
20
  Avatar as UserAvatar,
@@ -136,34 +136,19 @@ export function useResourceVisibilityMutation(
136
136
  }
137
137
 
138
138
  // ---------------------------------------------------------------------------
139
- // Header (title + owner)
139
+ // Compact section labels
140
140
  // ---------------------------------------------------------------------------
141
141
 
142
- export function ShareCardHeader({
143
- title,
144
- ownerEmail,
145
- reserveCloseButton = false,
142
+ export function ShareSectionLabel({
143
+ children,
144
+ className,
146
145
  }: {
147
- title: string;
148
- ownerEmail?: string | null;
149
- reserveCloseButton?: boolean;
146
+ children: ReactNode;
147
+ className?: string;
150
148
  }) {
151
- const t = useT();
152
149
  return (
153
- <div
154
- className={cn(
155
- "min-w-0 border-b border-border px-4 pb-3 pt-3",
156
- reserveCloseButton && "pe-12",
157
- )}
158
- >
159
- <div className="min-w-0 truncate text-sm font-semibold" title={title}>
160
- {title}
161
- </div>
162
- {ownerEmail ? (
163
- <div className="mt-0.5 truncate text-xs text-muted-foreground">
164
- {t("shareUi.owner", { email: ownerEmail })}
165
- </div>
166
- ) : null}
150
+ <div className={cn("text-xs font-medium text-muted-foreground", className)}>
151
+ {children}
167
152
  </div>
168
153
  );
169
154
  }
@@ -197,9 +182,9 @@ export function GeneralAccessSelect({
197
182
 
198
183
  return (
199
184
  <div>
200
- <div className="mb-2 text-xs font-semibold">
185
+ <ShareSectionLabel className="mb-2">
201
186
  {t("shareUi.generalAccess")}
202
- </div>
187
+ </ShareSectionLabel>
203
188
  <div className="flex items-center gap-3">
204
189
  <span
205
190
  aria-hidden
@@ -245,9 +230,11 @@ export function GeneralAccessSelect({
245
230
  export function MakePublicCard({
246
231
  isPending,
247
232
  onMakePublic,
233
+ secondaryAction,
248
234
  }: {
249
235
  isPending: boolean;
250
236
  onMakePublic: () => void;
237
+ secondaryAction?: ReactNode;
251
238
  }) {
252
239
  const t = useT();
253
240
  return (
@@ -259,16 +246,21 @@ export function MakePublicCard({
259
246
  strokeWidth={1.8}
260
247
  className="text-muted-foreground"
261
248
  />
262
- <Button
263
- type="button"
264
- variant="outline"
265
- size="sm"
266
- className="h-7"
267
- onClick={onMakePublic}
268
- disabled={isPending}
269
- >
270
- {isPending ? t("shareUi.makingPublic") : t("shareUi.makePublicAndCopy")}
271
- </Button>
249
+ <div className="flex items-center gap-2">
250
+ {secondaryAction}
251
+ <Button
252
+ type="button"
253
+ variant="outline"
254
+ size="sm"
255
+ className="h-7"
256
+ onClick={onMakePublic}
257
+ disabled={isPending}
258
+ >
259
+ {isPending
260
+ ? t("shareUi.makingPublic")
261
+ : t("shareUi.makePublicAndCopy")}
262
+ </Button>
263
+ </div>
272
264
  </div>
273
265
  );
274
266
  }
@@ -297,9 +289,7 @@ export function CopyField({
297
289
  return (
298
290
  <div>
299
291
  {label ? (
300
- <div className="mb-1 text-xs font-medium text-muted-foreground">
301
- {label}
302
- </div>
292
+ <ShareSectionLabel className="mb-1">{label}</ShareSectionLabel>
303
293
  ) : null}
304
294
  <div className="flex items-stretch gap-2">
305
295
  <Input
@@ -704,7 +704,6 @@ export default function MeetingDetailRoute() {
704
704
  ) : null}
705
705
  <ShareMeetingPopover
706
706
  meetingId={meeting.id}
707
- meetingTitle={meeting.title}
708
707
  shareTranscript={meeting.shareTranscript === true}
709
708
  transcriptReady={
710
709
  meeting.transcriptStatus === "ready" &&