@ai-matrx/media 0.7.16 → 0.9.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 (191) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/files/engine/api/assets.d.ts +223 -0
  3. package/dist/files/engine/api/assets.js +124 -0
  4. package/dist/files/engine/api/assets.js.map +1 -0
  5. package/dist/files/engine/api/direct.d.ts +43 -0
  6. package/dist/files/engine/api/direct.js +73 -0
  7. package/dist/files/engine/api/direct.js.map +1 -0
  8. package/dist/files/engine/api/fileOrganization.d.ts +34 -0
  9. package/dist/files/engine/api/fileOrganization.js +38 -0
  10. package/dist/files/engine/api/fileOrganization.js.map +1 -0
  11. package/dist/files/engine/api/files.d.ts +249 -0
  12. package/dist/files/engine/api/files.js +231 -0
  13. package/dist/files/engine/api/files.js.map +1 -0
  14. package/dist/files/engine/api/folders.d.ts +63 -0
  15. package/dist/files/engine/api/folders.js +56 -0
  16. package/dist/files/engine/api/folders.js.map +1 -0
  17. package/dist/files/engine/api/office.d.ts +27 -0
  18. package/dist/files/engine/api/office.js +19 -0
  19. package/dist/files/engine/api/office.js.map +1 -0
  20. package/dist/files/engine/api/permissions.d.ts +37 -0
  21. package/dist/files/engine/api/permissions.js +109 -0
  22. package/dist/files/engine/api/permissions.js.map +1 -0
  23. package/dist/files/engine/api/versions.d.ts +26 -0
  24. package/dist/files/engine/api/versions.js +37 -0
  25. package/dist/files/engine/api/versions.js.map +1 -0
  26. package/dist/files/engine/cache/idb-store.d.ts +95 -0
  27. package/dist/files/engine/cache/idb-store.js +172 -0
  28. package/dist/files/engine/cache/idb-store.js.map +1 -0
  29. package/dist/files/engine/cache/policy.d.ts +14 -0
  30. package/dist/files/engine/cache/policy.js +40 -0
  31. package/dist/files/engine/cache/policy.js.map +1 -0
  32. package/dist/files/engine/cache/register-service-worker.d.ts +57 -0
  33. package/dist/files/engine/cache/register-service-worker.js +80 -0
  34. package/dist/files/engine/cache/register-service-worker.js.map +1 -0
  35. package/dist/files/engine/db-types.d.ts +48865 -0
  36. package/dist/files/engine/db-types.js +1 -0
  37. package/dist/files/engine/db-types.js.map +1 -0
  38. package/dist/files/engine/filesDb.d.ts +1913 -0
  39. package/dist/files/engine/filesDb.js +28 -0
  40. package/dist/files/engine/filesDb.js.map +1 -0
  41. package/dist/files/engine/handler/handler.d.ts +82 -0
  42. package/dist/files/engine/handler/handler.js +124 -0
  43. package/dist/files/engine/handler/handler.js.map +1 -0
  44. package/dist/files/engine/handler/hooks/useFile.d.ts +17 -0
  45. package/dist/files/engine/handler/hooks/useFile.js +75 -0
  46. package/dist/files/engine/handler/hooks/useFile.js.map +1 -0
  47. package/dist/files/engine/handler/hooks/useFileUpload.d.ts +76 -0
  48. package/dist/files/engine/handler/hooks/useFileUpload.js +67 -0
  49. package/dist/files/engine/handler/hooks/useFileUpload.js.map +1 -0
  50. package/dist/files/engine/handler/input/normalize.d.ts +14 -0
  51. package/dist/files/engine/handler/input/normalize.js +365 -0
  52. package/dist/files/engine/handler/input/normalize.js.map +1 -0
  53. package/dist/files/engine/handler/intelligence/access.d.ts +35 -0
  54. package/dist/files/engine/handler/intelligence/access.js +85 -0
  55. package/dist/files/engine/handler/intelligence/access.js.map +1 -0
  56. package/dist/files/engine/handler/intelligence/magic-bytes.d.ts +21 -0
  57. package/dist/files/engine/handler/intelligence/magic-bytes.js +67 -0
  58. package/dist/files/engine/handler/intelligence/magic-bytes.js.map +1 -0
  59. package/dist/files/engine/handler/output/target.d.ts +19 -0
  60. package/dist/files/engine/handler/output/target.js +222 -0
  61. package/dist/files/engine/handler/output/target.js.map +1 -0
  62. package/dist/files/engine/handler/resolver.d.ts +34 -0
  63. package/dist/files/engine/handler/resolver.js +133 -0
  64. package/dist/files/engine/handler/resolver.js.map +1 -0
  65. package/dist/files/engine/handler/types.d.ts +367 -0
  66. package/dist/files/engine/handler/types.js +1 -0
  67. package/dist/files/engine/handler/types.js.map +1 -0
  68. package/dist/files/engine/handler/upload.d.ts +32 -0
  69. package/dist/files/engine/handler/upload.js +295 -0
  70. package/dist/files/engine/handler/upload.js.map +1 -0
  71. package/dist/files/engine/handler/utils/classify.d.ts +14 -0
  72. package/dist/files/engine/handler/utils/classify.js +27 -0
  73. package/dist/files/engine/handler/utils/classify.js.map +1 -0
  74. package/dist/files/engine/handler/utils/prefer-locator.d.ts +32 -0
  75. package/dist/files/engine/handler/utils/prefer-locator.js +34 -0
  76. package/dist/files/engine/handler/utils/prefer-locator.js.map +1 -0
  77. package/dist/files/engine/handler/utils/python-base.d.ts +129 -0
  78. package/dist/files/engine/handler/utils/python-base.js +60 -0
  79. package/dist/files/engine/handler/utils/python-base.js.map +1 -0
  80. package/dist/files/engine/hooks/blob-cache.d.ts +130 -0
  81. package/dist/files/engine/hooks/blob-cache.js +162 -0
  82. package/dist/files/engine/hooks/blob-cache.js.map +1 -0
  83. package/dist/files/engine/hooks/office-extraction-cache.d.ts +28 -0
  84. package/dist/files/engine/hooks/office-extraction-cache.js +67 -0
  85. package/dist/files/engine/hooks/office-extraction-cache.js.map +1 -0
  86. package/dist/files/engine/host/configure.d.ts +166 -0
  87. package/dist/files/engine/host/configure.js +30 -0
  88. package/dist/files/engine/host/configure.js.map +1 -0
  89. package/dist/files/engine/host/org.d.ts +8 -0
  90. package/dist/files/engine/host/org.js +16 -0
  91. package/dist/files/engine/host/org.js.map +1 -0
  92. package/dist/files/engine/host/python-client.d.ts +60 -0
  93. package/dist/files/engine/host/python-client.js +46 -0
  94. package/dist/files/engine/host/python-client.js.map +1 -0
  95. package/dist/files/engine/host/share-links.d.ts +20 -0
  96. package/dist/files/engine/host/share-links.js +32 -0
  97. package/dist/files/engine/host/share-links.js.map +1 -0
  98. package/dist/files/engine/host/store.d.ts +24 -0
  99. package/dist/files/engine/host/store.js +23 -0
  100. package/dist/files/engine/host/store.js.map +1 -0
  101. package/dist/files/engine/host/supabase.d.ts +3808 -0
  102. package/dist/files/engine/host/supabase.js +33 -0
  103. package/dist/files/engine/host/supabase.js.map +1 -0
  104. package/dist/files/engine/host/toast.d.ts +14 -0
  105. package/dist/files/engine/host/toast.js +20 -0
  106. package/dist/files/engine/host/toast.js.map +1 -0
  107. package/dist/files/engine/host/typed-client.d.ts +136 -0
  108. package/dist/files/engine/host/typed-client.js +66 -0
  109. package/dist/files/engine/host/typed-client.js.map +1 -0
  110. package/dist/files/engine/index.d.ts +22 -0
  111. package/dist/files/engine/index.js +49 -0
  112. package/dist/files/engine/index.js.map +1 -0
  113. package/dist/files/engine/media/our-file-sources.d.ts +39 -0
  114. package/dist/files/engine/media/our-file-sources.js +83 -0
  115. package/dist/files/engine/media/our-file-sources.js.map +1 -0
  116. package/dist/files/engine/media/signed-url.d.ts +1 -0
  117. package/dist/files/engine/media/signed-url.js +6 -0
  118. package/dist/files/engine/media/signed-url.js.map +1 -0
  119. package/dist/files/engine/redux/converters.d.ts +73 -0
  120. package/dist/files/engine/redux/converters.js +286 -0
  121. package/dist/files/engine/redux/converters.js.map +1 -0
  122. package/dist/files/engine/redux/file-hydration.d.ts +15 -0
  123. package/dist/files/engine/redux/file-hydration.js +46 -0
  124. package/dist/files/engine/redux/file-hydration.js.map +1 -0
  125. package/dist/files/engine/redux/file-tree-auth-boundary.d.ts +5 -0
  126. package/dist/files/engine/redux/file-tree-auth-boundary.js +28 -0
  127. package/dist/files/engine/redux/file-tree-auth-boundary.js.map +1 -0
  128. package/dist/files/engine/redux/file-tree-timeout.d.ts +32 -0
  129. package/dist/files/engine/redux/file-tree-timeout.js +73 -0
  130. package/dist/files/engine/redux/file-tree-timeout.js.map +1 -0
  131. package/dist/files/engine/redux/mutation-toast-middleware.d.ts +27 -0
  132. package/dist/files/engine/redux/mutation-toast-middleware.js +103 -0
  133. package/dist/files/engine/redux/mutation-toast-middleware.js.map +1 -0
  134. package/dist/files/engine/redux/realtime-middleware.d.ts +61 -0
  135. package/dist/files/engine/redux/realtime-middleware.js +431 -0
  136. package/dist/files/engine/redux/realtime-middleware.js.map +1 -0
  137. package/dist/files/engine/redux/request-ledger.d.ts +68 -0
  138. package/dist/files/engine/redux/request-ledger.js +66 -0
  139. package/dist/files/engine/redux/request-ledger.js.map +1 -0
  140. package/dist/files/engine/redux/selectors.d.ts +3254 -0
  141. package/dist/files/engine/redux/selectors.js +428 -0
  142. package/dist/files/engine/redux/selectors.js.map +1 -0
  143. package/dist/files/engine/redux/slice.d.ts +157 -0
  144. package/dist/files/engine/redux/slice.js +836 -0
  145. package/dist/files/engine/redux/slice.js.map +1 -0
  146. package/dist/files/engine/redux/thunks.d.ts +449 -0
  147. package/dist/files/engine/redux/thunks.js +1684 -0
  148. package/dist/files/engine/redux/thunks.js.map +1 -0
  149. package/dist/files/engine/redux/tree-utils.d.ts +90 -0
  150. package/dist/files/engine/redux/tree-utils.js +200 -0
  151. package/dist/files/engine/redux/tree-utils.js.map +1 -0
  152. package/dist/files/engine/support/claimsUser.d.ts +77 -0
  153. package/dist/files/engine/support/claimsUser.js +48 -0
  154. package/dist/files/engine/support/claimsUser.js.map +1 -0
  155. package/dist/files/engine/support/datetime.d.ts +6 -0
  156. package/dist/files/engine/support/datetime.js +15 -0
  157. package/dist/files/engine/support/datetime.js.map +1 -0
  158. package/dist/files/engine/support/document-visibility.d.ts +14 -0
  159. package/dist/files/engine/support/document-visibility.js +28 -0
  160. package/dist/files/engine/support/document-visibility.js.map +1 -0
  161. package/dist/files/engine/support/logger.d.ts +28 -0
  162. package/dist/files/engine/support/logger.js +36 -0
  163. package/dist/files/engine/support/logger.js.map +1 -0
  164. package/dist/files/engine/types.d.ts +1081 -0
  165. package/dist/files/engine/types.js +30 -0
  166. package/dist/files/engine/types.js.map +1 -0
  167. package/dist/files/engine/upload/cloudUpload.d.ts +182 -0
  168. package/dist/files/engine/upload/cloudUpload.js +418 -0
  169. package/dist/files/engine/upload/cloudUpload.js.map +1 -0
  170. package/dist/files/engine/upload/tusUpload.d.ts +100 -0
  171. package/dist/files/engine/upload/tusUpload.js +258 -0
  172. package/dist/files/engine/upload/tusUpload.js.map +1 -0
  173. package/dist/files/engine/upload/uploadDedupGuard.d.ts +58 -0
  174. package/dist/files/engine/upload/uploadDedupGuard.js +41 -0
  175. package/dist/files/engine/upload/uploadDedupGuard.js.map +1 -0
  176. package/dist/files/engine/upload/uploadGuardOpeners.d.ts +70 -0
  177. package/dist/files/engine/upload/uploadGuardOpeners.js +54 -0
  178. package/dist/files/engine/upload/uploadGuardOpeners.js.map +1 -0
  179. package/dist/files/engine/utils/file-types.d.ts +243 -0
  180. package/dist/files/engine/utils/file-types.js +1722 -0
  181. package/dist/files/engine/utils/file-types.js.map +1 -0
  182. package/dist/files/engine/utils/user-visible.d.ts +133 -0
  183. package/dist/files/engine/utils/user-visible.js +115 -0
  184. package/dist/files/engine/utils/user-visible.js.map +1 -0
  185. package/dist/files.cjs +1298 -0
  186. package/dist/files.cjs.map +1 -0
  187. package/dist/files.d.cts +1171 -0
  188. package/dist/files.d.ts +1171 -0
  189. package/dist/files.js +1275 -0
  190. package/dist/files.js.map +1 -0
  191. package/package.json +404 -9
