@tpsdev-ai/flair 0.3.14 → 0.3.16
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,6 +1,6 @@
|
|
|
1
1
|
import { patchRecord } from "./table-helpers.js";
|
|
2
2
|
import { server, databases } from "@harperfast/harper";
|
|
3
|
-
import {
|
|
3
|
+
import { getEmbedding } from "./embeddings-provider.js";
|
|
4
4
|
// --- Admin credentials ---
|
|
5
5
|
// Admin auth is sourced exclusively from Harper's own environment variables
|
|
6
6
|
// (HDB_ADMIN_PASSWORD / FLAIR_ADMIN_PASSWORD). No filesystem token file.
|
|
@@ -93,7 +93,6 @@ async function importEd25519Key(publicKeyStr) {
|
|
|
93
93
|
keyCache.set(publicKeyStr, key);
|
|
94
94
|
return key;
|
|
95
95
|
}
|
|
96
|
-
initEmbeddings().catch((err) => console.error("[embeddings] init:", err.message));
|
|
97
96
|
async function backfillEmbedding(memoryId) {
|
|
98
97
|
try {
|
|
99
98
|
const record = await databases.flair.Memory.get(memoryId);
|
|
@@ -2,59 +2,35 @@
|
|
|
2
2
|
* embeddings-provider.ts
|
|
3
3
|
*
|
|
4
4
|
* Thin wrapper around harper-fabric-embeddings for Flair resources.
|
|
5
|
-
* harper-fabric-embeddings
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* returns null and semantic search falls back to keyword matching.
|
|
5
|
+
* harper-fabric-embeddings is loaded by Harper as a sub-component
|
|
6
|
+
* (declared in config.yaml). It downloads the model and initializes
|
|
7
|
+
* in the background. We just call embed() — if it's not ready yet,
|
|
8
|
+
* we return null and the caller handles it gracefully.
|
|
10
9
|
*/
|
|
11
10
|
import * as hfe from "harper-fabric-embeddings";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
export async function initEmbeddings() {
|
|
20
|
-
const state = getState();
|
|
21
|
-
if (state.initialized)
|
|
22
|
-
return;
|
|
23
|
-
// harper-fabric-embeddings is initialized by Harper as a sub-component
|
|
24
|
-
// (declared in config.yaml). It inits in the background so it may not
|
|
25
|
-
// be ready when resources first load. Retry a few times before giving up.
|
|
26
|
-
for (let attempt = 1; attempt <= 10; attempt++) {
|
|
27
|
-
try {
|
|
28
|
-
const dims = hfe.dimensions();
|
|
29
|
-
state.available = true;
|
|
30
|
-
state.initialized = true;
|
|
31
|
-
console.log(`[embeddings] ready (${dims} dims, attempt ${attempt})`);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
if (attempt < 10)
|
|
36
|
-
await new Promise(r => setTimeout(r, 500));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
console.log("[embeddings] not available after 10 attempts — search will be keyword-only");
|
|
40
|
-
state.available = false;
|
|
41
|
-
state.initialized = true;
|
|
42
|
-
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate an embedding vector for the given text.
|
|
13
|
+
* Returns null if the embedding engine isn't ready yet (model still loading)
|
|
14
|
+
* or not available on this platform. Never gives up permanently — each call
|
|
15
|
+
* checks independently.
|
|
16
|
+
*/
|
|
43
17
|
export async function getEmbedding(text) {
|
|
44
|
-
const state = getState();
|
|
45
|
-
if (!state.initialized)
|
|
46
|
-
await initEmbeddings();
|
|
47
|
-
if (!state.available)
|
|
48
|
-
return null;
|
|
49
18
|
try {
|
|
50
|
-
return hfe.embed(text);
|
|
19
|
+
return await hfe.embed(text);
|
|
51
20
|
}
|
|
52
|
-
catch
|
|
53
|
-
console.log(`[embeddings] embed failed: ${err.message}`);
|
|
21
|
+
catch {
|
|
54
22
|
return null;
|
|
55
23
|
}
|
|
56
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if the embedding engine is currently available.
|
|
27
|
+
*/
|
|
57
28
|
export function getMode() {
|
|
58
|
-
|
|
59
|
-
|
|
29
|
+
try {
|
|
30
|
+
hfe.dimensions();
|
|
31
|
+
return "local";
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return "none";
|
|
35
|
+
}
|
|
60
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tpsdev-ai/flair",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"description": "Identity, memory, and soul for AI agents. Cryptographic identity (Ed25519), semantic memory with local embeddings, and persistent personality — all in a single process.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@harperfast/harper": "5.0.0-beta.4",
|
|
53
53
|
"commander": "14.0.3",
|
|
54
|
-
"harper-fabric-embeddings": "^0.2.
|
|
54
|
+
"harper-fabric-embeddings": "^0.2.2",
|
|
55
55
|
"tweetnacl": "1.0.3"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { patchRecord } from "./table-helpers.js";
|
|
2
2
|
import { server, databases } from "@harperfast/harper";
|
|
3
|
-
import {
|
|
3
|
+
import { getEmbedding } from "./embeddings-provider.js";
|
|
4
4
|
|
|
5
5
|
// --- Admin credentials ---
|
|
6
6
|
// Admin auth is sourced exclusively from Harper's own environment variables
|
|
@@ -102,7 +102,6 @@ async function importEd25519Key(publicKeyStr: string): Promise<CryptoKey> {
|
|
|
102
102
|
return key;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
initEmbeddings().catch((err: any) => console.error("[embeddings] init:", err.message));
|
|
106
105
|
|
|
107
106
|
async function backfillEmbedding(memoryId: string): Promise<void> {
|
|
108
107
|
try {
|
|
@@ -2,66 +2,36 @@
|
|
|
2
2
|
* embeddings-provider.ts
|
|
3
3
|
*
|
|
4
4
|
* Thin wrapper around harper-fabric-embeddings for Flair resources.
|
|
5
|
-
* harper-fabric-embeddings
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* returns null and semantic search falls back to keyword matching.
|
|
5
|
+
* harper-fabric-embeddings is loaded by Harper as a sub-component
|
|
6
|
+
* (declared in config.yaml). It downloads the model and initializes
|
|
7
|
+
* in the background. We just call embed() — if it's not ready yet,
|
|
8
|
+
* we return null and the caller handles it gracefully.
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
import * as hfe from "harper-fabric-embeddings";
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function getState(): ProviderState {
|
|
22
|
-
if (!(globalThis as any)[SINGLETON_KEY]) {
|
|
23
|
-
(globalThis as any)[SINGLETON_KEY] = { initialized: false, available: false };
|
|
24
|
-
}
|
|
25
|
-
return (globalThis as any)[SINGLETON_KEY];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function initEmbeddings(): Promise<void> {
|
|
29
|
-
const state = getState();
|
|
30
|
-
if (state.initialized) return;
|
|
31
|
-
|
|
32
|
-
// harper-fabric-embeddings is initialized by Harper as a sub-component
|
|
33
|
-
// (declared in config.yaml). It inits in the background so it may not
|
|
34
|
-
// be ready when resources first load. Retry a few times before giving up.
|
|
35
|
-
for (let attempt = 1; attempt <= 10; attempt++) {
|
|
36
|
-
try {
|
|
37
|
-
const dims = hfe.dimensions();
|
|
38
|
-
state.available = true;
|
|
39
|
-
state.initialized = true;
|
|
40
|
-
console.log(`[embeddings] ready (${dims} dims, attempt ${attempt})`);
|
|
41
|
-
return;
|
|
42
|
-
} catch {
|
|
43
|
-
if (attempt < 10) await new Promise(r => setTimeout(r, 500));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
console.log("[embeddings] not available after 10 attempts — search will be keyword-only");
|
|
48
|
-
state.available = false;
|
|
49
|
-
state.initialized = true;
|
|
50
|
-
}
|
|
51
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Generate an embedding vector for the given text.
|
|
15
|
+
* Returns null if the embedding engine isn't ready yet (model still loading)
|
|
16
|
+
* or not available on this platform. Never gives up permanently — each call
|
|
17
|
+
* checks independently.
|
|
18
|
+
*/
|
|
52
19
|
export async function getEmbedding(text: string): Promise<number[] | null> {
|
|
53
|
-
const state = getState();
|
|
54
|
-
if (!state.initialized) await initEmbeddings();
|
|
55
|
-
if (!state.available) return null;
|
|
56
20
|
try {
|
|
57
|
-
return hfe.embed(text);
|
|
58
|
-
} catch
|
|
59
|
-
console.log(`[embeddings] embed failed: ${err.message}`);
|
|
21
|
+
return await hfe.embed(text);
|
|
22
|
+
} catch {
|
|
60
23
|
return null;
|
|
61
24
|
}
|
|
62
25
|
}
|
|
63
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Check if the embedding engine is currently available.
|
|
29
|
+
*/
|
|
64
30
|
export function getMode(): "local" | "none" {
|
|
65
|
-
|
|
66
|
-
|
|
31
|
+
try {
|
|
32
|
+
hfe.dimensions();
|
|
33
|
+
return "local";
|
|
34
|
+
} catch {
|
|
35
|
+
return "none";
|
|
36
|
+
}
|
|
67
37
|
}
|