@aigne/afs-index 1.12.0-beta.5

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 (186) hide show
  1. package/LICENSE.md +26 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
  4. package/dist/backend/d1-index-backend.cjs +656 -0
  5. package/dist/backend/d1-index-backend.d.cts +149 -0
  6. package/dist/backend/d1-index-backend.d.cts.map +1 -0
  7. package/dist/backend/d1-index-backend.d.mts +149 -0
  8. package/dist/backend/d1-index-backend.d.mts.map +1 -0
  9. package/dist/backend/d1-index-backend.mjs +657 -0
  10. package/dist/backend/d1-index-backend.mjs.map +1 -0
  11. package/dist/backend/d1-vector-backend.cjs +83 -0
  12. package/dist/backend/d1-vector-backend.d.cts +21 -0
  13. package/dist/backend/d1-vector-backend.d.cts.map +1 -0
  14. package/dist/backend/d1-vector-backend.d.mts +21 -0
  15. package/dist/backend/d1-vector-backend.d.mts.map +1 -0
  16. package/dist/backend/d1-vector-backend.mjs +84 -0
  17. package/dist/backend/d1-vector-backend.mjs.map +1 -0
  18. package/dist/backend/memory-backend.cjs +304 -0
  19. package/dist/backend/memory-backend.d.cts +66 -0
  20. package/dist/backend/memory-backend.d.cts.map +1 -0
  21. package/dist/backend/memory-backend.d.mts +66 -0
  22. package/dist/backend/memory-backend.d.mts.map +1 -0
  23. package/dist/backend/memory-backend.mjs +305 -0
  24. package/dist/backend/memory-backend.mjs.map +1 -0
  25. package/dist/backend/prefix-range.cjs +25 -0
  26. package/dist/backend/prefix-range.mjs +25 -0
  27. package/dist/backend/prefix-range.mjs.map +1 -0
  28. package/dist/backend/schema.cjs +187 -0
  29. package/dist/backend/schema.mjs +188 -0
  30. package/dist/backend/schema.mjs.map +1 -0
  31. package/dist/backend/sqlite-backend.cjs +889 -0
  32. package/dist/backend/sqlite-backend.d.cts +96 -0
  33. package/dist/backend/sqlite-backend.d.cts.map +1 -0
  34. package/dist/backend/sqlite-backend.d.mts +96 -0
  35. package/dist/backend/sqlite-backend.d.mts.map +1 -0
  36. package/dist/backend/sqlite-backend.mjs +890 -0
  37. package/dist/backend/sqlite-backend.mjs.map +1 -0
  38. package/dist/backend/types.d.cts +209 -0
  39. package/dist/backend/types.d.cts.map +1 -0
  40. package/dist/backend/types.d.mts +209 -0
  41. package/dist/backend/types.d.mts.map +1 -0
  42. package/dist/backend/upstash-vector-backend.cjs +98 -0
  43. package/dist/backend/upstash-vector-backend.d.cts +21 -0
  44. package/dist/backend/upstash-vector-backend.d.cts.map +1 -0
  45. package/dist/backend/upstash-vector-backend.d.mts +21 -0
  46. package/dist/backend/upstash-vector-backend.d.mts.map +1 -0
  47. package/dist/backend/upstash-vector-backend.mjs +98 -0
  48. package/dist/backend/upstash-vector-backend.mjs.map +1 -0
  49. package/dist/backend/vector-backend.d.cts +29 -0
  50. package/dist/backend/vector-backend.d.cts.map +1 -0
  51. package/dist/backend/vector-backend.d.mts +29 -0
  52. package/dist/backend/vector-backend.d.mts.map +1 -0
  53. package/dist/dirty-queue.d.cts +41 -0
  54. package/dist/dirty-queue.d.cts.map +1 -0
  55. package/dist/dirty-queue.d.mts +41 -0
  56. package/dist/dirty-queue.d.mts.map +1 -0
  57. package/dist/embed.cjs +45 -0
  58. package/dist/embed.d.cts +20 -0
  59. package/dist/embed.d.cts.map +1 -0
  60. package/dist/embed.d.mts +20 -0
  61. package/dist/embed.d.mts.map +1 -0
  62. package/dist/embed.mjs +46 -0
  63. package/dist/embed.mjs.map +1 -0
  64. package/dist/extraction/defaults.cjs +242 -0
  65. package/dist/extraction/defaults.d.cts +14 -0
  66. package/dist/extraction/defaults.d.cts.map +1 -0
  67. package/dist/extraction/defaults.d.mts +14 -0
  68. package/dist/extraction/defaults.d.mts.map +1 -0
  69. package/dist/extraction/defaults.mjs +242 -0
  70. package/dist/extraction/defaults.mjs.map +1 -0
  71. package/dist/extraction/field-map.cjs +162 -0
  72. package/dist/extraction/field-map.d.cts +70 -0
  73. package/dist/extraction/field-map.d.cts.map +1 -0
  74. package/dist/extraction/field-map.d.mts +70 -0
  75. package/dist/extraction/field-map.d.mts.map +1 -0
  76. package/dist/extraction/field-map.mjs +157 -0
  77. package/dist/extraction/field-map.mjs.map +1 -0
  78. package/dist/extraction/manager.cjs +74 -0
  79. package/dist/extraction/manager.d.cts +47 -0
  80. package/dist/extraction/manager.d.cts.map +1 -0
  81. package/dist/extraction/manager.d.mts +47 -0
  82. package/dist/extraction/manager.d.mts.map +1 -0
  83. package/dist/extraction/manager.mjs +74 -0
  84. package/dist/extraction/manager.mjs.map +1 -0
  85. package/dist/extraction/path-anchors.cjs +86 -0
  86. package/dist/extraction/path-anchors.d.cts +72 -0
  87. package/dist/extraction/path-anchors.d.cts.map +1 -0
  88. package/dist/extraction/path-anchors.d.mts +72 -0
  89. package/dist/extraction/path-anchors.d.mts.map +1 -0
  90. package/dist/extraction/path-anchors.mjs +86 -0
  91. package/dist/extraction/path-anchors.mjs.map +1 -0
  92. package/dist/follower-scheduler.cjs +92 -0
  93. package/dist/follower-scheduler.d.cts +58 -0
  94. package/dist/follower-scheduler.d.cts.map +1 -0
  95. package/dist/follower-scheduler.d.mts +58 -0
  96. package/dist/follower-scheduler.d.mts.map +1 -0
  97. package/dist/follower-scheduler.mjs +92 -0
  98. package/dist/follower-scheduler.mjs.map +1 -0
  99. package/dist/follower.cjs +577 -0
  100. package/dist/follower.d.cts +241 -0
  101. package/dist/follower.d.cts.map +1 -0
  102. package/dist/follower.d.mts +241 -0
  103. package/dist/follower.d.mts.map +1 -0
  104. package/dist/follower.mjs +571 -0
  105. package/dist/follower.mjs.map +1 -0
  106. package/dist/index-provider.cjs +1166 -0
  107. package/dist/index-provider.d.cts +175 -0
  108. package/dist/index-provider.d.cts.map +1 -0
  109. package/dist/index-provider.d.mts +175 -0
  110. package/dist/index-provider.d.mts.map +1 -0
  111. package/dist/index-provider.mjs +1167 -0
  112. package/dist/index-provider.mjs.map +1 -0
  113. package/dist/index.cjs +53 -0
  114. package/dist/index.d.cts +22 -0
  115. package/dist/index.d.mts +22 -0
  116. package/dist/index.mjs +20 -0
  117. package/dist/keys/exact.cjs +20 -0
  118. package/dist/keys/exact.mjs +20 -0
  119. package/dist/keys/exact.mjs.map +1 -0
  120. package/dist/keys/location.cjs +13 -0
  121. package/dist/keys/location.mjs +13 -0
  122. package/dist/keys/location.mjs.map +1 -0
  123. package/dist/keys/normalized.cjs +62 -0
  124. package/dist/keys/normalized.mjs +63 -0
  125. package/dist/keys/normalized.mjs.map +1 -0
  126. package/dist/keys/person.cjs +15 -0
  127. package/dist/keys/person.mjs +15 -0
  128. package/dist/keys/person.mjs.map +1 -0
  129. package/dist/keys/registry.cjs +45 -0
  130. package/dist/keys/registry.d.cts +15 -0
  131. package/dist/keys/registry.d.cts.map +1 -0
  132. package/dist/keys/registry.d.mts +15 -0
  133. package/dist/keys/registry.d.mts.map +1 -0
  134. package/dist/keys/registry.mjs +46 -0
  135. package/dist/keys/registry.mjs.map +1 -0
  136. package/dist/keys/time.cjs +128 -0
  137. package/dist/keys/time.mjs +128 -0
  138. package/dist/keys/time.mjs.map +1 -0
  139. package/dist/keys/topic.cjs +23 -0
  140. package/dist/keys/topic.mjs +23 -0
  141. package/dist/keys/topic.mjs.map +1 -0
  142. package/dist/manifest-index.cjs +29 -0
  143. package/dist/manifest-index.d.cts +24 -0
  144. package/dist/manifest-index.d.cts.map +1 -0
  145. package/dist/manifest-index.d.mts +24 -0
  146. package/dist/manifest-index.d.mts.map +1 -0
  147. package/dist/manifest-index.mjs +28 -0
  148. package/dist/manifest-index.mjs.map +1 -0
  149. package/dist/offline-rebuild.cjs +48 -0
  150. package/dist/offline-rebuild.d.cts +57 -0
  151. package/dist/offline-rebuild.d.cts.map +1 -0
  152. package/dist/offline-rebuild.d.mts +57 -0
  153. package/dist/offline-rebuild.d.mts.map +1 -0
  154. package/dist/offline-rebuild.mjs +49 -0
  155. package/dist/offline-rebuild.mjs.map +1 -0
  156. package/dist/query/engine.cjs +433 -0
  157. package/dist/query/engine.d.cts +34 -0
  158. package/dist/query/engine.d.cts.map +1 -0
  159. package/dist/query/engine.d.mts +34 -0
  160. package/dist/query/engine.d.mts.map +1 -0
  161. package/dist/query/engine.mjs +433 -0
  162. package/dist/query/engine.mjs.map +1 -0
  163. package/dist/query/limits.cjs +12 -0
  164. package/dist/query/limits.mjs +12 -0
  165. package/dist/query/limits.mjs.map +1 -0
  166. package/dist/text/cjk.cjs +30 -0
  167. package/dist/text/cjk.d.cts +24 -0
  168. package/dist/text/cjk.d.cts.map +1 -0
  169. package/dist/text/cjk.d.mts +24 -0
  170. package/dist/text/cjk.d.mts.map +1 -0
  171. package/dist/text/cjk.mjs +30 -0
  172. package/dist/text/cjk.mjs.map +1 -0
  173. package/dist/text/fts.cjs +244 -0
  174. package/dist/text/fts.mjs +245 -0
  175. package/dist/text/fts.mjs.map +1 -0
  176. package/dist/text/host.cjs +39 -0
  177. package/dist/text/host.mjs +38 -0
  178. package/dist/text/host.mjs.map +1 -0
  179. package/dist/types.cjs +44 -0
  180. package/dist/types.d.cts +393 -0
  181. package/dist/types.d.cts.map +1 -0
  182. package/dist/types.d.mts +393 -0
  183. package/dist/types.d.mts.map +1 -0
  184. package/dist/types.mjs +42 -0
  185. package/dist/types.mjs.map +1 -0
  186. package/package.json +59 -0
