@agent-native/core 0.114.5 → 0.114.7

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 (210) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +14 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/cli/mcp-config-writers.ts +6 -4
  5. package/corpus/core/src/cli/mcp.ts +124 -0
  6. package/corpus/core/src/cli/skills-content/help.ts +4 -3
  7. package/corpus/core/src/cli/skills-content/index.ts +1 -0
  8. package/corpus/core/src/cli/skills-content/rewind-skill.ts +52 -0
  9. package/corpus/core/src/cli/skills.ts +115 -13
  10. package/corpus/core/src/client/resources/ResourceTree.tsx +11 -5
  11. package/corpus/core/src/client/resources/ResourcesPanel.tsx +141 -18
  12. package/corpus/core/src/mcp/screen-memory-stdio.ts +1360 -104
  13. package/corpus/core/src/mcp-client/index.ts +9 -0
  14. package/corpus/core/src/mcp-client/screen-memory-local.ts +847 -13
  15. package/corpus/templates/clips/actions/apply-rewind-extension.ts +195 -0
  16. package/corpus/templates/clips/actions/delete-agent-recording-if-unpromoted.ts +64 -0
  17. package/corpus/templates/clips/actions/get-rewind-extension-request.ts +22 -0
  18. package/corpus/templates/clips/actions/get-screen-memory-status.ts +18 -2
  19. package/corpus/templates/clips/actions/list-rewind-extension-requests.ts +52 -0
  20. package/corpus/templates/clips/actions/make-recording-private-for-rewind.ts +55 -0
  21. package/corpus/templates/clips/actions/query-screen-memory-context.ts +4 -4
  22. package/corpus/templates/clips/actions/request-rewind-extension.ts +81 -0
  23. package/corpus/templates/clips/actions/update-rewind-extension-request.ts +47 -0
  24. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +25 -0
  25. package/corpus/templates/clips/app/components/editor/editor-toolbar.tsx +36 -0
  26. package/corpus/templates/clips/app/components/editor/rewind-extension-dialog.tsx +338 -0
  27. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +1 -16
  28. package/corpus/templates/clips/app/components/editor/timeline.tsx +26 -0
  29. package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +1 -2
  30. package/corpus/templates/clips/app/i18n/en-US.ts +18 -0
  31. package/corpus/templates/clips/app/lib/ffmpeg-export.ts +19 -12
  32. package/corpus/templates/clips/app/lib/rewind-visibility.ts +31 -0
  33. package/corpus/templates/clips/app/lib/timestamp-mapping.ts +7 -0
  34. package/corpus/templates/clips/app/lib/upload-file-client.ts +17 -0
  35. package/corpus/templates/clips/changelog/2026-07-14-rewind-keeps-recent-screen-context-local-and-turns-it-into-clips.md +6 -0
  36. package/corpus/templates/clips/changelog/2026-07-17-active-clips-keep-rewind-stable-and-settings-clear.md +12 -0
  37. package/corpus/templates/clips/changelog/2026-07-17-clicking-the-clips-icon-during-a-recording-now-opens-the-app.md +6 -0
  38. package/corpus/templates/clips/changelog/2026-07-17-default-mic-now-uses-the-mac-default-and-transcription-shares-one-capture.md +6 -0
  39. package/corpus/templates/clips/changelog/2026-07-17-full-screen-clips-finalize-even-when-screencapturekit-stop-hangs.md +6 -0
  40. package/corpus/templates/clips/changelog/2026-07-17-normal-full-screen-clips-no-longer-stop-immediately-after-th.md +6 -0
  41. package/corpus/templates/clips/changelog/2026-07-17-rewind-can-hand-one-bounded-private-clip-to-your-agent.md +12 -0
  42. package/corpus/templates/clips/changelog/2026-07-17-rewind-home-can-copy-a-local-agent-prompt.md +6 -0
  43. package/corpus/templates/clips/changelog/2026-07-17-rewind-now-has-a-calm-home-status-focused-first-run-consent-.md +6 -0
  44. package/corpus/templates/clips/changelog/2026-07-17-rewind-settings-are-smaller-clearer-and-agent-first.md +6 -0
  45. package/corpus/templates/clips/changelog/2026-07-17-the-full-clips-interface-stays-available-while-recording.md +6 -0
  46. package/corpus/templates/clips/changelog/2026-07-18-rewind-organizes-recent-work-into-local-searchable-chapters.md +8 -0
  47. package/corpus/templates/clips/changelog/2026-07-18-searchable-rewind-chapters.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-07-19-rewind-backed-recordings-now-start-immediately-after-the-cou.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-07-20-opening-zoom-meeting-launches-native-app.md +6 -0
  50. package/corpus/templates/clips/changelog/2026-07-20-rewind-can-set-up-your-local-agent-once-so-future-requests-w.md +6 -0
  51. package/corpus/templates/clips/desktop/package.json +1 -0
  52. package/corpus/templates/clips/desktop/scripts/sign-macos-local.ts +12 -1
  53. package/corpus/templates/clips/desktop/src/app.tsx +2478 -223
  54. package/corpus/templates/clips/desktop/src/components/ReadinessPanel.tsx +21 -1
  55. package/corpus/templates/clips/desktop/src/components/Switch.tsx +3 -0
  56. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +156 -24
  57. package/corpus/templates/clips/desktop/src/lib/native-recording-warm.ts +6 -7
  58. package/corpus/templates/clips/desktop/src/lib/open-meeting-join-url.ts +22 -0
  59. package/corpus/templates/clips/desktop/src/lib/recorder.ts +1763 -1160
  60. package/corpus/templates/clips/desktop/src/lib/rewind-agent-prompt.ts +9 -0
  61. package/corpus/templates/clips/desktop/src/lib/rewind-recording-start.ts +20 -0
  62. package/corpus/templates/clips/desktop/src/main.tsx +3 -0
  63. package/corpus/templates/clips/desktop/src/overlays/countdown.tsx +14 -14
  64. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +2 -3
  65. package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +4 -4
  66. package/corpus/templates/clips/desktop/src/overlays/preparing.tsx +13 -0
  67. package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +27 -2
  68. package/corpus/templates/clips/desktop/src/shared/config.ts +16 -0
  69. package/corpus/templates/clips/desktop/src/styles.css +956 -134
  70. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +5 -0
  71. package/corpus/templates/clips/desktop/src-tauri/build.rs +69 -1
  72. package/corpus/templates/clips/desktop/src-tauri/src/accessibility.rs +386 -12
  73. package/corpus/templates/clips/desktop/src-tauri/src/capture_audio_bus.rs +382 -0
  74. package/corpus/templates/clips/desktop/src-tauri/src/capture_graph.rs +777 -0
  75. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +249 -22
  76. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +148 -1
  77. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +58 -4
  78. package/corpus/templates/clips/desktop/src-tauri/src/logfile.rs +13 -1
  79. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +1505 -51
  80. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +124 -0
  81. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1006 -95
  82. package/corpus/templates/clips/desktop/src-tauri/src/rewind_capture_suspension.rs +165 -0
  83. package/corpus/templates/clips/desktop/src-tauri/src/rewind_chapters.rs +2434 -0
  84. package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +1650 -0
  85. package/corpus/templates/clips/desktop/src-tauri/src/rewind_egress.rs +643 -0
  86. package/corpus/templates/clips/desktop/src-tauri/src/rewind_local_ask.rs +803 -0
  87. package/corpus/templates/clips/desktop/src-tauri/src/rewind_meeting_history.rs +595 -0
  88. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +2900 -91
  89. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory_ocr.rs +360 -0
  90. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory_transcript.rs +408 -0
  91. package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +114 -33
  92. package/corpus/templates/clips/desktop/src-tauri/src/state.rs +2 -2
  93. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +13 -3
  94. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +4 -1
  95. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +7 -13
  96. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +198 -11
  97. package/corpus/templates/clips/desktop/src-tauri/tauri.alpha.conf.json +17 -0
  98. package/corpus/templates/clips/shared/meeting-join-url.ts +0 -5
  99. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +9 -1
  100. package/corpus/templates/content/AGENTS.md +4 -1
  101. package/corpus/templates/content/actions/_content-spaces.ts +6 -1
  102. package/corpus/templates/content/actions/_database-row-batch.ts +15 -2
  103. package/corpus/templates/content/actions/_database-utils.ts +83 -15
  104. package/corpus/templates/content/actions/add-database-item.ts +3 -0
  105. package/corpus/templates/content/actions/connect-local-folder-source.ts +2 -1
  106. package/corpus/templates/content/actions/delete-content-database.ts +12 -9
  107. package/corpus/templates/content/actions/delete-database-items.ts +3 -2
  108. package/corpus/templates/content/actions/delete-document.ts +233 -6
  109. package/corpus/templates/content/actions/duplicate-database-item.ts +1 -0
  110. package/corpus/templates/content/actions/get-document.ts +4 -1
  111. package/corpus/templates/content/actions/list-content-databases.ts +1 -0
  112. package/corpus/templates/content/actions/list-documents.ts +1 -0
  113. package/corpus/templates/content/actions/list-trashed-content-databases.ts +8 -2
  114. package/corpus/templates/content/actions/list-trashed-documents.ts +50 -0
  115. package/corpus/templates/content/actions/permanently-delete-document.ts +28 -0
  116. package/corpus/templates/content/actions/pull-document.ts +15 -2
  117. package/corpus/templates/content/actions/restore-content-database.ts +48 -11
  118. package/corpus/templates/content/actions/restore-document.ts +28 -0
  119. package/corpus/templates/content/actions/search-documents.ts +2 -1
  120. package/corpus/templates/content/actions/view-screen.ts +2 -1
  121. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +149 -55
  122. package/corpus/templates/content/app/components/editor/database/GalleryView.tsx +7 -2
  123. package/corpus/templates/content/app/components/editor/database/ListView.tsx +7 -2
  124. package/corpus/templates/content/app/components/editor/database/TimelineView.tsx +3 -0
  125. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +26 -5
  126. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +243 -163
  127. package/corpus/templates/content/app/components/sidebar/WorkspaceSourceMenu.tsx +154 -0
  128. package/corpus/templates/content/app/components/sidebar/select-content-space.ts +11 -0
  129. package/corpus/templates/content/app/hooks/use-content-database.ts +6 -0
  130. package/corpus/templates/content/app/hooks/use-documents.ts +57 -0
  131. package/corpus/templates/content/app/i18n-data.ts +83 -2
  132. package/corpus/templates/content/app/routes/_app.local-files.tsx +8 -1
  133. package/corpus/templates/content/changelog/2026-07-19-pages-now-move-to-a-reversible-trash-and-the-organization-pi.md +6 -0
  134. package/corpus/templates/content/changelog/2026-07-20-trash-actions-now-preserve-independent-archived-pages-enforc.md +6 -0
  135. package/corpus/templates/content/changelog/2026-07-20-workspace-toggles-now-stay-independently-open-or-closed-and-.md +6 -0
  136. package/corpus/templates/content/changelog/2026-07-20-workspaces-can-be-added-from-a-blank-workspace-or-a-connecte.md +6 -0
  137. package/corpus/templates/content/parity/matrix.md +1 -1
  138. package/corpus/templates/content/parity/matrix.ts +3 -0
  139. package/corpus/templates/content/server/db/schema.ts +2 -0
  140. package/corpus/templates/content/server/lib/public-documents.ts +8 -2
  141. package/corpus/templates/content/server/plugins/db.ts +52 -0
  142. package/corpus/templates/content/server/routes/api/document-agent-context.json.get.ts +2 -2
  143. package/corpus/templates/content/shared/api.ts +10 -0
  144. package/corpus/toolkit/CHANGELOG.md +6 -0
  145. package/corpus/toolkit/package.json +1 -1
  146. package/corpus/toolkit/src/ui/progress.tsx +3 -2
  147. package/dist/cli/mcp-config-writers.d.ts +2 -2
  148. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  149. package/dist/cli/mcp-config-writers.js +6 -6
  150. package/dist/cli/mcp-config-writers.js.map +1 -1
  151. package/dist/cli/mcp.d.ts +14 -0
  152. package/dist/cli/mcp.d.ts.map +1 -1
  153. package/dist/cli/mcp.js +79 -0
  154. package/dist/cli/mcp.js.map +1 -1
  155. package/dist/cli/skills-content/help.d.ts +1 -1
  156. package/dist/cli/skills-content/help.d.ts.map +1 -1
  157. package/dist/cli/skills-content/help.js +4 -3
  158. package/dist/cli/skills-content/help.js.map +1 -1
  159. package/dist/cli/skills-content/index.d.ts +1 -0
  160. package/dist/cli/skills-content/index.d.ts.map +1 -1
  161. package/dist/cli/skills-content/index.js +1 -0
  162. package/dist/cli/skills-content/index.js.map +1 -1
  163. package/dist/cli/skills-content/rewind-skill.d.ts +2 -0
  164. package/dist/cli/skills-content/rewind-skill.d.ts.map +1 -0
  165. package/dist/cli/skills-content/rewind-skill.js +53 -0
  166. package/dist/cli/skills-content/rewind-skill.js.map +1 -0
  167. package/dist/cli/skills.d.ts +6 -0
  168. package/dist/cli/skills.d.ts.map +1 -1
  169. package/dist/cli/skills.js +90 -14
  170. package/dist/cli/skills.js.map +1 -1
  171. package/dist/client/resources/ResourceTree.d.ts +3 -1
  172. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  173. package/dist/client/resources/ResourceTree.js +4 -4
  174. package/dist/client/resources/ResourceTree.js.map +1 -1
  175. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  176. package/dist/client/resources/ResourcesPanel.js +55 -6
  177. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  178. package/dist/collab/routes.d.ts +1 -1
  179. package/dist/collab/struct-routes.d.ts +1 -1
  180. package/dist/mcp/screen-memory-stdio.d.ts +365 -0
  181. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
  182. package/dist/mcp/screen-memory-stdio.js +1014 -91
  183. package/dist/mcp/screen-memory-stdio.js.map +1 -1
  184. package/dist/mcp-client/index.d.ts +1 -1
  185. package/dist/mcp-client/index.d.ts.map +1 -1
  186. package/dist/mcp-client/index.js +1 -1
  187. package/dist/mcp-client/index.js.map +1 -1
  188. package/dist/mcp-client/screen-memory-local.d.ts +90 -0
  189. package/dist/mcp-client/screen-memory-local.d.ts.map +1 -1
  190. package/dist/mcp-client/screen-memory-local.js +590 -12
  191. package/dist/mcp-client/screen-memory-local.js.map +1 -1
  192. package/dist/notifications/routes.d.ts +2 -2
  193. package/dist/observability/routes.d.ts +5 -5
  194. package/dist/progress/routes.d.ts +1 -1
  195. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  196. package/dist/resources/handlers.d.ts +1 -1
  197. package/dist/secrets/routes.d.ts +9 -9
  198. package/dist/server/transcribe-voice.d.ts +1 -1
  199. package/package.json +2 -2
  200. package/src/cli/mcp-config-writers.ts +6 -4
  201. package/src/cli/mcp.ts +124 -0
  202. package/src/cli/skills-content/help.ts +4 -3
  203. package/src/cli/skills-content/index.ts +1 -0
  204. package/src/cli/skills-content/rewind-skill.ts +52 -0
  205. package/src/cli/skills.ts +115 -13
  206. package/src/client/resources/ResourceTree.tsx +11 -5
  207. package/src/client/resources/ResourcesPanel.tsx +141 -18
  208. package/src/mcp/screen-memory-stdio.ts +1360 -104
  209. package/src/mcp-client/index.ts +9 -0
  210. package/src/mcp-client/screen-memory-local.ts +847 -13