package/dist/files.cjs ADDED
@@ -0,0 +1,1298 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/files.ts
21
+ var files_exports = {};
22
+ __export(files_exports, {
23
+ CloudFolderDescriptions: () => CloudFolderDescriptions,
24
+ CloudFolders: () => CloudFolders,
25
+ ExternalFetchError: () => ExternalFetchError,
26
+ FileAccessDeniedError: () => FileAccessDeniedError,
27
+ FileDeletedError: () => FileDeletedError,
28
+ FileHandlerError: () => FileHandlerError,
29
+ FileNotFoundError: () => FileNotFoundError,
30
+ FileUploadError: () => FileUploadError,
31
+ ShareLinkInvalidError: () => ShareLinkInvalidError,
32
+ UploadCancelledError: () => UploadCancelledError,
33
+ VideoPublishDate: () => VideoPublishDate,
34
+ blockFromMediaRef: () => blockFromMediaRef,
35
+ composeUploadFolderPath: () => composeUploadFolderPath,
36
+ createTrackedObjectUrl: () => createTrackedObjectUrl,
37
+ deriveViewerUrl: () => deriveViewerUrl,
38
+ extractFileIdFromUrl: () => extractFileIdFromUrl,
39
+ fileIdToMediaRef: () => fileIdToMediaRef,
40
+ folderForAgentApp: () => folderForAgentApp,
41
+ folderForAgentBlock: () => folderForAgentBlock,
42
+ folderForCaptures: () => folderForCaptures,
43
+ folderForConversation: () => folderForConversation,
44
+ folderForIntakeAsset: () => folderForIntakeAsset,
45
+ folderForOrg: () => folderForOrg,
46
+ folderForPodcast: () => folderForPodcast,
47
+ folderForProductCaptureItem: () => folderForProductCaptureItem,
48
+ folderForTask: () => folderForTask,
49
+ folderForWarRoomThread: () => folderForWarRoomThread,
50
+ formatVideoPublishDate: () => formatVideoPublishDate,
51
+ formatVideoPublishDateTitle: () => formatVideoPublishDateTitle,
52
+ fromCxAudioPart: () => fromCxAudioPart,
53
+ fromCxMediaPart: () => fromCxMediaPart,
54
+ fromCxVideoPart: () => fromCxVideoPart,
55
+ fromImageOutputData: () => fromImageOutputData,
56
+ fromMediaBlock: () => fromMediaBlock,
57
+ fromPartialImageData: () => fromPartialImageData,
58
+ fromRenderBlock: () => fromRenderBlock,
59
+ imageBlockFromMediaRef: () => imageBlockFromMediaRef,
60
+ isAudioBlock: () => isAudioBlock,
61
+ isConventionalFolder: () => isConventionalFolder,
62
+ isDocumentBlock: () => isDocumentBlock,
63
+ isExternalImageBlock: () => isExternalImageBlock,
64
+ isExternalMediaBlock: () => isExternalMediaBlock,
65
+ isHiddenFolder: () => isHiddenFolder,
66
+ isImageBlock: () => isImageBlock,
67
+ isMatrxImageBlock: () => isMatrxImageBlock,
68
+ isMatrxMediaBlock: () => isMatrxMediaBlock,
69
+ isMediaBlockData: () => isMediaBlockData,
70
+ isSystemPath: () => isSystemPath,
71
+ isUnifiedImageBlock: () => isUnifiedImageBlock,
72
+ isUnifiedMediaBlock: () => isUnifiedMediaBlock,
73
+ isUploadCancelledError: () => isUploadCancelledError,
74
+ isVideoBlock: () => isVideoBlock,
75
+ isYouTubeBlock: () => isYouTubeBlock,
76
+ parseFilenameFromUrl: () => parseFilenameFromUrl,
77
+ parseGenerationMetadata: () => parseGenerationMetadata,
78
+ resolveDefaultVisibility: () => resolveDefaultVisibility,
79
+ revokeTrackedObjectUrl: () => revokeTrackedObjectUrl,
80
+ toCxMediaPart: () => toCxMediaPart,
81
+ toVisibility: () => toVisibility,
82
+ urlToMediaRef: () => urlToMediaRef,
83
+ videoBlockFromMediaRef: () => videoBlockFromMediaRef,
84
+ videoPublishDateFromMetadata: () => videoPublishDateFromMetadata
85
+ });
86
+ module.exports = __toCommonJS(files_exports);
87
+
88
+ // src/files/ref-types.ts
89
+ function toVisibility(raw) {
90
+ if (raw === "public") return "public";
91
+ if (raw === "link") return "link";
92
+ if (raw === "internal") return "internal";
93
+ return "personal";
94
+ }
95
+ function fileIdToMediaRef(fileId, mimeType) {
96
+ const ref = { file_id: fileId };
97
+ if (mimeType) ref.mime_type = mimeType;
98
+ return ref;
99
+ }
100
+ function urlToMediaRef(url, mimeType) {
101
+ const ref = { url };
102
+ if (mimeType) ref.mime_type = mimeType;
103
+ return ref;
104
+ }
105
+
106
+ // src/files/blocks/types.ts
107
+ function parseGenerationMetadata(metadata) {
108
+ if (!metadata) return null;
109
+ const raw = metadata.generation;
110
+ if (!raw || typeof raw !== "object") return null;
111
+ const w = raw;
112
+ if (typeof w.kind !== "string") return null;
113
+ if (typeof w.provider !== "string") return null;
114
+ if (typeof w.model !== "string") return null;
115
+ if (typeof w.prompt !== "string") return null;
116
+ return {
117
+ kind: w.kind,
118
+ provider: w.provider,
119
+ model: w.model,
120
+ prompt: w.prompt,
121
+ negativePrompt: w.negative_prompt ?? null,
122
+ revisedPrompt: w.revised_prompt ?? null,
123
+ width: w.width ?? null,
124
+ height: w.height ?? null,
125
+ aspectRatio: w.aspect_ratio ?? null,
126
+ durationSeconds: w.duration_seconds ?? null,
127
+ quality: w.quality ?? null,
128
+ style: w.style ?? null,
129
+ seed: w.seed ?? null,
130
+ steps: w.steps ?? null,
131
+ cfgScale: w.cfg_scale ?? null,
132
+ nRequested: w.n_requested ?? 1,
133
+ nReturned: w.n_returned ?? 1,
134
+ responseId: w.response_id ?? null,
135
+ durationMs: w.duration_ms ?? null,
136
+ costUsd: w.cost_usd ?? null,
137
+ finishReason: w.finish_reason ?? null,
138
+ safetyFlagged: w.safety_flagged ?? false,
139
+ providerExtras: w.provider_extras ?? {}
140
+ };
141
+ }
142
+
143
+ // src/files/blocks/guards.ts
144
+ function isObject(value) {
145
+ return value !== null && typeof value === "object";
146
+ }
147
+ function hasMediaShape(value) {
148
+ if (!isObject(value)) return false;
149
+ if (typeof value.kind !== "string") return false;
150
+ if (value.origin !== "matrx" && value.origin !== "external") return false;
151
+ return true;
152
+ }
153
+ function isMatrxMediaBlock(value) {
154
+ if (!hasMediaShape(value)) return false;
155
+ if (value.origin !== "matrx") return false;
156
+ return typeof value.fileId === "string";
157
+ }
158
+ function isExternalMediaBlock(value) {
159
+ if (!hasMediaShape(value)) return false;
160
+ if (value.origin !== "external") return false;
161
+ return typeof value.externalUrl === "string";
162
+ }
163
+ function isUnifiedMediaBlock(value) {
164
+ return isMatrxMediaBlock(value) || isExternalMediaBlock(value);
165
+ }
166
+ function isImageBlock(value) {
167
+ return isUnifiedMediaBlock(value) && value.kind === "image";
168
+ }
169
+ function isVideoBlock(value) {
170
+ return isUnifiedMediaBlock(value) && value.kind === "video";
171
+ }
172
+ function isAudioBlock(value) {
173
+ return isUnifiedMediaBlock(value) && value.kind === "audio";
174
+ }
175
+ function isDocumentBlock(value) {
176
+ return isUnifiedMediaBlock(value) && value.kind === "document";
177
+ }
178
+ function isYouTubeBlock(value) {
179
+ return isUnifiedMediaBlock(value) && value.kind === "youtube";
180
+ }
181
+ function isMatrxImageBlock(value) {
182
+ return isImageBlock(value) && value.origin === "matrx";
183
+ }
184
+ function isExternalImageBlock(value) {
185
+ return isImageBlock(value) && value.origin === "external";
186
+ }
187
+
188
+ // src/files/blocks/image/guards.ts
189
+ function isUnifiedImageBlock(value) {
190
+ return isImageBlock(value);
191
+ }
192
+
193
+ // src/files/blocks/adapters/from-cx-av-part.ts
194
+ function str(v) {
195
+ return typeof v === "string" && v.length > 0 ? v : null;
196
+ }
197
+ function liftUrls(part) {
198
+ const metadata = part.metadata ?? null;
199
+ const cdn = str(metadata?.cdn_url);
200
+ const download = str(metadata?.download_url);
201
+ return {
202
+ // The on-disk `url` is a save-time snapshot; forward it as the fallback
203
+ // the handler only uses when no identity is available.
204
+ url: str(part.url) ?? cdn ?? "",
205
+ file_id: str(part.file_id) ?? str(metadata?.file_id),
206
+ cdn_url: cdn,
207
+ download_url: download
208
+ };
209
+ }
210
+ function fromCxAudioPart(part) {
211
+ return {
212
+ type: "audio_output",
213
+ ...liftUrls(part),
214
+ mime_type: part.mime_type ?? "audio/*",
215
+ transcription_result: part.transcription_result ?? null
216
+ };
217
+ }
218
+ function fromCxVideoPart(part) {
219
+ return {
220
+ type: "video_output",
221
+ ...liftUrls(part),
222
+ mime_type: part.mime_type ?? "video/*",
223
+ // A video reference's role (extend / restyle) and its `@name` — carried so
224
+ // a reload redisplays them (see ReferenceRoleCaption).
225
+ reference_role: part.role ?? null,
226
+ reference_name: part.name ?? null
227
+ };
228
+ }
229
+
230
+ // src/files/blocks/adapters/from-media-block.ts
231
+ function pickStatus(s) {
232
+ return s === "streaming" || s === "error" ? s : "complete";
233
+ }
234
+ function pickVisibility(v) {
235
+ return toVisibility(v);
236
+ }
237
+ function commonFields(wire) {
238
+ return {
239
+ status: pickStatus(wire.status),
240
+ progress: wire.progress ?? null,
241
+ errorMessage: wire.error_message ?? null,
242
+ mimeType: wire.mime_type ?? null,
243
+ fileName: wire.file_name ?? null,
244
+ sizeBytes: wire.size_bytes ?? null,
245
+ base64: wire.base64 ?? null,
246
+ metadata: wire.metadata ?? null
247
+ };
248
+ }
249
+ function matrxFields(wire) {
250
+ if (wire.origin !== "matrx") return null;
251
+ if (!wire.file_id) return null;
252
+ return {
253
+ origin: "matrx",
254
+ fileId: wire.file_id,
255
+ visibility: pickVisibility(wire.visibility),
256
+ cdnUrl: wire.cdn_url ?? null,
257
+ downloadUrl: wire.download_url ?? null,
258
+ parentFileId: wire.parent_file_id ?? null,
259
+ derivationKind: wire.derivation_kind ?? null
260
+ };
261
+ }
262
+ function externalFields(wire) {
263
+ return {
264
+ origin: "external",
265
+ externalUrl: wire.external_url ?? "",
266
+ sourceLabel: wire.source_label ?? null
267
+ };
268
+ }
269
+ function liftImage(wire) {
270
+ const common = commonFields(wire);
271
+ const matrx = matrxFields(wire);
272
+ const imageBits = {
273
+ kind: "image",
274
+ width: wire.width ?? null,
275
+ height: wire.height ?? null,
276
+ visionClass: wire.vision_class ?? null
277
+ };
278
+ if (matrx) {
279
+ const block2 = { ...common, ...matrx, ...imageBits };
280
+ return block2;
281
+ }
282
+ const block = {
283
+ ...common,
284
+ ...externalFields(wire),
285
+ ...imageBits
286
+ };
287
+ return block;
288
+ }
289
+ function liftVideo(wire) {
290
+ const common = commonFields(wire);
291
+ const matrx = matrxFields(wire);
292
+ const videoBits = {
293
+ kind: "video",
294
+ width: wire.width ?? null,
295
+ height: wire.height ?? null,
296
+ durationMs: wire.duration_ms ?? null,
297
+ posterUrl: wire.poster_url ?? null
298
+ };
299
+ if (matrx) {
300
+ const block2 = { ...common, ...matrx, ...videoBits };
301
+ return block2;
302
+ }
303
+ const block = {
304
+ ...common,
305
+ ...externalFields(wire),
306
+ ...videoBits
307
+ };
308
+ return block;
309
+ }
310
+ function liftAudio(wire) {
311
+ const common = commonFields(wire);
312
+ const matrx = matrxFields(wire);
313
+ const audioBits = {
314
+ kind: "audio",
315
+ durationMs: wire.duration_ms ?? null,
316
+ transcript: wire.transcript ?? null
317
+ };
318
+ if (matrx) {
319
+ const block2 = { ...common, ...matrx, ...audioBits };
320
+ return block2;
321
+ }
322
+ const block = {
323
+ ...common,
324
+ ...externalFields(wire),
325
+ ...audioBits
326
+ };
327
+ return block;
328
+ }
329
+ function liftDocument(wire) {
330
+ const common = commonFields(wire);
331
+ const matrx = matrxFields(wire);
332
+ const docBits = {
333
+ kind: "document",
334
+ pageCount: wire.page_count ?? null,
335
+ page1Url: wire.page1_url ?? null
336
+ };
337
+ if (matrx) {
338
+ const block2 = { ...common, ...matrx, ...docBits };
339
+ return block2;
340
+ }
341
+ const block = {
342
+ ...common,
343
+ ...externalFields(wire),
344
+ ...docBits
345
+ };
346
+ return block;
347
+ }
348
+ function liftYouTube(wire) {
349
+ const common = commonFields(wire);
350
+ const block = {
351
+ ...common,
352
+ ...externalFields(wire),
353
+ kind: "youtube",
354
+ videoId: wire.video_id ?? null
355
+ };
356
+ return block;
357
+ }
358
+ function fromMediaBlock(wire) {
359
+ switch (wire.kind) {
360
+ case "image":
361
+ return liftImage(wire);
362
+ case "video":
363
+ return liftVideo(wire);
364
+ case "audio":
365
+ return liftAudio(wire);
366
+ case "document":
367
+ return liftDocument(wire);
368
+ case "youtube":
369
+ return liftYouTube(wire);
370
+ default: {
371
+ const base = wire;
372
+ const unknownKind = wire.kind;
373
+ const fallback = {
374
+ ...commonFields(base),
375
+ ...externalFields(base),
376
+ kind: "image",
377
+ width: null,
378
+ height: null,
379
+ visionClass: null,
380
+ metadata: {
381
+ ...base.metadata ?? {},
382
+ _unknown_media_kind: unknownKind
383
+ },
384
+ errorMessage: `Unsupported media kind: ${unknownKind}`,
385
+ status: "error"
386
+ };
387
+ return fallback;
388
+ }
389
+ }
390
+ }
391
+ function isMediaBlockData(value) {
392
+ if (value === null || typeof value !== "object") return false;
393
+ const v = value;
394
+ if (v.type !== "media_block") return false;
395
+ if (!v.block || typeof v.block !== "object") return false;
396
+ const b = v.block;
397
+ return typeof b.kind === "string" && typeof b.origin === "string";
398
+ }
399
+
400
+ // src/files/blocks/adapters/from-media-ref.ts
401
+ function commonBase(ref) {
402
+ return {
403
+ status: "complete",
404
+ progress: null,
405
+ errorMessage: null,
406
+ mimeType: ref.mime_type ?? null,
407
+ fileName: null,
408
+ sizeBytes: null,
409
+ base64: null,
410
+ metadata: null
411
+ };
412
+ }
413
+ function matrxBase(fileId) {
414
+ return {
415
+ origin: "matrx",
416
+ fileId,
417
+ visibility: "personal",
418
+ cdnUrl: null,
419
+ downloadUrl: null,
420
+ parentFileId: null,
421
+ derivationKind: null
422
+ };
423
+ }
424
+ function externalBase(url) {
425
+ return {
426
+ origin: "external",
427
+ externalUrl: url,
428
+ sourceLabel: null
429
+ };
430
+ }
431
+ function imageBlockFromMediaRef(ref) {
432
+ if (!ref) return null;
433
+ const common = commonBase(ref);
434
+ const imageBits = {
435
+ kind: "image",
436
+ width: null,
437
+ height: null,
438
+ visionClass: null
439
+ };
440
+ if (ref.file_id) {
441
+ const block2 = {
442
+ ...common,
443
+ ...matrxBase(ref.file_id),
444
+ ...imageBits
445
+ };
446
+ return block2;
447
+ }
448
+ const block = {
449
+ ...common,
450
+ ...externalBase(ref.url ?? ""),
451
+ ...imageBits
452
+ };
453
+ return block;
454
+ }
455
+ function videoBlockFromMediaRef(ref) {
456
+ if (!ref) return null;
457
+ const common = commonBase(ref);
458
+ const videoBits = {
459
+ kind: "video",
460
+ width: null,
461
+ height: null,
462
+ durationMs: null,
463
+ posterUrl: null
464
+ };
465
+ if (ref.file_id) {
466
+ const block2 = {
467
+ ...common,
468
+ ...matrxBase(ref.file_id),
469
+ ...videoBits
470
+ };
471
+ return block2;
472
+ }
473
+ const block = {
474
+ ...common,
475
+ ...externalBase(ref.url ?? ""),
476
+ ...videoBits
477
+ };
478
+ return block;
479
+ }
480
+ function blockFromMediaRef(ref, kind) {
481
+ return kind === "video" ? videoBlockFromMediaRef(ref) : imageBlockFromMediaRef(ref);
482
+ }
483
+
484
+ // src/files/blocks/image/helpers/extract-file-id-from-url.ts
485
+ var import_uuid = require("@ai-matrx/kit/uuid");
486
+ function extractFileIdFromUrl(url) {
487
+ if (!url) return null;
488
+ try {
489
+ const parts = new URL(url).pathname.split("/").filter(Boolean);
490
+ if (parts.length >= 2) {
491
+ const candidate = parts[1];
492
+ if ((0, import_uuid.isUuidShape)(candidate)) return candidate;
493
+ }
494
+ const last = parts[parts.length - 1] ?? "";
495
+ const stripped = last.replace(/\.[^.]+$/, "");
496
+ if ((0, import_uuid.isUuidShape)(stripped)) return stripped;
497
+ return null;
498
+ } catch {
499
+ return null;
500
+ }
501
+ }
502
+
503
+ // src/files/blocks/image/helpers/parse-filename-from-url.ts
504
+ var FILENAME_QUERY_KEYS = [
505
+ "response-content-disposition",
506
+ "content-disposition"
507
+ ];
508
+ function parseFilenameFromUrl(url) {
509
+ if (!url) return null;
510
+ let parsed;
511
+ try {
512
+ parsed = new URL(url);
513
+ } catch {
514
+ return null;
515
+ }
516
+ for (const key of FILENAME_QUERY_KEYS) {
517
+ const disposition = parsed.searchParams.get(key);
518
+ if (disposition) {
519
+ const name = parseContentDisposition(disposition);
520
+ if (name) return name;
521
+ }
522
+ }
523
+ return null;
524
+ }
525
+ function parseContentDisposition(value) {
526
+ const extMatch = /filename\*\s*=\s*([A-Za-z0-9_-]+)'(?:[A-Za-z0-9_-]*)'([^;]+)/i.exec(value);
527
+ if (extMatch) {
528
+ const charset = extMatch[1];
529
+ const encoded = extMatch[2].trim();
530
+ try {
531
+ const decoded = decodeURIComponent(encoded);
532
+ if (charset.toLowerCase() === "utf-8") return safeName(decoded);
533
+ return safeName(decoded);
534
+ } catch {
535
+ }
536
+ }
537
+ const basicMatch = /filename\s*=\s*(?:"([^"]+)"|([^;]+))/i.exec(value);
538
+ if (basicMatch) {
539
+ const raw = (basicMatch[1] ?? basicMatch[2] ?? "").trim();
540
+ if (raw) return safeName(raw);
541
+ }
542
+ return null;
543
+ }
544
+ function safeName(name) {
545
+ const leaf = name.split(/[/\\]/).pop()?.trim();
546
+ if (!leaf) return null;
547
+ if (/[\x00-\x1f]/.test(leaf)) return null;
548
+ return leaf;
549
+ }
550
+
551
+ // src/files/blocks/image/adapters/from-image-output-data.ts
552
+ var import_files = require("@ai-matrx/data/files");
553
+ function metaString(metadata, key) {
554
+ if (!metadata) return null;
555
+ const value = metadata[key];
556
+ return typeof value === "string" ? value : null;
557
+ }
558
+ function metaNumber(metadata, key) {
559
+ if (!metadata) return null;
560
+ const value = metadata[key];
561
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
562
+ }
563
+ function metaVisibility(metadata) {
564
+ const value = metaString(metadata, "visibility");
565
+ if (value === "public" || value === "personal" || value === "internal" || value === "link")
566
+ return value;
567
+ if (value === "shared" || value === "private") return "personal";
568
+ return "personal";
569
+ }
570
+ function fromImageOutputData(data, carriedMetadata) {
571
+ const metadata = carriedMetadata ?? null;
572
+ const cdnUrl = data.cdn_url ?? null;
573
+ const downloadUrl = data.download_url ?? null;
574
+ const fallbackUrl = data.url;
575
+ const fallbackLooksSigned = (0, import_files.isSignedUrl)(fallbackUrl);
576
+ const finalCdnUrl = cdnUrl ?? (fallbackLooksSigned ? null : fallbackUrl ?? null);
577
+ const explicitFileId = data.file_id ?? null;
578
+ const inferredFileId = explicitFileId ?? extractFileIdFromUrl(finalCdnUrl) ?? extractFileIdFromUrl(fallbackUrl) ?? null;
579
+ const common = {
580
+ kind: "image",
581
+ base64: null,
582
+ mimeType: data.mime_type ?? null,
583
+ // Filename priority:
584
+ // 1. Explicit `file_name` in the event metadata (Python's intent).
585
+ // 2. The filename baked into the signed URL's
586
+ // `response-content-disposition` query param — Python sets this
587
+ // to the AI-chosen name on every signed-URL mint, and it's the
588
+ // ground truth for "what should the user see on download".
589
+ // 3. null — fall back to a generic `image.<ext>` at the callsite.
590
+ fileName: metaString(metadata, "file_name") ?? parseFilenameFromUrl(downloadUrl) ?? parseFilenameFromUrl(finalCdnUrl) ?? null,
591
+ width: metaNumber(metadata, "width"),
592
+ height: metaNumber(metadata, "height"),
593
+ // Phase 0 wire rename: prefer `size_bytes`, accept legacy `file_size`
594
+ // from in-flight services that haven't redeployed yet.
595
+ sizeBytes: metaNumber(metadata, "size_bytes") ?? metaNumber(metadata, "file_size"),
596
+ visionClass: metaString(metadata, "vision_class"),
597
+ status: "complete",
598
+ progress: null,
599
+ errorMessage: null,
600
+ metadata: metadata ?? null
601
+ };
602
+ if (inferredFileId) {
603
+ const matrx = {
604
+ ...common,
605
+ origin: "matrx",
606
+ fileId: inferredFileId,
607
+ visibility: metaVisibility(metadata),
608
+ cdnUrl: finalCdnUrl,
609
+ downloadUrl,
610
+ // Phase 1b: thumbnails removed from MatrxImageBlock — the canonical
611
+ // source is `Asset.variants["thumbnail_url"].url` via GET /assets/{id}.
612
+ // For top-level listings, `CloudFile.thumbnailUrl` (lifted from
613
+ // `FileRecord.thumbnail_url`) is the FE-side cache of that resolved URL.
614
+ parentFileId: metaString(metadata, "parent_file_id"),
615
+ derivationKind: metaString(metadata, "derivation_kind")
616
+ };
617
+ return matrx;
618
+ }
619
+ const externalUrl = fallbackUrl ?? finalCdnUrl ?? "";
620
+ if (!externalUrl) {
621
+ const broken = {
622
+ ...common,
623
+ origin: "external",
624
+ externalUrl: "",
625
+ sourceLabel: metaString(metadata, "source_label")
626
+ };
627
+ return broken;
628
+ }
629
+ const external = {
630
+ ...common,
631
+ origin: "external",
632
+ externalUrl,
633
+ sourceLabel: metaString(metadata, "source_label")
634
+ };
635
+ return external;
636
+ }
637
+
638
+ // src/files/blocks/image/adapters/from-cx-media-part.ts
639
+ function fromCxMediaPart(part) {
640
+ const metadata = part.metadata ?? null;
641
+ const cdnFromMeta = typeof metadata?.cdn_url === "string" ? metadata.cdn_url : null;
642
+ const downloadFromMeta = typeof metadata?.download_url === "string" ? metadata.download_url : null;
643
+ const fileId = (typeof part.file_id === "string" ? part.file_id : null) ?? (typeof metadata?.file_id === "string" ? metadata.file_id : null);
644
+ const fallbackUrl = part.url ?? cdnFromMeta ?? "";
645
+ const block = fromImageOutputData(
646
+ {
647
+ type: "image_output",
648
+ url: fallbackUrl,
649
+ mime_type: part.mime_type ?? "image/*",
650
+ file_id: fileId,
651
+ cdn_url: cdnFromMeta,
652
+ download_url: downloadFromMeta
653
+ },
654
+ {
655
+ // Pass through all metadata so the extension fields (visibility,
656
+ // thumbnail, dimensions, etc.) get lifted by the rich adapter.
657
+ // Stored parts from before the storage-location eradication may
658
+ ...metadata ?? {}
659
+ }
660
+ );
661
+ const withRole = {
662
+ ...block,
663
+ referenceRole: part.role ?? null,
664
+ referenceName: part.name ?? null
665
+ };
666
+ if (typeof metadata?.base64_data === "string") {
667
+ return { ...withRole, base64: metadata.base64_data };
668
+ }
669
+ return withRole;
670
+ }
671
+
672
+ // src/files/blocks/image/adapters/from-partial-image-data.ts
673
+ function fromPartialImageData(data, carriedMetadata) {
674
+ return {
675
+ kind: "image",
676
+ origin: "external",
677
+ base64: data.b64_json,
678
+ mimeType: data.mime_type ?? "image/png",
679
+ fileName: null,
680
+ width: null,
681
+ height: null,
682
+ sizeBytes: null,
683
+ visionClass: null,
684
+ status: "streaming",
685
+ progress: data.progress ?? null,
686
+ errorMessage: null,
687
+ metadata: carriedMetadata ?? null,
688
+ externalUrl: "",
689
+ sourceLabel: "Generating"
690
+ };
691
+ }
692
+
693
+ // src/files/blocks/image/adapters/from-render-block.ts
694
+ function fromRenderBlock(block) {
695
+ const data = block.data ?? {};
696
+ const src = typeof data.src === "string" ? data.src : "";
697
+ const mimeType = typeof data.mime_type === "string" ? data.mime_type : "image/*";
698
+ return fromImageOutputData(
699
+ {
700
+ type: "image_output",
701
+ url: src,
702
+ mime_type: mimeType
703
+ },
704
+ block.metadata ?? null
705
+ );
706
+ }
707
+
708
+ // src/files/blocks/image/adapters/to-cx-media-part.ts
709
+ function toCxMediaPart(block) {
710
+ const visibleUrl = block.origin === "matrx" ? block.cdnUrl ?? void 0 : block.externalUrl || void 0;
711
+ const callerMetadata = block.metadata ?? {};
712
+ const packed = {
713
+ ...callerMetadata,
714
+ kind: block.kind,
715
+ origin: block.origin,
716
+ mime_type: block.mimeType,
717
+ file_name: block.fileName,
718
+ width: block.width,
719
+ height: block.height,
720
+ size_bytes: block.sizeBytes,
721
+ vision_class: block.visionClass,
722
+ status: block.status,
723
+ progress: block.progress,
724
+ error_message: block.errorMessage
725
+ };
726
+ delete packed.signed_url;
727
+ delete packed.signed_url_expires_at;
728
+ if (block.origin === "matrx") {
729
+ packed.cdn_url = block.cdnUrl;
730
+ packed.download_url = block.downloadUrl;
731
+ packed.file_id = block.fileId;
732
+ packed.visibility = block.visibility;
733
+ packed.parent_file_id = block.parentFileId;
734
+ packed.derivation_kind = block.derivationKind;
735
+ } else {
736
+ packed.external_url = block.externalUrl;
737
+ packed.source_label = block.sourceLabel;
738
+ }
739
+ if (block.base64) {
740
+ packed.base64_data = block.base64;
741
+ }
742
+ const common = {
743
+ type: "media",
744
+ kind: "image",
745
+ ...block.mimeType !== null ? { mime_type: block.mimeType } : {},
746
+ ...block.sizeBytes !== null ? { size_bytes: block.sizeBytes } : {},
747
+ ...block.width !== null ? { width: block.width } : {},
748
+ ...block.height !== null ? { height: block.height } : {},
749
+ metadata: packed
750
+ };
751
+ if (block.origin === "matrx") {
752
+ return {
753
+ ...common,
754
+ origin: "matrx",
755
+ file_id: block.fileId,
756
+ ...visibleUrl ? { url: visibleUrl } : {}
757
+ };
758
+ }
759
+ const externalUrl = visibleUrl ?? (block.base64 ? `data:${block.mimeType ?? "image/*"};base64,${block.base64}` : null);
760
+ if (!externalUrl) {
761
+ throw new TypeError(
762
+ "Cannot project external image into chat.message.content: missing URL and base64 locator"
763
+ );
764
+ }
765
+ return {
766
+ ...common,
767
+ origin: "external",
768
+ url: externalUrl
769
+ };
770
+ }
771
+
772
+ // src/files/blocks/image/helpers/derive-viewer-url.ts
773
+ function deriveViewerUrl(block) {
774
+ if (block.origin === "external") return null;
775
+ return `/files/f/${block.fileId}`;
776
+ }
777
+
778
+ // src/react/cn.ts
779
+ var import_tailwind_merge = require("tailwind-merge");
780
+ function cn(...inputs) {
781
+ return (0, import_tailwind_merge.twMerge)(inputs.filter(Boolean).join(" "));
782
+ }
783
+
784
+ // src/files/media/video-date.ts
785
+ var COMPACT_VIDEO_DATE = new Intl.DateTimeFormat("en-US", {
786
+ month: "2-digit",
787
+ day: "2-digit",
788
+ year: "2-digit",
789
+ timeZone: "UTC"
790
+ });
791
+ var FULL_VIDEO_DATE = new Intl.DateTimeFormat("en-US", {
792
+ month: "long",
793
+ day: "numeric",
794
+ year: "numeric",
795
+ timeZone: "UTC"
796
+ });
797
+ function parseVideoDate(value) {
798
+ if (!value) return null;
799
+ const date = new Date(value);
800
+ return Number.isNaN(date.getTime()) ? null : date;
801
+ }
802
+ function formatVideoPublishDate(value) {
803
+ const date = parseVideoDate(value);
804
+ return date ? COMPACT_VIDEO_DATE.format(date) : "No Date";
805
+ }
806
+ function formatVideoPublishDateTitle(value) {
807
+ const date = parseVideoDate(value);
808
+ return date ? `Published ${FULL_VIDEO_DATE.format(date)}` : "Publish date unavailable";
809
+ }
810
+ var VIDEO_DATE_KEYS = [
811
+ "published_at",
812
+ "publishedAt",
813
+ "publish_date",
814
+ "publishDate",
815
+ "uploadDate",
816
+ "datePublished"
817
+ ];
818
+ var VIDEO_METADATA_CONTAINERS = [
819
+ "video_metadata",
820
+ "schema_org",
821
+ "metadata"
822
+ ];
823
+ function videoPublishDateFromMetadata(value) {
824
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
825
+ const record = value;
826
+ for (const key of VIDEO_DATE_KEYS) {
827
+ const candidate = record[key];
828
+ if (typeof candidate === "string" && parseVideoDate(candidate)) {
829
+ return candidate;
830
+ }
831
+ }
832
+ for (const key of VIDEO_METADATA_CONTAINERS) {
833
+ const nested = videoPublishDateFromMetadata(record[key]);
834
+ if (nested) return nested;
835
+ }
836
+ return null;
837
+ }
838
+
839
+ // src/files/blocks/video/VideoPublishDate.tsx
840
+ var import_jsx_runtime = require("react/jsx-runtime");
841
+ function VideoPublishDate({
842
+ publishedAt,
843
+ className
844
+ }) {
845
+ const dateTime = publishedAt && !Number.isNaN(new Date(publishedAt).getTime()) ? publishedAt : void 0;
846
+ const content = formatVideoPublishDate(publishedAt);
847
+ const sharedProps = {
848
+ className: cn(
849
+ "shrink-0 whitespace-nowrap text-[10px] tabular-nums text-muted-foreground",
850
+ className
851
+ ),
852
+ title: formatVideoPublishDateTitle(publishedAt),
853
+ "aria-label": formatVideoPublishDateTitle(publishedAt)
854
+ };
855
+ return dateTime ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", { ...sharedProps, dateTime, children: content }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...sharedProps, children: content });
856
+ }
857
+
858
+ // src/files/handler/errors.ts
859
+ var FileHandlerError = class extends Error {
860
+ code;
861
+ fileId;
862
+ cause;
863
+ constructor(code, message, opts) {
864
+ super(message);
865
+ this.name = "FileHandlerError";
866
+ this.code = code;
867
+ this.fileId = opts?.fileId;
868
+ this.cause = opts?.cause;
869
+ }
870
+ };
871
+ var FileAccessDeniedError = class extends FileHandlerError {
872
+ constructor(message = "This file isn't available to you.", opts) {
873
+ super("access_denied", message, opts);
874
+ this.name = "FileAccessDeniedError";
875
+ }
876
+ };
877
+ var FileNotFoundError = class extends FileHandlerError {
878
+ // A 404 from the file server. It proves the server could not retrieve the
879
+ // file — NOT that the file was deleted (that is `FileDeletedError`, which
880
+ // has a `deleted_at` to point at) and not that it never existed.
881
+ constructor(message = "We couldn't retrieve this file.", opts) {
882
+ super("not_found", message, opts);
883
+ this.name = "FileNotFoundError";
884
+ }
885
+ };
886
+ var FileDeletedError = class extends FileHandlerError {
887
+ constructor(message = "File is in trash", opts) {
888
+ super("deleted", message, opts);
889
+ this.name = "FileDeletedError";
890
+ }
891
+ };
892
+ var ShareLinkInvalidError = class extends FileHandlerError {
893
+ constructor(message = "Share link is invalid, expired, or revoked") {
894
+ super("share_link_invalid", message);
895
+ this.name = "ShareLinkInvalidError";
896
+ }
897
+ };
898
+ var ExternalFetchError = class extends FileHandlerError {
899
+ constructor(message = "Failed to fetch external URL", opts) {
900
+ super("external_fetch_failed", message, opts);
901
+ this.name = "ExternalFetchError";
902
+ }
903
+ };
904
+ var FileUploadError = class extends FileHandlerError {
905
+ constructor(message, opts) {
906
+ super("upload_failed", message, opts);
907
+ this.name = "FileUploadError";
908
+ }
909
+ };
910
+ var UploadCancelledError = class extends FileHandlerError {
911
+ constructor(message = "Upload cancelled \u2014 no workspace was selected.") {
912
+ super("upload_cancelled", message);
913
+ this.name = "UploadCancelledError";
914
+ }
915
+ };
916
+ function isUploadCancelledError(error) {
917
+ return error instanceof Error && error.name === "UploadCancelledError";
918
+ }
919
+
920
+ // src/files/utils/folder-conventions.ts
921
+ var CloudFolders = {
922
+ // ── Visible / user-managed ────────────────────────────────────────────
923
+ /** Top-level "Images" drawer. */
924
+ IMAGES: "Images",
925
+ /** Images pasted/attached inside a chat. */
926
+ IMAGES_CHAT: "Images/Chat",
927
+ /** Screenshots dragged or pasted into the app. */
928
+ IMAGES_SCREENSHOTS: "Images/Screenshots",
929
+ /** User avatars / profile images. */
930
+ IMAGES_AVATARS: "Images/Avatars",
931
+ /** Images generated by AI tools. */
932
+ IMAGES_GENERATED: "Images/Generated",
933
+ /** Screenshots and images flattened with user-authored markup. */
934
+ IMAGES_ANNOTATED: "Images/Annotated",
935
+ /** Top-level "Audio" drawer. */
936
+ AUDIO: "Audio",
937
+ /** User-initiated audio recordings (voice-to-text, voice pad, etc.). */
938
+ AUDIO_RECORDINGS: "Audio/Recordings",
939
+ /** Podcast asset uploads. */
940
+ AUDIO_PODCASTS: "Audio/Podcasts",
941
+ /** Top-level "Captures" drawer — everything the in-browser media-capture
942
+ * system saves (features/media-capture). User-produced, so visible. */
943
+ CAPTURES: "Captures",
944
+ /** Photos taken with the in-app camera (Capture Studio / device fallback). */
945
+ CAPTURES_PHOTOS: "Captures/Photos",
946
+ /** Videos recorded with the in-app camera (media-capture Phase 7). */
947
+ CAPTURES_VIDEOS: "Captures/Videos",
948
+ /** Audio recorded through the Capture Studio (media-capture Phase 7). */
949
+ CAPTURES_AUDIO: "Captures/Audio",
950
+ /** Product-capture staging (features/product-capture) — per-item folders of
951
+ * photos/videos/voice notes shot ahead of listing creation. Org-namespaced
952
+ * via `folderForProductCaptureItem` (same server one-path-one-org rule as
953
+ * Captures). User-produced, so visible. */
954
+ PRODUCT_CAPTURES: "Product Captures",
955
+ /** Commerce intake (W4 capture app): per-asset media filed under
956
+ * `Commerce Intake/<orgId>/<batchId>/<asset-leaf>` via
957
+ * `folderForIntakeAsset` (same server one-path-one-org rule as Captures).
958
+ * User-produced, so visible. */
959
+ COMMERCE_INTAKE: "Commerce Intake",
960
+ /**
961
+ * Static app assets (sounds, hero images, model-card thumbnails, demo
962
+ * data) owned by an admin service account and rendered globally.
963
+ * Always public — CDN URL is the goal. Source of truth for the
964
+ * static-asset migration (see scripts/migrate-public-assets-to-cdn.ts).
965
+ */
966
+ APP_ASSETS: "App Assets",
967
+ /** Top-level documents (PDF, DOCX, etc.). */
968
+ DOCUMENTS: "Documents",
969
+ /** PDF-specific drawer. */
970
+ DOCUMENTS_PDFS: "Documents/PDFs",
971
+ /** Top-level code files (scripts, snippets). */
972
+ CODE: "Code",
973
+ /** Code saved via the code-editor window. */
974
+ CODE_EDITOR: "Code/Editor",
975
+ /** Generic AI-generated outputs. */
976
+ GENERATED: "Generated",
977
+ /** Files attached to agent apps, keyed by app id at runtime. */
978
+ AGENT_APPS: "Agent Apps",
979
+ /** Files attached to tasks, keyed by task id at runtime. */
980
+ TASK_ATTACHMENTS: "Task Attachments",
981
+ /** Files attached to War Room tiles, keyed by tile id at runtime. */
982
+ WAR_ROOM: "War Room",
983
+ /** Files dropped into a chat composer (pre-send or history). */
984
+ CHAT_ATTACHMENTS: "Chat Attachments",
985
+ /** Slack-imported files. */
986
+ SLACK_IMPORTS: "Slack Imports",
987
+ /** Web-scrape captures (HTML snapshots, exported markdown). */
988
+ SCRAPED_CONTENT: "Scraped Content",
989
+ // ── Shared assets / org-scoped public surfaces ─────────────────────────
990
+ /**
991
+ * Org-scoped shared assets — logos, hero images, anything an
992
+ * organization renders on a public surface. Keyed by org id at
993
+ * runtime (e.g. `Shared Assets/orgs/<org-id>`). Always public —
994
+ * the CDN URL is the rendering target.
995
+ */
996
+ SHARED_ASSETS_ORGS: "Shared Assets/orgs",
997
+ /** Public screenshot attachments submitted through the feedback window. */
998
+ FEEDBACK_IMAGES: "Shared Assets/feedback-images",
999
+ /**
1000
+ * OG / social-preview covers for HTML pages the user publishes.
1001
+ * Lives under Shared Assets so all org/public-surface previews
1002
+ * share one CDN-backed bucket.
1003
+ */
1004
+ HTML_PAGES_OG: "Shared Assets/html-pages",
1005
+ // ── App-asset subfolders ───────────────────────────────────────────────
1006
+ /**
1007
+ * Favicons rendered by prompt-app / agent-app standalone pages.
1008
+ * Always public — favicon requests are anonymous.
1009
+ */
1010
+ PROMPT_APPS_FAVICONS: "App Assets/prompt-apps/favicons",
1011
+ /**
1012
+ * Per-block assets attached to agent blocks (icons, illustrations,
1013
+ * inline media). Keyed by block id at runtime via
1014
+ * `folderForAgentBlock(blockId)`.
1015
+ */
1016
+ AGENT_BLOCKS: "Agent Apps/blocks",
1017
+ // ── Canvas / image-editor ──────────────────────────────────────────────
1018
+ /**
1019
+ * Cover images rendered on canvas social/share surfaces. Public so
1020
+ * the share-card OG image is a stable CDN URL.
1021
+ */
1022
+ CANVAS_COVERS: "Images/Canvas/Covers",
1023
+ /**
1024
+ * Source images the user is editing in the image studio. Private —
1025
+ * these are the user's working files, NOT public render targets.
1026
+ * Outputs that the user explicitly publishes land elsewhere.
1027
+ */
1028
+ IMAGES_EDITED_SOURCES: "Images/Edited/Sources",
1029
+ // ── Hidden / ephemeral ─────────────────────────────────────────────────
1030
+ // All hidden roots live under ".matrx-tmp/" so the tree has a single
1031
+ // ignorable folder rather than many. Callers that use these MUST delete
1032
+ // the file when done.
1033
+ /** Root for all ephemeral cloud-files work. Hidden in the tree. */
1034
+ TMP: ".matrx-tmp",
1035
+ /** Short-lived audio files staged for URL-based transcription. */
1036
+ TMP_TRANSCRIPTS: ".matrx-tmp/transcripts",
1037
+ /** Upload-in-progress staging (future use). */
1038
+ TMP_UPLOADS: ".matrx-tmp/uploads",
1039
+ // ── System / infrastructure ────────────────────────────────────────────
1040
+ // Owned and populated by the Python backend (not the user). These rows
1041
+ // exist in `cld_files` / `cld_folders` so they have asset IDs, but they
1042
+ // must NEVER appear in the user-facing tree.
1043
+ //
1044
+ // The Phase 1b/1c "SOCIAL_BASELINE" backfill (2026-05-16) created
1045
+ // `cld_files` rows under `system-files/variants/<file_id>/<og|thumb|tiny|page1_url>.jpg`
1046
+ // — three to four rows per source file. The cascade was cleaned up
1047
+ // server-side on 2026-05-16 (migrations 012/013); the tree RPCs now
1048
+ // exclude `parent_file_id IS NOT NULL` and `file_path LIKE
1049
+ // 'system-files/%'`. The FE keeps `isSystemPath` as a defensive guard
1050
+ // at every tree boundary (loadUserFileTree, loadFolderContents,
1051
+ // realtime middleware). See common-docs systems/files/file-service/WIRE_CONTRACT.md.
1052
+ /** Root for backend-owned infrastructure files (variants, posters, etc.). */
1053
+ SYSTEM_FILES: "system-files",
1054
+ /** SOCIAL_BASELINE variant storage: og.jpg / thumb.jpg / tiny.jpg / page1_url.jpg. */
1055
+ SYSTEM_VARIANTS: "system-files/variants",
1056
+ /**
1057
+ * Backend "generations" registry root — every AI generation (image,
1058
+ * video, audio/TTS) the server materializes lands under
1059
+ * `generations/<images|video|audio>/...`. Backend-owned; mirrors the
1060
+ * server's `is_system_path()` (which treats `system-files` AND
1061
+ * `generations` as system). Never shown in the user tree.
1062
+ */
1063
+ GENERATIONS: "generations",
1064
+ /**
1065
+ * Recorded audio captured by the Transcripts / voice features. As of
1066
+ * 2026-06-14 the backend relocates every `origin: "transcripts"` upload
1067
+ * here, UNDER the hidden `system-files/` root — one
1068
+ * `recording_<iso>_<rand>.webm` per capture (80+ for an active user).
1069
+ * Because it's under `system-files/`, `isSystemPath` already hides it
1070
+ * from the tree, folder views, AND Recents — no separate predicate
1071
+ * needed. Managed exclusively via the Transcripts UI (by `cld_files.id`).
1072
+ * See docs/files/transcript-recordings-system-relocation.md.
1073
+ */
1074
+ TRANSCRIPT_RECORDINGS: "system-files/transcripts/Recordings",
1075
+ /**
1076
+ * LEGACY user-namespace location for transcript recordings, before the
1077
+ * 2026-06-14 backend relocation to `system-files/transcripts/...`. Kept
1078
+ * ONLY as a defensive Recents guard: the backend relocates every
1079
+ * `origin: "transcripts"` upload, but the presigned/TUS (chunked + large
1080
+ * file) relocation path was genuinely missing and is committed but NOT yet
1081
+ * in prod as of 2026-06-15.
1082
+ *
1083
+ * DO NOT DROP THIS GUARD until that backend fix has DEPLOYED to prod —
1084
+ * dropping it earlier would let a chunked/large recording slip through
1085
+ * unhidden. Sequence: backend deploys → then remove this constant from
1086
+ * `isSystemManagedContentPath` (and delete it). See the FE-response /
1087
+ * "open items" in docs/files/transcript-recordings-system-relocation.md.
1088
+ */
1089
+ TRANSCRIPT_RECORDINGS_LEGACY: "Transcripts/Recordings",
1090
+ // ── System-managed user content (browsable, but NOT in Recents) ─────────
1091
+ // Lives under USER roots (so it stays visible in the Files browser), but
1092
+ // is machine-named, high-volume, and background-produced — so it must
1093
+ // never pollute the Recents stream (your "entire reality" on open).
1094
+ /**
1095
+ * Per-tool generated image variants — `tool-images/<id>/v/<name>.jpg`,
1096
+ * multiple sizes per source. Machine-produced output, excluded from
1097
+ * Recents (see `isSystemManagedContentPath`).
1098
+ */
1099
+ TOOL_IMAGES: "tool-images",
1100
+ /**
1101
+ * FastFire voice-drill recordings — full-session + per-card response clips.
1102
+ * Live under the hidden `system-files/fastfire/...` root (same class as
1103
+ * transcript recordings). Managed via Education / FastFire UI only.
1104
+ */
1105
+ SYSTEM_FASTFIRE: "system-files/fastfire",
1106
+ SYSTEM_FASTFIRE_SESSIONS: "system-files/fastfire/sessions",
1107
+ SYSTEM_FASTFIRE_RESPONSES: "system-files/fastfire/responses",
1108
+ /**
1109
+ * Spoken Practice (oral exam / interview / debate) recordings — full-session
1110
+ * clips + per-prompt spoken-answer clips. Same hidden `system-files/` class as
1111
+ * FastFire (so `isSystemPath` keeps them out of the Files browser + Recents).
1112
+ */
1113
+ SYSTEM_SPOKEN_PRACTICE: "system-files/spoken-practice",
1114
+ SYSTEM_SPOKEN_PRACTICE_SESSIONS: "system-files/spoken-practice/sessions",
1115
+ SYSTEM_SPOKEN_PRACTICE_RESPONSES: "system-files/spoken-practice/responses",
1116
+ /**
1117
+ * Handwritten / image-answer grading — photos of worked problems a learner
1118
+ * submits to the vision grader (assessment written-item photo answers +
1119
+ * the standalone "Grade my handwritten work" surface). Same hidden
1120
+ * `system-files/` class (kept out of the Files browser + Recents).
1121
+ */
1122
+ SYSTEM_IMAGE_GRADE: "system-files/image-grade",
1123
+ SYSTEM_IMAGE_GRADE_RESPONSES: "system-files/image-grade/responses",
1124
+ /**
1125
+ * LEGACY user-namespace FastFire paths (pre-2026-07 relocation). Kept as a
1126
+ * defensive tree + Recents guard until every row is backfilled under
1127
+ * `system-files/fastfire/`.
1128
+ */
1129
+ FASTFIRE_SESSIONS: "FastFire/sessions",
1130
+ FASTFIRE_RESPONSES: "FastFire/responses"
1131
+ };
1132
+ function folderForTask(taskId) {
1133
+ return `${CloudFolders.TASK_ATTACHMENTS}/${taskId}`;
1134
+ }
1135
+ function folderForWarRoomThread(threadId) {
1136
+ return `${CloudFolders.WAR_ROOM}/${threadId}`;
1137
+ }
1138
+ function folderForConversation(conversationId) {
1139
+ return `${CloudFolders.CHAT_ATTACHMENTS}/${conversationId}`;
1140
+ }
1141
+ function folderForAgentApp(appId) {
1142
+ return `${CloudFolders.AGENT_APPS}/${appId}`;
1143
+ }
1144
+ function folderForPodcast(podcastId) {
1145
+ return `${CloudFolders.AUDIO_PODCASTS}/${podcastId}`;
1146
+ }
1147
+ function folderForOrg(orgId) {
1148
+ return `${CloudFolders.SHARED_ASSETS_ORGS}/${orgId}`;
1149
+ }
1150
+ function folderForAgentBlock(blockId) {
1151
+ return `${CloudFolders.AGENT_BLOCKS}/${blockId}`;
1152
+ }
1153
+ function folderForCaptures(kind, orgId) {
1154
+ const leaf = kind === "photo" ? "Photos" : kind === "video" ? "Videos" : "Audio";
1155
+ const trimmed = typeof orgId === "string" ? orgId.trim() : "";
1156
+ if (trimmed) {
1157
+ return `${CloudFolders.CAPTURES}/${trimmed}/${leaf}`;
1158
+ }
1159
+ return kind === "photo" ? CloudFolders.CAPTURES_PHOTOS : kind === "video" ? CloudFolders.CAPTURES_VIDEOS : CloudFolders.CAPTURES_AUDIO;
1160
+ }
1161
+ function folderForProductCaptureItem(orgId, leaf) {
1162
+ const safe = leaf.replace(/[^A-Za-z0-9._@-]+/g, "-").replace(/^-+|-+$/g, "");
1163
+ return `${CloudFolders.PRODUCT_CAPTURES}/${orgId.trim()}/${safe}`;
1164
+ }
1165
+ function folderForIntakeAsset(orgId, batchId, leaf) {
1166
+ const safe = leaf.replace(/[^A-Za-z0-9._@-]+/g, "-").replace(/^-+|-+$/g, "");
1167
+ return `${CloudFolders.COMMERCE_INTAKE}/${orgId.trim()}/${batchId.trim()}/${safe || batchId.trim()}`;
1168
+ }
1169
+ function isHiddenFolder(folderPath) {
1170
+ return folderPath === CloudFolders.TMP || folderPath.startsWith(".matrx-tmp/");
1171
+ }
1172
+ function isSystemPath(path) {
1173
+ if (!path) return false;
1174
+ return path === CloudFolders.SYSTEM_FILES || path.startsWith(`${CloudFolders.SYSTEM_FILES}/`) || path === CloudFolders.GENERATIONS || path.startsWith(`${CloudFolders.GENERATIONS}/`) || path === CloudFolders.TMP || path.startsWith(`${CloudFolders.TMP}/`);
1175
+ }
1176
+ function isConventionalFolder(folderPath) {
1177
+ const all = Object.values(CloudFolders);
1178
+ return all.includes(folderPath);
1179
+ }
1180
+ var CloudFolderDescriptions = {
1181
+ [CloudFolders.IMAGES]: "All your images, organized.",
1182
+ [CloudFolders.IMAGES_CHAT]: "Images shared in chat.",
1183
+ [CloudFolders.IMAGES_SCREENSHOTS]: "Screenshots you pasted or dragged in.",
1184
+ [CloudFolders.IMAGES_AVATARS]: "Profile pictures and avatars.",
1185
+ [CloudFolders.IMAGES_GENERATED]: "AI-generated images.",
1186
+ [CloudFolders.AUDIO]: "Audio files.",
1187
+ [CloudFolders.AUDIO_RECORDINGS]: "Voice recordings.",
1188
+ [CloudFolders.AUDIO_PODCASTS]: "Podcast assets.",
1189
+ [CloudFolders.CAPTURES]: "Photos, videos, and audio captured in the app.",
1190
+ [CloudFolders.CAPTURES_PHOTOS]: "Photos taken with the in-app camera.",
1191
+ [CloudFolders.CAPTURES_VIDEOS]: "Videos recorded with the in-app camera.",
1192
+ [CloudFolders.CAPTURES_AUDIO]: "Audio recorded in the Capture Studio.",
1193
+ [CloudFolders.APP_ASSETS]: "Static app assets shared across the platform.",
1194
+ [CloudFolders.DOCUMENTS]: "Documents and reports.",
1195
+ [CloudFolders.DOCUMENTS_PDFS]: "PDFs.",
1196
+ [CloudFolders.CODE]: "Code files.",
1197
+ [CloudFolders.GENERATED]: "Files produced by AI tools.",
1198
+ [CloudFolders.AGENT_APPS]: "Assets attached to your agent apps.",
1199
+ [CloudFolders.TASK_ATTACHMENTS]: "Files attached to tasks.",
1200
+ [CloudFolders.CHAT_ATTACHMENTS]: "Files shared in conversations.",
1201
+ [CloudFolders.SLACK_IMPORTS]: "Files imported from Slack.",
1202
+ [CloudFolders.SCRAPED_CONTENT]: "Captures from the web scraper.",
1203
+ [CloudFolders.SHARED_ASSETS_ORGS]: "Organization-scoped shared assets.",
1204
+ [CloudFolders.HTML_PAGES_OG]: "OG covers for HTML pages.",
1205
+ [CloudFolders.PROMPT_APPS_FAVICONS]: "Favicons for prompt-app pages.",
1206
+ [CloudFolders.AGENT_BLOCKS]: "Per-block agent app assets.",
1207
+ [CloudFolders.CANVAS_COVERS]: "Canvas social cover images.",
1208
+ [CloudFolders.IMAGES_EDITED_SOURCES]: "Source images for the image studio.",
1209
+ [CloudFolders.TMP]: "Internal temporary workspace (hidden)."
1210
+ };
1211
+ var DEFAULT_VISIBILITY_RULES = [
1212
+ // Most-specific rules first — longest-prefix wins.
1213
+ { prefix: "Shared Assets/feedback-images", visibility: "public" },
1214
+ { prefix: CloudFolders.SHARED_ASSETS_ORGS, visibility: "public" },
1215
+ { prefix: CloudFolders.HTML_PAGES_OG, visibility: "public" },
1216
+ { prefix: CloudFolders.PROMPT_APPS_FAVICONS, visibility: "public" },
1217
+ { prefix: CloudFolders.AGENT_BLOCKS, visibility: "public" },
1218
+ { prefix: CloudFolders.CANVAS_COVERS, visibility: "public" },
1219
+ { prefix: CloudFolders.APP_ASSETS, visibility: "public" },
1220
+ { prefix: CloudFolders.IMAGES_AVATARS, visibility: "public" },
1221
+ { prefix: CloudFolders.AUDIO_PODCASTS, visibility: "public" },
1222
+ { prefix: CloudFolders.AGENT_APPS, visibility: "public" },
1223
+ { prefix: "Shared Assets", visibility: "public" },
1224
+ // IMAGES_EDITED_SOURCES is private — these are the user's working
1225
+ // source files for the image studio, not public render targets.
1226
+ // Captures are the user's own camera/mic output — never public render
1227
+ // targets. Explicit rule (not just the fallback) so the intent is recorded.
1228
+ { prefix: CloudFolders.CAPTURES, visibility: "personal" },
1229
+ { prefix: CloudFolders.IMAGES_EDITED_SOURCES, visibility: "personal" },
1230
+ { prefix: CloudFolders.IMAGES_GENERATED, visibility: "personal" },
1231
+ { prefix: CloudFolders.CHAT_ATTACHMENTS, visibility: "personal" },
1232
+ { prefix: CloudFolders.TASK_ATTACHMENTS, visibility: "personal" },
1233
+ { prefix: CloudFolders.WAR_ROOM, visibility: "personal" },
1234
+ { prefix: CloudFolders.SLACK_IMPORTS, visibility: "personal" },
1235
+ { prefix: CloudFolders.SCRAPED_CONTENT, visibility: "personal" },
1236
+ { prefix: "Private Assets", visibility: "personal" },
1237
+ { prefix: CloudFolders.TMP, visibility: "personal" }
1238
+ ];
1239
+ function resolveDefaultVisibility(folderPath) {
1240
+ const normalized = folderPath.replace(/^\/+|\/+$/g, "");
1241
+ let best = null;
1242
+ for (const rule of DEFAULT_VISIBILITY_RULES) {
1243
+ if (normalized === rule.prefix || normalized.startsWith(`${rule.prefix}/`)) {
1244
+ if (!best || rule.prefix.length > best.prefix.length) {
1245
+ best = rule;
1246
+ }
1247
+ }
1248
+ }
1249
+ return best?.visibility ?? "personal";
1250
+ }
1251
+
1252
+ // src/files/handler/utils/upload-folder-path.ts
1253
+ var TOP_LEVEL_FOLDERS = {
1254
+ userContent: "My Files",
1255
+ images: CloudFolders.IMAGES,
1256
+ Images: CloudFolders.IMAGES,
1257
+ audio: CloudFolders.AUDIO,
1258
+ Audio: CloudFolders.AUDIO,
1259
+ "audio-recordings": CloudFolders.AUDIO_RECORDINGS,
1260
+ documents: CloudFolders.DOCUMENTS,
1261
+ Documents: CloudFolders.DOCUMENTS,
1262
+ code: CloudFolders.CODE,
1263
+ Code: CloudFolders.CODE,
1264
+ "any-file": "Uploads",
1265
+ attachments: CloudFolders.CHAT_ATTACHMENTS
1266
+ };
1267
+ function composeUploadFolderPath(root = "Uploads", path) {
1268
+ const top = (TOP_LEVEL_FOLDERS[root] ?? root).replace(/^\/+|\/+$/g, "");
1269
+ const sub = (path ?? "").replace(/^\/+|\/+$/g, "");
1270
+ return sub ? `${top}/${sub}` : top;
1271
+ }
1272
+
1273
+ // src/files/media/object-url-registry.ts
1274
+ var MAX_LIVE = 256;
1275
+ var live = /* @__PURE__ */ new Map();
1276
+ function createTrackedObjectUrl(blob) {
1277
+ const url = URL.createObjectURL(blob);
1278
+ live.set(url, true);
1279
+ while (live.size > MAX_LIVE) {
1280
+ const oldest = live.keys().next().value;
1281
+ if (!oldest) break;
1282
+ live.delete(oldest);
1283
+ try {
1284
+ URL.revokeObjectURL(oldest);
1285
+ } catch {
1286
+ }
1287
+ }
1288
+ return url;
1289
+ }
1290
+ function revokeTrackedObjectUrl(url) {
1291
+ if (!url || !live.has(url)) return;
1292
+ live.delete(url);
1293
+ try {
1294
+ URL.revokeObjectURL(url);
1295
+ } catch {
1296
+ }
1297
+ }
1298
+ //# sourceMappingURL=files.cjs.map