mem-os-python 1.6.27__py3-none-any.whl
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.
- mem_os_python-1.6.27.dist-info/METADATA +1032 -0
- mem_os_python-1.6.27.dist-info/RECORD +253 -0
- mem_os_python-1.6.27.dist-info/WHEEL +4 -0
- mem_os_python-1.6.27.dist-info/entry_points.txt +2 -0
- mem_os_python-1.6.27.dist-info/licenses/LICENSE +21 -0
- memos/__init__.py +16 -0
- memos/_js/adapters/anthropic.d.ts +279 -0
- memos/_js/adapters/anthropic.d.ts.map +1 -0
- memos/_js/adapters/anthropic.js +348 -0
- memos/_js/adapters/anthropic.js.map +1 -0
- memos/_js/adapters/base.d.ts +10 -0
- memos/_js/adapters/base.d.ts.map +1 -0
- memos/_js/adapters/base.js +2 -0
- memos/_js/adapters/base.js.map +1 -0
- memos/_js/adapters/openai.d.ts +264 -0
- memos/_js/adapters/openai.d.ts.map +1 -0
- memos/_js/adapters/openai.js +342 -0
- memos/_js/adapters/openai.js.map +1 -0
- memos/_js/apps/explorer.d.ts +244 -0
- memos/_js/apps/explorer.d.ts.map +1 -0
- memos/_js/apps/explorer.js +738 -0
- memos/_js/apps/explorer.js.map +1 -0
- memos/_js/citations.d.ts +65 -0
- memos/_js/citations.d.ts.map +1 -0
- memos/_js/citations.js +143 -0
- memos/_js/citations.js.map +1 -0
- memos/_js/cli-browse.d.ts +3 -0
- memos/_js/cli-browse.d.ts.map +1 -0
- memos/_js/cli-browse.js +129 -0
- memos/_js/cli-browse.js.map +1 -0
- memos/_js/cli-completion.d.ts +31 -0
- memos/_js/cli-completion.d.ts.map +1 -0
- memos/_js/cli-completion.js +340 -0
- memos/_js/cli-completion.js.map +1 -0
- memos/_js/cli-help.d.ts +18 -0
- memos/_js/cli-help.d.ts.map +1 -0
- memos/_js/cli-help.js +357 -0
- memos/_js/cli-help.js.map +1 -0
- memos/_js/cli.d.ts +28 -0
- memos/_js/cli.d.ts.map +1 -0
- memos/_js/cli.js +2880 -0
- memos/_js/cli.js.map +1 -0
- memos/_js/compression.d.ts +25 -0
- memos/_js/compression.d.ts.map +1 -0
- memos/_js/compression.js +319 -0
- memos/_js/compression.js.map +1 -0
- memos/_js/confidence-machine.d.ts +99 -0
- memos/_js/confidence-machine.d.ts.map +1 -0
- memos/_js/confidence-machine.js +222 -0
- memos/_js/confidence-machine.js.map +1 -0
- memos/_js/context-pack.d.ts +506 -0
- memos/_js/context-pack.d.ts.map +1 -0
- memos/_js/context-pack.js +1435 -0
- memos/_js/context-pack.js.map +1 -0
- memos/_js/contradictions.d.ts +160 -0
- memos/_js/contradictions.d.ts.map +1 -0
- memos/_js/contradictions.js +255 -0
- memos/_js/contradictions.js.map +1 -0
- memos/_js/dashboard.d.ts +30 -0
- memos/_js/dashboard.d.ts.map +1 -0
- memos/_js/dashboard.js +302 -0
- memos/_js/dashboard.js.map +1 -0
- memos/_js/ebbinghaus.d.ts +29 -0
- memos/_js/ebbinghaus.d.ts.map +1 -0
- memos/_js/ebbinghaus.js +32 -0
- memos/_js/ebbinghaus.js.map +1 -0
- memos/_js/embedding-queue.d.ts +190 -0
- memos/_js/embedding-queue.d.ts.map +1 -0
- memos/_js/embedding-queue.js +316 -0
- memos/_js/embedding-queue.js.map +1 -0
- memos/_js/embeddings.d.ts +187 -0
- memos/_js/embeddings.d.ts.map +1 -0
- memos/_js/embeddings.js +633 -0
- memos/_js/embeddings.js.map +1 -0
- memos/_js/entity-extraction.d.ts +54 -0
- memos/_js/entity-extraction.d.ts.map +1 -0
- memos/_js/entity-extraction.js +325 -0
- memos/_js/entity-extraction.js.map +1 -0
- memos/_js/entity-index.d.ts +93 -0
- memos/_js/entity-index.d.ts.map +1 -0
- memos/_js/entity-index.js +165 -0
- memos/_js/entity-index.js.map +1 -0
- memos/_js/event-memory.d.ts +147 -0
- memos/_js/event-memory.d.ts.map +1 -0
- memos/_js/event-memory.js +290 -0
- memos/_js/event-memory.js.map +1 -0
- memos/_js/external-import.d.ts +98 -0
- memos/_js/external-import.d.ts.map +1 -0
- memos/_js/external-import.js +669 -0
- memos/_js/external-import.js.map +1 -0
- memos/_js/fidelity.d.ts +367 -0
- memos/_js/fidelity.d.ts.map +1 -0
- memos/_js/fidelity.js +911 -0
- memos/_js/fidelity.js.map +1 -0
- memos/_js/graph-expansion.d.ts +119 -0
- memos/_js/graph-expansion.d.ts.map +1 -0
- memos/_js/graph-expansion.js +213 -0
- memos/_js/graph-expansion.js.map +1 -0
- memos/_js/graph-mermaid.d.ts +13 -0
- memos/_js/graph-mermaid.d.ts.map +1 -0
- memos/_js/graph-mermaid.js +32 -0
- memos/_js/graph-mermaid.js.map +1 -0
- memos/_js/graph.d.ts +170 -0
- memos/_js/graph.d.ts.map +1 -0
- memos/_js/graph.js +482 -0
- memos/_js/graph.js.map +1 -0
- memos/_js/harness.d.ts +63 -0
- memos/_js/harness.d.ts.map +1 -0
- memos/_js/harness.js +93 -0
- memos/_js/harness.js.map +1 -0
- memos/_js/importance.d.ts +118 -0
- memos/_js/importance.d.ts.map +1 -0
- memos/_js/importance.js +144 -0
- memos/_js/importance.js.map +1 -0
- memos/_js/index.d.ts +51 -0
- memos/_js/index.d.ts.map +1 -0
- memos/_js/index.js +53 -0
- memos/_js/index.js.map +1 -0
- memos/_js/mcp.d.ts +58 -0
- memos/_js/mcp.d.ts.map +1 -0
- memos/_js/mcp.js +1853 -0
- memos/_js/mcp.js.map +1 -0
- memos/_js/memory.d.ts +1762 -0
- memos/_js/memory.d.ts.map +1 -0
- memos/_js/memory.js +6283 -0
- memos/_js/memory.js.map +1 -0
- memos/_js/procedural.d.ts +74 -0
- memos/_js/procedural.d.ts.map +1 -0
- memos/_js/procedural.js +125 -0
- memos/_js/procedural.js.map +1 -0
- memos/_js/project-config.d.ts +68 -0
- memos/_js/project-config.d.ts.map +1 -0
- memos/_js/project-config.js +59 -0
- memos/_js/project-config.js.map +1 -0
- memos/_js/proof-of-forgetting.d.ts +57 -0
- memos/_js/proof-of-forgetting.d.ts.map +1 -0
- memos/_js/proof-of-forgetting.js +80 -0
- memos/_js/proof-of-forgetting.js.map +1 -0
- memos/_js/provenance.d.ts +122 -0
- memos/_js/provenance.d.ts.map +1 -0
- memos/_js/provenance.js +182 -0
- memos/_js/provenance.js.map +1 -0
- memos/_js/quarantine-commands.d.ts +23 -0
- memos/_js/quarantine-commands.d.ts.map +1 -0
- memos/_js/quarantine-commands.js +42 -0
- memos/_js/quarantine-commands.js.map +1 -0
- memos/_js/quarantine.d.ts +120 -0
- memos/_js/quarantine.d.ts.map +1 -0
- memos/_js/quarantine.js +873 -0
- memos/_js/quarantine.js.map +1 -0
- memos/_js/redact.d.ts +12 -0
- memos/_js/redact.d.ts.map +1 -0
- memos/_js/redact.js +26 -0
- memos/_js/redact.js.map +1 -0
- memos/_js/repl.d.ts +57 -0
- memos/_js/repl.d.ts.map +1 -0
- memos/_js/repl.js +295 -0
- memos/_js/repl.js.map +1 -0
- memos/_js/rerank-local.d.ts +61 -0
- memos/_js/rerank-local.d.ts.map +1 -0
- memos/_js/rerank-local.js +210 -0
- memos/_js/rerank-local.js.map +1 -0
- memos/_js/retain-filter.d.ts +98 -0
- memos/_js/retain-filter.d.ts.map +1 -0
- memos/_js/retain-filter.js +232 -0
- memos/_js/retain-filter.js.map +1 -0
- memos/_js/retrieval.d.ts +265 -0
- memos/_js/retrieval.d.ts.map +1 -0
- memos/_js/retrieval.js +1018 -0
- memos/_js/retrieval.js.map +1 -0
- memos/_js/revert.d.ts +77 -0
- memos/_js/revert.d.ts.map +1 -0
- memos/_js/revert.js +252 -0
- memos/_js/revert.js.map +1 -0
- memos/_js/scope.d.ts +30 -0
- memos/_js/scope.d.ts.map +1 -0
- memos/_js/scope.js +71 -0
- memos/_js/scope.js.map +1 -0
- memos/_js/semantic-screen.d.ts +152 -0
- memos/_js/semantic-screen.d.ts.map +1 -0
- memos/_js/semantic-screen.js +290 -0
- memos/_js/semantic-screen.js.map +1 -0
- memos/_js/session-hooks.d.ts +127 -0
- memos/_js/session-hooks.d.ts.map +1 -0
- memos/_js/session-hooks.js +482 -0
- memos/_js/session-hooks.js.map +1 -0
- memos/_js/storage/sqlite.d.ts +427 -0
- memos/_js/storage/sqlite.d.ts.map +1 -0
- memos/_js/storage/sqlite.js +2428 -0
- memos/_js/storage/sqlite.js.map +1 -0
- memos/_js/sync.d.ts +213 -0
- memos/_js/sync.d.ts.map +1 -0
- memos/_js/sync.js +389 -0
- memos/_js/sync.js.map +1 -0
- memos/_js/tamper-log.d.ts +98 -0
- memos/_js/tamper-log.d.ts.map +1 -0
- memos/_js/tamper-log.js +327 -0
- memos/_js/tamper-log.js.map +1 -0
- memos/_js/temporal.d.ts +92 -0
- memos/_js/temporal.d.ts.map +1 -0
- memos/_js/temporal.js +536 -0
- memos/_js/temporal.js.map +1 -0
- memos/_js/time-travel.d.ts +38 -0
- memos/_js/time-travel.d.ts.map +1 -0
- memos/_js/time-travel.js +46 -0
- memos/_js/time-travel.js.map +1 -0
- memos/_js/timestamp-format.d.ts +18 -0
- memos/_js/timestamp-format.d.ts.map +1 -0
- memos/_js/timestamp-format.js +52 -0
- memos/_js/timestamp-format.js.map +1 -0
- memos/_js/triple-extraction.d.ts +31 -0
- memos/_js/triple-extraction.d.ts.map +1 -0
- memos/_js/triple-extraction.js +116 -0
- memos/_js/triple-extraction.js.map +1 -0
- memos/_js/types.d.ts +2474 -0
- memos/_js/types.d.ts.map +1 -0
- memos/_js/types.js +20 -0
- memos/_js/types.js.map +1 -0
- memos/_js/updater.d.ts +95 -0
- memos/_js/updater.d.ts.map +1 -0
- memos/_js/updater.js +268 -0
- memos/_js/updater.js.map +1 -0
- memos/_js/version.d.ts +17 -0
- memos/_js/version.d.ts.map +1 -0
- memos/_js/version.js +34 -0
- memos/_js/version.js.map +1 -0
- memos/_js/vision/clip-query-cache.d.ts +58 -0
- memos/_js/vision/clip-query-cache.d.ts.map +1 -0
- memos/_js/vision/clip-query-cache.js +79 -0
- memos/_js/vision/clip-query-cache.js.map +1 -0
- memos/_js/vision/clip.d.ts +113 -0
- memos/_js/vision/clip.d.ts.map +1 -0
- memos/_js/vision/clip.js +224 -0
- memos/_js/vision/clip.js.map +1 -0
- memos/_js/vision/fake-clip.d.ts +55 -0
- memos/_js/vision/fake-clip.d.ts.map +1 -0
- memos/_js/vision/fake-clip.js +122 -0
- memos/_js/vision/fake-clip.js.map +1 -0
- memos/_js/vision/index.d.ts +15 -0
- memos/_js/vision/index.d.ts.map +1 -0
- memos/_js/vision/index.js +13 -0
- memos/_js/vision/index.js.map +1 -0
- memos/_js/vision/store.d.ts +137 -0
- memos/_js/vision/store.d.ts.map +1 -0
- memos/_js/vision/store.js +383 -0
- memos/_js/vision/store.js.map +1 -0
- memos/adapters/__init__.py +0 -0
- memos/adapters/crewai.py +385 -0
- memos/adapters/langchain.py +301 -0
- memos/adapters/ollama.py +396 -0
- memos/server/__init__.py +0 -0
- memos/server/main.py +547 -0
- memos/server/routes.py +360 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressed blob store for image memories.
|
|
3
|
+
*
|
|
4
|
+
* Image bytes never go into SQLite. A 400 KB JPEG dragged through the
|
|
5
|
+
* WAL, the encrypted-sync channel, and the tamper-log hash chain would
|
|
6
|
+
* cost far more than the bytes are worth — all three are tuned for small
|
|
7
|
+
* text rows. Instead the DB stores a reference (`img_<sha256[0:12]>`)
|
|
8
|
+
* and the file lives in a sibling directory next to the database.
|
|
9
|
+
*
|
|
10
|
+
* Content addressing gives three properties for free:
|
|
11
|
+
* - **Dedupe:** identical bytes stored twice cost one file. The write
|
|
12
|
+
* path hashes before creating a node, so a repeated image produces a
|
|
13
|
+
* single blob and (in the same namespace) a single node.
|
|
14
|
+
* - **Integrity:** the ref is derived from the digest, so a truncated
|
|
15
|
+
* or corrupted file is detectable by re-hashing.
|
|
16
|
+
* - **Portability:** the root is derived from the database path, so a
|
|
17
|
+
* store moves as a unit.
|
|
18
|
+
*
|
|
19
|
+
* Dependency-free by design — MemOS carries only three runtime deps and
|
|
20
|
+
* prizes that, so image dimensions are read straight from the PNG IHDR
|
|
21
|
+
* and JPEG SOFn headers rather than pulling in an image library. WebP
|
|
22
|
+
* and GIF report `0x0` dimensions rather than failing: the dimensions
|
|
23
|
+
* are used for prompt context, not for correctness.
|
|
24
|
+
*
|
|
25
|
+
* @module @memos/vision/store
|
|
26
|
+
*/
|
|
27
|
+
import type { ImageInput, ImageKind } from "../types.js";
|
|
28
|
+
/**
|
|
29
|
+
* Thrown when image bytes are rejected before anything is persisted.
|
|
30
|
+
* Fail-closed: the caller must not write a node when this is thrown.
|
|
31
|
+
*/
|
|
32
|
+
export declare class ImageRejectedError extends Error {
|
|
33
|
+
readonly kind: "mime" | "size" | "empty";
|
|
34
|
+
constructor(message: string, kind: "mime" | "size" | "empty");
|
|
35
|
+
}
|
|
36
|
+
/** What a stored image looks like once written. */
|
|
37
|
+
export interface StoredImage {
|
|
38
|
+
/** Content-addressed key, `img_<sha256[0:12]>`. */
|
|
39
|
+
ref: string;
|
|
40
|
+
/** Absolute path of the blob file. */
|
|
41
|
+
path: string;
|
|
42
|
+
/** Full hex digest of the bytes. */
|
|
43
|
+
sha256: string;
|
|
44
|
+
/** Detected pixel width, or 0 when the header could not be parsed. */
|
|
45
|
+
width: number;
|
|
46
|
+
/** Detected pixel height, or 0 when the header could not be parsed. */
|
|
47
|
+
height: number;
|
|
48
|
+
/** Size of the stored blob in bytes. */
|
|
49
|
+
bytes: number;
|
|
50
|
+
/** Sniffed MIME type. */
|
|
51
|
+
mime: string;
|
|
52
|
+
}
|
|
53
|
+
/** Derive the blob-store root from a database path (`<dbDir>/memos-images`). */
|
|
54
|
+
export declare function blobRoot(dbPath: string): string;
|
|
55
|
+
/** Build the content-addressed ref for a digest. */
|
|
56
|
+
export declare function refFor(sha256: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Detect the MIME type from magic bytes rather than trusting the
|
|
59
|
+
* caller's declared type — a `.png` name on JPEG bytes would otherwise
|
|
60
|
+
* be stored and later mis-decoded by a vision model.
|
|
61
|
+
*/
|
|
62
|
+
export declare function sniffMime(bytes: Uint8Array): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Read pixel dimensions from the container header.
|
|
65
|
+
*
|
|
66
|
+
* PNG: bytes 16-19 (big-endian width), 20-23 (height) after the 8-byte
|
|
67
|
+
* signature and the 4-byte length + 4-byte "IHDR" chunk type.
|
|
68
|
+
* JPEG: walk the marker segments to the first SOFn; width/height are
|
|
69
|
+
* big-endian 16-bit fields at a fixed offset within that frame header.
|
|
70
|
+
* Anything else returns `0x0` — dimensions are prompt context, not
|
|
71
|
+
* correctness, and a failed parse must never fail a write.
|
|
72
|
+
*/
|
|
73
|
+
export declare function readDimensions(bytes: Uint8Array, mime: string): {
|
|
74
|
+
width: number;
|
|
75
|
+
height: number;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Write image bytes to the blob store, content-addressed.
|
|
79
|
+
*
|
|
80
|
+
* Idempotent: writing the same bytes twice rewrites the same file with
|
|
81
|
+
* the same content, so a repeated call is a no-op on disk and returns
|
|
82
|
+
* an identical `StoredImage`. Callers still dedupe at the NODE level
|
|
83
|
+
* (same digest in the same namespace → one node) in `memory.ts`.
|
|
84
|
+
*
|
|
85
|
+
* @throws {@link ImageRejectedError} when the bytes are empty, an
|
|
86
|
+
* unrecognised format, or above `maxBytes`.
|
|
87
|
+
*/
|
|
88
|
+
export declare function writeImage(bytes: Buffer | Uint8Array, declaredMime: string | undefined, root: string, maxBytes: number): StoredImage;
|
|
89
|
+
/** Read a blob back by ref. Returns null when it is missing. */
|
|
90
|
+
export declare function readImage(ref: string, root: string): Buffer | null;
|
|
91
|
+
/**
|
|
92
|
+
* Resolve a ref to an on-disk path, tolerating any of the accepted
|
|
93
|
+
* extensions (the format is recorded in the metadata, but the store
|
|
94
|
+
* stays addressable by ref alone so a pack consumer holding only
|
|
95
|
+
* `[img:…]` can still resolve it).
|
|
96
|
+
*/
|
|
97
|
+
export declare function resolveRef(ref: string, root: string): string | null;
|
|
98
|
+
/** Delete a blob by ref. Returns true when a file was removed. */
|
|
99
|
+
export declare function deleteRef(ref: string, root: string): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Coarse classification from MIME type only.
|
|
102
|
+
*
|
|
103
|
+
* Deliberately NOT content analysis: `photo` vs `screenshot` cannot be
|
|
104
|
+
* told apart from a header, and guessing would put a wrong label in
|
|
105
|
+
* every image node. `chart`/`diagram`/`memo` are caller-declared via
|
|
106
|
+
* `addImageMemory({ kind })`; the sniffed value is the safe default.
|
|
107
|
+
*/
|
|
108
|
+
export declare function kindFromMime(mime: string): ImageKind;
|
|
109
|
+
/**
|
|
110
|
+
* Delete blobs that no live node references anymore.
|
|
111
|
+
*
|
|
112
|
+
* Called explicitly (never on a background timer) because eviction
|
|
113
|
+
* (`forgetByDecay`, `archive`) deletes nodes, and a blob whose node is
|
|
114
|
+
* gone is unreachable garbage. Returns how many files were removed so
|
|
115
|
+
* maintenance commands can report it.
|
|
116
|
+
*/
|
|
117
|
+
export declare function purgeOrphanImages(root: string, liveRefs: ReadonlySet<string>): number;
|
|
118
|
+
/** Size of a stored blob in bytes, or null when missing. */
|
|
119
|
+
export declare function imageSize(path: string): number | null;
|
|
120
|
+
/**
|
|
121
|
+
* Normalize every accepted {@link ImageInput} shape into raw bytes plus
|
|
122
|
+
* a declared MIME type.
|
|
123
|
+
*
|
|
124
|
+
* Resolution order matters: a `data:` URL is checked BEFORE a path
|
|
125
|
+
* (both are strings), and base64-with-explicit-mime is checked before
|
|
126
|
+
* the fetch path (both can be objects). Bytes pass through untouched —
|
|
127
|
+
* the caller's `writeImage` sniffs the true format from the header
|
|
128
|
+
* anyway, so a wrong declared MIME can never mislabel the blob.
|
|
129
|
+
*
|
|
130
|
+
* `file:` and `http(s):` URLs are fetched; everything else that looks
|
|
131
|
+
* like a URL but isn't fetchable throws rather than being guessed at.
|
|
132
|
+
*/
|
|
133
|
+
export declare function normalizeImageInput(input: ImageInput): Promise<{
|
|
134
|
+
bytes: Buffer;
|
|
135
|
+
mime: string | undefined;
|
|
136
|
+
}>;
|
|
137
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/vision/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAeH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA+CzD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO;IAF1C,YACE,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAIzC;CACF;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,oDAAoD;AACpD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAwB1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAsDnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,GAAG,UAAU,EAC1B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,WAAW,CAkCb;AAED,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOnE;AAED,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAS5D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAKpD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAC5B,MAAM,CAUR;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMrD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC,CA2CtD"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressed blob store for image memories.
|
|
3
|
+
*
|
|
4
|
+
* Image bytes never go into SQLite. A 400 KB JPEG dragged through the
|
|
5
|
+
* WAL, the encrypted-sync channel, and the tamper-log hash chain would
|
|
6
|
+
* cost far more than the bytes are worth — all three are tuned for small
|
|
7
|
+
* text rows. Instead the DB stores a reference (`img_<sha256[0:12]>`)
|
|
8
|
+
* and the file lives in a sibling directory next to the database.
|
|
9
|
+
*
|
|
10
|
+
* Content addressing gives three properties for free:
|
|
11
|
+
* - **Dedupe:** identical bytes stored twice cost one file. The write
|
|
12
|
+
* path hashes before creating a node, so a repeated image produces a
|
|
13
|
+
* single blob and (in the same namespace) a single node.
|
|
14
|
+
* - **Integrity:** the ref is derived from the digest, so a truncated
|
|
15
|
+
* or corrupted file is detectable by re-hashing.
|
|
16
|
+
* - **Portability:** the root is derived from the database path, so a
|
|
17
|
+
* store moves as a unit.
|
|
18
|
+
*
|
|
19
|
+
* Dependency-free by design — MemOS carries only three runtime deps and
|
|
20
|
+
* prizes that, so image dimensions are read straight from the PNG IHDR
|
|
21
|
+
* and JPEG SOFn headers rather than pulling in an image library. WebP
|
|
22
|
+
* and GIF report `0x0` dimensions rather than failing: the dimensions
|
|
23
|
+
* are used for prompt context, not for correctness.
|
|
24
|
+
*
|
|
25
|
+
* @module @memos/vision/store
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
28
|
+
import { readFile } from "node:fs/promises";
|
|
29
|
+
import { fileURLToPath } from "node:url";
|
|
30
|
+
import { join } from "node:path";
|
|
31
|
+
import { createHash } from "node:crypto";
|
|
32
|
+
/** Prefix for every content-addressed image reference. */
|
|
33
|
+
const REF_PREFIX = "img_";
|
|
34
|
+
/** Number of hex digest characters used in a ref (12 = 48 bits). */
|
|
35
|
+
const REF_HASH_LENGTH = 12;
|
|
36
|
+
/**
|
|
37
|
+
* Accepted image MIME types. An unknown type is rejected at the write
|
|
38
|
+
* path (fail-closed: no node is created) rather than stored with a
|
|
39
|
+
* guess — a mislabeled blob is worse than a rejected write.
|
|
40
|
+
*/
|
|
41
|
+
const ALLOWED_MIME_TYPES = new Set([
|
|
42
|
+
"image/png",
|
|
43
|
+
"image/jpeg",
|
|
44
|
+
"image/gif",
|
|
45
|
+
"image/webp",
|
|
46
|
+
]);
|
|
47
|
+
/** Magic-number signatures for the accepted formats. */
|
|
48
|
+
const MIME_SIGNATURES = [
|
|
49
|
+
// PNG: 89 50 4E 47 0D 0A 1A 0A
|
|
50
|
+
{
|
|
51
|
+
mime: "image/png",
|
|
52
|
+
bytes: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
|
|
53
|
+
},
|
|
54
|
+
// JPEG: FF D8 FF
|
|
55
|
+
{ mime: "image/jpeg", bytes: [0xff, 0xd8, 0xff] },
|
|
56
|
+
// GIF: "GIF87a" / "GIF89a"
|
|
57
|
+
{ mime: "image/gif", bytes: [0x47, 0x49, 0x46, 0x38] },
|
|
58
|
+
// WebP: "RIFF" .... "WEBP"
|
|
59
|
+
{ mime: "image/webp", bytes: [0x52, 0x49, 0x46, 0x46] },
|
|
60
|
+
];
|
|
61
|
+
/** File extension per accepted MIME type. */
|
|
62
|
+
const MIME_EXTENSION = {
|
|
63
|
+
"image/png": "png",
|
|
64
|
+
"image/jpeg": "jpg",
|
|
65
|
+
"image/gif": "gif",
|
|
66
|
+
"image/webp": "webp",
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Thrown when image bytes are rejected before anything is persisted.
|
|
70
|
+
* Fail-closed: the caller must not write a node when this is thrown.
|
|
71
|
+
*/
|
|
72
|
+
export class ImageRejectedError extends Error {
|
|
73
|
+
kind;
|
|
74
|
+
constructor(message, kind) {
|
|
75
|
+
super(message);
|
|
76
|
+
this.kind = kind;
|
|
77
|
+
this.name = "ImageRejectedError";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Derive the blob-store root from a database path (`<dbDir>/memos-images`). */
|
|
81
|
+
export function blobRoot(dbPath) {
|
|
82
|
+
// The DB path's directory is the anchor so a store moves as a unit.
|
|
83
|
+
const lastSlash = Math.max(dbPath.lastIndexOf("/"), dbPath.lastIndexOf("\\"));
|
|
84
|
+
const dir = lastSlash >= 0 ? dbPath.slice(0, lastSlash) : ".";
|
|
85
|
+
return join(dir, "memos-images");
|
|
86
|
+
}
|
|
87
|
+
/** Build the content-addressed ref for a digest. */
|
|
88
|
+
export function refFor(sha256) {
|
|
89
|
+
return REF_PREFIX + sha256.slice(0, REF_HASH_LENGTH);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Detect the MIME type from magic bytes rather than trusting the
|
|
93
|
+
* caller's declared type — a `.png` name on JPEG bytes would otherwise
|
|
94
|
+
* be stored and later mis-decoded by a vision model.
|
|
95
|
+
*/
|
|
96
|
+
export function sniffMime(bytes) {
|
|
97
|
+
for (const sig of MIME_SIGNATURES) {
|
|
98
|
+
const offset = sig.offset ?? 0;
|
|
99
|
+
if (bytes.length < offset + sig.bytes.length)
|
|
100
|
+
continue;
|
|
101
|
+
let match = true;
|
|
102
|
+
for (let i = 0; i < sig.bytes.length; i++) {
|
|
103
|
+
if (bytes[offset + i] !== sig.bytes[i]) {
|
|
104
|
+
match = false;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!match)
|
|
109
|
+
continue;
|
|
110
|
+
// WebP needs the trailing "WEBP" fourcc at offset 8 to disambiguate
|
|
111
|
+
// from other RIFF containers.
|
|
112
|
+
if (sig.mime === "image/webp") {
|
|
113
|
+
if (bytes.length < 12)
|
|
114
|
+
return null;
|
|
115
|
+
const fourcc = [bytes[8], bytes[9], bytes[10], bytes[11]]
|
|
116
|
+
.map((b) => String.fromCharCode(b))
|
|
117
|
+
.join("");
|
|
118
|
+
if (fourcc !== "WEBP")
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return sig.mime;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Read pixel dimensions from the container header.
|
|
127
|
+
*
|
|
128
|
+
* PNG: bytes 16-19 (big-endian width), 20-23 (height) after the 8-byte
|
|
129
|
+
* signature and the 4-byte length + 4-byte "IHDR" chunk type.
|
|
130
|
+
* JPEG: walk the marker segments to the first SOFn; width/height are
|
|
131
|
+
* big-endian 16-bit fields at a fixed offset within that frame header.
|
|
132
|
+
* Anything else returns `0x0` — dimensions are prompt context, not
|
|
133
|
+
* correctness, and a failed parse must never fail a write.
|
|
134
|
+
*/
|
|
135
|
+
export function readDimensions(bytes, mime) {
|
|
136
|
+
try {
|
|
137
|
+
if (mime === "image/png") {
|
|
138
|
+
if (bytes.length < 24)
|
|
139
|
+
return { width: 0, height: 0 };
|
|
140
|
+
const width = (bytes[16] << 24) | (bytes[17] << 16) | (bytes[18] << 8) | bytes[19];
|
|
141
|
+
const height = (bytes[20] << 24) | (bytes[21] << 16) | (bytes[22] << 8) | bytes[23];
|
|
142
|
+
return { width: width >>> 0, height: height >>> 0 };
|
|
143
|
+
}
|
|
144
|
+
if (mime === "image/jpeg") {
|
|
145
|
+
if (bytes.length < 4 || bytes[0] !== 0xff || bytes[1] !== 0xd8) {
|
|
146
|
+
return { width: 0, height: 0 };
|
|
147
|
+
}
|
|
148
|
+
let offset = 2;
|
|
149
|
+
while (offset + 9 < bytes.length) {
|
|
150
|
+
if (bytes[offset] !== 0xff) {
|
|
151
|
+
offset += 1;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const marker = bytes[offset + 1];
|
|
155
|
+
// SOF0..SOF15 except DHT (C4), JPGA (C8) and DAC (CC).
|
|
156
|
+
const isSof = marker >= 0xc0 &&
|
|
157
|
+
marker <= 0xcf &&
|
|
158
|
+
marker !== 0xc4 &&
|
|
159
|
+
marker !== 0xc8 &&
|
|
160
|
+
marker !== 0xcc;
|
|
161
|
+
if (isSof) {
|
|
162
|
+
const height = (bytes[offset + 5] << 8) | bytes[offset + 6];
|
|
163
|
+
const width = (bytes[offset + 7] << 8) | bytes[offset + 8];
|
|
164
|
+
return { width, height };
|
|
165
|
+
}
|
|
166
|
+
// Standalone markers carry no length field.
|
|
167
|
+
if (marker === 0xd8 ||
|
|
168
|
+
marker === 0xd9 ||
|
|
169
|
+
(marker >= 0xd0 && marker <= 0xd7)) {
|
|
170
|
+
offset += 2;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const segmentLength = (bytes[offset + 2] << 8) | bytes[offset + 3];
|
|
174
|
+
if (segmentLength < 2)
|
|
175
|
+
break;
|
|
176
|
+
offset += 2 + segmentLength;
|
|
177
|
+
}
|
|
178
|
+
return { width: 0, height: 0 };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// A malformed header must never fail a write — dimensions default
|
|
183
|
+
// to 0x0 and the caller records them as unknown.
|
|
184
|
+
return { width: 0, height: 0 };
|
|
185
|
+
}
|
|
186
|
+
return { width: 0, height: 0 };
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Write image bytes to the blob store, content-addressed.
|
|
190
|
+
*
|
|
191
|
+
* Idempotent: writing the same bytes twice rewrites the same file with
|
|
192
|
+
* the same content, so a repeated call is a no-op on disk and returns
|
|
193
|
+
* an identical `StoredImage`. Callers still dedupe at the NODE level
|
|
194
|
+
* (same digest in the same namespace → one node) in `memory.ts`.
|
|
195
|
+
*
|
|
196
|
+
* @throws {@link ImageRejectedError} when the bytes are empty, an
|
|
197
|
+
* unrecognised format, or above `maxBytes`.
|
|
198
|
+
*/
|
|
199
|
+
export function writeImage(bytes, declaredMime, root, maxBytes) {
|
|
200
|
+
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
|
|
201
|
+
if (buf.length === 0) {
|
|
202
|
+
throw new ImageRejectedError("image bytes are empty", "empty");
|
|
203
|
+
}
|
|
204
|
+
if (buf.length > maxBytes) {
|
|
205
|
+
throw new ImageRejectedError(`image is ${buf.length} bytes, above the ${maxBytes}-byte limit`, "size");
|
|
206
|
+
}
|
|
207
|
+
// Sniffed type wins over the declared one — a wrong declared type is
|
|
208
|
+
// the more dangerous error (a vision model would mis-decode the blob).
|
|
209
|
+
const sniffed = sniffMime(new Uint8Array(buf));
|
|
210
|
+
const mime = sniffed ?? declaredMime ?? null;
|
|
211
|
+
if (!mime || !ALLOWED_MIME_TYPES.has(mime)) {
|
|
212
|
+
throw new ImageRejectedError(`unsupported image format (detected ${sniffed ?? "none"}, declared ${declaredMime ?? "none"})`, "mime");
|
|
213
|
+
}
|
|
214
|
+
const sha256 = createHash("sha256").update(buf).digest("hex");
|
|
215
|
+
const ref = refFor(sha256);
|
|
216
|
+
const extension = MIME_EXTENSION[mime] ?? "bin";
|
|
217
|
+
if (!existsSync(root))
|
|
218
|
+
mkdirSync(root, { recursive: true });
|
|
219
|
+
const path = join(root, `${ref}.${extension}`);
|
|
220
|
+
// Write only when absent: content-addressed means the file is already
|
|
221
|
+
// correct, so a rewrite is wasted I/O (and a needless mtime bump).
|
|
222
|
+
if (!existsSync(path))
|
|
223
|
+
writeFileSync(path, buf);
|
|
224
|
+
const { width, height } = readDimensions(new Uint8Array(buf), mime);
|
|
225
|
+
return { ref, path, sha256, width, height, bytes: buf.length, mime };
|
|
226
|
+
}
|
|
227
|
+
/** Read a blob back by ref. Returns null when it is missing. */
|
|
228
|
+
export function readImage(ref, root) {
|
|
229
|
+
const resolved = resolveRef(ref, root);
|
|
230
|
+
if (!resolved)
|
|
231
|
+
return null;
|
|
232
|
+
try {
|
|
233
|
+
return readFileSync(resolved);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Resolve a ref to an on-disk path, tolerating any of the accepted
|
|
241
|
+
* extensions (the format is recorded in the metadata, but the store
|
|
242
|
+
* stays addressable by ref alone so a pack consumer holding only
|
|
243
|
+
* `[img:…]` can still resolve it).
|
|
244
|
+
*/
|
|
245
|
+
export function resolveRef(ref, root) {
|
|
246
|
+
if (!/^img_[a-f0-9]{4,64}$/.test(ref))
|
|
247
|
+
return null;
|
|
248
|
+
for (const ext of Object.values(MIME_EXTENSION)) {
|
|
249
|
+
const candidate = join(root, `${ref}.${ext}`);
|
|
250
|
+
if (existsSync(candidate))
|
|
251
|
+
return candidate;
|
|
252
|
+
}
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
/** Delete a blob by ref. Returns true when a file was removed. */
|
|
256
|
+
export function deleteRef(ref, root) {
|
|
257
|
+
const resolved = resolveRef(ref, root);
|
|
258
|
+
if (!resolved)
|
|
259
|
+
return false;
|
|
260
|
+
try {
|
|
261
|
+
unlinkSync(resolved);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Coarse classification from MIME type only.
|
|
270
|
+
*
|
|
271
|
+
* Deliberately NOT content analysis: `photo` vs `screenshot` cannot be
|
|
272
|
+
* told apart from a header, and guessing would put a wrong label in
|
|
273
|
+
* every image node. `chart`/`diagram`/`memo` are caller-declared via
|
|
274
|
+
* `addImageMemory({ kind })`; the sniffed value is the safe default.
|
|
275
|
+
*/
|
|
276
|
+
export function kindFromMime(mime) {
|
|
277
|
+
// Every accepted raster format is a photo by default — the caller
|
|
278
|
+
// overrides with the real kind when it knows one.
|
|
279
|
+
if (ALLOWED_MIME_TYPES.has(mime))
|
|
280
|
+
return "photo";
|
|
281
|
+
return "other";
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Delete blobs that no live node references anymore.
|
|
285
|
+
*
|
|
286
|
+
* Called explicitly (never on a background timer) because eviction
|
|
287
|
+
* (`forgetByDecay`, `archive`) deletes nodes, and a blob whose node is
|
|
288
|
+
* gone is unreachable garbage. Returns how many files were removed so
|
|
289
|
+
* maintenance commands can report it.
|
|
290
|
+
*/
|
|
291
|
+
export function purgeOrphanImages(root, liveRefs) {
|
|
292
|
+
if (!existsSync(root))
|
|
293
|
+
return 0;
|
|
294
|
+
let purged = 0;
|
|
295
|
+
for (const entry of readdirSync(root)) {
|
|
296
|
+
const ref = entry.replace(/\.[a-z0-9]+$/i, "");
|
|
297
|
+
if (!ref.startsWith(REF_PREFIX))
|
|
298
|
+
continue;
|
|
299
|
+
if (liveRefs.has(ref))
|
|
300
|
+
continue;
|
|
301
|
+
if (deleteRef(ref, root))
|
|
302
|
+
purged += 1;
|
|
303
|
+
}
|
|
304
|
+
return purged;
|
|
305
|
+
}
|
|
306
|
+
/** Size of a stored blob in bytes, or null when missing. */
|
|
307
|
+
export function imageSize(path) {
|
|
308
|
+
try {
|
|
309
|
+
return statSync(path).size;
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Normalize every accepted {@link ImageInput} shape into raw bytes plus
|
|
317
|
+
* a declared MIME type.
|
|
318
|
+
*
|
|
319
|
+
* Resolution order matters: a `data:` URL is checked BEFORE a path
|
|
320
|
+
* (both are strings), and base64-with-explicit-mime is checked before
|
|
321
|
+
* the fetch path (both can be objects). Bytes pass through untouched —
|
|
322
|
+
* the caller's `writeImage` sniffs the true format from the header
|
|
323
|
+
* anyway, so a wrong declared MIME can never mislabel the blob.
|
|
324
|
+
*
|
|
325
|
+
* `file:` and `http(s):` URLs are fetched; everything else that looks
|
|
326
|
+
* like a URL but isn't fetchable throws rather than being guessed at.
|
|
327
|
+
*/
|
|
328
|
+
export async function normalizeImageInput(input) {
|
|
329
|
+
// Raw bytes — the fastest and most common programmatic path.
|
|
330
|
+
if (Buffer.isBuffer(input)) {
|
|
331
|
+
return { bytes: input, mime: undefined };
|
|
332
|
+
}
|
|
333
|
+
if (input instanceof Uint8Array) {
|
|
334
|
+
return { bytes: Buffer.from(input), mime: undefined };
|
|
335
|
+
}
|
|
336
|
+
// Explicit base64 + mime.
|
|
337
|
+
if (typeof input === "object" && input !== null && "data" in input) {
|
|
338
|
+
return { bytes: Buffer.from(input.data, "base64"), mime: input.mime };
|
|
339
|
+
}
|
|
340
|
+
// URL fetch.
|
|
341
|
+
if (typeof input === "object" && input !== null && "url" in input) {
|
|
342
|
+
return fetchImageUrl(input.url);
|
|
343
|
+
}
|
|
344
|
+
if (typeof input !== "string") {
|
|
345
|
+
throw new ImageRejectedError("image input must be a path, bytes, { data, mime }, or { url }", "empty");
|
|
346
|
+
}
|
|
347
|
+
// A data: URL is a string too — check the prefix before treating the
|
|
348
|
+
// value as a filesystem path.
|
|
349
|
+
if (input.startsWith("data:")) {
|
|
350
|
+
const match = /^data:([^;,]+)?(;base64)?,(.*)$/s.exec(input);
|
|
351
|
+
if (!match) {
|
|
352
|
+
throw new ImageRejectedError("malformed data: URL", "mime");
|
|
353
|
+
}
|
|
354
|
+
const mime = match[1] ?? undefined;
|
|
355
|
+
const payload = match[3] ?? "";
|
|
356
|
+
const bytes = match[2]
|
|
357
|
+
? Buffer.from(payload, "base64")
|
|
358
|
+
: Buffer.from(decodeURIComponent(payload), "utf8");
|
|
359
|
+
return { bytes, mime };
|
|
360
|
+
}
|
|
361
|
+
// Filesystem path.
|
|
362
|
+
return { bytes: await readFile(input), mime: undefined };
|
|
363
|
+
}
|
|
364
|
+
/** Fetch an image from an http(s)/file URL into bytes. */
|
|
365
|
+
async function fetchImageUrl(url) {
|
|
366
|
+
if (url.startsWith("file:")) {
|
|
367
|
+
// A file: URL is a local path — read it directly rather than
|
|
368
|
+
// routing a local file through the network stack.
|
|
369
|
+
const { readFile } = await import("node:fs/promises");
|
|
370
|
+
return { bytes: await readFile(fileURLToPath(url)), mime: undefined };
|
|
371
|
+
}
|
|
372
|
+
if (!/^https?:\/\//i.test(url)) {
|
|
373
|
+
throw new ImageRejectedError(`unsupported image URL scheme: ${url.slice(0, 32)}`, "mime");
|
|
374
|
+
}
|
|
375
|
+
const response = await fetch(url);
|
|
376
|
+
if (!response.ok) {
|
|
377
|
+
throw new ImageRejectedError(`fetching image failed with HTTP ${response.status}`, "empty");
|
|
378
|
+
}
|
|
379
|
+
const mime = response.headers.get("content-type") ?? undefined;
|
|
380
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
381
|
+
return { bytes, mime };
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/vision/store.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|