MCPcopy
hub / github.com/garrytan/gstack / downloadFile

Function downloadFile

browse/src/security-classifier.ts:138–171  ·  view source on GitHub ↗
(url: string, dest: string)

Source from the content-addressed store, hash-verified

136// ─── Model download + staging ────────────────────────────────
137
138export async function downloadFile(url: string, dest: string): Promise<void> {
139 const res = await fetch(url);
140 if (!res.ok || !res.body) {
141 throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
142 }
143 const tmp = `${dest}.tmp.${process.pid}`;
144 const writer = fs.createWriteStream(tmp);
145 // @ts-ignore — Node stream compat
146 const reader = res.body.getReader();
147 try {
148 let done = false;
149 while (!done) {
150 const chunk = await reader.read();
151 if (chunk.done) { done = true; break; }
152 writer.write(chunk.value);
153 }
154 await new Promise<void>((resolve, reject) => {
155 writer.end((err?: Error | null) => (err ? reject(err) : resolve()));
156 });
157 fs.renameSync(tmp, dest);
158 } catch (err) {
159 // Drop the half-written tmp so we don't ship a truncated model file to
160 // a retry's renameSync. Wait for the writer to close fully before
161 // unlinking: Node's createWriteStream lazily opens the FD and flushes
162 // buffered writes during destroy(), so a naive unlinkSync hits ENOENT
163 // first and the writer re-creates the file on the next tick.
164 await new Promise<void>((resolve) => {
165 writer.once('close', () => resolve());
166 writer.destroy();
167 });
168 try { fs.unlinkSync(tmp); } catch { /* nothing to clean */ }
169 throw err;
170 }
171}
172
173async function ensureTestsavantStaged(onProgress?: (msg: string) => void): Promise<void> {
174 mkdirSecure(path.join(TESTSAVANT_DIR, 'onnx'));

Calls 2

endMethod · 0.80
fetchFunction · 0.70

Tested by

no test coverage detected