@tpsdev-ai/flair 0.3.17 → 0.3.19

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.
@@ -1,61 +0,0 @@
1
- /**
2
- * embeddings-provider.ts
3
- *
4
- * Wrapper around harper-fabric-embeddings for Flair resources.
5
- *
6
- * Harper loads resources in a VM sandbox with a separate module cache from
7
- * the main thread. This means our import of harper-fabric-embeddings gets
8
- * a different (uninitialized) instance from the one Harper initialized via
9
- * handleApplication in config.yaml.
10
- *
11
- * Solution: we call hfe.init() ourselves on first use. The model is already
12
- * on disk (downloaded by Harper's plugin loader), so init just loads the
13
- * native binary and model file — no download needed.
14
- */
15
-
16
- import * as hfe from "harper-fabric-embeddings";
17
- import { join } from "node:path";
18
-
19
- let _ready = false;
20
-
21
- async function ensureInit(): Promise<void> {
22
- if (_ready) return;
23
- try {
24
- // Check if already initialized (e.g. shared context)
25
- hfe.dimensions();
26
- _ready = true;
27
- return;
28
- } catch {
29
- // Not initialized — init with modelsDir pointing to where Harper's
30
- // plugin loader downloaded the model (process.cwd() is the app dir)
31
- const modelsDir = join(process.cwd(), "models");
32
- await hfe.init({ modelsDir });
33
- _ready = true;
34
- }
35
- }
36
-
37
- /**
38
- * Generate an embedding vector for the given text.
39
- * Returns null if the embedding engine isn't available on this platform.
40
- */
41
- export async function getEmbedding(text: string): Promise<number[] | null> {
42
- try {
43
- await ensureInit();
44
- return await hfe.embed(text);
45
- } catch (err: any) {
46
- console.error(`[embeddings] embed failed: ${err.message}`);
47
- return null;
48
- }
49
- }
50
-
51
- /**
52
- * Check if the embedding engine is currently available.
53
- */
54
- export function getMode(): "local" | "none" {
55
- try {
56
- hfe.dimensions();
57
- return "local";
58
- } catch {
59
- return "none";
60
- }
61
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Fallback hash-based embedding (used when sidecar is unavailable).
3
- * Real embeddings come from the embed-server sidecar (harper-fabric-embeddings).
4
- */
5
- const DIMS = 512;
6
- function h1(s: string): number { let h = 5381; for (let i = 0; i < s.length; i++) h = ((h << 5) + h + s.charCodeAt(i)) >>> 0; return h % DIMS; }
7
- function h2(s: string): number { let h = 0x811c9dc5; for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 0x01000193) >>> 0; } return h % DIMS; }
8
-
9
- export function fallbackEmbed(text: string): number[] {
10
- const tokens = text.toLowerCase().replace(/[^a-z0-9\s-]/g, ' ').split(/\s+/).filter(t => t.length > 1);
11
- const clean = text.toLowerCase().replace(/\s+/g, ' ');
12
- const vec = new Float64Array(DIMS);
13
- for (const t of tokens) { vec[h1(t)] += 2; vec[h2(t)] += 1; }
14
- for (let i = 0; i < tokens.length - 1; i++) vec[h1(tokens[i] + '_' + tokens[i + 1])] += 1.5;
15
- for (let i = 0; i <= clean.length - 3; i++) vec[h1(clean.slice(i, i + 3))] += 0.5;
16
- for (let i = 0; i < DIMS; i++) if (vec[i] > 0) vec[i] = 1 + Math.log(vec[i]);
17
- let norm = 0; for (let i = 0; i < DIMS; i++) norm += vec[i] * vec[i];
18
- norm = Math.sqrt(norm);
19
- if (norm > 0) for (let i = 0; i < DIMS; i++) vec[i] /= norm;
20
- return Array.from(vec);
21
- }
22
-
23
- export function cosineSimilarity(a: number[], b: number[]): number {
24
- let dot = 0;
25
- const len = Math.min(a.length, b.length);
26
- for (let i = 0; i < len; i++) dot += a[i] * b[i];
27
- return dot;
28
- }
@@ -1,7 +0,0 @@
1
- import { Resource } from "@harperfast/harper";
2
-
3
- export class Health extends Resource {
4
- async get() {
5
- return { ok: true };
6
- }
7
- }
@@ -1,22 +0,0 @@
1
- import { createHash } from "node:crypto";
2
-
3
- export function computeContentHash(agentId: string, content: string): string {
4
- return createHash("sha256")
5
- .update(`${agentId}${content}`)
6
- .digest("hex")
7
- .slice(0, 16);
8
- }
9
-
10
- export async function findExistingMemoryByContentHash(
11
- records: AsyncIterable<any> | Iterable<any>,
12
- agentId: string,
13
- contentHash: string,
14
- ): Promise<any | null> {
15
- for await (const record of records) {
16
- if (record?.agentId === agentId && record?.contentHash === contentHash) {
17
- return record;
18
- }
19
- }
20
-
21
- return null;
22
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Safe read-modify-write helper for Harper tables.
3
- *
4
- * Harper's `put()` is FULL RECORD REPLACEMENT. If you pass a partial
5
- * object, all missing fields (including embeddings!) are permanently
6
- * deleted. This helper ensures you always read the full record first.
7
- *
8
- * Usage:
9
- * import { patchRecord } from "./table-helpers.js";
10
- * await patchRecord(tables.Memory, id, { lastReflected: now });
11
- */
12
-
13
- export async function patchRecord(
14
- table: any,
15
- id: string,
16
- patch: Record<string, unknown>,
17
- ): Promise<void> {
18
- const existing = await table.get(id);
19
- if (!existing) throw new Error(`Record ${id} not found`);
20
- await table.put({ ...existing, ...patch });
21
- }
22
-
23
- /**
24
- * Fire-and-forget variant — swallows errors silently.
25
- * Use for best-effort metadata updates (lastReflected, lastRetrieved, etc.)
26
- * where a failure should never break the calling request.
27
- */
28
- export function patchRecordSilent(
29
- table: any,
30
- id: string,
31
- patch: Record<string, unknown>,
32
- ): void {
33
- patchRecord(table, id, patch).catch(() => {});
34
- }
35
-
36
- // ── RULE ──────────────────────────────────────────────────────────────────────
37
- // Never call `tables.X.put(partial)` directly anywhere in Flair resources.
38
- // Harper put() = FULL RECORD REPLACEMENT. Missing fields are deleted permanently.
39
- // Always use patchRecord() or patchRecordSilent().
40
- // ─────────────────────────────────────────────────────────────────────────────
41
-
42
- // ── RULE ──────────────────────────────────────────────────────────────────────
43
- // Never call `tables.X.put(partial)` directly anywhere in Flair resources.
44
- // Harper put() = FULL RECORD REPLACEMENT. Missing fields are deleted permanently.
45
- // Always use patchRecord() or patchRecordSilent().
46
- // ─────────────────────────────────────────────────────────────────────────────