tingly-box 0.2601.51800-preview → 0.2601.71440-preview
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.js +80 -48
- package/package.json +3 -2
package/bin.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { execFileSync } from "child_process";
|
|
4
|
-
import { chmodSync, createWriteStream, existsSync, fsyncSync, mkdirSync } from "fs";
|
|
5
|
-
import { tmpdir } from "os";
|
|
4
|
+
import { chmodSync, createWriteStream, existsSync, fsyncSync, mkdirSync, statSync } from "fs";
|
|
6
5
|
import { join } from "path";
|
|
7
6
|
import { Readable } from "stream";
|
|
8
7
|
import { ProxyAgent } from "undici";
|
|
8
|
+
import unzipper from "unzipper";
|
|
9
9
|
|
|
10
10
|
// Configuration for binary downloads
|
|
11
11
|
const BASE_URL = "https://github.com/tingly-dev/tingly-box/releases/download/";
|
|
@@ -15,7 +15,7 @@ const LATEST_RELEASE_API_URL = "https://github.com/tingly-dev/tingly-box/release
|
|
|
15
15
|
|
|
16
16
|
// Default branch to use when not specified via transport version
|
|
17
17
|
// This will be replaced during the NPX build process
|
|
18
|
-
const BINARY_RELEASE_BRANCH = 'v0.2601.
|
|
18
|
+
const BINARY_RELEASE_BRANCH = 'v0.2601.071440-preview';
|
|
19
19
|
|
|
20
20
|
// Create proxy agent from environment variables (HTTP_PROXY, HTTPS_PROXY)
|
|
21
21
|
// Only create ProxyAgent if proxy is configured, otherwise use undefined (direct connection)
|
|
@@ -199,62 +199,94 @@ async function downloadAndExtractZip(url, extractDir, binaryName) {
|
|
|
199
199
|
process.exit(1);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
// Create a temporary file for the ZIP
|
|
203
|
-
const zipPath = join(tmpdir(), `tingly-box-${Date.now()}.zip`);
|
|
204
|
-
const fileStream = createWriteStream(zipPath, { flags: "w" });
|
|
205
|
-
|
|
206
202
|
const contentLength = res.headers.get("content-length");
|
|
207
203
|
const totalSize = contentLength ? parseInt(contentLength, 10) : null;
|
|
208
204
|
let downloadedSize = 0;
|
|
209
205
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
// Convert the fetch response body to a Node.js readable stream
|
|
207
|
+
const nodeStream = Readable.fromWeb(res.body);
|
|
208
|
+
|
|
209
|
+
// Collect the entire ZIP into a buffer
|
|
210
|
+
const chunks = [];
|
|
211
|
+
for await (const chunk of nodeStream) {
|
|
212
|
+
chunks.push(chunk);
|
|
213
|
+
downloadedSize += chunk.length;
|
|
214
|
+
if (totalSize) {
|
|
215
|
+
const progress = ((downloadedSize / totalSize) * 100).toFixed(1);
|
|
216
|
+
process.stdout.write(`\r⏱️ Downloading: ${progress}% (${formatBytes(downloadedSize)}/${formatBytes(totalSize)})`);
|
|
217
|
+
} else {
|
|
218
|
+
process.stdout.write(`\r⏱️ Downloaded: ${formatBytes(downloadedSize)}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const zipBuffer = Buffer.concat(chunks);
|
|
213
222
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const progress = ((downloadedSize / totalSize) * 100).toFixed(1);
|
|
218
|
-
process.stdout.write(`\r⏱️ Downloading ZIP: ${progress}% (${formatBytes(downloadedSize)}/${formatBytes(totalSize)})`);
|
|
219
|
-
} else {
|
|
220
|
-
process.stdout.write(`\r⏱️ Downloaded: ${formatBytes(downloadedSize)}`);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
+
// Extract ZIP from buffer using unzipper
|
|
224
|
+
try {
|
|
225
|
+
console.log(`\n📦 Extracting ZIP to ${extractDir}...`);
|
|
223
226
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
nodeStream.on("error", reject);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
reject(error);
|
|
227
|
+
const directory = await unzipper.Open.buffer(zipBuffer);
|
|
228
|
+
|
|
229
|
+
// Debug: List all entries in the ZIP
|
|
230
|
+
console.log(`📋 ZIP contents (${directory.files.length} entries):`);
|
|
231
|
+
for (const file of directory.files) {
|
|
232
|
+
console.log(` ${file.type}: ${file.path} (permissions: ${file.unixPermissions?.toString(8)})`);
|
|
233
233
|
}
|
|
234
|
-
});
|
|
235
234
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
235
|
+
// Extract all files to the target directory
|
|
236
|
+
for (const file of directory.files) {
|
|
237
|
+
// Skip directory entries and __MACOSX metadata
|
|
238
|
+
if (file.type === 'Directory' || file.path.startsWith('__MACOSX/') || file.path.includes('.DS_Store')) {
|
|
239
|
+
console.log(`⏭️ Skipping: ${file.path} (type: ${file.type})`);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const filePath = join(extractDir, file.path);
|
|
244
|
+
// Get parent directory of the file in the ZIP
|
|
245
|
+
const pathParts = file.path.split('/');
|
|
246
|
+
pathParts.pop(); // Remove the filename
|
|
247
|
+
const fileDir = pathParts.length > 0 ? join(extractDir, ...pathParts) : extractDir;
|
|
248
|
+
|
|
249
|
+
console.log(`📄 Extracting: ${file.path} -> ${filePath}`);
|
|
250
|
+
|
|
251
|
+
// Ensure parent directory exists
|
|
252
|
+
if (fileDir !== extractDir && !existsSync(fileDir)) {
|
|
253
|
+
mkdirSync(fileDir, { recursive: true });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Remove existing directory if it exists (this was created incorrectly before)
|
|
257
|
+
if (existsSync(filePath) && statSync(filePath).isDirectory()) {
|
|
258
|
+
console.log(`🧹 Removing incorrect directory: ${filePath}`);
|
|
259
|
+
// Can't easily remove a directory in Node without fs.rm (Node 14.14+)
|
|
260
|
+
// Skip and let user clean up manually
|
|
261
|
+
console.log(`⚠️ Please manually remove: rm -rf "${filePath}"`);
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Extract file
|
|
266
|
+
const content = await file.buffer();
|
|
267
|
+
const fileStream = createWriteStream(filePath);
|
|
268
|
+
await new Promise((resolve, reject) => {
|
|
269
|
+
fileStream.write(content, (err) => {
|
|
270
|
+
if (err) reject(err);
|
|
271
|
+
else {
|
|
272
|
+
fileStream.end();
|
|
273
|
+
resolve();
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
// Set file permissions after writing
|
|
278
|
+
if (process.platform !== "win32") {
|
|
279
|
+
// Use ZIP permissions if available, otherwise default to 0o755 (executable)
|
|
280
|
+
const permissions = file.unixPermissions && file.unixPermissions > 0 ? file.unixPermissions : 0o755;
|
|
281
|
+
chmodSync(filePath, permissions);
|
|
282
|
+
}
|
|
250
283
|
}
|
|
251
|
-
}
|
|
252
284
|
|
|
253
|
-
|
|
254
|
-
try {
|
|
255
|
-
execFileSync("rm", ["-f", zipPath]);
|
|
285
|
+
console.log(`✅ Extracted ZIP to ${extractDir}`);
|
|
256
286
|
} catch (error) {
|
|
257
|
-
|
|
287
|
+
console.error(`\n❌ Failed to extract ZIP: ${error.message}`);
|
|
288
|
+
console.error(`Stack: ${error.stack}`);
|
|
289
|
+
process.exit(1);
|
|
258
290
|
}
|
|
259
291
|
}
|
|
260
292
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tingly-box",
|
|
3
|
-
"version": "0.2601.
|
|
3
|
+
"version": "0.2601.71440-preview",
|
|
4
4
|
"description": "High-performance AI gateway CLI - connect to multiple AI providers through a single API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"type": "module",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"undici": "^7.0.0"
|
|
32
|
+
"undici": "^7.0.0",
|
|
33
|
+
"unzipper": "^0.12.3"
|
|
33
34
|
}
|
|
34
35
|
}
|