offgrid-ai 0.3.8 → 0.3.10
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/package.json +1 -1
- package/src/cli.mjs +60 -1
- package/src/logs.mjs +2 -1
- package/src/ui.mjs +3 -2
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -11,10 +11,65 @@ import { tailFriendly } from "./logs.mjs";
|
|
|
11
11
|
import { estimateMemory } from "./estimate.mjs";
|
|
12
12
|
import { pc, formatBytes, renderRows, renderSection, startInteractive, createPrompt, parseOptions } from "./ui.mjs";
|
|
13
13
|
|
|
14
|
+
// ── Update check ────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
const UPDATE_CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
|
|
17
|
+
|
|
18
|
+
async function checkForUpdate() {
|
|
19
|
+
if (process.env.OFFGRID_NO_UPDATE_CHECK) return null;
|
|
20
|
+
const { readFile, writeFile } = await import("node:fs/promises");
|
|
21
|
+
const { join } = await import("node:path");
|
|
22
|
+
const cacheFile = join(DATA_DIR, "update-cache.json");
|
|
23
|
+
|
|
24
|
+
// Read cached check
|
|
25
|
+
let cached;
|
|
26
|
+
try {
|
|
27
|
+
cached = JSON.parse(await readFile(cacheFile, "utf8"));
|
|
28
|
+
} catch { cached = null; }
|
|
29
|
+
|
|
30
|
+
// Skip if checked recently
|
|
31
|
+
if (cached?.lastChecked && Date.now() - cached.lastChecked < UPDATE_CHECK_INTERVAL) {
|
|
32
|
+
return cached.latestVersion && cached.latestVersion !== cached.currentVersion ? { current: cached.currentVersion, latest: cached.latestVersion } : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Fetch latest version from npm registry
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch("https://registry.npmjs.org/offgrid-ai/latest", {
|
|
38
|
+
signal: AbortSignal.timeout(3000),
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) return null;
|
|
41
|
+
const body = await response.json();
|
|
42
|
+
const latestVersion = body.version;
|
|
43
|
+
|
|
44
|
+
// Get current version
|
|
45
|
+
const { readFileSync } = await import("node:fs");
|
|
46
|
+
const { dirname } = await import("node:path");
|
|
47
|
+
const { fileURLToPath } = await import("node:url");
|
|
48
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
const currentVersion = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8")).version;
|
|
50
|
+
|
|
51
|
+
// Cache the result
|
|
52
|
+
await writeFile(cacheFile, JSON.stringify({ lastChecked: Date.now(), currentVersion, latestVersion }), "utf8");
|
|
53
|
+
|
|
54
|
+
return latestVersion !== currentVersion ? { current: currentVersion, latest: latestVersion } : null;
|
|
55
|
+
} catch {
|
|
56
|
+
// Network error or timeout — fail silently
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
14
61
|
// ── Entry point ────────────────────────────────────────────────────────────
|
|
15
62
|
|
|
16
63
|
export async function run(argv) {
|
|
17
|
-
if (argv.length === 0)
|
|
64
|
+
if (argv.length === 0) {
|
|
65
|
+
const update = await checkForUpdate();
|
|
66
|
+
if (update) {
|
|
67
|
+
console.log(pc.yellow(`\nUpdate available: ${update.latest}. You have v${update.current}.`));
|
|
68
|
+
console.log(pc.dim("Run: npm install -g offgrid-ai@latest"));
|
|
69
|
+
console.log();
|
|
70
|
+
}
|
|
71
|
+
return mainFlow();
|
|
72
|
+
}
|
|
18
73
|
const [command] = argv;
|
|
19
74
|
|
|
20
75
|
if (command === "help" || command === "--help" || command === "-h") return printHelp();
|
|
@@ -967,6 +1022,10 @@ async function printVersion() {
|
|
|
967
1022
|
try {
|
|
968
1023
|
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
969
1024
|
console.log(`offgrid-ai v${pkg.version}`);
|
|
1025
|
+
const update = await checkForUpdate();
|
|
1026
|
+
if (update) {
|
|
1027
|
+
console.log(pc.yellow(`Update available: ${update.latest}. Run: npm install -g offgrid-ai@latest`));
|
|
1028
|
+
}
|
|
970
1029
|
} catch {
|
|
971
1030
|
console.log("offgrid-ai v0.1.0");
|
|
972
1031
|
}
|
package/src/logs.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, statSync } from "node:fs";
|
|
|
2
2
|
import { appendFile } from "node:fs/promises";
|
|
3
3
|
import { createReadStream } from "node:fs";
|
|
4
4
|
import pc from "picocolors";
|
|
5
|
+
import { stripVTControlCharacters } from "node:util";
|
|
5
6
|
|
|
6
7
|
export function tailFriendly(rawLogPath, friendlyLogPath) {
|
|
7
8
|
let offset = existsSync(rawLogPath) ? statSync(rawLogPath).size : 0;
|
|
@@ -21,7 +22,7 @@ export function tailFriendly(rawLogPath, friendlyLogPath) {
|
|
|
21
22
|
if (!friendly || seen.has(friendly)) continue;
|
|
22
23
|
seen.add(friendly);
|
|
23
24
|
console.log(friendly);
|
|
24
|
-
await appendFile(friendlyLogPath,
|
|
25
|
+
await appendFile(friendlyLogPath, stripVTControlCharacters(friendly) + "\n", "utf8");
|
|
25
26
|
}
|
|
26
27
|
} catch { /* friendly logging must never crash */ }
|
|
27
28
|
}, 300);
|
package/src/ui.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cancel, confirm, intro, isCancel, select, text } from "@clack/prompts";
|
|
2
2
|
import pc from "picocolors";
|
|
3
|
+
import { stripVTControlCharacters } from "node:util";
|
|
3
4
|
|
|
4
5
|
export { pc };
|
|
5
6
|
export { pc as colors };
|
|
@@ -50,9 +51,9 @@ function handleCancel(value) {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export function renderRows(rows) {
|
|
53
|
-
const width = Math.max(...rows.map(([key]) =>
|
|
54
|
+
const width = Math.max(...rows.map(([key]) => stripVTControlCharacters(String(key)).length));
|
|
54
55
|
return rows.map(([key, value]) => {
|
|
55
|
-
const visible =
|
|
56
|
+
const visible = stripVTControlCharacters(String(key)).length;
|
|
56
57
|
return `${key}${" ".repeat(Math.max(1, width - visible + 2))}${value}`;
|
|
57
58
|
}).join("\n");
|
|
58
59
|
}
|