stellar-memory 0.5.0
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.
- package/LICENSE +21 -0
- package/README.md +362 -0
- package/dist/api/routes/analytics.d.ts +15 -0
- package/dist/api/routes/analytics.js +131 -0
- package/dist/api/routes/analytics.js.map +1 -0
- package/dist/api/routes/conflicts.d.ts +12 -0
- package/dist/api/routes/conflicts.js +67 -0
- package/dist/api/routes/conflicts.js.map +1 -0
- package/dist/api/routes/consolidation.d.ts +11 -0
- package/dist/api/routes/consolidation.js +63 -0
- package/dist/api/routes/consolidation.js.map +1 -0
- package/dist/api/routes/constellation.d.ts +4 -0
- package/dist/api/routes/constellation.js +84 -0
- package/dist/api/routes/constellation.js.map +1 -0
- package/dist/api/routes/memories.d.ts +4 -0
- package/dist/api/routes/memories.js +219 -0
- package/dist/api/routes/memories.js.map +1 -0
- package/dist/api/routes/observations.d.ts +10 -0
- package/dist/api/routes/observations.js +42 -0
- package/dist/api/routes/observations.js.map +1 -0
- package/dist/api/routes/orbit.d.ts +4 -0
- package/dist/api/routes/orbit.js +71 -0
- package/dist/api/routes/orbit.js.map +1 -0
- package/dist/api/routes/projects.d.ts +15 -0
- package/dist/api/routes/projects.js +121 -0
- package/dist/api/routes/projects.js.map +1 -0
- package/dist/api/routes/scan.d.ts +4 -0
- package/dist/api/routes/scan.js +403 -0
- package/dist/api/routes/scan.js.map +1 -0
- package/dist/api/routes/sun.d.ts +4 -0
- package/dist/api/routes/sun.js +43 -0
- package/dist/api/routes/sun.js.map +1 -0
- package/dist/api/routes/system.d.ts +4 -0
- package/dist/api/routes/system.js +70 -0
- package/dist/api/routes/system.js.map +1 -0
- package/dist/api/routes/temporal.d.ts +13 -0
- package/dist/api/routes/temporal.js +82 -0
- package/dist/api/routes/temporal.js.map +1 -0
- package/dist/api/server.d.ts +2 -0
- package/dist/api/server.js +99 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/websocket.d.ts +53 -0
- package/dist/api/websocket.js +168 -0
- package/dist/api/websocket.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +10 -0
- package/dist/cli/init.js +163 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/engine/analytics.d.ts +93 -0
- package/dist/engine/analytics.js +437 -0
- package/dist/engine/analytics.js.map +1 -0
- package/dist/engine/conflict.d.ts +54 -0
- package/dist/engine/conflict.js +322 -0
- package/dist/engine/conflict.js.map +1 -0
- package/dist/engine/consolidation.d.ts +83 -0
- package/dist/engine/consolidation.js +368 -0
- package/dist/engine/consolidation.js.map +1 -0
- package/dist/engine/constellation.d.ts +66 -0
- package/dist/engine/constellation.js +382 -0
- package/dist/engine/constellation.js.map +1 -0
- package/dist/engine/corona.d.ts +53 -0
- package/dist/engine/corona.js +181 -0
- package/dist/engine/corona.js.map +1 -0
- package/dist/engine/embedding.d.ts +44 -0
- package/dist/engine/embedding.js +168 -0
- package/dist/engine/embedding.js.map +1 -0
- package/dist/engine/gravity.d.ts +63 -0
- package/dist/engine/gravity.js +121 -0
- package/dist/engine/gravity.js.map +1 -0
- package/dist/engine/multiproject.d.ts +75 -0
- package/dist/engine/multiproject.js +241 -0
- package/dist/engine/multiproject.js.map +1 -0
- package/dist/engine/observation.d.ts +82 -0
- package/dist/engine/observation.js +357 -0
- package/dist/engine/observation.js.map +1 -0
- package/dist/engine/orbit.d.ts +91 -0
- package/dist/engine/orbit.js +249 -0
- package/dist/engine/orbit.js.map +1 -0
- package/dist/engine/planet.d.ts +64 -0
- package/dist/engine/planet.js +432 -0
- package/dist/engine/planet.js.map +1 -0
- package/dist/engine/procedural.d.ts +71 -0
- package/dist/engine/procedural.js +259 -0
- package/dist/engine/procedural.js.map +1 -0
- package/dist/engine/quality.d.ts +48 -0
- package/dist/engine/quality.js +245 -0
- package/dist/engine/quality.js.map +1 -0
- package/dist/engine/repository.d.ts +79 -0
- package/dist/engine/repository.js +13 -0
- package/dist/engine/repository.js.map +1 -0
- package/dist/engine/sun.d.ts +61 -0
- package/dist/engine/sun.js +240 -0
- package/dist/engine/sun.js.map +1 -0
- package/dist/engine/temporal.d.ts +67 -0
- package/dist/engine/temporal.js +283 -0
- package/dist/engine/temporal.js.map +1 -0
- package/dist/engine/types.d.ts +179 -0
- package/dist/engine/types.js +27 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/connector-registry.d.ts +20 -0
- package/dist/mcp/connector-registry.js +35 -0
- package/dist/mcp/connector-registry.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +242 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/daemon-tool.d.ts +16 -0
- package/dist/mcp/tools/daemon-tool.js +58 -0
- package/dist/mcp/tools/daemon-tool.js.map +1 -0
- package/dist/mcp/tools/ingestion-tools.d.ts +20 -0
- package/dist/mcp/tools/ingestion-tools.js +34 -0
- package/dist/mcp/tools/ingestion-tools.js.map +1 -0
- package/dist/mcp/tools/memory-tools.d.ts +122 -0
- package/dist/mcp/tools/memory-tools.js +1037 -0
- package/dist/mcp/tools/memory-tools.js.map +1 -0
- package/dist/scanner/cloud/github.d.ts +34 -0
- package/dist/scanner/cloud/github.js +260 -0
- package/dist/scanner/cloud/github.js.map +1 -0
- package/dist/scanner/cloud/google-drive.d.ts +30 -0
- package/dist/scanner/cloud/google-drive.js +289 -0
- package/dist/scanner/cloud/google-drive.js.map +1 -0
- package/dist/scanner/cloud/notion.d.ts +33 -0
- package/dist/scanner/cloud/notion.js +231 -0
- package/dist/scanner/cloud/notion.js.map +1 -0
- package/dist/scanner/cloud/slack.d.ts +38 -0
- package/dist/scanner/cloud/slack.js +282 -0
- package/dist/scanner/cloud/slack.js.map +1 -0
- package/dist/scanner/cloud/types.d.ts +73 -0
- package/dist/scanner/cloud/types.js +9 -0
- package/dist/scanner/cloud/types.js.map +1 -0
- package/dist/scanner/index.d.ts +35 -0
- package/dist/scanner/index.js +420 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/local/filesystem.d.ts +33 -0
- package/dist/scanner/local/filesystem.js +203 -0
- package/dist/scanner/local/filesystem.js.map +1 -0
- package/dist/scanner/local/git.d.ts +24 -0
- package/dist/scanner/local/git.js +161 -0
- package/dist/scanner/local/git.js.map +1 -0
- package/dist/scanner/local/parsers/code.d.ts +3 -0
- package/dist/scanner/local/parsers/code.js +127 -0
- package/dist/scanner/local/parsers/code.js.map +1 -0
- package/dist/scanner/local/parsers/index.d.ts +11 -0
- package/dist/scanner/local/parsers/index.js +24 -0
- package/dist/scanner/local/parsers/index.js.map +1 -0
- package/dist/scanner/local/parsers/json-parser.d.ts +3 -0
- package/dist/scanner/local/parsers/json-parser.js +117 -0
- package/dist/scanner/local/parsers/json-parser.js.map +1 -0
- package/dist/scanner/local/parsers/markdown.d.ts +3 -0
- package/dist/scanner/local/parsers/markdown.js +120 -0
- package/dist/scanner/local/parsers/markdown.js.map +1 -0
- package/dist/scanner/local/parsers/text.d.ts +3 -0
- package/dist/scanner/local/parsers/text.js +41 -0
- package/dist/scanner/local/parsers/text.js.map +1 -0
- package/dist/scanner/metadata-scanner.d.ts +67 -0
- package/dist/scanner/metadata-scanner.js +356 -0
- package/dist/scanner/metadata-scanner.js.map +1 -0
- package/dist/scanner/types.d.ts +47 -0
- package/dist/scanner/types.js +19 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/service/daemon.d.ts +23 -0
- package/dist/service/daemon.js +105 -0
- package/dist/service/daemon.js.map +1 -0
- package/dist/service/scheduler.d.ts +73 -0
- package/dist/service/scheduler.js +281 -0
- package/dist/service/scheduler.js.map +1 -0
- package/dist/storage/database.d.ts +10 -0
- package/dist/storage/database.js +265 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/queries.d.ts +85 -0
- package/dist/storage/queries.js +865 -0
- package/dist/storage/queries.js.map +1 -0
- package/dist/storage/sqlite-repository.d.ts +32 -0
- package/dist/storage/sqlite-repository.js +68 -0
- package/dist/storage/sqlite-repository.js.map +1 -0
- package/dist/storage/vec.d.ts +62 -0
- package/dist/storage/vec.js +111 -0
- package/dist/storage/vec.js.map +1 -0
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +60 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.js +86 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/time.d.ts +21 -0
- package/dist/utils/time.js +42 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/tokenizer.d.ts +13 -0
- package/dist/utils/tokenizer.js +46 -0
- package/dist/utils/tokenizer.js.map +1 -0
- package/package.json +77 -0
- package/scripts/check-node.mjs +36 -0
- package/scripts/setup.mjs +157 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight token estimator for mixed English/Korean text.
|
|
3
|
+
*
|
|
4
|
+
* Unicode-aware estimation:
|
|
5
|
+
* - ASCII/Latin text: ~1.3 tokens per whitespace-delimited word
|
|
6
|
+
* - CJK characters (Korean/Chinese/Japanese): ~2.0 tokens per character
|
|
7
|
+
* - Other Unicode: ~1.5 tokens per word
|
|
8
|
+
*
|
|
9
|
+
* This replaces the old 0.75 tokens/word estimate which underestimated
|
|
10
|
+
* by ~50%, causing sun token budget overflows.
|
|
11
|
+
*/
|
|
12
|
+
export function estimateTokens(text) {
|
|
13
|
+
if (!text || text.length === 0)
|
|
14
|
+
return 0;
|
|
15
|
+
let tokens = 0;
|
|
16
|
+
// CJK Unicode ranges:
|
|
17
|
+
// Hangul Syllables: U+AC00–U+D7AF
|
|
18
|
+
// Hangul Jamo: U+1100–U+11FF
|
|
19
|
+
// CJK Unified: U+4E00–U+9FFF
|
|
20
|
+
// Katakana/Hiragana: U+3040–U+30FF
|
|
21
|
+
const CJK_REGEX = /[\u1100-\u11FF\u3040-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF]/;
|
|
22
|
+
// Split into whitespace-delimited segments
|
|
23
|
+
const segments = text.split(/\s+/).filter(w => w.length > 0);
|
|
24
|
+
for (const segment of segments) {
|
|
25
|
+
if (CJK_REGEX.test(segment)) {
|
|
26
|
+
// For CJK-containing segments, count chars individually
|
|
27
|
+
for (const char of segment) {
|
|
28
|
+
if (CJK_REGEX.test(char)) {
|
|
29
|
+
tokens += 2.0; // CJK chars typically split into 2+ tokens
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
tokens += 0.5; // Punctuation/ASCII mixed in with CJK
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// English/Latin word: ~1.3 tokens per word
|
|
38
|
+
tokens += 1.3;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Account for whitespace tokens (roughly 1 token per 4 spaces/newlines)
|
|
42
|
+
const whitespace = text.length - text.replace(/\s/g, '').length;
|
|
43
|
+
tokens += whitespace * 0.25;
|
|
44
|
+
return Math.ceil(tokens);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=tokenizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../src/utils/tokenizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEzC,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,sBAAsB;IACtB,oCAAoC;IACpC,oCAAoC;IACpC,oCAAoC;IACpC,qCAAqC;IACrC,MAAM,SAAS,GAAG,wDAAwD,CAAC;IAE3E,2CAA2C;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE7D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,wDAAwD;YACxD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzB,MAAM,IAAI,GAAG,CAAC,CAAE,2CAA2C;gBAC7D,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,GAAG,CAAC,CAAE,sCAAsC;gBACxD,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,2CAA2C;YAC3C,MAAM,IAAI,GAAG,CAAC;QAChB,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;IAChE,MAAM,IAAI,UAAU,GAAG,IAAI,CAAC;IAE5B,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stellar-memory",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "AI memory system using celestial mechanics metaphor - MCP server for persistent context across sessions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"stellar-memory": "dist/cli/index.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/sangjun0000/stellar-memory-core.git"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://stellar-memory.com",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/**/*.js",
|
|
17
|
+
"dist/**/*.d.ts",
|
|
18
|
+
"dist/**/*.js.map",
|
|
19
|
+
"scripts/check-node.mjs",
|
|
20
|
+
"scripts/setup.mjs",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22.0.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"preinstall": "node scripts/check-node.mjs",
|
|
29
|
+
"postinstall": "node scripts/setup.mjs || true",
|
|
30
|
+
"setup": "node scripts/setup.mjs",
|
|
31
|
+
"init": "node dist/cli/init.js",
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"build:web": "cd web && npx vite build",
|
|
34
|
+
"build:electron": "tsc -p electron/tsconfig.json && node --input-type=commonjs -e \"require('fs').writeFileSync('dist-electron/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\"",
|
|
35
|
+
"build:all": "npm run build && npm run build:web && npm run build:electron",
|
|
36
|
+
"dev": "tsx src/index.ts",
|
|
37
|
+
"start": "node dist/index.js",
|
|
38
|
+
"api": "tsx src/api/server.ts",
|
|
39
|
+
"api:start": "node dist/api/server.js",
|
|
40
|
+
"electron:dev": "npm run build:all && electron dist-electron/main.js",
|
|
41
|
+
"electron:pack": "npm run build:all && electron-builder --config electron-builder.yml",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"daemon": "tsx src/service/daemon.ts",
|
|
45
|
+
"daemon:start": "node dist/service/daemon.js",
|
|
46
|
+
"docker:build": "docker build -t stellar-memory .",
|
|
47
|
+
"docker:run": "docker compose up -d",
|
|
48
|
+
"benchmark": "npx tsx benchmarks/index.ts",
|
|
49
|
+
"benchmark:skip-embeddings": "npx tsx benchmarks/index.ts --skip-embeddings"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"mcp",
|
|
53
|
+
"memory",
|
|
54
|
+
"ai",
|
|
55
|
+
"context",
|
|
56
|
+
"stellar"
|
|
57
|
+
],
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@hono/node-server": "^1.19.9",
|
|
61
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
62
|
+
"@xenova/transformers": "^2.17.2",
|
|
63
|
+
"hono": "^4.12.3",
|
|
64
|
+
"sqlite-vec": "^0.1.7-alpha.2",
|
|
65
|
+
"ws": "^8.19.0",
|
|
66
|
+
"zod": "^3.25.76"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/node": "^22.19.13",
|
|
70
|
+
"@types/ws": "^8.18.1",
|
|
71
|
+
"electron": "^40.6.1",
|
|
72
|
+
"electron-builder": "^26.8.1",
|
|
73
|
+
"tsx": "^4.21.0",
|
|
74
|
+
"typescript": "^5.9.3",
|
|
75
|
+
"vitest": "^2.1.9"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* check-node.mjs — Preinstall script that validates Node.js version.
|
|
4
|
+
* Runs before `npm install` via the "preinstall" hook in package.json.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const REQUIRED_MAJOR = 22;
|
|
8
|
+
|
|
9
|
+
const [major] = process.versions.node.split('.').map(Number);
|
|
10
|
+
|
|
11
|
+
if (major < REQUIRED_MAJOR) {
|
|
12
|
+
console.error(`
|
|
13
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
14
|
+
║ Stellar Memory — Node.js Version Error ║
|
|
15
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
16
|
+
║ ║
|
|
17
|
+
║ Required: Node.js 22 or higher ║
|
|
18
|
+
║ Detected: Node.js ${process.versions.node.padEnd(40)}║
|
|
19
|
+
║ ║
|
|
20
|
+
║ Stellar Memory uses the built-in node:sqlite module which ║
|
|
21
|
+
║ was introduced in Node.js 22. It will not work on older ║
|
|
22
|
+
║ versions. ║
|
|
23
|
+
║ ║
|
|
24
|
+
║ How to upgrade: ║
|
|
25
|
+
║ ║
|
|
26
|
+
║ Option A — nvm (recommended): ║
|
|
27
|
+
║ nvm install 22 ║
|
|
28
|
+
║ nvm use 22 ║
|
|
29
|
+
║ ║
|
|
30
|
+
║ Option B — Direct download: ║
|
|
31
|
+
║ https://nodejs.org/en/download ║
|
|
32
|
+
║ ║
|
|
33
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
34
|
+
`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* setup.mjs — Pre-downloads the embedding model so first use is instant.
|
|
4
|
+
*
|
|
5
|
+
* Run once after installing: npm run setup
|
|
6
|
+
*
|
|
7
|
+
* What this does:
|
|
8
|
+
* 1. Downloads Xenova/all-MiniLM-L6-v2 (~90 MB, quantized) from HuggingFace.
|
|
9
|
+
* 2. Caches it in ~/.cache/huggingface (standard HuggingFace cache location).
|
|
10
|
+
* 3. Shows real-time download progress so you know it's working.
|
|
11
|
+
*
|
|
12
|
+
* After this completes, Stellar Memory starts instantly without any network delay.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const MODEL_NAME = 'Xenova/all-MiniLM-L6-v2';
|
|
16
|
+
const TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
17
|
+
|
|
18
|
+
console.log('Stellar Memory — Model Setup');
|
|
19
|
+
console.log('============================');
|
|
20
|
+
console.log(`Model: ${MODEL_NAME}`);
|
|
21
|
+
console.log('Size: ~90 MB (quantized int8)');
|
|
22
|
+
console.log('Cache: ~/.cache/huggingface');
|
|
23
|
+
console.log('');
|
|
24
|
+
console.log('Downloading embedding model...');
|
|
25
|
+
console.log('(This only happens once — subsequent starts are instant)');
|
|
26
|
+
console.log('');
|
|
27
|
+
|
|
28
|
+
let lastFile = '';
|
|
29
|
+
let startTime = Date.now();
|
|
30
|
+
let downloadedBytes = 0;
|
|
31
|
+
let totalBytes = 0;
|
|
32
|
+
|
|
33
|
+
function formatBytes(bytes) {
|
|
34
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
35
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
36
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function formatTime(seconds) {
|
|
40
|
+
if (seconds < 60) return `${Math.round(seconds)}s`;
|
|
41
|
+
return `${Math.floor(seconds / 60)}m ${Math.round(seconds % 60)}s`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function renderProgressBar(percent, width = 30) {
|
|
45
|
+
const filled = Math.round((percent / 100) * width);
|
|
46
|
+
const empty = width - filled;
|
|
47
|
+
return '[' + '#'.repeat(filled) + '-'.repeat(empty) + ']';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function onProgress(info) {
|
|
51
|
+
// info: { status, name, file, progress, loaded, total }
|
|
52
|
+
const { status, file, progress, loaded, total } = info;
|
|
53
|
+
|
|
54
|
+
if (status === 'initiate') {
|
|
55
|
+
if (file && file !== lastFile) {
|
|
56
|
+
lastFile = file;
|
|
57
|
+
const fileName = file.split('/').pop() ?? file;
|
|
58
|
+
process.stdout.write(` Fetching: ${fileName}\n`);
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (status === 'download') {
|
|
64
|
+
if (loaded != null) downloadedBytes = loaded;
|
|
65
|
+
if (total != null) totalBytes = total;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (status === 'progress' && progress != null) {
|
|
70
|
+
const pct = Math.min(100, Math.round(progress));
|
|
71
|
+
const bar = renderProgressBar(pct);
|
|
72
|
+
const elapsed = (Date.now() - startTime) / 1000;
|
|
73
|
+
const eta = pct > 0 ? (elapsed / pct) * (100 - pct) : 0;
|
|
74
|
+
const sizeInfo = totalBytes > 0
|
|
75
|
+
? `${formatBytes(downloadedBytes)} / ${formatBytes(totalBytes)}`
|
|
76
|
+
: (downloadedBytes > 0 ? formatBytes(downloadedBytes) : '');
|
|
77
|
+
const etaInfo = eta > 1 ? ` ETA: ${formatTime(eta)}` : '';
|
|
78
|
+
|
|
79
|
+
process.stdout.write(
|
|
80
|
+
`\r ${bar} ${String(pct).padStart(3)}%${sizeInfo ? ' ' + sizeInfo : ''}${etaInfo} `
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (status === 'done') {
|
|
86
|
+
// Clear the progress line and print completion
|
|
87
|
+
process.stdout.write('\r' + ' '.repeat(80) + '\r');
|
|
88
|
+
const fileName = (file ?? lastFile).split('/').pop() ?? '';
|
|
89
|
+
if (fileName) {
|
|
90
|
+
console.log(` [OK] ${fileName}`);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (status === 'ready') {
|
|
96
|
+
return; // Pipeline ready — handled below
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Race setup against a timeout
|
|
101
|
+
const timeoutPromise = new Promise((_, reject) =>
|
|
102
|
+
setTimeout(() => reject(new Error('timeout')), TIMEOUT_MS)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const setupPromise = (async () => {
|
|
106
|
+
const { pipeline, env } = await import('@xenova/transformers');
|
|
107
|
+
|
|
108
|
+
// Respect custom cache dir if set, otherwise use HuggingFace default
|
|
109
|
+
env.cacheDir = process.env['TRANSFORMERS_CACHE'] ?? undefined;
|
|
110
|
+
|
|
111
|
+
const pipe = await pipeline('feature-extraction', MODEL_NAME, {
|
|
112
|
+
quantized: true,
|
|
113
|
+
progress_callback: onProgress,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Run a quick smoke test to make sure the model is functional
|
|
117
|
+
const testOutput = await pipe('test', { pooling: 'mean', normalize: true });
|
|
118
|
+
const dims = testOutput.data.length;
|
|
119
|
+
|
|
120
|
+
return dims;
|
|
121
|
+
})();
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const dims = await Promise.race([setupPromise, timeoutPromise]);
|
|
125
|
+
|
|
126
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
127
|
+
console.log('');
|
|
128
|
+
console.log(`Setup complete in ${elapsed}s`);
|
|
129
|
+
console.log(`Model output: ${dims}-dimensional embeddings`);
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('Stellar Memory is ready. Start with:');
|
|
132
|
+
console.log(' npm run dev (MCP server)');
|
|
133
|
+
console.log(' npm run api (REST API)');
|
|
134
|
+
} catch (err) {
|
|
135
|
+
if (err.message === 'timeout') {
|
|
136
|
+
console.error('');
|
|
137
|
+
console.error('ERROR: Download timed out after 5 minutes.');
|
|
138
|
+
console.error('');
|
|
139
|
+
console.error('Possible causes:');
|
|
140
|
+
console.error(' - Slow internet connection');
|
|
141
|
+
console.error(' - HuggingFace servers unreachable');
|
|
142
|
+
console.error(' - Firewall blocking the download');
|
|
143
|
+
console.error('');
|
|
144
|
+
console.error('To retry: npm run setup');
|
|
145
|
+
console.error('');
|
|
146
|
+
console.error('If the problem persists, you can set a custom cache directory:');
|
|
147
|
+
console.error(' TRANSFORMERS_CACHE=/path/to/cache npm run setup');
|
|
148
|
+
} else {
|
|
149
|
+
console.error('');
|
|
150
|
+
console.error('ERROR: Model download failed.');
|
|
151
|
+
console.error('');
|
|
152
|
+
console.error('Details:', err.message);
|
|
153
|
+
console.error('');
|
|
154
|
+
console.error('To retry: npm run setup');
|
|
155
|
+
}
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|