@@ -0,0 +1,242 @@
1
+
2
+ //#region src/extraction/defaults.ts
3
+ const MIME_CATEGORIES = {
4
+ image: "image",
5
+ video: "video",
6
+ audio: "audio",
7
+ text: "document",
8
+ application: "document"
9
+ };
10
+ const EXT_MIME = {
11
+ ".jpg": {
12
+ mime: "image/jpeg",
13
+ category: "image"
14
+ },
15
+ ".jpeg": {
16
+ mime: "image/jpeg",
17
+ category: "image"
18
+ },
19
+ ".png": {
20
+ mime: "image/png",
21
+ category: "image"
22
+ },
23
+ ".gif": {
24
+ mime: "image/gif",
25
+ category: "image"
26
+ },
27
+ ".webp": {
28
+ mime: "image/webp",
29
+ category: "image"
30
+ },
31
+ ".svg": {
32
+ mime: "image/svg+xml",
33
+ category: "image"
34
+ },
35
+ ".mp4": {
36
+ mime: "video/mp4",
37
+ category: "video"
38
+ },
39
+ ".mov": {
40
+ mime: "video/quicktime",
41
+ category: "video"
42
+ },
43
+ ".mp3": {
44
+ mime: "audio/mpeg",
45
+ category: "audio"
46
+ },
47
+ ".wav": {
48
+ mime: "audio/wav",
49
+ category: "audio"
50
+ },
51
+ ".md": {
52
+ mime: "text/markdown",
53
+ category: "document"
54
+ },
55
+ ".txt": {
56
+ mime: "text/plain",
57
+ category: "document"
58
+ },
59
+ ".pdf": {
60
+ mime: "application/pdf",
61
+ category: "document"
62
+ },
63
+ ".json": {
64
+ mime: "application/json",
65
+ category: "document"
66
+ },
67
+ ".yaml": {
68
+ mime: "application/yaml",
69
+ category: "document"
70
+ },
71
+ ".yml": {
72
+ mime: "application/yaml",
73
+ category: "document"
74
+ },
75
+ ".html": {
76
+ mime: "text/html",
77
+ category: "document"
78
+ },
79
+ ".css": {
80
+ mime: "text/css",
81
+ category: "document"
82
+ },
83
+ ".js": {
84
+ mime: "application/javascript",
85
+ category: "code"
86
+ },
87
+ ".ts": {
88
+ mime: "application/typescript",
89
+ category: "code"
90
+ },
91
+ ".py": {
92
+ mime: "text/x-python",
93
+ category: "code"
94
+ },
95
+ ".rs": {
96
+ mime: "text/x-rust",
97
+ category: "code"
98
+ },
99
+ ".go": {
100
+ mime: "text/x-go",
101
+ category: "code"
102
+ }
103
+ };
104
+ function mimeCategory(mime) {
105
+ return MIME_CATEGORIES[mime.split("/")[0] ?? ""] ?? "other";
106
+ }
107
+ function fileExtension(path) {
108
+ const lastDot = path.lastIndexOf(".");
109
+ if (lastDot === -1) return "";
110
+ return path.slice(lastDot).toLowerCase();
111
+ }
112
+ function fileName(path) {
113
+ const segments = path.split("/").filter(Boolean);
114
+ return segments[segments.length - 1] ?? path;
115
+ }
116
+ const BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
117
+ function encodeGeohash(lat, lon, precision = 7) {
118
+ let minLat = -90;
119
+ let maxLat = 90;
120
+ let minLon = -180;
121
+ let maxLon = 180;
122
+ let hash = "";
123
+ let bit = 0;
124
+ let ch = 0;
125
+ let isLon = true;
126
+ while (hash.length < precision) {
127
+ if (isLon) {
128
+ const mid = (minLon + maxLon) / 2;
129
+ if (lon >= mid) {
130
+ ch |= 1 << 4 - bit;
131
+ minLon = mid;
132
+ } else maxLon = mid;
133
+ } else {
134
+ const mid = (minLat + maxLat) / 2;
135
+ if (lat >= mid) {
136
+ ch |= 1 << 4 - bit;
137
+ minLat = mid;
138
+ } else maxLat = mid;
139
+ }
140
+ isLon = !isLon;
141
+ bit++;
142
+ if (bit === 5) {
143
+ hash += BASE32[ch];
144
+ bit = 0;
145
+ ch = 0;
146
+ }
147
+ }
148
+ return hash;
149
+ }
150
+ /**
151
+ * Extract anchors and summary from AFS entry metadata.
152
+ *
153
+ * @param path - The entry path
154
+ * @param meta - The entry metadata (from AFSEntry.meta)
155
+ * @returns ExtractionResult or null if nothing useful can be extracted
156
+ */
157
+ function extractFromMeta(path, meta) {
158
+ if (!meta) return null;
159
+ if (meta.kind === "afs:directory") return null;
160
+ const anchors = [];
161
+ const timeAnchor = extractTimeAnchor(meta);
162
+ if (timeAnchor) anchors.push(timeAnchor);
163
+ const locationAnchor = extractLocationAnchor(meta);
164
+ if (locationAnchor) anchors.push(locationAnchor);
165
+ const contentTypeAnchor = extractContentTypeAnchor(path, meta);
166
+ if (contentTypeAnchor) anchors.push(contentTypeAnchor);
167
+ return {
168
+ anchors,
169
+ summary: buildSummary(path, meta)
170
+ };
171
+ }
172
+ function extractTimeAnchor(meta) {
173
+ const exifDate = meta.exif?.DateTimeOriginal;
174
+ if (exifDate) return {
175
+ type: "time",
176
+ confidence: 1,
177
+ timestamp: exifDate
178
+ };
179
+ const createdAt = meta.createdAt;
180
+ if (createdAt) return {
181
+ type: "time",
182
+ confidence: .9,
183
+ timestamp: createdAt
184
+ };
185
+ const updatedAt = meta.updatedAt;
186
+ if (updatedAt) return {
187
+ type: "time",
188
+ confidence: .7,
189
+ timestamp: updatedAt
190
+ };
191
+ return null;
192
+ }
193
+ function extractLocationAnchor(meta) {
194
+ const exif = meta.exif;
195
+ if (!exif) return null;
196
+ const lat = exif.GPSLatitude;
197
+ const lon = exif.GPSLongitude;
198
+ if (lat == null || lon == null) return null;
199
+ return {
200
+ type: "location",
201
+ confidence: .95,
202
+ geohash: encodeGeohash(lat, lon)
203
+ };
204
+ }
205
+ function extractContentTypeAnchor(path, meta) {
206
+ const mime = meta.mime;
207
+ if (mime) return {
208
+ type: "content-type",
209
+ confidence: 1,
210
+ mime,
211
+ category: mimeCategory(mime)
212
+ };
213
+ const inferred = EXT_MIME[fileExtension(path)];
214
+ if (inferred) return {
215
+ type: "content-type",
216
+ confidence: .8,
217
+ mime: inferred.mime,
218
+ category: inferred.category
219
+ };
220
+ return null;
221
+ }
222
+ function buildSummary(path, meta) {
223
+ const parts = [];
224
+ const name = fileName(path);
225
+ parts.push(name);
226
+ const description = meta.description;
227
+ if (description) parts.push(description);
228
+ const mime = meta.mime;
229
+ if (mime) parts.push(mime);
230
+ const size = meta.size;
231
+ if (size != null) parts.push(formatSize(size));
232
+ return parts.join(" — ");
233
+ }
234
+ function formatSize(bytes) {
235
+ if (bytes < 1024) return `${bytes}B`;
236
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)}KB`;
237
+ if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)}MB`;
238
+ return `${(bytes / 1073741824).toFixed(1)}GB`;
239
+ }
240
+
241
+ //#endregion
242
+ exports.extractFromMeta = extractFromMeta;
@@ -0,0 +1,14 @@
1
+ import { ExtractionResult } from "../types.cjs";
2
+
3
+ //#region src/extraction/defaults.d.ts
4
+ /**
5
+ * Extract anchors and summary from AFS entry metadata.
6
+ *
7
+ * @param path - The entry path
8
+ * @param meta - The entry metadata (from AFSEntry.meta)
9
+ * @returns ExtractionResult or null if nothing useful can be extracted
10
+ */
11
+ declare function extractFromMeta(path: string, meta: Record<string, unknown> | null | undefined): ExtractionResult | null;
12
+ //#endregion
13
+ export { extractFromMeta };
14
+ //# sourceMappingURL=defaults.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.cts","names":[],"sources":["../../src/extraction/defaults.ts"],"mappings":";;;;;;;;;;iBAsHgB,eAAA,CACd,IAAA,UACA,IAAA,EAAM,MAAA,uCACL,gBAAA"}
@@ -0,0 +1,14 @@
1
+ import { ExtractionResult } from "../types.mjs";
2
+
3
+ //#region src/extraction/defaults.d.ts
4
+ /**
5
+ * Extract anchors and summary from AFS entry metadata.
6
+ *
7
+ * @param path - The entry path
8
+ * @param meta - The entry metadata (from AFSEntry.meta)
9
+ * @returns ExtractionResult or null if nothing useful can be extracted
10
+ */
11
+ declare function extractFromMeta(path: string, meta: Record<string, unknown> | null | undefined): ExtractionResult | null;
12
+ //#endregion
13
+ export { extractFromMeta };
14
+ //# sourceMappingURL=defaults.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.mts","names":[],"sources":["../../src/extraction/defaults.ts"],"mappings":";;;;;;;;;;iBAsHgB,eAAA,CACd,IAAA,UACA,IAAA,EAAM,MAAA,uCACL,gBAAA"}
@@ -0,0 +1,242 @@
1
+ //#region src/extraction/defaults.ts
2
+ const MIME_CATEGORIES = {
3
+ image: "image",
4
+ video: "video",
5
+ audio: "audio",
6
+ text: "document",
7
+ application: "document"
8
+ };
9
+ const EXT_MIME = {
10
+ ".jpg": {
11
+ mime: "image/jpeg",
12
+ category: "image"
13
+ },
14
+ ".jpeg": {
15
+ mime: "image/jpeg",
16
+ category: "image"
17
+ },
18
+ ".png": {
19
+ mime: "image/png",
20
+ category: "image"
21
+ },
22
+ ".gif": {
23
+ mime: "image/gif",
24
+ category: "image"
25
+ },
26
+ ".webp": {
27
+ mime: "image/webp",
28
+ category: "image"
29
+ },
30
+ ".svg": {
31
+ mime: "image/svg+xml",
32
+ category: "image"
33
+ },
34
+ ".mp4": {
35
+ mime: "video/mp4",
36
+ category: "video"
37
+ },
38
+ ".mov": {
39
+ mime: "video/quicktime",
40
+ category: "video"
41
+ },
42
+ ".mp3": {
43
+ mime: "audio/mpeg",
44
+ category: "audio"
45
+ },
46
+ ".wav": {
47
+ mime: "audio/wav",
48
+ category: "audio"
49
+ },
50
+ ".md": {
51
+ mime: "text/markdown",
52
+ category: "document"
53
+ },
54
+ ".txt": {
55
+ mime: "text/plain",
56
+ category: "document"
57
+ },
58
+ ".pdf": {
59
+ mime: "application/pdf",
60
+ category: "document"
61
+ },
62
+ ".json": {
63
+ mime: "application/json",
64
+ category: "document"
65
+ },
66
+ ".yaml": {
67
+ mime: "application/yaml",
68
+ category: "document"
69
+ },
70
+ ".yml": {
71
+ mime: "application/yaml",
72
+ category: "document"
73
+ },
74
+ ".html": {
75
+ mime: "text/html",
76
+ category: "document"
77
+ },
78
+ ".css": {
79
+ mime: "text/css",
80
+ category: "document"
81
+ },
82
+ ".js": {
83
+ mime: "application/javascript",
84
+ category: "code"
85
+ },
86
+ ".ts": {
87
+ mime: "application/typescript",
88
+ category: "code"
89
+ },
90
+ ".py": {
91
+ mime: "text/x-python",
92
+ category: "code"
93
+ },
94
+ ".rs": {
95
+ mime: "text/x-rust",
96
+ category: "code"
97
+ },
98
+ ".go": {
99
+ mime: "text/x-go",
100
+ category: "code"
101
+ }
102
+ };
103
+ function mimeCategory(mime) {
104
+ return MIME_CATEGORIES[mime.split("/")[0] ?? ""] ?? "other";
105
+ }
106
+ function fileExtension(path) {
107
+ const lastDot = path.lastIndexOf(".");
108
+ if (lastDot === -1) return "";
109
+ return path.slice(lastDot).toLowerCase();
110
+ }
111
+ function fileName(path) {
112
+ const segments = path.split("/").filter(Boolean);
113
+ return segments[segments.length - 1] ?? path;
114
+ }
115
+ const BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
116
+ function encodeGeohash(lat, lon, precision = 7) {
117
+ let minLat = -90;
118
+ let maxLat = 90;
119
+ let minLon = -180;
120
+ let maxLon = 180;
121
+ let hash = "";
122
+ let bit = 0;
123
+ let ch = 0;
124
+ let isLon = true;
125
+ while (hash.length < precision) {
126
+ if (isLon) {
127
+ const mid = (minLon + maxLon) / 2;
128
+ if (lon >= mid) {
129
+ ch |= 1 << 4 - bit;
130
+ minLon = mid;
131
+ } else maxLon = mid;
132
+ } else {
133
+ const mid = (minLat + maxLat) / 2;
134
+ if (lat >= mid) {
135
+ ch |= 1 << 4 - bit;
136
+ minLat = mid;
137
+ } else maxLat = mid;
138
+ }
139
+ isLon = !isLon;
140
+ bit++;
141
+ if (bit === 5) {
142
+ hash += BASE32[ch];
143
+ bit = 0;
144
+ ch = 0;
145
+ }
146
+ }
147
+ return hash;
148
+ }
149
+ /**
150
+ * Extract anchors and summary from AFS entry metadata.
151
+ *
152
+ * @param path - The entry path
153
+ * @param meta - The entry metadata (from AFSEntry.meta)
154
+ * @returns ExtractionResult or null if nothing useful can be extracted
155
+ */
156
+ function extractFromMeta(path, meta) {
157
+ if (!meta) return null;
158
+ if (meta.kind === "afs:directory") return null;
159
+ const anchors = [];
160
+ const timeAnchor = extractTimeAnchor(meta);
161
+ if (timeAnchor) anchors.push(timeAnchor);
162
+ const locationAnchor = extractLocationAnchor(meta);
163
+ if (locationAnchor) anchors.push(locationAnchor);
164
+ const contentTypeAnchor = extractContentTypeAnchor(path, meta);
165
+ if (contentTypeAnchor) anchors.push(contentTypeAnchor);
166
+ return {
167
+ anchors,
168
+ summary: buildSummary(path, meta)
169
+ };
170
+ }
171
+ function extractTimeAnchor(meta) {
172
+ const exifDate = meta.exif?.DateTimeOriginal;
173
+ if (exifDate) return {
174
+ type: "time",
175
+ confidence: 1,
176
+ timestamp: exifDate
177
+ };
178
+ const createdAt = meta.createdAt;
179
+ if (createdAt) return {
180
+ type: "time",
181
+ confidence: .9,
182
+ timestamp: createdAt
183
+ };
184
+ const updatedAt = meta.updatedAt;
185
+ if (updatedAt) return {
186
+ type: "time",
187
+ confidence: .7,
188
+ timestamp: updatedAt
189
+ };
190
+ return null;
191
+ }
192
+ function extractLocationAnchor(meta) {
193
+ const exif = meta.exif;
194
+ if (!exif) return null;
195
+ const lat = exif.GPSLatitude;
196
+ const lon = exif.GPSLongitude;
197
+ if (lat == null || lon == null) return null;
198
+ return {
199
+ type: "location",
200
+ confidence: .95,
201
+ geohash: encodeGeohash(lat, lon)
202
+ };
203
+ }
204
+ function extractContentTypeAnchor(path, meta) {
205
+ const mime = meta.mime;
206
+ if (mime) return {
207
+ type: "content-type",
208
+ confidence: 1,
209
+ mime,
210
+ category: mimeCategory(mime)
211
+ };
212
+ const inferred = EXT_MIME[fileExtension(path)];
213
+ if (inferred) return {
214
+ type: "content-type",
215
+ confidence: .8,
216
+ mime: inferred.mime,
217
+ category: inferred.category
218
+ };
219
+ return null;
220
+ }
221
+ function buildSummary(path, meta) {
222
+ const parts = [];
223
+ const name = fileName(path);
224
+ parts.push(name);
225
+ const description = meta.description;
226
+ if (description) parts.push(description);
227
+ const mime = meta.mime;
228
+ if (mime) parts.push(mime);
229
+ const size = meta.size;
230
+ if (size != null) parts.push(formatSize(size));
231
+ return parts.join(" — ");
232
+ }
233
+ function formatSize(bytes) {
234
+ if (bytes < 1024) return `${bytes}B`;
235
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)}KB`;
236
+ if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)}MB`;
237
+ return `${(bytes / 1073741824).toFixed(1)}GB`;
238
+ }
239
+
240
+ //#endregion
241
+ export { extractFromMeta };
242
+ //# sourceMappingURL=defaults.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.mjs","names":[],"sources":["../../src/extraction/defaults.ts"],"sourcesContent":["/**\n * Default metadata-based extractor — generates anchors and summary from AFS entry metadata.\n *\n * No LLM required. Extracts:\n * - Time anchor from timestamps (EXIF DateTimeOriginal > createdAt > updatedAt)\n * - Location anchor from EXIF GPS coordinates (via geohash encoding)\n * - Content-type anchor from mime type or file extension\n * - Summary from path + description + metadata\n */\nimport type { Anchor, ExtractionResult } from \"../types.js\";\n\n// --- Mime category mapping ---\n\nconst MIME_CATEGORIES: Record<string, string> = {\n image: \"image\",\n video: \"video\",\n audio: \"audio\",\n text: \"document\",\n application: \"document\",\n};\n\nconst EXT_MIME: Record<string, { mime: string; category: string }> = {\n \".jpg\": { mime: \"image/jpeg\", category: \"image\" },\n \".jpeg\": { mime: \"image/jpeg\", category: \"image\" },\n \".png\": { mime: \"image/png\", category: \"image\" },\n \".gif\": { mime: \"image/gif\", category: \"image\" },\n \".webp\": { mime: \"image/webp\", category: \"image\" },\n \".svg\": { mime: \"image/svg+xml\", category: \"image\" },\n \".mp4\": { mime: \"video/mp4\", category: \"video\" },\n \".mov\": { mime: \"video/quicktime\", category: \"video\" },\n \".mp3\": { mime: \"audio/mpeg\", category: \"audio\" },\n \".wav\": { mime: \"audio/wav\", category: \"audio\" },\n \".md\": { mime: \"text/markdown\", category: \"document\" },\n \".txt\": { mime: \"text/plain\", category: \"document\" },\n \".pdf\": { mime: \"application/pdf\", category: \"document\" },\n \".json\": { mime: \"application/json\", category: \"document\" },\n \".yaml\": { mime: \"application/yaml\", category: \"document\" },\n \".yml\": { mime: \"application/yaml\", category: \"document\" },\n \".html\": { mime: \"text/html\", category: \"document\" },\n \".css\": { mime: \"text/css\", category: \"document\" },\n \".js\": { mime: \"application/javascript\", category: \"code\" },\n \".ts\": { mime: \"application/typescript\", category: \"code\" },\n \".py\": { mime: \"text/x-python\", category: \"code\" },\n \".rs\": { mime: \"text/x-rust\", category: \"code\" },\n \".go\": { mime: \"text/x-go\", category: \"code\" },\n};\n\nfunction mimeCategory(mime: string): string {\n const primary = mime.split(\"/\")[0] ?? \"\";\n return MIME_CATEGORIES[primary] ?? \"other\";\n}\n\nfunction fileExtension(path: string): string {\n const lastDot = path.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n return path.slice(lastDot).toLowerCase();\n}\n\nfunction fileName(path: string): string {\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] ?? path;\n}\n\n// --- Geohash encoding (basic) ---\n\nconst BASE32 = \"0123456789bcdefghjkmnpqrstuvwxyz\";\n\nfunction encodeGeohash(lat: number, lon: number, precision = 7): string {\n let minLat = -90;\n let maxLat = 90;\n let minLon = -180;\n let maxLon = 180;\n let hash = \"\";\n let bit = 0;\n let ch = 0;\n let isLon = true;\n\n while (hash.length < precision) {\n if (isLon) {\n const mid = (minLon + maxLon) / 2;\n if (lon >= mid) {\n ch |= 1 << (4 - bit);\n minLon = mid;\n } else {\n maxLon = mid;\n }\n } else {\n const mid = (minLat + maxLat) / 2;\n if (lat >= mid) {\n ch |= 1 << (4 - bit);\n minLat = mid;\n } else {\n maxLat = mid;\n }\n }\n\n isLon = !isLon;\n bit++;\n\n if (bit === 5) {\n hash += BASE32[ch];\n bit = 0;\n ch = 0;\n }\n }\n\n return hash;\n}\n\n// --- Core extraction ---\n\n/**\n * Extract anchors and summary from AFS entry metadata.\n *\n * @param path - The entry path\n * @param meta - The entry metadata (from AFSEntry.meta)\n * @returns ExtractionResult or null if nothing useful can be extracted\n */\nexport function extractFromMeta(\n path: string,\n meta: Record<string, unknown> | null | undefined,\n): ExtractionResult | null {\n if (!meta) return null;\n\n // Skip directories — only index leaf content\n const kind = meta.kind as string | undefined;\n if (kind === \"afs:directory\") return null;\n\n const anchors: Anchor[] = [];\n\n // --- Time anchor ---\n const timeAnchor = extractTimeAnchor(meta);\n if (timeAnchor) anchors.push(timeAnchor);\n\n // --- Location anchor ---\n const locationAnchor = extractLocationAnchor(meta);\n if (locationAnchor) anchors.push(locationAnchor);\n\n // --- Content-type anchor ---\n const contentTypeAnchor = extractContentTypeAnchor(path, meta);\n if (contentTypeAnchor) anchors.push(contentTypeAnchor);\n\n // --- Summary ---\n const summary = buildSummary(path, meta);\n\n return { anchors, summary };\n}\n\nfunction extractTimeAnchor(meta: Record<string, unknown>): Anchor | null {\n const exif = meta.exif as Record<string, unknown> | undefined;\n const exifDate = exif?.DateTimeOriginal as string | undefined;\n\n if (exifDate) {\n return { type: \"time\", confidence: 1.0, timestamp: exifDate };\n }\n\n const createdAt = meta.createdAt as string | undefined;\n if (createdAt) {\n return { type: \"time\", confidence: 0.9, timestamp: createdAt };\n }\n\n const updatedAt = meta.updatedAt as string | undefined;\n if (updatedAt) {\n return { type: \"time\", confidence: 0.7, timestamp: updatedAt };\n }\n\n return null;\n}\n\nfunction extractLocationAnchor(meta: Record<string, unknown>): Anchor | null {\n const exif = meta.exif as Record<string, unknown> | undefined;\n if (!exif) return null;\n\n const lat = exif.GPSLatitude as number | undefined;\n const lon = exif.GPSLongitude as number | undefined;\n\n if (lat == null || lon == null) return null;\n\n const geohash = encodeGeohash(lat, lon);\n return { type: \"location\", confidence: 0.95, geohash };\n}\n\nfunction extractContentTypeAnchor(path: string, meta: Record<string, unknown>): Anchor | null {\n const mime = meta.mime as string | undefined;\n\n if (mime) {\n return {\n type: \"content-type\",\n confidence: 1.0,\n mime,\n category: mimeCategory(mime),\n };\n }\n\n // Fallback: infer from extension\n const ext = fileExtension(path);\n const inferred = EXT_MIME[ext];\n if (inferred) {\n return {\n type: \"content-type\",\n confidence: 0.8,\n mime: inferred.mime,\n category: inferred.category,\n };\n }\n\n return null;\n}\n\nfunction buildSummary(path: string, meta: Record<string, unknown>): string {\n const parts: string[] = [];\n const name = fileName(path);\n\n parts.push(name);\n\n const description = meta.description as string | undefined;\n if (description) {\n parts.push(description);\n }\n\n const mime = meta.mime as string | undefined;\n if (mime) {\n parts.push(mime);\n }\n\n const size = meta.size as number | undefined;\n if (size != null) {\n parts.push(formatSize(size));\n }\n\n return parts.join(\" — \");\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)}KB`;\n if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)}MB`;\n return `${(bytes / 1073741824).toFixed(1)}GB`;\n}\n"],"mappings":"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"}