@agent-native/core 0.149.6 → 0.151.0

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 (177) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  3. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +83 -45
  4. package/corpus/templates/analytics/changelog/2026-08-11-analytics-dashboards-keep-the-selected-tab-when-reopened.md +6 -0
  5. package/corpus/templates/assets/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  6. package/corpus/templates/brain/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  7. package/corpus/templates/calendar/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  8. package/corpus/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  9. package/corpus/templates/clips/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  10. package/corpus/templates/clips/changelog/2026-08-11-clips-recovers-from-transient-updates-and-avoids-macos-priva.md +6 -0
  11. package/corpus/templates/clips/desktop/src/app.tsx +32 -176
  12. package/corpus/templates/clips/desktop/src/lib/updater.ts +52 -37
  13. package/corpus/templates/clips/desktop/src/styles.css +1 -166
  14. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +2 -0
  15. package/corpus/templates/clips/desktop/src-tauri/Info.plist +4 -0
  16. package/corpus/templates/clips/desktop/src-tauri/src/eventkit.rs +28 -1
  17. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
  18. package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +48 -1
  19. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +3 -0
  20. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +5 -0
  21. package/corpus/templates/clips/server/plugins/auth.ts +3 -0
  22. package/corpus/templates/content/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  23. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +2 -1
  24. package/corpus/templates/design/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  25. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -1
  26. package/corpus/templates/design/changelog/2026-08-11-design-agent-prompts-copy-successfully-in-the-desktop-app.md +6 -0
  27. package/corpus/templates/dispatch/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  28. package/corpus/templates/dispatch/app/global.css +2 -2
  29. package/corpus/templates/dispatch/changelog/2026-08-10-desktop-workspace-sign-in.md +6 -0
  30. package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-no-longer-shows-the-generic-chat-starter-among-defa.md +6 -0
  31. package/corpus/templates/dispatch/changelog/2026-08-11-integrations-and-scheduled-work-open-as-first-class-electron-pages.md +6 -0
  32. package/corpus/templates/dispatch/changelog/2026-08-11-sidebar-text-is-slightly-easier-to-read-in-light-and-dark-mo.md +6 -0
  33. package/corpus/templates/dispatch/server/lib/identity-sso.ts +57 -31
  34. package/corpus/templates/dispatch/server/plugins/feature-flags.ts +5 -0
  35. package/corpus/templates/dispatch/server/plugins/identity-sso.ts +82 -33
  36. package/corpus/templates/dispatch/server/plugins/org-apps-directory.ts +7 -15
  37. package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +9 -1
  38. package/corpus/templates/dispatch/shared/feature-flags.ts +15 -0
  39. package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  40. package/corpus/templates/forms/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  41. package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +8 -7
  42. package/corpus/templates/forms/app/hooks/use-forms.ts +8 -1
  43. package/corpus/templates/forms/changelog/2026-08-11-fixed-public-forms-so-conditional-questions-stay-hidden-unti.md +6 -0
  44. package/corpus/templates/forms/server/handlers/submissions.ts +2 -1
  45. package/corpus/templates/forms/server/lib/public-form-ssr.ts +37 -2
  46. package/corpus/templates/forms/shared/page-url.ts +54 -0
  47. package/corpus/templates/forms/shared/types.ts +4 -4
  48. package/corpus/templates/mail/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  49. package/corpus/templates/plan/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  50. package/corpus/templates/slides/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  51. package/corpus/templates/slides/actions/add-slide.ts +0 -27
  52. package/corpus/templates/slides/actions/import-file.ts +28 -9
  53. package/corpus/templates/slides/actions/view-screen.ts +4 -4
  54. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +8 -1
  55. package/corpus/templates/slides/app/components/editor/AiEditingMarker.tsx +25 -0
  56. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +43 -48
  57. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +9 -6
  58. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -9
  59. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +2 -0
  60. package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +0 -26
  61. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +904 -217
  62. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
  63. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +11 -0
  64. package/corpus/templates/slides/app/components/editor/inline-edit-session.ts +16 -0
  65. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +22 -6
  66. package/corpus/templates/slides/app/components/editor/style-clipboard.ts +61 -0
  67. package/corpus/templates/slides/app/components/layout/Layout.tsx +26 -2
  68. package/corpus/templates/slides/app/components/ui/context-menu.tsx +1 -0
  69. package/corpus/templates/slides/app/context/DeckContext.tsx +75 -25
  70. package/corpus/templates/slides/app/global.css +1 -1
  71. package/corpus/templates/slides/app/i18n/en-US.ts +6 -1
  72. package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -1
  73. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +12 -12
  74. package/corpus/templates/slides/app/lib/slide-agent-context.ts +52 -0
  75. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +61 -0
  76. package/corpus/templates/slides/app/pages/DeckEditor.tsx +55 -116
  77. package/corpus/templates/slides/app/pages/Index.tsx +28 -3
  78. package/corpus/templates/slides/changelog/2026-08-11-agent-chat-now-follows-the-current-slide-and-selection.md +6 -0
  79. package/corpus/templates/slides/changelog/2026-08-11-deck-titles-now-use-slide-content-instead-of-placeholder-filenames.md +6 -0
  80. package/corpus/templates/slides/changelog/2026-08-11-history-now-opens-from-the-deck-overflow-menu.md +6 -0
  81. package/corpus/templates/slides/changelog/2026-08-11-images-can-be-dropped-directly-onto-slides-and-resized-or-re.md +6 -0
  82. package/corpus/templates/slides/changelog/2026-08-11-new-decks-now-transition-directly-to-a-full-page-editor-load.md +6 -0
  83. package/corpus/templates/slides/changelog/2026-08-11-selected-slide-layers-can-be-nudged-precisely-with-arrow-key.md +6 -0
  84. package/corpus/templates/slides/changelog/2026-08-11-slides-can-copy-and-paste-element-styles-with-cmd-option-c-v.md +6 -0
  85. package/corpus/templates/slides/changelog/2026-08-11-slides-shows-one-compact-ai-marker-and-keeps-your-current-sl.md +6 -0
  86. package/corpus/templates/slides/changelog/2026-08-11-text-edits-preserve-slide-layout-when-no-changes-are-made.md +6 -0
  87. package/corpus/templates/slides/changelog/2026-08-11-the-style-toolbar-now-uses-the-full-available-width.md +6 -0
  88. package/corpus/templates/slides/changelog/2026-08-11-undo-and-redo-now-move-one-visible-slide-state-at-a-time.md +6 -0
  89. package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -2
  90. package/corpus/templates/slides/shared/deck-title.ts +56 -0
  91. package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  92. package/dist/agent/run-store.js +6 -1
  93. package/dist/agent/thread-data-builder.js +19 -44
  94. package/dist/agent/types.d.ts +13 -0
  95. package/dist/catalog.json +1 -0
  96. package/dist/cli/create.js +1 -1
  97. package/dist/client/AssistantChat.js +58 -10
  98. package/dist/client/FileStorageSetupCard.d.ts +6 -0
  99. package/dist/client/FileStorageSetupCard.js +18 -0
  100. package/dist/client/NewWorkspaceAppFlow.js +10 -0
  101. package/dist/client/agent-chat-adapter.js +87 -11
  102. package/dist/client/agent-chat.d.ts +1 -1
  103. package/dist/client/agent-chat.js +8 -3
  104. package/dist/client/chat/attachment-adapters.js +10 -0
  105. package/dist/client/chat/message-components.d.ts +4 -1
  106. package/dist/client/chat/message-components.js +37 -13
  107. package/dist/client/chat/tool-call-display.js +14 -0
  108. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  109. package/dist/client/chat-first/apps-rail.js +6 -6
  110. package/dist/client/chat-first/copy.js +1 -0
  111. package/dist/client/chat-first/types.d.ts +1 -0
  112. package/dist/client/extensions/EmbeddedExtension.js +1 -1
  113. package/dist/client/extensions/ExtensionViewer.js +1 -1
  114. package/dist/client/extensions/InlineExtensionFrame.js +1 -1
  115. package/dist/client/onboarding/FirstRunOnboarding.js +17 -2
  116. package/dist/client/settings/FileStorageSettingsForm.d.ts +2 -0
  117. package/dist/client/settings/FileStorageSettingsForm.js +113 -0
  118. package/dist/client/settings/SettingsPanel.js +2 -1
  119. package/dist/client/sse-event-processor.js +21 -0
  120. package/dist/collab/awareness.d.ts +2 -2
  121. package/dist/collab/struct-routes.d.ts +1 -1
  122. package/dist/extensions/actions.js +2 -2
  123. package/dist/extensions/html-shell.js +3 -1
  124. package/dist/file-upload/pre-upload-attachments.d.ts +15 -10
  125. package/dist/file-upload/pre-upload-attachments.js +68 -24
  126. package/dist/file-upload/registry.d.ts +4 -5
  127. package/dist/file-upload/registry.js +7 -14
  128. package/dist/file-upload/s3.d.ts +9 -0
  129. package/dist/file-upload/s3.js +168 -0
  130. package/dist/file-upload/types.d.ts +3 -3
  131. package/dist/file-upload/types.js +2 -2
  132. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  133. package/dist/notifications/routes.d.ts +6 -6
  134. package/dist/observability/routes.d.ts +3 -3
  135. package/dist/onboarding/app-profile.js +23 -1
  136. package/dist/onboarding/default-steps.js +69 -0
  137. package/dist/onboarding/types.d.ts +2 -0
  138. package/dist/progress/routes.d.ts +1 -1
  139. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  140. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  141. package/dist/secrets/routes.d.ts +3 -3
  142. package/dist/server/agent-chat/browser-team-tools.js +20 -0
  143. package/dist/server/agent-chat-plugin.js +12 -3
  144. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  145. package/dist/server/auth.js +45 -21
  146. package/dist/server/better-auth-instance.d.ts +2 -0
  147. package/dist/server/better-auth-instance.js +2 -2
  148. package/dist/server/core-routes-plugin.d.ts +1 -0
  149. package/dist/server/core-routes-plugin.js +26 -16
  150. package/dist/server/identity-sso-store.d.ts +3 -0
  151. package/dist/server/identity-sso-store.js +45 -0
  152. package/dist/server/identity-sso.d.ts +20 -10
  153. package/dist/server/identity-sso.js +79 -31
  154. package/dist/server/index.d.ts +1 -1
  155. package/dist/server/index.js +1 -1
  156. package/dist/server/realtime-token.d.ts +1 -1
  157. package/dist/server/transcribe-voice.d.ts +1 -1
  158. package/dist/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  159. package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  160. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
  161. package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  162. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
  163. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
  164. package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
  165. package/docs/content/authentication.mdx +27 -0
  166. package/docs/content/cross-app-sso.mdx +38 -8
  167. package/docs/content/extensions.mdx +15 -15
  168. package/docs/content/file-uploads.mdx +10 -12
  169. package/docs/content/generative-ui.mdx +6 -1
  170. package/package.json +2 -2
  171. package/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  172. package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  173. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
  174. package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  175. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
  176. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
  177. package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -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: 8044
