ozali 0.7.0 → 0.7.1
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/cli/lib/commands.mjs +25 -17
- package/cli/lib/util.mjs +23 -0
- package/cli/test/smoke.test.mjs +29 -1
- package/package.json +1 -1
package/cli/lib/commands.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import os from "node:os";
|
|
|
5
5
|
import {
|
|
6
6
|
c, ok, warn, err, info, step,
|
|
7
7
|
SKILL_SRC, COMMIT_SKILL_SRC, TEMPLATES_SRC, exists, ensureDir, copyDir, readJSON, writeJSON,
|
|
8
|
-
ensureGitignore, tryExec, spawnCmd, which, engramAssetName,
|
|
8
|
+
ensureGitignore, tryExec, spawnCmd, which, engramAssetName, pickEngramAsset,
|
|
9
9
|
projectName, pkgVersion, DEFAULT_KNOWLEDGE, HOME, openURL, gitInfo,
|
|
10
10
|
} from "./util.mjs";
|
|
11
11
|
import { detectAll, detectWorkspace, detectReferences } from "./detect.mjs";
|
|
@@ -305,19 +305,28 @@ function installEngram() {
|
|
|
305
305
|
return false;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
// Lista de releases (NO /releases/latest: ese endpoint puede devolver un tag especial
|
|
309
|
+
// sin binarios, p. ej. `pi-v*`). Recorremos la lista y elegimos el release estable.
|
|
310
|
+
const ENGRAM_RELEASES_LIST = "https://api.github.com/repos/Gentleman-Programming/engram/releases?per_page=30";
|
|
310
311
|
|
|
311
|
-
/**
|
|
312
|
-
function
|
|
313
|
-
|
|
314
|
-
if (which("
|
|
315
|
-
|
|
312
|
+
/** GET de texto con curl (o wget). Devuelve el body o null si no hay red/herramienta. */
|
|
313
|
+
function fetchText(url) {
|
|
314
|
+
if (which("curl")) return tryExec("curl", ["-fsSL", url]);
|
|
315
|
+
if (which("wget")) return tryExec("wget", ["-qO-", url]);
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Resuelve { version, url } del binario precompilado de Engram para este SO/arch,
|
|
321
|
+
* consultando la lista de releases y quedándose con el release estable más reciente
|
|
322
|
+
* que contenga el asset. Devuelve null si no hay red/herramienta o no hay binario.
|
|
323
|
+
*/
|
|
324
|
+
function resolveEngramAsset(platform, arch) {
|
|
325
|
+
const raw = fetchText(ENGRAM_RELEASES_LIST);
|
|
316
326
|
if (!raw) return null;
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
} catch { return null; }
|
|
327
|
+
let releases;
|
|
328
|
+
try { releases = JSON.parse(raw); } catch { return null; }
|
|
329
|
+
return pickEngramAsset(releases, platform, arch);
|
|
321
330
|
}
|
|
322
331
|
|
|
323
332
|
/** Descarga url → dest con curl (o wget como fallback). Devuelve true si tuvo éxito. */
|
|
@@ -359,14 +368,13 @@ function installEngramFromTarball() {
|
|
|
359
368
|
return false;
|
|
360
369
|
}
|
|
361
370
|
|
|
362
|
-
const
|
|
363
|
-
if (!
|
|
364
|
-
warn("No pude resolver
|
|
371
|
+
const resolved = resolveEngramAsset(plat, process.arch);
|
|
372
|
+
if (!resolved) {
|
|
373
|
+
warn("No pude resolver un binario precompilado de Engram para tu SO/arch (¿sin red, sin curl/wget, o release sin assets?).");
|
|
365
374
|
return false;
|
|
366
375
|
}
|
|
367
|
-
|
|
376
|
+
const { version, url } = resolved;
|
|
368
377
|
const asset = engramAssetName(plat, process.arch, version);
|
|
369
|
-
const url = `${ENGRAM_RELEASES_DL}/v${version}/${asset}`;
|
|
370
378
|
info(`Descargando binario precompilado de Engram ${c.bold("v" + version)} (${process.arch})…`);
|
|
371
379
|
|
|
372
380
|
let tmpDir;
|
package/cli/lib/util.mjs
CHANGED
|
@@ -37,6 +37,29 @@ export function engramAssetName(platform, arch, version) {
|
|
|
37
37
|
return `engram_${version}_${os}_${a}.${ext}`;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Elige el binario precompilado de Engram para un SO/arch dado a partir de la lista de
|
|
42
|
+
* releases (formato de la API de GitHub `/releases`). Se queda con el release ESTABLE
|
|
43
|
+
* más reciente cuyo tag sea semver `vX.Y.Z` y que **realmente contenga** el asset
|
|
44
|
+
* esperado, y devuelve su `browser_download_url` real. Ignora tags no-semver (p. ej.
|
|
45
|
+
* `pi-v*`, builds de Raspberry Pi que NO traen binarios) y draft/prerelease.
|
|
46
|
+
* Función pura (sin red). Devuelve { version, url } o null.
|
|
47
|
+
*/
|
|
48
|
+
export function pickEngramAsset(releases, platform, arch) {
|
|
49
|
+
if (!Array.isArray(releases)) return null;
|
|
50
|
+
for (const r of releases) {
|
|
51
|
+
if (!r || r.draft || r.prerelease) continue;
|
|
52
|
+
const m = /^v(\d+\.\d+\.\d+)$/.exec(r.tag_name || "");
|
|
53
|
+
if (!m) continue; // salta tags no-semver (pi-v*, etc.)
|
|
54
|
+
const version = m[1];
|
|
55
|
+
const name = engramAssetName(platform, arch, version);
|
|
56
|
+
if (!name) return null; // SO/arch sin binario publicado
|
|
57
|
+
const asset = Array.isArray(r.assets) ? r.assets.find((a) => a && a.name === name) : null;
|
|
58
|
+
if (asset && asset.browser_download_url) return { version, url: asset.browser_download_url };
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
40
63
|
// ---- colores (sin deps; respeta NO_COLOR y no-TTY) --------------------------
|
|
41
64
|
const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
42
65
|
const wrap = (code) => (s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : String(s));
|
package/cli/test/smoke.test.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import fs from "node:fs";
|
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { engramAssetName } from "../lib/util.mjs";
|
|
9
|
+
import { engramAssetName, pickEngramAsset } from "../lib/util.mjs";
|
|
10
10
|
|
|
11
11
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
const BIN = path.resolve(HERE, "..", "bin", "ozali.mjs");
|
|
@@ -335,3 +335,31 @@ test("engramAssetName respeta la convención de release por SO/arch", () => {
|
|
|
335
335
|
assert.equal(engramAssetName("linux", "ia32", "1.17.0"), null, "arch no soportada → null");
|
|
336
336
|
assert.equal(engramAssetName("freebsd", "x64", "1.17.0"), null, "SO no soportado → null");
|
|
337
337
|
});
|
|
338
|
+
|
|
339
|
+
test("pickEngramAsset ignora tags no-semver sin binarios (pi-v*) y draft/prerelease", () => {
|
|
340
|
+
// Shape real de la API de GitHub: el 'latest' es pi-v0.1.9 (0 assets); los binarios
|
|
341
|
+
// viven en tags vX.Y.Z. Además metemos un prerelease más nuevo que debe saltarse.
|
|
342
|
+
const releases = [
|
|
343
|
+
{ tag_name: "pi-v0.1.9", prerelease: false, draft: false, assets: [] },
|
|
344
|
+
{ tag_name: "v2.0.0", prerelease: true, draft: false, assets: [
|
|
345
|
+
{ name: "engram_2.0.0_linux_amd64.tar.gz", browser_download_url: "https://x/pre" },
|
|
346
|
+
] },
|
|
347
|
+
{ tag_name: "v1.17.0", prerelease: false, draft: false, assets: [
|
|
348
|
+
{ name: "checksums.txt", browser_download_url: "https://x/sum" },
|
|
349
|
+
{ name: "engram_1.17.0_linux_amd64.tar.gz", browser_download_url: "https://x/engram_1.17.0_linux_amd64.tar.gz" },
|
|
350
|
+
{ name: "engram_1.17.0_darwin_arm64.tar.gz", browser_download_url: "https://x/darwin" },
|
|
351
|
+
] },
|
|
352
|
+
];
|
|
353
|
+
// Linux x64 → salta pi-v* (sin assets) y el prerelease → v1.17.0, con la URL REAL del asset.
|
|
354
|
+
assert.deepEqual(pickEngramAsset(releases, "linux", "x64"), {
|
|
355
|
+
version: "1.17.0",
|
|
356
|
+
url: "https://x/engram_1.17.0_linux_amd64.tar.gz",
|
|
357
|
+
});
|
|
358
|
+
// macOS arm64 → mismo release, su asset darwin_arm64.
|
|
359
|
+
assert.deepEqual(pickEngramAsset(releases, "darwin", "arm64"), { version: "1.17.0", url: "https://x/darwin" });
|
|
360
|
+
// Arch sin binario → null.
|
|
361
|
+
assert.equal(pickEngramAsset(releases, "linux", "ia32"), null);
|
|
362
|
+
// Sin releases utilizables → null.
|
|
363
|
+
assert.equal(pickEngramAsset([{ tag_name: "pi-v0.1.9", assets: [] }], "linux", "x64"), null);
|
|
364
|
+
assert.equal(pickEngramAsset(null, "linux", "x64"), null);
|
|
365
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ozali",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Bootstrap interactivo de IA por equipo: calibra el proyecto, genera la skill de ejecución (cdk) con TDD/SDD, y mantiene memoria de equipo (Engram) con histórico aislado.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|