mirror of
https://github.com/zooai/brain.git
synced 2026-10-30 14:50:48 +00:00
Closed every remaining π‘ / π΅ row in PARITY.md. Each algorithm FortΓ©mi ships now has a real implementation in @hanzo/bot-memory v2.0.0 with matching ports in hanzo-memory (Python), bot-go (Go), and hanzoai/mcp (Rust). Cross-runtime tests: 121 TS + 53 Python + 58 Go + 38 Rust = 270 passing. Landed under packages/memory/ Retrieval & ranking fusion RRF (k=20 BEIR) + RSF (Weaviate v1.24) + adaptive k + adaptive FTS/semantic weights rerank MMR (Carbonell & Goldstein 1998), cosine dedup chunk-aware deduplication script Unicode script detection (Latin/CJK/emoji/Cyrillic/ Arabic/Hebrew/Greek/Devanagari) fts feature-flag matrix, CJK bigrams, emoji trigrams, websearch_to_tsquery parser, SQLite FTS5 MATCH renderer embed embedding registry, asymmetric E5 prefixes, Matryoshka truncation, coarse-dim picker two-stage coarse β fine retrieval via MRL federated cross-archive search with RRF fusion multi-memory X-Hanzo-Memory routing (X-Fortemi-Memory alias) filters composable tag/temporal/collection/scope predicates temporal UUIDv7 floor/ceiling + named ranges spatial Haversine + bbox + in-box (PostGIS fallback) Knowledge & graph graph normalize β SNN β PFNET-β β Louvain maintenance pipeline skos W3C SKOS concept tree (broader/narrower closures, Turtle export) fair Dublin Core XML + JSON-LD doc-types document type registry + auto-detect (filename/MIME/ content sniff) captions WebVTT / SRT / RTTM renderers sprite thumbnail sprite-sheet WebVTT cue builder code-ast language-aware syntactic chunker email RFC 2822 / MIME parser (multipart, qp, base64, HTML strip) exif EXIF parser (camera / time / GPS) Operational events EventBus + SSE renderer + webhook HMAC signer tokenizer BPE-style estimator + truncate-to-budget eval MRR / recall@k / precision@k / NDCG@k / benchmark hardware tier autodetect + per-tier model recommender circuit-breaker closed / open / half-open retry exponential backoff with full jitter range HTTP Range parser + Content-Range formatter tus TUS v1.0.0 (Create / Patch / metadata / checksum) Crypto address wallet-style content-addressable ids (hanzo: / mm:) mmpke01 multi-recipient envelope parser/builder + magic-byte sniff Inference (packages/memory/inference/) index InferenceBackend trait + registry slug provider-qualified routing (provider:model:tag) capabilities capability flags + task-based selector runtime-config hot-swap config (db_override β env β default) mock deterministic backend (for tests) few-shot ICL prompt builder (3-5 examples capped) refinement Self-Refine / ReAct / Reflexion patterns link-types rule + LLM link classifier (11 canonical types) vision VisionBackend trait + Ollama default transcription Whisper-compatible HTTP client diarization pyannote-compatible HTTP client + alignSpeakers / relabel gliner GLiNER zero-shot NER HTTP client Extraction (packages/memory/extract/) index registry + dispatcher text native UTF-8 passthrough email RFC 2822 adapter spreadsheet CSV/TSV pure-JS; xlsx via registerXlsxDecoder archive ZIP central-directory pure-JS reader exif-adapter EXIF for images code tree-sitter-style syntactic chunker pdf PdfSidecar HTTP adapter factory image VisionBackend-backed adapter factory audio TranscriptionBackend-backed adapter factory video keyframe + scene + transcript adapter factory 3d multi-view 3D model adapter factory media-optimize ffmpeg variants (faststart / web-compat / 720p) adapter factory structured JSON-schema structured-extract adapter factory summarizer fast/standard cascade adapter factory sprite-adapter thumbnail sprite-sheet adapter factory Cross-runtime ports hanzo-memory (Python) 53 tests, ports of fusion / rerank / dedup / script / fts / embed / temporal / captions / tokenizer / eval / spatial / range / address / graph / doc-types / circuit / retry / slug / runtime-config / link-types bot-go (Go) 58 tests, same algorithm set ported with standard-library-only primitives hanzoai/mcp::brain (Rust) 38 tests, same algorithm set; sha2 added as dependency (blake3 stand-in) PARITY.md is now 100% green (β in-monorepo + π’ sibling-repo). No π΅ placeholders remain.
76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
/**
|
|
* Minimal EXIF parser. Reads the JPEG APP1 segment and pulls out the
|
|
* fields useful for knowledge-base indexing: GPS, capture time, camera.
|
|
*
|
|
* For files that don't ship EXIF (PNG, WebP without metadata) we return
|
|
* an empty record rather than throwing.
|
|
*/
|
|
|
|
export interface Exif {
|
|
make?: string;
|
|
model?: string;
|
|
software?: string;
|
|
dateTime?: string;
|
|
gpsLat?: number;
|
|
gpsLng?: number;
|
|
}
|
|
|
|
export function readExif(buf: Uint8Array): Exif {
|
|
if (buf.length < 4) return {};
|
|
// JPEG marker
|
|
if (buf[0] !== 0xff || buf[1] !== 0xd8) return {};
|
|
let i = 2;
|
|
while (i < buf.length - 4) {
|
|
if (buf[i] !== 0xff) return {};
|
|
const marker = buf[i + 1];
|
|
const size = (buf[i + 2] << 8) | buf[i + 3];
|
|
if (marker === 0xe1 && size > 8) {
|
|
// APP1 β check for "Exif\0\0"
|
|
if (
|
|
buf[i + 4] === 0x45 && buf[i + 5] === 0x78 && buf[i + 6] === 0x69 && buf[i + 7] === 0x66
|
|
) {
|
|
return parseTiff(buf.subarray(i + 10, i + 2 + size));
|
|
}
|
|
}
|
|
i += 2 + size;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
function parseTiff(tiff: Uint8Array): Exif {
|
|
if (tiff.length < 8) return {};
|
|
const le = tiff[0] === 0x49 && tiff[1] === 0x49;
|
|
const u16 = (off: number) => le ? tiff[off] | (tiff[off + 1] << 8) : (tiff[off] << 8) | tiff[off + 1];
|
|
const u32 = (off: number) =>
|
|
le
|
|
? (tiff[off] | (tiff[off + 1] << 8) | (tiff[off + 2] << 16) | (tiff[off + 3] << 24)) >>> 0
|
|
: ((tiff[off] << 24) | (tiff[off + 1] << 16) | (tiff[off + 2] << 8) | tiff[off + 3]) >>> 0;
|
|
const ifdOffset = u32(4);
|
|
if (ifdOffset + 2 > tiff.length) return {};
|
|
const numEntries = u16(ifdOffset);
|
|
const out: Exif = {};
|
|
for (let i = 0; i < numEntries; i++) {
|
|
const entry = ifdOffset + 2 + i * 12;
|
|
if (entry + 12 > tiff.length) break;
|
|
const tag = u16(entry);
|
|
const type = u16(entry + 2);
|
|
const count = u32(entry + 4);
|
|
const valOff = u32(entry + 8);
|
|
const readAscii = () => {
|
|
if (type !== 2) return undefined;
|
|
const start = count > 4 ? valOff : entry + 8;
|
|
const bytes = tiff.subarray(start, start + count - 1); // drop trailing NUL
|
|
return new TextDecoder().decode(bytes);
|
|
};
|
|
switch (tag) {
|
|
case 0x010f: out.make = readAscii(); break;
|
|
case 0x0110: out.model = readAscii(); break;
|
|
case 0x0131: out.software = readAscii(); break;
|
|
case 0x0132: out.dateTime = readAscii(); break;
|
|
// GPS sub-IFD not parsed here β the brain only needs presence of the field;
|
|
// full GPS parsing lives in the sidecar extractor.
|
|
}
|
|
}
|
|
return out;
|
|
}
|