mn-docs-mcp 0.2.3 → 0.3.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.
Files changed (2) hide show
  1. package/mcp/lib.mjs +47 -4
  2. package/package.json +1 -1
package/mcp/lib.mjs CHANGED
@@ -43,6 +43,8 @@ let proxyInitialized = false;
43
43
  const MAX_EXTRACTOR_RETRIES = 3;
44
44
  const IS_STDIO = process.env.MCP_STDIO === '1';
45
45
  const IS_SILENT = process.env.MCP_SILENT === '1';
46
+ const NO_COLOR = process.env.MCP_NO_COLOR === '1';
47
+ let lastDownloadProgress = -1;
46
48
 
47
49
  function logInfo(message) {
48
50
  if (IS_SILENT) return;
@@ -53,6 +55,47 @@ function logInfo(message) {
53
55
  }
54
56
  }
55
57
 
58
+ function color(text, code) {
59
+ if (NO_COLOR) return text;
60
+ return `\x1b[${code}m${text}\x1b[0m`;
61
+ }
62
+
63
+ function formatBytes(bytes) {
64
+ if (!Number.isFinite(bytes)) return '';
65
+ const units = ['B', 'KB', 'MB', 'GB'];
66
+ let idx = 0;
67
+ let value = bytes;
68
+ while (value >= 1024 && idx < units.length - 1) {
69
+ value /= 1024;
70
+ idx += 1;
71
+ }
72
+ return `${value.toFixed(1)}${units[idx]}`;
73
+ }
74
+
75
+ function logDownloadProgress(info) {
76
+ if (IS_SILENT) return;
77
+ if (info?.status === 'download') {
78
+ logInfo(color('开始下载模型...', '38;5;45'));
79
+ return;
80
+ }
81
+ if (info?.status === 'progress' && typeof info.progress === 'number') {
82
+ const pct = Math.max(0, Math.min(100, Math.round(info.progress)));
83
+ if (pct === lastDownloadProgress) return;
84
+ lastDownloadProgress = pct;
85
+ const loaded = formatBytes(info.loaded);
86
+ const total = formatBytes(info.total);
87
+ const suffix = loaded && total ? ` ${loaded}/${total}` : '';
88
+ const line = `${color('模型下载进度', '38;5;45')}: ${pct}%${suffix}`;
89
+ if (IS_STDIO) {
90
+ process.stderr.write(`\r${line}`);
91
+ if (pct === 100) process.stderr.write('\n');
92
+ } else {
93
+ process.stdout.write(`\r${line}`);
94
+ if (pct === 100) process.stdout.write('\n');
95
+ }
96
+ }
97
+ }
98
+
56
99
  function loadEnv() {
57
100
  dotenv.config({ path: path.join(ROOT_DIR, '.env') });
58
101
  }
@@ -74,14 +117,15 @@ async function getExtractor() {
74
117
  if (extractorPromise) return extractorPromise;
75
118
  loadEnv();
76
119
  setupProxy();
77
- env.cacheDir = path.join(MCP_DIR, 'models');
78
120
  env.allowRemoteModels = true;
79
121
  if (process.env.HF_ENDPOINT) {
80
122
  env.HF_ENDPOINT = process.env.HF_ENDPOINT;
81
123
  }
82
124
 
83
- const modelDir = path.join(env.cacheDir, 'Xenova', 'bge-small-zh-v1.5');
84
- const create = async () => pipeline('feature-extraction', MODEL_ID);
125
+ const create = async () =>
126
+ pipeline('feature-extraction', MODEL_ID, {
127
+ progress_callback: logDownloadProgress,
128
+ });
85
129
 
86
130
  extractorPromise = (async () => {
87
131
  for (let attempt = 1; attempt <= MAX_EXTRACTOR_RETRIES; attempt += 1) {
@@ -100,7 +144,6 @@ async function getExtractor() {
100
144
  }
101
145
 
102
146
  logInfo(`模型下载失败,准备重试(${attempt}/${MAX_EXTRACTOR_RETRIES})...`);
103
- await fs.rm(modelDir, { recursive: true, force: true });
104
147
  }
105
148
  }
106
149
  throw new Error('模型加载失败');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mn-docs-mcp",
3
3
  "type": "module",
4
- "version": "0.2.3",
4
+ "version": "0.3.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/Temsys-Shen/marginnote-addon-docs.git"