umadev 1.0.8 → 1.0.9
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/bin/cli.js +49 -19
- package/package.json +7 -7
package/bin/cli.js
CHANGED
|
@@ -128,6 +128,26 @@ function modelPresent(dir) {
|
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
+
// Render one frame of the download progress bar (in place, via \r). Block-glyph
|
|
132
|
+
// bar + percent + downloaded/total + live speed; ANSI-colored only on a TTY so a
|
|
133
|
+
// piped/redirected install stays clean.
|
|
134
|
+
function drawBar(label, got, total, startTime) {
|
|
135
|
+
const tty = process.stderr.isTTY;
|
|
136
|
+
const c = (code) => (tty ? '\x1b[' + code + 'm' : '');
|
|
137
|
+
const w = 22;
|
|
138
|
+
const ratio = total > 0 ? Math.min(1, got / total) : 0;
|
|
139
|
+
const fill = Math.round(ratio * w);
|
|
140
|
+
const bar = c('38;5;45') + '█'.repeat(fill) + c('0') + c('38;5;238') + '░'.repeat(w - fill) + c('0');
|
|
141
|
+
const pct = String(Math.floor(ratio * 100)).padStart(3);
|
|
142
|
+
const mb = (got / 1048576).toFixed(1);
|
|
143
|
+
const tot = (total / 1048576).toFixed(0);
|
|
144
|
+
const sec = (Date.now() - startTime) / 1000;
|
|
145
|
+
const spd = sec > 0.3 ? (got / 1048576 / sec).toFixed(1) + ' MB/s' : '…';
|
|
146
|
+
process.stderr.write(
|
|
147
|
+
'\r ' + c('1') + label + c('0') + ' ' + bar + ' ' + c('1') + pct + '%' + c('0') +
|
|
148
|
+
c('2') + ' · ' + mb + '/' + tot + ' MB · ' + spd + c('0') + ' ',
|
|
149
|
+
);
|
|
150
|
+
}
|
|
131
151
|
// Download one URL to `dest`, following redirects (GitHub → CDN), drawing a
|
|
132
152
|
// progress bar when `withBar`. Resolves on success, rejects on any error.
|
|
133
153
|
function downloadTo(url, dest, withBar, label) {
|
|
@@ -149,22 +169,24 @@ function downloadTo(url, dest, withBar, label) {
|
|
|
149
169
|
const total = parseInt(res.headers['content-length'] || '0', 10);
|
|
150
170
|
let got = 0;
|
|
151
171
|
let lastPct = -1;
|
|
172
|
+
let lastDraw = 0;
|
|
173
|
+
const startTime = Date.now();
|
|
152
174
|
const tmp = dest + '.part';
|
|
153
175
|
const out = fs.createWriteStream(tmp);
|
|
176
|
+
// Draw the bar at 0% the instant the response starts — on a slow link the
|
|
177
|
+
// first 1% can take a while, and a silent gap reads as "stuck / failed".
|
|
178
|
+
if (withBar && total > 0) drawBar(label, 0, total, startTime);
|
|
154
179
|
res.on('data', (chunk) => {
|
|
155
180
|
got += chunk.length;
|
|
156
181
|
if (withBar && total > 0) {
|
|
182
|
+
const now = Date.now();
|
|
157
183
|
const pct = Math.floor((got / total) * 100);
|
|
158
|
-
|
|
184
|
+
// Redraw on each new percent OR every ~250ms — keeps the live speed
|
|
185
|
+
// ticking even while a single percent of a 224MB file streams in.
|
|
186
|
+
if (pct !== lastPct || now - lastDraw > 250) {
|
|
159
187
|
lastPct = pct;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const bar = '#'.repeat(fill) + '-'.repeat(w - fill);
|
|
163
|
-
const mb = (got / 1048576).toFixed(0);
|
|
164
|
-
const tot = (total / 1048576).toFixed(0);
|
|
165
|
-
process.stderr.write(
|
|
166
|
-
'\r ' + label + ' [' + bar + '] ' + pct + '% (' + mb + '/' + tot + ' MB)',
|
|
167
|
-
);
|
|
188
|
+
lastDraw = now;
|
|
189
|
+
drawBar(label, got, total, startTime);
|
|
168
190
|
}
|
|
169
191
|
}
|
|
170
192
|
});
|
|
@@ -177,7 +199,10 @@ function downloadTo(url, dest, withBar, label) {
|
|
|
177
199
|
} catch (er) {
|
|
178
200
|
return reject(er);
|
|
179
201
|
}
|
|
180
|
-
if (withBar)
|
|
202
|
+
if (withBar && total > 0) {
|
|
203
|
+
drawBar(label, total, total, startTime);
|
|
204
|
+
process.stderr.write('\n');
|
|
205
|
+
}
|
|
181
206
|
resolve();
|
|
182
207
|
}),
|
|
183
208
|
);
|
|
@@ -197,12 +222,15 @@ function releaseBases(version) {
|
|
|
197
222
|
if (process.env.UMADEV_MODEL_BASE_URL) {
|
|
198
223
|
return [process.env.UMADEV_MODEL_BASE_URL.replace(/\/+$/, '')];
|
|
199
224
|
}
|
|
225
|
+
// GitHub Release ships the quantized fp16 model (~224MB, smaller). HuggingFace
|
|
226
|
+
// and its China mirror hf-mirror.com serve the upstream f32 model (~448MB —
|
|
227
|
+
// bigger, but the candle loader handles either). hf-mirror is the FAST + reliable
|
|
228
|
+
// source inside mainland China, where github.com's release CDN is slow and the
|
|
229
|
+
// community GitHub proxies are flaky for release-asset URLs.
|
|
200
230
|
const gh = 'https://github.com/umacloud/umadev/releases/download/v' + version;
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
'https://gh-proxy.com/' + gh,
|
|
205
|
-
];
|
|
231
|
+
const ghProxies = ['https://ghproxy.net/' + gh, 'https://ghfast.top/' + gh];
|
|
232
|
+
const hf = 'https://huggingface.co/intfloat/multilingual-e5-small/resolve/main';
|
|
233
|
+
const hfMirror = 'https://hf-mirror.com/intfloat/multilingual-e5-small/resolve/main';
|
|
206
234
|
let cn = false;
|
|
207
235
|
try {
|
|
208
236
|
const opts = Intl.DateTimeFormat().resolvedOptions();
|
|
@@ -212,9 +240,11 @@ function releaseBases(version) {
|
|
|
212
240
|
/Shanghai|Chongqing|Urumqi|Harbin|Hong_Kong|Macau/.test(tz) ||
|
|
213
241
|
/zh[_-]?(CN|Hans)/i.test(loc);
|
|
214
242
|
} catch (_) {
|
|
215
|
-
/* default to
|
|
243
|
+
/* default to international order */
|
|
216
244
|
}
|
|
217
|
-
|
|
245
|
+
// China: hf-mirror first (fast + reliable in CN), then GitHub proxies + direct.
|
|
246
|
+
// International: GitHub Release first (smaller fp16), then HuggingFace + mirror.
|
|
247
|
+
return cn ? [hfMirror, ...ghProxies, gh, hf] : [gh, hf, hfMirror, ...ghProxies];
|
|
218
248
|
}
|
|
219
249
|
// Try each base for `name` in order; resolve on first success, throw the last
|
|
220
250
|
// error if all fail. A China mirror can cover a blocked github.com (or vice
|
|
@@ -244,13 +274,13 @@ async function ensureModel() {
|
|
|
244
274
|
try {
|
|
245
275
|
fs.mkdirSync(dir, { recursive: true });
|
|
246
276
|
process.stderr.write(
|
|
247
|
-
'\n 本地向量检索模型缺失,正在下载
|
|
277
|
+
'\n 本地向量检索模型缺失,正在下载 multilingual-e5-small(国内自动走镜像)…\n',
|
|
248
278
|
);
|
|
249
279
|
process.stderr.write(
|
|
250
280
|
' 一次性下载;之后完全本地、运行时无需联网。失败不影响使用(降级为 BM25)。\n',
|
|
251
281
|
);
|
|
252
282
|
await downloadFile(bases, 'config.json', path.join(dir, 'config.json'), false, '');
|
|
253
|
-
await downloadFile(bases, 'tokenizer.json', path.join(dir, 'tokenizer.json'),
|
|
283
|
+
await downloadFile(bases, 'tokenizer.json', path.join(dir, 'tokenizer.json'), true, '下载分词器 ');
|
|
254
284
|
await downloadFile(
|
|
255
285
|
bases,
|
|
256
286
|
'model.safetensors',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "umadev",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "A project-director Agent for AI coding hosts — drives your logged-in Claude Code / Codex through a 9-phase commercial delivery pipeline with governance. No API key needed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"node": ">=18"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
|
-
"@umacloud/cli-darwin-arm64": "1.0.
|
|
41
|
-
"@umacloud/cli-darwin-x64": "1.0.
|
|
42
|
-
"@umacloud/cli-linux-x64": "1.0.
|
|
43
|
-
"@umacloud/cli-linux-arm64": "1.0.
|
|
44
|
-
"@umacloud/cli-win32-x64": "1.0.
|
|
45
|
-
"@umacloud/knowledge": "1.0.
|
|
40
|
+
"@umacloud/cli-darwin-arm64": "1.0.9",
|
|
41
|
+
"@umacloud/cli-darwin-x64": "1.0.9",
|
|
42
|
+
"@umacloud/cli-linux-x64": "1.0.9",
|
|
43
|
+
"@umacloud/cli-linux-arm64": "1.0.9",
|
|
44
|
+
"@umacloud/cli-win32-x64": "1.0.9",
|
|
45
|
+
"@umacloud/knowledge": "1.0.9"
|
|
46
46
|
}
|
|
47
47
|
}
|