flowleap 0.1.1 → 0.1.3
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/flowleap +1 -1
- package/install.mjs +79 -3
- package/package.json +2 -3
package/bin/flowleap
CHANGED
package/install.mjs
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { createWriteStream, chmodSync, mkdirSync, existsSync } from "fs";
|
|
1
|
+
import { createWriteStream, chmodSync, mkdirSync, existsSync, readFileSync } from "fs";
|
|
2
2
|
import { join, dirname } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { get } from "https";
|
|
5
5
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const REPO = "abdullahatrash/flowleap-cli";
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
// Read version from package.json so the release tag stays in sync with the
|
|
10
|
+
// published npm version automatically. Assumes release tags are named "v<version>".
|
|
11
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf8"));
|
|
12
|
+
const VERSION = `v${pkg.version}`;
|
|
9
13
|
|
|
10
14
|
const PLATFORM_MAP = {
|
|
11
15
|
"darwin-arm64": "flowleap-darwin-aarch64",
|
|
@@ -39,10 +43,69 @@ const url = `https://github.com/${REPO}/releases/download/${VERSION}/${asset}`;
|
|
|
39
43
|
|
|
40
44
|
console.log(`Downloading flowleap ${VERSION} for ${key}...`);
|
|
41
45
|
|
|
46
|
+
function formatBytes(n) {
|
|
47
|
+
if (!Number.isFinite(n) || n <= 0) return "0 B";
|
|
48
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
49
|
+
let i = 0;
|
|
50
|
+
while (n >= 1024 && i < units.length - 1) {
|
|
51
|
+
n /= 1024;
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
return `${n.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function renderBar(fraction, width = 24) {
|
|
58
|
+
const filled = Math.max(0, Math.min(width, Math.round(fraction * width)));
|
|
59
|
+
const empty = width - filled;
|
|
60
|
+
return `[${"=".repeat(filled)}${filled > 0 && empty > 0 ? ">" : ""}${" ".repeat(Math.max(0, empty - (filled > 0 ? 1 : 0)))}]`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function createProgressReporter(total) {
|
|
64
|
+
const isTTY = Boolean(process.stdout.isTTY);
|
|
65
|
+
const hasTotal = Number.isFinite(total) && total > 0;
|
|
66
|
+
let received = 0;
|
|
67
|
+
let lastRenderAt = 0;
|
|
68
|
+
let lastMilestone = -1;
|
|
69
|
+
|
|
70
|
+
const update = (chunkSize) => {
|
|
71
|
+
received += chunkSize;
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
|
|
74
|
+
if (isTTY) {
|
|
75
|
+
// Throttle TTY redraws to ~10 Hz
|
|
76
|
+
if (now - lastRenderAt < 100 && received !== total) return;
|
|
77
|
+
lastRenderAt = now;
|
|
78
|
+
if (hasTotal) {
|
|
79
|
+
const fraction = received / total;
|
|
80
|
+
const pct = Math.floor(fraction * 100);
|
|
81
|
+
const line = ` ${renderBar(fraction)} ${formatBytes(received)} / ${formatBytes(total)} (${pct}%)`;
|
|
82
|
+
process.stdout.write(`\r${line}`);
|
|
83
|
+
} else {
|
|
84
|
+
process.stdout.write(`\r Downloaded ${formatBytes(received)}...`);
|
|
85
|
+
}
|
|
86
|
+
} else if (hasTotal) {
|
|
87
|
+
// Non-TTY: emit milestone lines so CI logs stay readable
|
|
88
|
+
const pct = Math.floor((received / total) * 100);
|
|
89
|
+
const milestone = Math.floor(pct / 25) * 25;
|
|
90
|
+
if (milestone > lastMilestone && milestone <= 100) {
|
|
91
|
+
lastMilestone = milestone;
|
|
92
|
+
console.log(` ${milestone}% (${formatBytes(received)} / ${formatBytes(total)})`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const finish = () => {
|
|
98
|
+
if (isTTY) process.stdout.write("\n");
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return { update, finish };
|
|
102
|
+
}
|
|
103
|
+
|
|
42
104
|
function download(url) {
|
|
43
105
|
return new Promise((resolve, reject) => {
|
|
44
106
|
get(url, (res) => {
|
|
45
107
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
108
|
+
res.resume();
|
|
46
109
|
download(res.headers.location).then(resolve).catch(reject);
|
|
47
110
|
return;
|
|
48
111
|
}
|
|
@@ -50,16 +113,29 @@ function download(url) {
|
|
|
50
113
|
reject(new Error(`Download failed: HTTP ${res.statusCode}`));
|
|
51
114
|
return;
|
|
52
115
|
}
|
|
116
|
+
|
|
117
|
+
const total = parseInt(res.headers["content-length"] || "", 10);
|
|
118
|
+
const progress = createProgressReporter(total);
|
|
119
|
+
|
|
53
120
|
const file = createWriteStream(binPath);
|
|
121
|
+
res.on("data", (chunk) => progress.update(chunk.length));
|
|
54
122
|
res.pipe(file);
|
|
55
123
|
file.on("finish", () => {
|
|
56
124
|
file.close();
|
|
125
|
+
progress.finish();
|
|
57
126
|
if (!isWindows) {
|
|
58
127
|
chmodSync(binPath, 0o755);
|
|
59
128
|
}
|
|
60
129
|
resolve();
|
|
61
130
|
});
|
|
62
|
-
file.on("error",
|
|
131
|
+
file.on("error", (err) => {
|
|
132
|
+
progress.finish();
|
|
133
|
+
reject(err);
|
|
134
|
+
});
|
|
135
|
+
res.on("error", (err) => {
|
|
136
|
+
progress.finish();
|
|
137
|
+
reject(err);
|
|
138
|
+
});
|
|
63
139
|
}).on("error", reject);
|
|
64
140
|
});
|
|
65
141
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowleap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "One CLI for FlowLeap Patent AI — built for humans and AI agents",
|
|
5
5
|
"bin": {
|
|
6
6
|
"flowleap": "bin/flowleap"
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
"cli",
|
|
15
15
|
"flowleap",
|
|
16
16
|
"epo",
|
|
17
|
-
"ops"
|
|
18
|
-
"ocr"
|
|
17
|
+
"ops"
|
|
19
18
|
],
|
|
20
19
|
"author": "FlowLeap",
|
|
21
20
|
"type": "module",
|