@@ -15,10 +15,10 @@ const POPOVER_DEFAULT_HEIGHT_LOGICAL: f64 = 520.0;
15
15
  //
16
16
  // Clips-owned recording chrome (toolbar / countdown / finalizing /
17
17
  // recording-pill) gets `NSWindow.sharingType = NSWindowSharingNone` so it does
18
- // not leak into the recorded video. The main popover is different: users expect
19
- // to screenshot it for feedback, so it stays shareable during normal idle /
20
- // settings use and is flipped to NSWindowSharingNone only while it is parked as
21
- // the hidden recording controller.
18
+ // not leak into the recorded video. The main popover follows the same user
19
+ // preference: private by default, shareable only when "Show Clips in screen
20
+ // captures" is enabled. Reopening it during a recording must not silently
21
+ // override that choice.
22
22
  // Recording-time exclusion has two effects on macOS: screen pickers don't list
23
23
  // excluded windows, and full-screen captures omit them from the compositor
24
24
  // output. This is the same mechanism Loom, 1Password, and CleanShot use to keep
@@ -183,12 +183,9 @@ pub fn set_capture_included(_window: &WebviewWindow) {
183
183
  /// immediately on anything currently on screen. Called from
184
184
  /// `set_feature_config` when the toggle flips.
185
185
  ///
186
- /// The popover is intentionally skipped its sharing-type is dynamic
187
- /// (`set_capture_included` while shown, `set_capture_excluded` while
188
- /// parked at 2x2 px during recording). Both of those helpers now consult
189
- /// the toggle, so the next `show_popover` / `park_popover_offscreen` call
190
- /// picks up the new setting. Rewriting it here would clobber the parked
191
- /// state mid-recording.
186
+ /// The popover follows the same preference as ordinary Clips chrome. Applying
187
+ /// it here makes the toggle take effect immediately whether the popover is
188
+ /// visible or parked as the 2x2 recording controller.
192
189
  ///
193
190
  /// Region-guide overlays are private recorder aids, not Clips chrome demos, so
194
191
  /// they stay excluded even when the debug toggle makes the rest visible.
@@ -198,9 +195,6 @@ pub fn reapply_capture_exclusion_to_overlays(app: &tauri::AppHandle) {
198
195
  let visible = crate::config::show_in_screen_capture(app);
199
196
  let windows = app.webview_windows();
200
197
  for (label, window) in &windows {
201
- if label.as_str() == "popover" {
202
- continue;
203
- }
204
198
  // The meeting reminder is a notification, not Clips recording
205
199
  // chrome — keep it visible in captures regardless of the debug
206
200
  // toggle so it never gets re-excluded on a config change.
@@ -16,6 +16,36 @@
16
16
  //!
17
17
  use tauri::AppHandle;
18
18
 
19
+ /// One timestamped segment produced by bounded, offline-file transcription.
20
+ /// Timestamps are relative to the supplied audio, never to wall-clock time.
21
+ #[derive(Debug, Clone, PartialEq, Eq)]
22
+ pub(crate) struct OfflineTranscriptSegment {
23
+ pub start_ms: i64,
24
+ pub end_ms: i64,
25
+ pub text: String,
26
+ }
27
+
28
+ /// Transcribe already-decoded 16 kHz mono samples with the process-wide
29
+ /// Whisper context. This is the reusable file-transcription entry point: the
30
+ /// caller owns container decoding and the samples are never persisted here.
31
+ ///
32
+ /// Blocking work -- call from a dedicated worker thread, not the async runtime.
33
+ pub(crate) fn transcribe_offline_file_samples(
34
+ app: &AppHandle,
35
+ samples: &[f32],
36
+ language: Option<&str>,
37
+ ) -> Result<Vec<OfflineTranscriptSegment>, String> {
38
+ #[cfg(target_os = "macos")]
39
+ {
40
+ macos::transcribe_offline_file_samples(app, samples, language)
41
+ }
42
+ #[cfg(not(target_os = "macos"))]
43
+ {
44
+ let _ = (app, samples, language);
45
+ Err("local Whisper file transcription is supported on macOS only".to_owned())
46
+ }
47
+ }
48
+
19
49
  #[tauri::command]
20
50
  pub async fn whisper_transcription_start(
21
51
  app: AppHandle,
@@ -112,6 +142,9 @@ mod macos {
112
142
  use tauri::{AppHandle, Emitter};
113
143
  use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};
114
144
 
145
+ use crate::capture_audio_bus::{
146
+ try_subscribe, AudioSources, AudioSubscription, SubscriptionAttempt,
147
+ };
115
148
  use crate::native_speech::macos::{
116
149
  start_raw_mic_capture, MicVoiceProcessingMode, RawMicCapture,
117
150
  };
@@ -121,6 +154,8 @@ mod macos {
121
154
  };
122
155
  use crate::whisper_model::{ensure_model, model_file};
123
156
 
157
+ const MEETING_AUDIO_OWNER: &str = "meeting-whisper";
158
+
124
159
  /// One transcript segment with real timestamps from whisper, already
125
160
  /// offset onto the meeting timeline (ms since capture start).
126
161
  #[derive(Serialize, Clone)]
@@ -185,6 +220,31 @@ mod macos {
185
220
  Ok(())
186
221
  }
187
222
 
223
+ pub(super) fn transcribe_offline_file_samples(
224
+ app: &AppHandle,
225
+ samples: &[f32],
226
+ language: Option<&str>,
227
+ ) -> Result<Vec<super::OfflineTranscriptSegment>, String> {
228
+ const CHUNK_SAMPLES: usize = 25 * 16_000;
229
+
230
+ let ctx = context(app)?;
231
+ let mut state = ctx
232
+ .create_state()
233
+ .map_err(|e| format!("whisper state init failed: {e}"))?;
234
+ let mut segments = Vec::new();
235
+ for (chunk_index, chunk) in samples.chunks(CHUNK_SAMPLES).enumerate() {
236
+ let chunk_offset_ms = chunk_index as i64 * 25_000;
237
+ segments.extend(infer(&mut state, chunk, language).into_iter().map(
238
+ |(start_ms, end_ms, text)| super::OfflineTranscriptSegment {
239
+ start_ms: chunk_offset_ms.saturating_add(start_ms),
240
+ end_ms: chunk_offset_ms.saturating_add(end_ms),
241
+ text,
242
+ },
243
+ ));
244
+ }
245
+ Ok(segments)
246
+ }
247
+
188
248
  // ---- resampling -------------------------------------------------------
189
249
 
190
250
  /// One linearly-interpolated 16 kHz output sample at output index `i`,
@@ -383,6 +443,12 @@ mod macos {
383
443
  /// deliberately deferred to the worker so we never allocate/compute on
384
444
  /// the realtime audio thread.
385
445
  fn push(&self, frames: &[f32]) {
446
+ // A bus publish may already have cloned this callback when the
447
+ // subscription is dropped. Refuse that final in-flight delivery
448
+ // once teardown has signalled the worker to stop.
449
+ if !self.running.load(Ordering::SeqCst) {
450
+ return;
451
+ }
386
452
  if let Ok(mut buf) = self.buf.lock() {
387
453
  buf.extend_from_slice(frames);
388
454
  }
@@ -826,18 +892,31 @@ mod macos {
826
892
  }
827
893
 
828
894
  struct Session {
895
+ app: AppHandle,
829
896
  // macOS 15+ meetings use a combined SCK capture, so there is no
830
897
  // competing AVAudioEngine / VoiceProcessingIO mic input to stop.
831
898
  mic_cap: Option<RawMicCapture>,
832
899
  // System capture is optional — skipped when the user turns system
833
900
  // audio off, so neither the recording nor the transcript include it.
834
901
  sys_cap: Option<RawSckAudioCapture>,
902
+ // When Rewind already owns the requested SCK audio sources, meeting
903
+ // Whisper receives fan-out PCM through this subscription and opens no
904
+ // physical mic/system recorder of its own.
905
+ _shared_audio: Option<AudioSubscription>,
906
+ temporary_audio: Option<crate::screen_memory::TemporaryAudioLease>,
835
907
  mic: Arc<WhisperStream>,
836
908
  sys: Option<Arc<WhisperStream>>,
837
909
  /// Who started this session — see `SessionOwner`.
838
910
  owner: SessionOwner,
839
911
  }
840
912
 
913
+ impl Drop for Session {
914
+ fn drop(&mut self) {
915
+ drop(self._shared_audio.take());
916
+ release_temporary_audio(&self.app, self.temporary_audio.take());
917
+ }
918
+ }
919
+
841
920
  // SAFETY: the capture handles hold refcounted ObjC objects (already
842
921
  // `Send`); the streams are `Arc` over `Send + Sync` interiors. We only move
843
922
  // the session through the `Mutex`, never alias across threads.
@@ -936,10 +1015,80 @@ mod macos {
936
1015
  as Arc<dyn Fn(&[f32]) + Send + Sync>
937
1016
  });
938
1017
 
939
- let combined_cap = if should_use_combined_sck_capture(
940
- owner,
941
- supports_sck_microphone_capture(),
942
- ) {
1018
+ // If Rewind is running visuals-only, upgrade that one physical
1019
+ // producer before touching the bus. Off/paused Rewind returns no lease
1020
+ // and preserves the legacy meeting capture path.
1021
+ let temporary_audio = if owner == SessionOwner::Meeting {
1022
+ match crate::screen_memory::acquire_temporary_audio_consumer(
1023
+ &app,
1024
+ MEETING_AUDIO_OWNER,
1025
+ crate::capture_graph::CaptureConsumer::Meeting,
1026
+ true,
1027
+ capture_system,
1028
+ ) {
1029
+ Ok(lease) => lease,
1030
+ Err(error) => {
1031
+ mic_stream.stop();
1032
+ if let Some(sys_stream) = &sys_stream {
1033
+ sys_stream.stop();
1034
+ }
1035
+ return Err(error);
1036
+ }
1037
+ }
1038
+ } else {
1039
+ None
1040
+ };
1041
+
1042
+ // Make the shared-vs-physical choice atomically inside the bus. If a
1043
+ // Rewind producer exists but lacks a requested source, `try_subscribe`
1044
+ // returns a typed error and we fail closed: no combined SCK fallback,
1045
+ // RawMicCapture, or raw system capture is opened.
1046
+ let shared_audio = if owner == SessionOwner::Meeting {
1047
+ let mic_for_shared = mic_stream.clone();
1048
+ let shared_mic = Arc::new(move |samples: &[f32], sample_rate: f64| {
1049
+ mic_for_shared.set_src_rate(sample_rate);
1050
+ mic_for_shared.push(samples);
1051
+ });
1052
+ let shared_system = sys_stream.as_ref().map(|stream| {
1053
+ let stream = stream.clone();
1054
+ Arc::new(move |samples: &[f32], sample_rate: f64| {
1055
+ stream.set_src_rate(sample_rate);
1056
+ stream.push(samples);
1057
+ }) as crate::capture_audio_bus::AudioCallback
1058
+ });
1059
+ match try_subscribe(
1060
+ AudioSources::new(true, capture_system),
1061
+ Some(shared_mic),
1062
+ shared_system,
1063
+ ) {
1064
+ Ok(SubscriptionAttempt::Subscribed(subscription)) => Some(subscription),
1065
+ Ok(SubscriptionAttempt::NoProducer) => {
1066
+ if temporary_audio.is_some() {
1067
+ release_temporary_audio(&app, temporary_audio);
1068
+ mic_stream.stop();
1069
+ if let Some(sys_stream) = &sys_stream {
1070
+ sys_stream.stop();
1071
+ }
1072
+ return Err("shared-audio-producer-unavailable-after-upgrade".into());
1073
+ }
1074
+ None
1075
+ }
1076
+ Err(error) => {
1077
+ release_temporary_audio(&app, temporary_audio);
1078
+ mic_stream.stop();
1079
+ if let Some(sys_stream) = &sys_stream {
1080
+ sys_stream.stop();
1081
+ }
1082
+ return Err(error.to_string());
1083
+ }
1084
+ }
1085
+ } else {
1086
+ None
1087
+ };
1088
+
1089
+ let combined_cap = if shared_audio.is_none()
1090
+ && should_use_combined_sck_capture(owner, supports_sck_microphone_capture())
1091
+ {
943
1092
  match start_raw_meeting_capture(
944
1093
  app.clone(),
945
1094
  mic_device_id.clone(),
@@ -963,7 +1112,10 @@ mod macos {
963
1112
  None
964
1113
  };
965
1114
 
966
- let (mic_cap, sys_cap) = if let Some(combined_cap) = combined_cap {
1115
+ let (mic_cap, sys_cap) = if shared_audio.is_some() {
1116
+ eprintln!("[whisper] using shared Rewind microphone/system PCM producer");
1117
+ (None, None)
1118
+ } else if let Some(combined_cap) = combined_cap {
967
1119
  // Both SCK outputs are configured at 48 kHz.
968
1120
  mic_stream.set_src_rate(48000.0);
969
1121
  (None, Some(combined_cap))
@@ -1004,10 +1156,30 @@ mod macos {
1004
1156
  (Some(mic_cap), sys_cap)
1005
1157
  };
1006
1158
 
1007
- let mut slot = session_slot().lock().map_err(|e| e.to_string())?;
1159
+ let mut slot = match session_slot().lock() {
1160
+ Ok(slot) => slot,
1161
+ Err(error) => {
1162
+ drop(shared_audio);
1163
+ release_temporary_audio(&app, temporary_audio);
1164
+ mic_stream.stop();
1165
+ if let Some(sys_stream) = &sys_stream {
1166
+ sys_stream.stop();
1167
+ }
1168
+ if let Some(mic_cap) = mic_cap {
1169
+ mic_cap.stop();
1170
+ }
1171
+ if let Some(sys_cap) = sys_cap {
1172
+ sys_cap.stop();
1173
+ }
1174
+ return Err(error.to_string());
1175
+ }
1176
+ };
1008
1177
  *slot = Some(Session {
1178
+ app: app.clone(),
1009
1179
  mic_cap,
1010
1180
  sys_cap,
1181
+ _shared_audio: shared_audio,
1182
+ temporary_audio,
1011
1183
  mic: mic_stream,
1012
1184
  sys: sys_stream,
1013
1185
  owner,
@@ -1039,12 +1211,23 @@ mod macos {
1039
1211
  eprintln!("[whisper] transcription timeline reset");
1040
1212
  }
1041
1213
 
1042
- pub fn stop(_app: &AppHandle) {
1214
+ fn release_temporary_audio(
1215
+ app: &AppHandle,
1216
+ lease: Option<crate::screen_memory::TemporaryAudioLease>,
1217
+ ) {
1218
+ if let Some(lease) = lease {
1219
+ if let Err(error) = crate::screen_memory::release_temporary_audio_consumer(app, lease) {
1220
+ eprintln!("[whisper] Rewind audio lease release failed: {error}");
1221
+ }
1222
+ }
1223
+ }
1224
+
1225
+ pub fn stop(app: &AppHandle) {
1043
1226
  let session = match session_slot().lock() {
1044
1227
  Ok(mut slot) => slot.take(),
1045
- Err(_) => return,
1228
+ Err(poisoned) => poisoned.into_inner().take(),
1046
1229
  };
1047
- let Some(session) = session else {
1230
+ let Some(mut session) = session else {
1048
1231
  return;
1049
1232
  };
1050
1233
  // Signal workers to stop. They flush a final transcript after the loop.
@@ -1053,12 +1236,16 @@ mod macos {
1053
1236
  sys.stop();
1054
1237
  }
1055
1238
  // Stop captures so no more samples arrive while workers flush.
1056
- if let Some(mic_cap) = session.mic_cap {
1239
+ if let Some(mic_cap) = session.mic_cap.take() {
1057
1240
  mic_cap.stop();
1058
1241
  }
1059
- if let Some(sys_cap) = session.sys_cap {
1242
+ if let Some(sys_cap) = session.sys_cap.take() {
1060
1243
  sys_cap.stop();
1061
1244
  }
1245
+ // Unsubscribe before a last-consumer release rotates the Rewind
1246
+ // producer back to its persisted visuals-only mode.
1247
+ drop(session._shared_audio.take());
1248
+ release_temporary_audio(app, session.temporary_audio.take());
1062
1249
  // Wait up to 4 s for both workers to finish their final flush so
1063
1250
  // trailing speech is not lost when the frontend unregisters listeners.
1064
1251
  let deadline = Instant::now() + Duration::from_secs(4);
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://schema.tauri.app/config/2",
3
+ "productName": "Clips Alpha",
4
+ "identifier": "com.clips.tray.alpha",
5
+ "bundle": {
6
+ "createUpdaterArtifacts": false,
7
+ "targets": ["app"],
8
+ "macOS": {
9
+ "minimumSystemVersion": "26.0"
10
+ }
11
+ },
12
+ "plugins": {
13
+ "updater": {
14
+ "active": false
15
+ }
16
+ }
17
+ }
@@ -5,11 +5,6 @@ function isZoomMeetingHost(hostname: string): boolean {
5
5
  return hostname === "zoom.us" || hostname.endsWith(".zoom.us");
6
6
  }
7
7
 
8
- /**
9
- * Prefer Zoom's native URI when an HTTPS calendar link carries a meeting id.
10
- * Other providers and URL shapes retain their original URL as the safe
11
- * fallback.
12
- */
13
8
  export function resolveNativeMeetingJoinUrl(joinUrl: string): string {
14
9
  try {
15
10
  const url = new URL(joinUrl);
@@ -82,12 +82,20 @@ pnpm action update-document --id abc123 --description "Stable guidance for what
82
82
 
83
83
  ### delete-document
84
84
 
85
- Delete a document and all its children recursively.
85
+ Move a document and all its children to Trash. IDs, bodies, hierarchy, and
86
+ database membership remain intact so the subtree can be restored.
86
87
 
87
88
  ```bash
88
89
  pnpm action delete-document --id abc123
89
90
  ```
90
91
 
92
+ Restore the root subtree, or permanently delete it only after it is in Trash:
93
+
94
+ ```bash
95
+ pnpm action restore-document --id abc123
96
+ pnpm action permanently-delete-document --id abc123
97
+ ```
98
+
91
99
  ## Comments
92
100
 
93
101
  Comments are Notion/Google-Docs-style **inline comments**. Selecting text and commenting leaves the passage **highlighted inline** via a ProseMirror decoration overlay — nothing is written into the markdown body, so the document round-trips unchanged. Each thread stores the quoted text plus surrounding context (`anchorPrefix`/`anchorSuffix`) and an approximate `anchorStartOffset`, so the highlight follows the text as the document is edited, disambiguates repeated text, and degrades gracefully (the thread stays in the sidebar) when its text is deleted.
@@ -146,6 +146,9 @@ cd templates/content && pnpm action <name> [args]
146
146
  | `get-content-database` | `--databaseId <id>` or `--documentId <id>` | Get a database with its description, property/option schema guidance, item pages, and computed ancestry context |
147
147
  | `list-trashed-content-databases` | | List soft-deleted databases visible in the sidebar Trash surface |
148
148
  | `restore-content-database` | `--databaseId <id>` | Restore a soft-deleted database from the sidebar Trash surface |
149
+ | `list-trashed-documents` | | List access-filtered page roots visible in the sidebar Trash surface |
150
+ | `restore-document` | `--id <id>` | Restore a page and the subtree moved to Trash with it |
151
+ | `permanently-delete-document` | `--id <id>` | Permanently destroy a document subtree already in Trash |
149
152
  | `get-content-database-source` | `--databaseId <id>` or `--documentId <id>` | Inspect local/no-source or source-backed status, mappings, row identity, freshness, and change sets |
150
153
  | `attach-content-database-source` | `--databaseId <id>` or `--documentId <id> [--sourceType mock-local\|builder-cms\|local-table\|notion-database] [--sourceName] [--sourceTable] [--relationshipMode items\|details] [--join <json>]` | Attach a source binding; use `items` to add more Builder rows and `details` to match a read-only local/Notion source onto existing rows |
151
154
  | `list-notion-database-sources` | `[--query <text>] [--limit <1-100>]` | List Notion data sources visible through the current user's OAuth connection; returns IDs/names only, never tokens |
@@ -175,7 +178,7 @@ cd templates/content && pnpm action <name> [args]
175
178
  | `reorder-document-property` | `--documentId <id> --propertyId <propertyId> --targetPropertyId <id> [--position before\|after]` | Reorder a property definition within its database (used to reorder Blocks fields on the page) |
176
179
  | `set-document-discoverability` | `--id <id> --hideFromSearch true\|false [--includeChildren true\|false]` | Hide/show an org-accessible document in Organization/search while keeping link access |
177
180
  | `move-document` | `--id <id> [--parentId] [--position]` | Move or reorder a document in the page tree |
178
- | `delete-document` | `--id <id>` | Delete with recursive children |
181
+ | `delete-document` | `--id <id>` | Move a document and its recursive children to Trash |
179
182
 
180
183
  Database views follow Notion-style tab labels. When creating or duplicating
181
184
  views in `viewConfig`, use unique default names (`Table 2`, `SEO copy 2`, etc.)
@@ -806,7 +806,11 @@ async function provisionOwnedContentSpace(
806
806
  export async function provisionSourceBackedContentSpace(
807
807
  db: Db,
808
808
  userEmail: string,
809
- input: { connectionId: string; name: string },
809
+ input: {
810
+ connectionId: string;
811
+ name: string;
812
+ propertyValues?: Record<string, unknown>;
813
+ },
810
814
  ) {
811
815
  const connectionId = input.connectionId.trim();
812
816
  if (!connectionId) throw new Error("Local folder connection ID is required");
@@ -814,6 +818,7 @@ export async function provisionSourceBackedContentSpace(
814
818
  spaceId: sourceBackedContentSpaceId(userEmail, connectionId),
815
819
  name: input.name.trim() || "Local folder",
816
820
  kind: "source_backed",
821
+ propertyValues: input.propertyValues,
817
822
  });
818
823
  }
819
824
 
@@ -151,6 +151,7 @@ export async function resolveDatabaseRowsForBatch(
151
151
  eq(schema.contentDatabaseItems.databaseId, database.id),
152
152
  rowPredicates.length === 1 ? rowPredicates[0] : or(...rowPredicates),
153
153
  isNull(schema.contentDatabases.deletedAt),
154
+ isNull(schema.documents.trashedAt),
154
155
  ),
155
156
  )
156
157
  .orderBy(asc(schema.contentDatabaseItems.position));
@@ -185,9 +186,21 @@ export async function renumberDatabaseRows(
185
186
  now: string,
186
187
  ) {
187
188
  const rows = await db
188
- .select()
189
+ .select({
190
+ id: schema.contentDatabaseItems.id,
191
+ documentId: schema.contentDatabaseItems.documentId,
192
+ })
189
193
  .from(schema.contentDatabaseItems)
190
- .where(eq(schema.contentDatabaseItems.databaseId, database.id))
194
+ .innerJoin(
195
+ schema.documents,
196
+ eq(schema.documents.id, schema.contentDatabaseItems.documentId),
197
+ )
198
+ .where(
199
+ and(
200
+ eq(schema.contentDatabaseItems.databaseId, database.id),
201
+ isNull(schema.documents.trashedAt),
202
+ ),
203
+ )
191
204
  .orderBy(asc(schema.contentDatabaseItems.position));
192
205
  if (rows.length === 0) return;
193
206
 
@@ -22,7 +22,10 @@ import type {
22
22
  ContentDatabaseResponse,
23
23
  } from "../shared/api.js";
24
24
  import { favoriteDocumentIds } from "./_content-favorites.js";
25
- import { listContentOrganizationMemberships } from "./_content-space-access.js";
25
+ import {
26
+ listContentOrganizationMemberships,
27
+ normalizeContentSpaceEmail,
28
+ } from "./_content-space-access.js";
26
29
  import { getAllContentDatabaseSourceSnapshots } from "./_database-source-utils.js";
27
30
  import {
28
31
  applyFederatedOverlayValues,
@@ -81,6 +84,8 @@ export const contentDatabaseListDocumentSelection = {
81
84
  sourcePath: schema.documents.sourcePath,
82
85
  sourceRootPath: schema.documents.sourceRootPath,
83
86
  sourceUpdatedAt: schema.documents.sourceUpdatedAt,
87
+ trashedAt: schema.documents.trashedAt,
88
+ trashRootId: schema.documents.trashRootId,
84
89
  visibility: schema.documents.visibility,
85
90
  ownerEmail: schema.documents.ownerEmail,
86
91
  orgId: schema.documents.orgId,
@@ -300,9 +305,14 @@ export async function getContentDatabaseResponse(
300
305
 
301
306
  const { limit, offset } = normalizeContentDatabasePageOptions(options);
302
307
  const userEmail = getRequestUserEmail();
308
+ const normalizedUserEmail = userEmail
309
+ ? normalizeContentSpaceEmail(userEmail)
310
+ : null;
303
311
  const activeOrgId = getRequestOrgId();
304
312
  const authorizedOrgIds =
305
- database.systemRole === "favorites" && userEmail
313
+ (database.systemRole === "favorites" ||
314
+ database.systemRole === "workspaces") &&
315
+ userEmail
306
316
  ? [
307
317
  ...new Set([
308
318
  ...(await listContentOrganizationMemberships(userEmail)).map(
@@ -312,6 +322,45 @@ export async function getContentDatabaseResponse(
312
322
  ]),
313
323
  ]
314
324
  : [];
325
+ const workspacesVisibleDocumentIds =
326
+ database.systemRole === "workspaces" && normalizedUserEmail
327
+ ? (
328
+ await db
329
+ .select({
330
+ documentId: schema.contentSpaceCatalogItems.documentId,
331
+ ownerEmail: schema.contentSpaces.ownerEmail,
332
+ orgId: schema.contentSpaces.orgId,
333
+ })
334
+ .from(schema.contentSpaceCatalogItems)
335
+ .innerJoin(
336
+ schema.contentSpaces,
337
+ eq(
338
+ schema.contentSpaces.id,
339
+ schema.contentSpaceCatalogItems.spaceId,
340
+ ),
341
+ )
342
+ .where(
343
+ and(
344
+ eq(
345
+ schema.contentSpaceCatalogItems.catalogDatabaseId,
346
+ databaseId,
347
+ ),
348
+ eq(
349
+ schema.contentSpaceCatalogItems.ownerEmail,
350
+ normalizedUserEmail,
351
+ ),
352
+ isNull(schema.contentSpaces.archivedAt),
353
+ ),
354
+ )
355
+ )
356
+ .filter(
357
+ (row) =>
358
+ normalizeContentSpaceEmail(row.ownerEmail) ===
359
+ normalizedUserEmail ||
360
+ (!!row.orgId && authorizedOrgIds.includes(row.orgId)),
361
+ )
362
+ .map((row) => row.documentId)
363
+ : null;
315
364
  const favoritesVisibleDocumentIds =
316
365
  database.systemRole === "favorites" && userEmail
317
366
  ? (
@@ -331,6 +380,7 @@ export async function getContentDatabaseResponse(
331
380
  }),
332
381
  ),
333
382
  ),
383
+ isNull(schema.documents.trashedAt),
334
384
  documentDiscoveryFilter({
335
385
  userEmail,
336
386
  orgIds: authorizedOrgIds,
@@ -351,6 +401,11 @@ export async function getContentDatabaseResponse(
351
401
  : undefined;
352
402
  const visibleItemFilter = and(
353
403
  eq(schema.contentDatabaseItems.databaseId, databaseId),
404
+ sql`exists (
405
+ select 1 from ${schema.documents}
406
+ where ${schema.documents.id} = ${schema.contentDatabaseItems.documentId}
407
+ and ${schema.documents.trashedAt} is null
408
+ )`,
354
409
  organizationFilesItemFilter,
355
410
  favoritesVisibleDocumentIds
356
411
  ? favoritesVisibleDocumentIds.length > 0
@@ -360,6 +415,14 @@ export async function getContentDatabaseResponse(
360
415
  )
361
416
  : sql`1 = 0`
362
417
  : undefined,
418
+ workspacesVisibleDocumentIds
419
+ ? workspacesVisibleDocumentIds.length > 0
420
+ ? inArray(
421
+ schema.contentDatabaseItems.documentId,
422
+ workspacesVisibleDocumentIds,
423
+ )
424
+ : sql`1 = 0`
425
+ : undefined,
363
426
  );
364
427
  const [itemCount] = await db
365
428
  .select({ count: sql<number>`COUNT(*)` })
@@ -388,23 +451,28 @@ export async function getContentDatabaseResponse(
388
451
  schema.documents.id,
389
452
  items.map((item) => item.documentId),
390
453
  ),
454
+ isNull(schema.documents.trashedAt),
391
455
  database.systemRole === "favorites"
392
456
  ? favoritesVisibleDocumentIds?.length
393
457
  ? inArray(schema.documents.id, favoritesVisibleDocumentIds)
394
458
  : sql`1 = 0`
395
- : database.systemRole === "files" && database.orgId
396
- ? and(
397
- eq(schema.documents.orgId, database.orgId),
398
- or(
399
- eq(schema.documents.visibility, "org"),
400
- eq(schema.documents.visibility, "public"),
401
- ),
402
- or(
403
- eq(schema.documents.hideFromSearch, 0),
404
- isNull(schema.documents.hideFromSearch),
405
- ),
406
- )
407
- : eq(schema.documents.ownerEmail, database.ownerEmail),
459
+ : database.systemRole === "workspaces"
460
+ ? workspacesVisibleDocumentIds?.length
461
+ ? inArray(schema.documents.id, workspacesVisibleDocumentIds)
462
+ : sql`1 = 0`
463
+ : database.systemRole === "files" && database.orgId
464
+ ? and(
465
+ eq(schema.documents.orgId, database.orgId),
466
+ or(
467
+ eq(schema.documents.visibility, "org"),
468
+ eq(schema.documents.visibility, "public"),
469
+ ),
470
+ or(
471
+ eq(schema.documents.hideFromSearch, 0),
472
+ isNull(schema.documents.hideFromSearch),
473
+ ),
474
+ )
475
+ : eq(schema.documents.ownerEmail, database.ownerEmail),
408
476
  ),
409
477
  )
410
478
  : [];
@@ -41,6 +41,9 @@ export default defineAction({
41
41
  ),
42
42
  );
43
43
  if (!database) throw new Error(`Database "${databaseId}" not found`);
44
+ if (database.systemRole === "workspaces") {
45
+ throw new Error("Use create-content-space to add a workspace");
46
+ }
44
47
 
45
48
  const access = await assertAccess(
46
49
  "document",
@@ -51,6 +51,7 @@ export default defineAction({
51
51
  .optional()
52
52
  .default(false)
53
53
  .describe("Create a separate private Content space for this folder"),
54
+ propertyValues: z.record(z.string(), z.unknown()).optional(),
54
55
  truthPolicy: truthPolicySchema.describe(
55
56
  "Whether Content, the folder, or reviewed conflict resolution is authoritative",
56
57
  ),
@@ -130,7 +131,7 @@ export default defineAction({
130
131
  const provisioned = await provisionSourceBackedContentSpace(
131
132
  db,
132
133
  userEmail,
133
- { connectionId, name: label },
134
+ { connectionId, name: label, propertyValues: args.propertyValues },
134
135
  );
135
136
  targetSpaceId = provisioned.spaceId;
136
137
  targetDatabaseId = provisioned.filesDatabaseId;