@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
@@ -0,0 +1,836 @@
1
+ import { createSlice } from "@reduxjs/toolkit";
2
+ import {
3
+ addField,
4
+ assignField,
5
+ createFieldFlags,
6
+ hasField,
7
+ removeField
8
+ } from "@ai-matrx/agents/field-flags";
9
+ import { DEFAULT_VISIBLE_COLUMNS } from "../types.js";
10
+ function emptyFileRecord(id) {
11
+ return {
12
+ id,
13
+ ownerId: "",
14
+ filePath: "",
15
+ fileName: "",
16
+ mimeType: null,
17
+ fileSize: null,
18
+ checksum: null,
19
+ visibility: "personal",
20
+ currentVersion: 1,
21
+ parentFolderId: null,
22
+ metadata: {},
23
+ createdAt: "",
24
+ updatedAt: "",
25
+ deletedAt: null,
26
+ publicUrl: null,
27
+ url: null,
28
+ cdnUrl: null,
29
+ downloadUrl: null,
30
+ thumbnailUrl: null,
31
+ source: { kind: "real" },
32
+ _dirty: false,
33
+ _dirtyFields: createFieldFlags(),
34
+ _fieldHistory: {},
35
+ _loadedFields: createFieldFlags(),
36
+ _loading: false,
37
+ _error: null,
38
+ _pendingRequestIds: []
39
+ };
40
+ }
41
+ function emptyFolderRecord(id) {
42
+ return {
43
+ id,
44
+ ownerId: "",
45
+ folderPath: "",
46
+ folderName: "",
47
+ parentId: null,
48
+ visibility: "personal",
49
+ metadata: {},
50
+ createdAt: "",
51
+ updatedAt: "",
52
+ deletedAt: null,
53
+ source: { kind: "real" },
54
+ _dirty: false,
55
+ _dirtyFields: createFieldFlags(),
56
+ _fieldHistory: {},
57
+ _loadedFields: createFieldFlags(),
58
+ _loading: false,
59
+ _error: null,
60
+ _pendingRequestIds: []
61
+ };
62
+ }
63
+ function mergeFileIntoRecord(record, partial) {
64
+ Object.keys(partial).forEach((key) => {
65
+ const value = partial[key];
66
+ if (value !== void 0) {
67
+ assignField(record, key, value);
68
+ addField(record._loadedFields, key);
69
+ }
70
+ });
71
+ }
72
+ function mergeFolderIntoRecord(record, partial) {
73
+ Object.keys(partial).forEach((key) => {
74
+ const value = partial[key];
75
+ if (value !== void 0) {
76
+ assignField(record, key, value);
77
+ addField(record._loadedFields, key);
78
+ }
79
+ });
80
+ }
81
+ function applyFileFieldEdit(record, field, value) {
82
+ if (!hasField(record._dirtyFields, field)) {
83
+ if (field === "fileName" || field === "filePath" || field === "visibility" || field === "parentFolderId" || field === "metadata" || field === "deletedAt") {
84
+ record._fieldHistory[field] = record[field];
85
+ }
86
+ }
87
+ assignField(record, field, value);
88
+ addField(record._dirtyFields, field);
89
+ record._dirty = true;
90
+ }
91
+ function applyFolderFieldEdit(record, field, value) {
92
+ if (!hasField(record._dirtyFields, field)) {
93
+ if (field === "folderName" || field === "folderPath" || field === "parentId" || field === "visibility" || field === "metadata") {
94
+ record._fieldHistory[field] = record[field];
95
+ }
96
+ }
97
+ assignField(record, field, value);
98
+ addField(record._dirtyFields, field);
99
+ record._dirty = true;
100
+ }
101
+ function markFileClean(record) {
102
+ record._dirty = false;
103
+ record._dirtyFields = createFieldFlags();
104
+ record._fieldHistory = {};
105
+ record._error = null;
106
+ }
107
+ function markFolderClean(record) {
108
+ record._dirty = false;
109
+ record._dirtyFields = createFieldFlags();
110
+ record._fieldHistory = {};
111
+ record._error = null;
112
+ }
113
+ const initialState = {
114
+ filesById: {},
115
+ foldersById: {},
116
+ versionsByFileId: {},
117
+ permissionsByResourceId: {},
118
+ shareLinksByResourceId: {},
119
+ tree: {
120
+ rootFolderIds: [],
121
+ rootFileIds: [],
122
+ childrenByFolderId: {},
123
+ fullyLoadedFolderIds: {},
124
+ status: "idle",
125
+ error: null,
126
+ lastReconciledAt: null
127
+ },
128
+ selection: {
129
+ selectedIds: [],
130
+ anchorId: null
131
+ },
132
+ ui: {
133
+ viewMode: "list",
134
+ // Files lists always open most-recently-updated first. Folders still
135
+ // group above files (see `compareNodes`); within each group the newest
136
+ // edit floats to the top.
137
+ sortBy: "updated_at",
138
+ sortDir: "desc",
139
+ kindFilter: "all",
140
+ detailsLevel: "compact",
141
+ columnFilters: {
142
+ name: "",
143
+ type: [],
144
+ extension: "",
145
+ mime: "",
146
+ path: "",
147
+ owner: [],
148
+ modified: "any",
149
+ created: "any",
150
+ size: "any",
151
+ access: "any",
152
+ rag: []
153
+ },
154
+ visibleColumns: { ...DEFAULT_VISIBLE_COLUMNS },
155
+ searchQuery: "",
156
+ chipFilter: null,
157
+ activeFileId: null,
158
+ activeFolderId: null,
159
+ focusedId: null
160
+ },
161
+ uploads: {},
162
+ ragStatus: {
163
+ byFileId: {},
164
+ isFetching: false,
165
+ lastFetchedAt: null
166
+ },
167
+ realtime: {
168
+ status: "detached",
169
+ userId: null,
170
+ lastEventAt: null,
171
+ error: null
172
+ }
173
+ };
174
+ const slice = createSlice({
175
+ name: "cloudFiles",
176
+ initialState,
177
+ reducers: {
178
+ // ---- Files: upsert / merge ---------------------------------------------
179
+ upsertFiles(state, action) {
180
+ for (const partial of action.payload) {
181
+ if (!partial.id) continue;
182
+ const existing = state.filesById[partial.id] ?? emptyFileRecord(partial.id);
183
+ mergeFileIntoRecord(existing, partial);
184
+ state.filesById[partial.id] = existing;
185
+ }
186
+ },
187
+ upsertFile(state, action) {
188
+ const partial = action.payload;
189
+ if (!partial.id) return;
190
+ const existing = state.filesById[partial.id] ?? emptyFileRecord(partial.id);
191
+ mergeFileIntoRecord(existing, partial);
192
+ state.filesById[partial.id] = existing;
193
+ },
194
+ // ---- Files: field edits (optimistic) -----------------------------------
195
+ setFileField(state, action) {
196
+ const { id, field, value } = action.payload;
197
+ const record = state.filesById[id];
198
+ if (!record) return;
199
+ applyFileFieldEdit(record, field, value);
200
+ },
201
+ resetFileField(state, action) {
202
+ const { id, field } = action.payload;
203
+ const record = state.filesById[id];
204
+ if (!record) return;
205
+ const snapKey = field;
206
+ const snapshotValue = record._fieldHistory[snapKey];
207
+ if (snapKey in record._fieldHistory && snapshotValue !== void 0) {
208
+ assignField(record, snapKey, snapshotValue);
209
+ delete record._fieldHistory[snapKey];
210
+ removeField(record._dirtyFields, field);
211
+ }
212
+ if (Object.keys(record._dirtyFields).length === 0) {
213
+ record._dirty = false;
214
+ }
215
+ },
216
+ markFileSaved(state, action) {
217
+ const record = state.filesById[action.payload.id];
218
+ if (!record) return;
219
+ markFileClean(record);
220
+ },
221
+ rollbackFileOptimisticUpdate(state, action) {
222
+ const { id, snapshot } = action.payload;
223
+ const record = state.filesById[id];
224
+ if (!record) return;
225
+ Object.assign(record, snapshot);
226
+ record._dirty = false;
227
+ record._dirtyFields = createFieldFlags();
228
+ record._fieldHistory = {};
229
+ },
230
+ // ---- Files: remove / pending requests ----------------------------------
231
+ removeFile(state, action) {
232
+ const { id } = action.payload;
233
+ delete state.filesById[id];
234
+ delete state.versionsByFileId[id];
235
+ for (const parentId of Object.keys(state.tree.childrenByFolderId)) {
236
+ const bucket = state.tree.childrenByFolderId[parentId];
237
+ const idx = bucket.fileIds.indexOf(id);
238
+ if (idx >= 0) bucket.fileIds.splice(idx, 1);
239
+ }
240
+ const rootIdx = state.tree.rootFileIds.indexOf(id);
241
+ if (rootIdx >= 0) state.tree.rootFileIds.splice(rootIdx, 1);
242
+ },
243
+ addFilePendingRequest(state, action) {
244
+ const { id, requestId } = action.payload;
245
+ const record = state.filesById[id];
246
+ if (!record) return;
247
+ if (!record._pendingRequestIds.includes(requestId)) {
248
+ record._pendingRequestIds.push(requestId);
249
+ }
250
+ },
251
+ removeFilePendingRequest(state, action) {
252
+ const { id, requestId } = action.payload;
253
+ const record = state.filesById[id];
254
+ if (!record) return;
255
+ const idx = record._pendingRequestIds.indexOf(requestId);
256
+ if (idx >= 0) record._pendingRequestIds.splice(idx, 1);
257
+ },
258
+ setFileLoading(state, action) {
259
+ const record = state.filesById[action.payload.id];
260
+ if (!record) return;
261
+ record._loading = action.payload.loading;
262
+ },
263
+ setFileError(state, action) {
264
+ const record = state.filesById[action.payload.id];
265
+ if (!record) return;
266
+ record._error = action.payload.error;
267
+ },
268
+ // ---- Folders: mirror of file reducers ----------------------------------
269
+ upsertFolders(state, action) {
270
+ for (const partial of action.payload) {
271
+ if (!partial.id) continue;
272
+ const existing = state.foldersById[partial.id] ?? emptyFolderRecord(partial.id);
273
+ mergeFolderIntoRecord(existing, partial);
274
+ state.foldersById[partial.id] = existing;
275
+ }
276
+ },
277
+ upsertFolder(state, action) {
278
+ const partial = action.payload;
279
+ if (!partial.id) return;
280
+ const existing = state.foldersById[partial.id] ?? emptyFolderRecord(partial.id);
281
+ mergeFolderIntoRecord(existing, partial);
282
+ state.foldersById[partial.id] = existing;
283
+ },
284
+ setFolderField(state, action) {
285
+ const { id, field, value } = action.payload;
286
+ const record = state.foldersById[id];
287
+ if (!record) return;
288
+ applyFolderFieldEdit(record, field, value);
289
+ },
290
+ markFolderSaved(state, action) {
291
+ const record = state.foldersById[action.payload.id];
292
+ if (!record) return;
293
+ markFolderClean(record);
294
+ },
295
+ rollbackFolderOptimisticUpdate(state, action) {
296
+ const { id, snapshot } = action.payload;
297
+ const record = state.foldersById[id];
298
+ if (!record) return;
299
+ Object.assign(record, snapshot);
300
+ record._dirty = false;
301
+ record._dirtyFields = createFieldFlags();
302
+ record._fieldHistory = {};
303
+ },
304
+ removeFolder(state, action) {
305
+ const { id } = action.payload;
306
+ delete state.foldersById[id];
307
+ delete state.tree.childrenByFolderId[id];
308
+ for (const parentId of Object.keys(state.tree.childrenByFolderId)) {
309
+ const bucket = state.tree.childrenByFolderId[parentId];
310
+ const idx = bucket.folderIds.indexOf(id);
311
+ if (idx >= 0) bucket.folderIds.splice(idx, 1);
312
+ }
313
+ const rootIdx = state.tree.rootFolderIds.indexOf(id);
314
+ if (rootIdx >= 0) state.tree.rootFolderIds.splice(rootIdx, 1);
315
+ },
316
+ // ---- Versions ----------------------------------------------------------
317
+ upsertVersionsForFile(state, action) {
318
+ state.versionsByFileId[action.payload.fileId] = action.payload.versions;
319
+ },
320
+ // ---- Permissions -------------------------------------------------------
321
+ upsertPermissionsForResource(state, action) {
322
+ state.permissionsByResourceId[action.payload.resourceId] = action.payload.permissions;
323
+ },
324
+ removePermissionForResource(state, action) {
325
+ const { resourceId, granteeId, granteeType } = action.payload;
326
+ const list = state.permissionsByResourceId[resourceId];
327
+ if (!list) return;
328
+ state.permissionsByResourceId[resourceId] = list.filter(
329
+ (p) => !(p.granteeId === granteeId && (granteeType ? p.granteeType === granteeType : true))
330
+ );
331
+ },
332
+ // ---- Share links -------------------------------------------------------
333
+ upsertShareLinksForResource(state, action) {
334
+ state.shareLinksByResourceId[action.payload.resourceId] = action.payload.shareLinks;
335
+ },
336
+ removeShareLink(state, action) {
337
+ const { linkId } = action.payload;
338
+ for (const resourceId of Object.keys(state.shareLinksByResourceId)) {
339
+ state.shareLinksByResourceId[resourceId] = state.shareLinksByResourceId[resourceId].filter((l) => l.id !== linkId);
340
+ }
341
+ },
342
+ // ---- Tree --------------------------------------------------------------
343
+ setTreeStatus(state, action) {
344
+ state.tree.status = action.payload.status;
345
+ state.tree.error = action.payload.error ?? null;
346
+ },
347
+ replaceTree(state, action) {
348
+ const incomingIds = new Set(action.payload.rootFolderIds);
349
+ const virtualRoots = state.tree.rootFolderIds.filter((id) => {
350
+ if (incomingIds.has(id)) return false;
351
+ return state.foldersById[id]?.source.kind === "virtual";
352
+ });
353
+ state.tree.rootFolderIds = [
354
+ ...virtualRoots,
355
+ ...action.payload.rootFolderIds
356
+ ];
357
+ state.tree.rootFileIds = action.payload.rootFileIds;
358
+ const preservedChildren = {};
359
+ for (const [folderId, children] of Object.entries(
360
+ state.tree.childrenByFolderId
361
+ )) {
362
+ if (state.foldersById[folderId]?.source.kind === "virtual") {
363
+ preservedChildren[folderId] = children;
364
+ }
365
+ }
366
+ state.tree.childrenByFolderId = {
367
+ ...preservedChildren,
368
+ ...action.payload.childrenByFolderId
369
+ };
370
+ state.tree.fullyLoadedFolderIds = action.payload.fullyLoadedFolderIds ?? {};
371
+ state.tree.status = "loaded";
372
+ state.tree.error = null;
373
+ state.tree.lastReconciledAt = Date.now();
374
+ },
375
+ markFolderFullyLoaded(state, action) {
376
+ state.tree.fullyLoadedFolderIds[action.payload.folderId] = true;
377
+ },
378
+ /**
379
+ * Mount a virtual adapter as a synthetic root folder. Called once per
380
+ * registered `VirtualSourceAdapter` from `attachVirtualRoots()` (a thunk
381
+ * fired during `/files` bootstrap). The synthetic folder has id
382
+ * `vfs:<adapterId>:__root__` and `source.kind: "virtual"` so the existing
383
+ * tree renderer and selectors treat it like any other folder.
384
+ */
385
+ attachVirtualRoot(state, action) {
386
+ const { adapterId, rootId, label } = action.payload;
387
+ if (state.foldersById[rootId]) return;
388
+ state.foldersById[rootId] = {
389
+ id: rootId,
390
+ ownerId: "",
391
+ folderPath: `/${label}`,
392
+ folderName: label,
393
+ parentId: null,
394
+ visibility: "personal",
395
+ metadata: {},
396
+ createdAt: "",
397
+ updatedAt: "",
398
+ deletedAt: null,
399
+ source: { kind: "virtual", adapterId, virtualId: "__root__" },
400
+ _dirty: false,
401
+ _dirtyFields: {},
402
+ _fieldHistory: {},
403
+ _loadedFields: {},
404
+ _loading: false,
405
+ _error: null,
406
+ _pendingRequestIds: []
407
+ };
408
+ if (!state.tree.rootFolderIds.includes(rootId)) {
409
+ state.tree.rootFolderIds.unshift(rootId);
410
+ }
411
+ },
412
+ attachChildToFolder(state, action) {
413
+ const { parentFolderId, kind, id } = action.payload;
414
+ if (!parentFolderId) {
415
+ if (kind === "file") {
416
+ if (!state.tree.rootFileIds.includes(id)) {
417
+ state.tree.rootFileIds.push(id);
418
+ }
419
+ } else {
420
+ if (!state.tree.rootFolderIds.includes(id)) {
421
+ state.tree.rootFolderIds.push(id);
422
+ }
423
+ }
424
+ return;
425
+ }
426
+ const bucket = state.tree.childrenByFolderId[parentFolderId] ??= {
427
+ folderIds: [],
428
+ fileIds: []
429
+ };
430
+ const list = kind === "file" ? bucket.fileIds : bucket.folderIds;
431
+ if (!list.includes(id)) list.push(id);
432
+ },
433
+ detachChildFromFolder(state, action) {
434
+ const { parentFolderId, kind, id } = action.payload;
435
+ if (!parentFolderId) {
436
+ const list2 = kind === "file" ? state.tree.rootFileIds : state.tree.rootFolderIds;
437
+ const idx2 = list2.indexOf(id);
438
+ if (idx2 >= 0) list2.splice(idx2, 1);
439
+ return;
440
+ }
441
+ const bucket = state.tree.childrenByFolderId[parentFolderId];
442
+ if (!bucket) return;
443
+ const list = kind === "file" ? bucket.fileIds : bucket.folderIds;
444
+ const idx = list.indexOf(id);
445
+ if (idx >= 0) list.splice(idx, 1);
446
+ },
447
+ // ---- Selection + UI ---------------------------------------------------
448
+ setSelection(state, action) {
449
+ state.selection = action.payload;
450
+ },
451
+ clearSelection(state) {
452
+ state.selection = { selectedIds: [], anchorId: null };
453
+ },
454
+ toggleSelection(state, action) {
455
+ const { id } = action.payload;
456
+ const idx = state.selection.selectedIds.indexOf(id);
457
+ if (idx >= 0) {
458
+ state.selection.selectedIds.splice(idx, 1);
459
+ if (state.selection.anchorId === id) state.selection.anchorId = null;
460
+ } else {
461
+ state.selection.selectedIds.push(id);
462
+ state.selection.anchorId = id;
463
+ }
464
+ },
465
+ setViewMode(state, action) {
466
+ state.ui.viewMode = action.payload;
467
+ },
468
+ setSort(state, action) {
469
+ state.ui.sortBy = action.payload.sortBy;
470
+ state.ui.sortDir = action.payload.sortDir;
471
+ },
472
+ setKindFilter(state, action) {
473
+ state.ui.kindFilter = action.payload;
474
+ },
475
+ setDetailsLevel(state, action) {
476
+ state.ui.detailsLevel = action.payload;
477
+ },
478
+ setColumnFilter(state, action) {
479
+ const next = action.payload;
480
+ switch (next.column) {
481
+ case "name":
482
+ state.ui.columnFilters.name = next.value;
483
+ break;
484
+ case "type":
485
+ state.ui.columnFilters.type = next.value;
486
+ break;
487
+ case "extension":
488
+ state.ui.columnFilters.extension = next.value;
489
+ break;
490
+ case "mime":
491
+ state.ui.columnFilters.mime = next.value;
492
+ break;
493
+ case "path":
494
+ state.ui.columnFilters.path = next.value;
495
+ break;
496
+ case "owner":
497
+ state.ui.columnFilters.owner = next.value;
498
+ break;
499
+ case "modified":
500
+ state.ui.columnFilters.modified = next.value;
501
+ break;
502
+ case "created":
503
+ state.ui.columnFilters.created = next.value;
504
+ break;
505
+ case "size":
506
+ state.ui.columnFilters.size = next.value;
507
+ break;
508
+ case "access":
509
+ state.ui.columnFilters.access = next.value;
510
+ break;
511
+ case "rag":
512
+ state.ui.columnFilters.rag = next.value;
513
+ break;
514
+ }
515
+ },
516
+ clearColumnFilters(state) {
517
+ state.ui.columnFilters = {
518
+ name: "",
519
+ type: [],
520
+ extension: "",
521
+ mime: "",
522
+ path: "",
523
+ owner: [],
524
+ modified: "any",
525
+ created: "any",
526
+ size: "any",
527
+ access: "any",
528
+ rag: []
529
+ };
530
+ },
531
+ setColumnVisibility(state, action) {
532
+ const { column, visible } = action.payload;
533
+ if (column === "name") {
534
+ state.ui.visibleColumns.name = true;
535
+ return;
536
+ }
537
+ state.ui.visibleColumns[column] = visible;
538
+ },
539
+ resetColumnVisibility(state) {
540
+ state.ui.visibleColumns = { ...DEFAULT_VISIBLE_COLUMNS };
541
+ },
542
+ setActiveFileId(state, action) {
543
+ state.ui.activeFileId = action.payload;
544
+ },
545
+ setActiveFolderId(state, action) {
546
+ state.ui.activeFolderId = action.payload;
547
+ },
548
+ /** Tree-wide search box value. Empty string clears the search. */
549
+ setSearchQuery(state, action) {
550
+ state.ui.searchQuery = action.payload;
551
+ },
552
+ /** Active sticky chip (Recents / Starred). Pass null to clear. */
553
+ setChipFilter(state, action) {
554
+ state.ui.chipFilter = action.payload;
555
+ },
556
+ /**
557
+ * Apply many UI fields in one transaction. Used by the URL-sync layer
558
+ * to hydrate Redux from a `?...` query string on first paint without
559
+ * dispatching N separate actions (which would each spawn a re-render).
560
+ *
561
+ * Only fields present in the payload are written. Pass `columnFilters`
562
+ * with the FULL shape — partial column-filter merges are intentionally
563
+ * not supported here; the URL serializer always emits the full shape.
564
+ */
565
+ setUiBatch(state, action) {
566
+ const next = action.payload;
567
+ if (next.viewMode !== void 0) state.ui.viewMode = next.viewMode;
568
+ if (next.sortBy !== void 0) state.ui.sortBy = next.sortBy;
569
+ if (next.sortDir !== void 0) state.ui.sortDir = next.sortDir;
570
+ if (next.kindFilter !== void 0) state.ui.kindFilter = next.kindFilter;
571
+ if (next.detailsLevel !== void 0) {
572
+ state.ui.detailsLevel = next.detailsLevel;
573
+ }
574
+ if (next.searchQuery !== void 0) {
575
+ state.ui.searchQuery = next.searchQuery;
576
+ }
577
+ if (next.chipFilter !== void 0) state.ui.chipFilter = next.chipFilter;
578
+ if (next.activeFileId !== void 0) {
579
+ state.ui.activeFileId = next.activeFileId;
580
+ }
581
+ if (next.activeFolderId !== void 0) {
582
+ state.ui.activeFolderId = next.activeFolderId;
583
+ }
584
+ if (next.columnFilters !== void 0) {
585
+ const cf = next.columnFilters;
586
+ if (cf.name !== void 0) state.ui.columnFilters.name = cf.name;
587
+ if (cf.type !== void 0) state.ui.columnFilters.type = cf.type;
588
+ if (cf.extension !== void 0) {
589
+ state.ui.columnFilters.extension = cf.extension;
590
+ }
591
+ if (cf.mime !== void 0) state.ui.columnFilters.mime = cf.mime;
592
+ if (cf.path !== void 0) state.ui.columnFilters.path = cf.path;
593
+ if (cf.owner !== void 0) state.ui.columnFilters.owner = cf.owner;
594
+ if (cf.modified !== void 0) {
595
+ state.ui.columnFilters.modified = cf.modified;
596
+ }
597
+ if (cf.created !== void 0) {
598
+ state.ui.columnFilters.created = cf.created;
599
+ }
600
+ if (cf.size !== void 0) state.ui.columnFilters.size = cf.size;
601
+ if (cf.access !== void 0) state.ui.columnFilters.access = cf.access;
602
+ if (cf.rag !== void 0) state.ui.columnFilters.rag = cf.rag;
603
+ }
604
+ if (next.visibleColumns !== void 0) {
605
+ state.ui.visibleColumns = {
606
+ ...DEFAULT_VISIBLE_COLUMNS,
607
+ ...next.visibleColumns,
608
+ // `name` is the row anchor — never hideable. Keep this invariant
609
+ // even when callers (or a malicious URL) try to flip it.
610
+ name: true
611
+ };
612
+ }
613
+ },
614
+ /**
615
+ * Move "focus" (Google-Drive-style single-item highlight) to the given id.
616
+ * Pass null to clear. Automatically set after folder/file creation so the
617
+ * newly-created item is highlighted and scrolled into view.
618
+ */
619
+ setFocusedId(state, action) {
620
+ state.ui.focusedId = action.payload;
621
+ },
622
+ // ---- Uploads -----------------------------------------------------------
623
+ trackUploadStart(state, action) {
624
+ const { requestId, fileName, fileSize, parentFolderId, folderPath } = action.payload;
625
+ state.uploads[requestId] = {
626
+ requestId,
627
+ fileName,
628
+ fileSize,
629
+ parentFolderId,
630
+ folderPath: folderPath ?? null,
631
+ status: "uploading",
632
+ bytesUploaded: 0,
633
+ startedAt: Date.now(),
634
+ completedAt: null,
635
+ error: null,
636
+ retries: 0,
637
+ fileId: null
638
+ };
639
+ },
640
+ updateUploadProgress(state, action) {
641
+ const entry = state.uploads[action.payload.requestId];
642
+ if (!entry) return;
643
+ entry.bytesUploaded = action.payload.bytesUploaded;
644
+ },
645
+ updateUploadStatus(state, action) {
646
+ const entry = state.uploads[action.payload.requestId];
647
+ if (!entry) return;
648
+ entry.status = action.payload.status;
649
+ if (action.payload.fileId !== void 0)
650
+ entry.fileId = action.payload.fileId;
651
+ if (action.payload.error !== void 0)
652
+ entry.error = action.payload.error;
653
+ if (action.payload.status === "success" || action.payload.status === "error" || action.payload.status === "cancelled") {
654
+ entry.completedAt = Date.now();
655
+ }
656
+ },
657
+ clearUpload(state, action) {
658
+ delete state.uploads[action.payload.requestId];
659
+ },
660
+ clearCompletedUploads(state) {
661
+ for (const id of Object.keys(state.uploads)) {
662
+ const entry = state.uploads[id];
663
+ if (entry.status === "success" || entry.status === "cancelled") {
664
+ delete state.uploads[id];
665
+ }
666
+ }
667
+ },
668
+ // ---- Realtime lifecycle -----------------------------------------------
669
+ setRealtimeStatus(state, action) {
670
+ state.realtime.status = action.payload.status;
671
+ if (action.payload.userId !== void 0) {
672
+ state.realtime.userId = action.payload.userId;
673
+ }
674
+ state.realtime.error = action.payload.error ?? null;
675
+ if (action.payload.status === "subscribed") {
676
+ state.realtime.lastEventAt = Date.now();
677
+ }
678
+ },
679
+ touchRealtime(state) {
680
+ state.realtime.lastEventAt = Date.now();
681
+ },
682
+ // ---- Knowledge status (per-file) ---------------------------------------------
683
+ setRagStatusForFile(state, action) {
684
+ const { fileId, status } = action.payload;
685
+ state.ragStatus.byFileId[fileId] = status;
686
+ },
687
+ setRagStatusBatch(state, action) {
688
+ Object.assign(state.ragStatus.byFileId, action.payload.entries);
689
+ state.ragStatus.lastFetchedAt = Date.now();
690
+ },
691
+ setRagStatusFetching(state, action) {
692
+ state.ragStatus.isFetching = action.payload;
693
+ },
694
+ clearRagStatuses(state) {
695
+ state.ragStatus.byFileId = {};
696
+ state.ragStatus.lastFetchedAt = null;
697
+ },
698
+ resetCloudFilesState() {
699
+ return initialState;
700
+ }
701
+ }
702
+ });
703
+ const {
704
+ // files
705
+ upsertFile,
706
+ upsertFiles,
707
+ setFileField,
708
+ resetFileField,
709
+ markFileSaved,
710
+ rollbackFileOptimisticUpdate,
711
+ removeFile,
712
+ addFilePendingRequest,
713
+ removeFilePendingRequest,
714
+ setFileLoading,
715
+ setFileError,
716
+ // folders
717
+ upsertFolder,
718
+ upsertFolders,
719
+ setFolderField,
720
+ markFolderSaved,
721
+ rollbackFolderOptimisticUpdate,
722
+ removeFolder,
723
+ // versions / permissions / shares
724
+ upsertVersionsForFile,
725
+ upsertPermissionsForResource,
726
+ removePermissionForResource,
727
+ upsertShareLinksForResource,
728
+ removeShareLink,
729
+ // tree
730
+ setTreeStatus,
731
+ replaceTree,
732
+ markFolderFullyLoaded,
733
+ attachVirtualRoot,
734
+ attachChildToFolder,
735
+ detachChildFromFolder,
736
+ // selection + ui
737
+ setSelection,
738
+ clearSelection,
739
+ toggleSelection,
740
+ setViewMode,
741
+ setSort,
742
+ setKindFilter,
743
+ setDetailsLevel,
744
+ setColumnFilter,
745
+ clearColumnFilters,
746
+ setColumnVisibility,
747
+ resetColumnVisibility,
748
+ setActiveFileId,
749
+ setActiveFolderId,
750
+ setSearchQuery,
751
+ setChipFilter,
752
+ setUiBatch,
753
+ setFocusedId,
754
+ // uploads
755
+ trackUploadStart,
756
+ updateUploadProgress,
757
+ updateUploadStatus,
758
+ clearUpload,
759
+ clearCompletedUploads,
760
+ // rag status
761
+ setRagStatusForFile,
762
+ setRagStatusBatch,
763
+ setRagStatusFetching,
764
+ clearRagStatuses,
765
+ // realtime
766
+ setRealtimeStatus,
767
+ touchRealtime,
768
+ // working copies
769
+ resetCloudFilesState
770
+ } = slice.actions;
771
+ const cloudFilesReducer = slice.reducer;
772
+ var slice_default = slice.reducer;
773
+ export {
774
+ addFilePendingRequest,
775
+ attachChildToFolder,
776
+ attachVirtualRoot,
777
+ clearColumnFilters,
778
+ clearCompletedUploads,
779
+ clearRagStatuses,
780
+ clearSelection,
781
+ clearUpload,
782
+ cloudFilesReducer,
783
+ slice_default as default,
784
+ detachChildFromFolder,
785
+ emptyFileRecord,
786
+ emptyFolderRecord,
787
+ markFileSaved,
788
+ markFolderFullyLoaded,
789
+ markFolderSaved,
790
+ removeFile,
791
+ removeFilePendingRequest,
792
+ removeFolder,
793
+ removePermissionForResource,
794
+ removeShareLink,
795
+ replaceTree,
796
+ resetCloudFilesState,
797
+ resetColumnVisibility,
798
+ resetFileField,
799
+ rollbackFileOptimisticUpdate,
800
+ rollbackFolderOptimisticUpdate,
801
+ setActiveFileId,
802
+ setActiveFolderId,
803
+ setChipFilter,
804
+ setColumnFilter,
805
+ setColumnVisibility,
806
+ setDetailsLevel,
807
+ setFileError,
808
+ setFileField,
809
+ setFileLoading,
810
+ setFocusedId,
811
+ setFolderField,
812
+ setKindFilter,
813
+ setRagStatusBatch,
814
+ setRagStatusFetching,
815
+ setRagStatusForFile,
816
+ setRealtimeStatus,
817
+ setSearchQuery,
818
+ setSelection,
819
+ setSort,
820
+ setTreeStatus,
821
+ setUiBatch,
822
+ setViewMode,
823
+ toggleSelection,
824
+ touchRealtime,
825
+ trackUploadStart,
826
+ updateUploadProgress,
827
+ updateUploadStatus,
828
+ upsertFile,
829
+ upsertFiles,
830
+ upsertFolder,
831
+ upsertFolders,
832
+ upsertPermissionsForResource,
833
+ upsertShareLinksForResource,
834
+ upsertVersionsForFile
835
+ };
836
+ //# sourceMappingURL=slice.js.map