34
+ - template files: 8070
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -1,4 +1,5 @@
1
1
  import { useAgentRouteState } from "@agent-native/core/client/navigation";
2
+ import { useLocation } from "react-router";
2
3
 
3
4
  import { rememberLastOpened } from "@/lib/last-opened";
4
5
  import { TAB_ID } from "@/lib/tab-id";
@@ -19,8 +20,11 @@ interface NavigationState {
19
20
  }
20
21
 
21
22
  const SESSION_FILTER_KEYS = ["range", "app", "q"] as const;
23
+ const DASHBOARD_PATH_RE = /^\/(?:adhoc|dashboards)\/([^/]+)\/?$/;
22
24
 
23
25
  export function useNavigationState() {
26
+ const location = useLocation();
27
+
24
28
  useAgentRouteState<NavigationState>({
25
29
  browserTabId: TAB_ID,
26
30
  getNavigationState: ({ pathname, searchParams }) => {
@@ -107,54 +111,88 @@ export function useNavigationState() {
107
111
 
108
112
  return state;
109
113
  },
110
- getCommandPath: (cmd) => {
111
- if (cmd.view === "adhoc" && cmd.dashboardId)
112
- return `/dashboards/${cmd.dashboardId}`;
113
- if (cmd.view === "analyses" && cmd.analysisId)
114
- return `/analyses/${cmd.analysisId}`;
115
- if (cmd.view === "analyses") return "/dashboards";
116
- if (cmd.view === "extensions" && cmd.extensionId)
117
- return `/extensions/${cmd.extensionId}`;
118
- if (cmd.view === "extensions") return "/settings/extensions";
119
- if (cmd.view === "sessions" && cmd.recordingId)
120
- return `/sessions/${encodeURIComponent(cmd.recordingId)}`;
121
- if (cmd.view === "sessions") return "/sessions";
122
- if (
123
- cmd.view === "agents" &&
124
- (cmd.agentsView === "database" ||
125
- cmd.agentsView === "dashboards" ||
126
- cmd.agentsView === "flags")
127
- ) {
128
- const params = new URLSearchParams({ view: cmd.agentsView });
129
- if (cmd.agentsView === "database" && cmd.dbAdminConnectionId) {
130
- params.set("db", cmd.dbAdminConnectionId);
131
- }
132
- return `/agents?${params.toString()}`;
133
- }
134
- if (cmd.view === "agents") return "/agents";
135
- if (cmd.view === "monitoring") {
136
- const params = new URLSearchParams();
137
- if (cmd.monitoringView === "errors") {
138
- params.set("view", "errors");
139
- if (cmd.errorIssueId) params.set("issue", cmd.errorIssueId);
140
- } else if (cmd.statusPageId) {
141
- params.set("statuspage", cmd.statusPageId);
142
- } else if (cmd.monitorId) {
143
- params.set("monitor", cmd.monitorId);
144
- }
145
- const qs = params.toString();
146
- return qs ? `/monitoring?${qs}` : "/monitoring";
147
- }
148
- if (cmd.view === "data-sources") return "/data-sources";
149
- if (cmd.view === "data-dictionary") return "/data-dictionary";
150
- if (cmd.view === "ask") return "/ask";
151
- if (cmd.view === "settings") return "/settings";
152
- if (cmd.view === "overview" || cmd.view === "home") return "/ask";
153
- return "/";
154
- },
114
+ getCommandPath: (cmd) =>
115
+ preserveActiveDashboardTab(
116
+ commandPathForNavigation(cmd),
117
+ location.pathname,
118
+ location.search,
119
+ ),
155
120
  });
156
121
  }
157
122
 
123
+ function commandPathForNavigation(cmd: NavigationState): string {
124
+ if (cmd.view === "adhoc" && cmd.dashboardId)
125
+ return `/dashboards/${cmd.dashboardId}`;
126
+ if (cmd.view === "analyses" && cmd.analysisId)
127
+ return `/analyses/${cmd.analysisId}`;
128
+ if (cmd.view === "analyses") return "/dashboards";
129
+ if (cmd.view === "extensions" && cmd.extensionId)
130
+ return `/extensions/${cmd.extensionId}`;
131
+ if (cmd.view === "extensions") return "/settings/extensions";
132
+ if (cmd.view === "sessions" && cmd.recordingId)
133
+ return `/sessions/${encodeURIComponent(cmd.recordingId)}`;
134
+ if (cmd.view === "sessions") return "/sessions";
135
+ if (
136
+ cmd.view === "agents" &&
137
+ (cmd.agentsView === "database" ||
138
+ cmd.agentsView === "dashboards" ||
139
+ cmd.agentsView === "flags")
140
+ ) {
141
+ const params = new URLSearchParams({ view: cmd.agentsView });
142
+ if (cmd.agentsView === "database" && cmd.dbAdminConnectionId) {
143
+ params.set("db", cmd.dbAdminConnectionId);
144
+ }
145
+ return `/agents?${params.toString()}`;
146
+ }
147
+ if (cmd.view === "agents") return "/agents";
148
+ if (cmd.view === "monitoring") {
149
+ const params = new URLSearchParams();
150
+ if (cmd.monitoringView === "errors") {
151
+ params.set("view", "errors");
152
+ if (cmd.errorIssueId) params.set("issue", cmd.errorIssueId);
153
+ } else if (cmd.statusPageId) {
154
+ params.set("statuspage", cmd.statusPageId);
155
+ } else if (cmd.monitorId) {
156
+ params.set("monitor", cmd.monitorId);
157
+ }
158
+ const qs = params.toString();
159
+ return qs ? `/monitoring?${qs}` : "/monitoring";
160
+ }
161
+ if (cmd.view === "data-sources") return "/data-sources";
162
+ if (cmd.view === "data-dictionary") return "/data-dictionary";
163
+ if (cmd.view === "ask") return "/ask";
164
+ if (cmd.view === "settings") return "/settings";
165
+ if (cmd.view === "overview" || cmd.view === "home") return "/ask";
166
+ return "/";
167
+ }
168
+
169
+ export function preserveActiveDashboardTab(
170
+ targetPath: string,
171
+ currentPathname: string,
172
+ currentSearch: string,
173
+ ): string {
174
+ const targetUrl = new URL(targetPath, "https://analytics.local");
175
+ if (targetUrl.search || targetUrl.hash) return targetPath;
176
+
177
+ const targetDashboardId = dashboardIdFromPath(targetUrl.pathname);
178
+ const currentDashboardId = dashboardIdFromPath(currentPathname);
179
+ if (!targetDashboardId || targetDashboardId !== currentDashboardId) {
180
+ return targetPath;
181
+ }
182
+
183
+ const activeTab = new URLSearchParams(currentSearch).get("tab");
184
+ if (!activeTab) return targetPath;
185
+
186
+ // Agent navigation identifies the dashboard, but the active tab is UI state
187
+ // held in the URL and is not part of the navigate action payload.
188
+ targetUrl.searchParams.set("tab", activeTab);
189
+ return `${targetUrl.pathname}${targetUrl.search}${targetUrl.hash}`;
190
+ }
191
+
192
+ function dashboardIdFromPath(pathname: string): string | undefined {
193
+ return pathname.match(DASHBOARD_PATH_RE)?.[1];
194
+ }
195
+
158
196
  function sessionFilters(
159
197
  searchParams?: URLSearchParams | Record<string, string>,
160
198
  ): Record<string, string> | undefined {
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-11
4
+ ---
5
+
6
+ Analytics dashboards keep the selected tab when reopened
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-11
4
+ ---
5
+
6
+ Clips recovers from transient updates and avoids macOS privacy crashes during restart.
@@ -2,8 +2,6 @@ import {
2
2
  IconAlertTriangle,
3
3
  IconArrowLeft,
4
4
  IconCalendarEvent,
5
- IconChevronDown,
6
- IconChevronRight,
7
5
  IconCircleCheck,
8
6
  IconCopy,
9
7
  IconDownload,
@@ -973,10 +971,6 @@ export function App() {
973
971
  const [rewindSettingsReturnView, setRewindSettingsReturnView] = useState<
974
972
  "recorder" | "settings"
975
973
  >("recorder");
976
- const [homeScreenMemoryStatus, setHomeScreenMemoryStatus] =
977
- useState<ScreenMemoryStatus | null>(null);
978
- const [homeScreenMemoryBusy, setHomeScreenMemoryBusy] = useState(false);
979
- const homeScreenMemoryRefreshVersionRef = useRef(0);
980
974
  const [rewindAgentPromptCopied, setRewindAgentPromptCopied] = useState(false);
981
975
  const [agentHandoff, setAgentHandoff] =
982
976
  useState<RewindAgentHandoffRequest | null>(null);
@@ -1002,7 +996,6 @@ export function App() {
1002
996
  const [readinessOpen, setReadinessOpen] = useState<boolean>(
1003
997
  () => !loadBool(READINESS_REVIEWED_KEY, false),
1004
998
  );
1005
- const [rewindHomeOpen, setRewindHomeOpen] = useState(false);
1006
999
  const [recorder, setRecorder] = useState<RecorderHandle | null>(null);
1007
1000
  const recordingStartAbortRef = useRef<AbortController | null>(null);
1008
1001
  const [recError, setRecError] = useState<string | null>(null);
@@ -1036,57 +1029,6 @@ export function App() {
1036
1029
  const isRecording = recorder !== null;
1037
1030
  // Whether the popover window is shown; driven by the visibility effect below.
1038
1031
  const [popoverVisible, setPopoverVisible] = useState(false);
1039
- const homeRewindPresentation = getRewindStatusPresentation({
1040
- status: homeScreenMemoryStatus,
1041
- config: featureConfig?.screenMemory ?? DEFAULT_SCREEN_MEMORY_CONFIG,
1042
- clipRecordingActive: isRecording || recordingFlowActive,
1043
- });
1044
- const homeRewindOn =
1045
- featureConfig?.screenMemory?.enabled === true &&
1046
- featureConfig.screenMemory.paused !== true;
1047
- const refreshHomeScreenMemoryStatus = useCallback(() => {
1048
- const version = ++homeScreenMemoryRefreshVersionRef.current;
1049
- invoke<ScreenMemoryStatus>("screen_memory_status")
1050
- .then((status) => {
1051
- if (version === homeScreenMemoryRefreshVersionRef.current) {
1052
- setHomeScreenMemoryStatus(status);
1053
- }
1054
- })
1055
- .catch(() => {});
1056
- }, []);
1057
- useEffect(() => {
1058
- if (featureConfig?.screenMemory?.enabled !== true) {
1059
- homeScreenMemoryRefreshVersionRef.current += 1;
1060
- setHomeScreenMemoryStatus(null);
1061
- return;
1062
- }
1063
- let cancelled = false;
1064
- const refresh = () => {
1065
- if (!cancelled) refreshHomeScreenMemoryStatus();
1066
- };
1067
- refresh();
1068
- const timer = window.setInterval(refresh, popoverVisible ? 5_000 : 30_000);
1069
- let unlisten: (() => void) | undefined;
1070
- listen("clips:screen-memory-changed", refresh)
1071
- .then((stopListening) => {
1072
- if (cancelled) {
1073
- stopListening();
1074
- return;
1075
- }
1076
- unlisten = stopListening;
1077
- })
1078
- .catch(() => {});
1079
- return () => {
1080
- cancelled = true;
1081
- homeScreenMemoryRefreshVersionRef.current += 1;
1082
- window.clearInterval(timer);
1083
- unlisten?.();
1084
- };
1085
- }, [
1086
- featureConfig?.screenMemory?.enabled,
1087
- popoverVisible,
1088
- refreshHomeScreenMemoryStatus,
1089
- ]);
1090
1032
  const recordShortcutHandlerRef = useRef<() => void>(() => {});
1091
1033
  const handleStartRecordingRef = useRef<
1092
1034
  (options?: {
@@ -3576,47 +3518,6 @@ export function App() {
3576
3518
  const showCameraRow = mode !== "screen"; // screen-only has no camera
3577
3519
  const showSourceRow = mode !== "camera"; // camera-only has no screen source
3578
3520
 
3579
- async function setHomeRewindRemembering(remembering: boolean) {
3580
- if (homeScreenMemoryBusy) return;
3581
- if (remembering && featureConfig?.screenMemory?.enabled !== true) {
3582
- setRewindSettingsReturnView("recorder");
3583
- setPromptRewindEnable(true);
3584
- setPopoverView("rewind-settings");
3585
- return;
3586
- }
3587
- setHomeScreenMemoryBusy(true);
3588
- try {
3589
- const current = await invoke<FeatureConfig>("get_feature_config");
3590
- await invoke("set_feature_config", {
3591
- config: {
3592
- ...current,
3593
- screenMemory: {
3594
- ...DEFAULT_SCREEN_MEMORY_CONFIG,
3595
- ...current.screenMemory,
3596
- // Once Rewind has been set up, the everyday Home switch is a
3597
- // pause/resume control. Full disable and capture permissions live
3598
- // in Rewind Settings, so an accidental Home click never tears
3599
- // down the configured memory system or asks for consent again.
3600
- enabled: true,
3601
- paused: !remembering,
3602
- },
3603
- },
3604
- });
3605
- // The native producer can take a moment to finish pausing. Do not keep
3606
- // the Home switch locked while that status request waits; the existing
3607
- // change event and bounded poll will reconcile it, and this best-effort
3608
- // refresh can do the same without blocking the next resume action.
3609
- refreshHomeScreenMemoryStatus();
3610
- } catch (err) {
3611
- console.error(
3612
- "[clips-tray] update Rewind remembering state failed:",
3613
- err,
3614
- );
3615
- } finally {
3616
- setHomeScreenMemoryBusy(false);
3617
- }
3618
- }
3619
-
3620
3521
  const pendingUploadBanner = recordingStopFinalizing ? (
3621
3522
  <FinalizingUploadBanner />
3622
3523
  ) : pendingUploads.length > 0 ? (
@@ -3831,6 +3732,9 @@ export function App() {
3831
3732
  setServerUrl(url.replace(/\/+$/, ""));
3832
3733
  setPopoverView("recorder");
3833
3734
  }}
3735
+ rewindAgentPromptCopied={rewindAgentPromptCopied}
3736
+ onCopyRewindAgentPrompt={copyRewindAgentPrompt}
3737
+ onOpenRewindDocs={openRewindDocs}
3834
3738
  onOpenRewind={() => setPopoverView("rewind-settings")}
3835
3739
  onOpenMemory={() => setPopoverView("memory")}
3836
3740
  onCancel={() => {
@@ -3877,6 +3781,9 @@ export function App() {
3877
3781
  setServerUrl(url.replace(/\/+$/, ""));
3878
3782
  setPopoverView("recorder");
3879
3783
  }}
3784
+ rewindAgentPromptCopied={rewindAgentPromptCopied}
3785
+ onCopyRewindAgentPrompt={copyRewindAgentPrompt}
3786
+ onOpenRewindDocs={openRewindDocs}
3880
3787
  onOpenRewind={() => {
3881
3788
  setPromptRewindEnable(false);
3882
3789
  setRewindSettingsReturnView("settings");
@@ -4093,83 +4000,6 @@ export function App() {
4093
4000
  onOpenChange={updateReadinessOpen}
4094
4001
  onOpenPermission={openPrivacySettings}
4095
4002
  />
4096
-
4097
- <section className="rewind-home-card" aria-label="Rewind">
4098
- <button
4099
- type="button"
4100
- className="rewind-home-summary"
4101
- aria-expanded={rewindHomeOpen}
4102
- onClick={() => setRewindHomeOpen((open) => !open)}
4103
- >
4104
- <span className="rewind-home-title">Rewind</span>
4105
- <span className="rewind-home-state">
4106
- {homeRewindOn ? "On" : "Off"}
4107
- {rewindHomeOpen ? (
4108
- <IconChevronDown size={11} stroke={2} />
4109
- ) : (
4110
- <IconChevronRight size={11} stroke={2} />
4111
- )}
4112
- </span>
4113
- </button>
4114
- {rewindHomeOpen ? (
4115
- <div className="rewind-home-details">
4116
- <p>{homeRewindPresentation.detail}</p>
4117
- <div className="rewind-home-detail-actions">
4118
- <button
4119
- type="button"
4120
- className="rewind-docs-link"
4121
- onClick={openRewindDocs}
4122
- >
4123
- Learn about Rewind
4124
- <IconExternalLink size={13} stroke={1.9} />
4125
- </button>
4126
- <div className="rewind-home-controls">
4127
- <Tooltip>
4128
- <TooltipTrigger asChild>
4129
- <button
4130
- type="button"
4131
- className="rewind-agent-prompt-copy"
4132
- onClick={() => void copyRewindAgentPrompt()}
4133
- aria-label={
4134
- rewindAgentPromptCopied
4135
- ? "Setup prompt copied — paste it into your agent once"
4136
- : "Copy setup prompt for your agent"
4137
- }
4138
- >
4139
- {rewindAgentPromptCopied ? (
4140
- <IconCircleCheck size={15} stroke={2} />
4141
- ) : (
4142
- <IconCopy size={15} stroke={1.9} />
4143
- )}
4144
- </button>
4145
- </TooltipTrigger>
4146
- <TooltipContent>
4147
- {rewindAgentPromptCopied
4148
- ? "Setup prompt copied"
4149
- : "Copy setup prompt for your agent"}
4150
- </TooltipContent>
4151
- </Tooltip>
4152
- <Switch
4153
- on={homeRewindOn}
4154
- disabled={
4155
- homeScreenMemoryBusy ||
4156
- isRecording ||
4157
- recordingFlowActive
4158
- }
4159
- onChange={(remembering) =>
4160
- void setHomeRewindRemembering(remembering)
4161
- }
4162
- label={
4163
- featureConfig?.screenMemory?.enabled === true
4164
- ? "Remember with Rewind"
4165
- : "Set up Rewind"
4166
- }
4167
- />
4168
- </div>
4169
- </div>
4170
- </div>
4171
- ) : null}
4172
- </section>
4173
4003
  </div>
4174
4004
 
4175
4005
  {!isRecording ? (
@@ -5445,6 +5275,9 @@ function Setup({
5445
5275
  onVoiceProviderChange,
5446
5276
  onVoiceInstructionsChange,
5447
5277
  onConnect,
5278
+ rewindAgentPromptCopied,
5279
+ onCopyRewindAgentPrompt,
5280
+ onOpenRewindDocs,
5448
5281
  onOpenRewind,
5449
5282
  onOpenMemory,
5450
5283
  onCancel,
@@ -5472,6 +5305,9 @@ function Setup({
5472
5305
  onVoiceProviderChange: (value: VoiceProvider) => void;
5473
5306
  onVoiceInstructionsChange: (value: string) => void;
5474
5307
  onConnect: (url: string) => void;
5308
+ rewindAgentPromptCopied: boolean;
5309
+ onCopyRewindAgentPrompt: () => void;
5310
+ onOpenRewindDocs: () => void;
5475
5311
  onOpenRewind?: () => void;
5476
5312
  onOpenMemory?: () => void;
5477
5313
  onCancel?: () => void;
@@ -6669,6 +6505,26 @@ function Setup({
6669
6505
  Rewind's reusable instructions and repairs the local
6670
6506
  connection, so later you can simply say “Look at Rewind.”
6671
6507
  </p>
6508
+ <div className="setup-button-row">
6509
+ <button
6510
+ type="button"
6511
+ className="secondary"
6512
+ onClick={onCopyRewindAgentPrompt}
6513
+ >
6514
+ <IconCopy size={14} stroke={1.9} />
6515
+ {rewindAgentPromptCopied
6516
+ ? "Setup prompt copied"
6517
+ : "Copy setup prompt"}
6518
+ </button>
6519
+ <button
6520
+ type="button"
6521
+ className="secondary"
6522
+ onClick={onOpenRewindDocs}
6523
+ >
6524
+ <IconExternalLink size={14} stroke={1.9} />
6525
+ Learn about Rewind
6526
+ </button>
6527
+ </div>
6672
6528
  </div>
6673
6529
  </div>
6674
6530
  <details className="setup-advanced rewind-agent-repair">