akili-specs 2.5.0 → 2.5.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/CHANGELOG.md +4 -0
- package/bin/akili.js +112 -1
- package/docs/cli.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,10 @@ The format is inspired by Keep a Changelog and the repository follows semantic v
|
|
|
10
10
|
|
|
11
11
|
- No unreleased changes yet.
|
|
12
12
|
|
|
13
|
+
## [2.5.1] - 2026-07-19
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **`akili update` now shows what changed:** After updating the npm package and reinstalling files, `akili update` prints a `What changed (<old> → <new>)` summary sourced from the installed package's `CHANGELOG.md`, listing every version section between the previously installed version and the new one. If the package was already up to date, it says so instead.
|
|
13
17
|
## [2.5.0] - 2026-07-19
|
|
14
18
|
|
|
15
19
|
### Added
|
package/bin/akili.js
CHANGED
|
@@ -78,7 +78,7 @@ Usage:
|
|
|
78
78
|
|
|
79
79
|
Commands:
|
|
80
80
|
install Install commands, skills, and helper resources
|
|
81
|
-
update Update npm package to latest version and
|
|
81
|
+
update Update npm package to latest version, reinstall files, and show what changed
|
|
82
82
|
doctor Check whether expected files are installed
|
|
83
83
|
list List packaged commands, skills, and helper resources
|
|
84
84
|
help Show this help
|
|
@@ -398,6 +398,107 @@ function detectInstallType() {
|
|
|
398
398
|
return "npx";
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
+
// Resolve the installed akili-specs package directory (global or local) after an update.
|
|
402
|
+
// Returns the absolute path to the package root, or null if it cannot be found.
|
|
403
|
+
function resolveInstalledPackageDir(installType) {
|
|
404
|
+
try {
|
|
405
|
+
const root = execSync(
|
|
406
|
+
installType === "global" ? "npm root -g 2>/dev/null" : "npm root 2>/dev/null",
|
|
407
|
+
{ encoding: "utf8" }
|
|
408
|
+
).trim();
|
|
409
|
+
if (root) {
|
|
410
|
+
const dir = path.join(root, "akili-specs");
|
|
411
|
+
if (fs.existsSync(path.join(dir, "package.json"))) return dir;
|
|
412
|
+
}
|
|
413
|
+
} catch (e) {}
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Read the version from an installed package's package.json.
|
|
418
|
+
function readInstalledVersion(packageDir) {
|
|
419
|
+
try {
|
|
420
|
+
return JSON.parse(fs.readFileSync(path.join(packageDir, "package.json"), "utf8")).version;
|
|
421
|
+
} catch (e) {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Parse CHANGELOG.md and return the raw text of every version section strictly
|
|
427
|
+
// newer than `fromVersion` up to and including `toVersion`. Sections look like
|
|
428
|
+
// `## [X.Y.Z] - date`. Returns an array of { version, body } newest-first.
|
|
429
|
+
function changelogSectionsBetween(changelogPath, fromVersion, toVersion) {
|
|
430
|
+
let text;
|
|
431
|
+
try {
|
|
432
|
+
text = fs.readFileSync(changelogPath, "utf8");
|
|
433
|
+
} catch (e) {
|
|
434
|
+
return [];
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const lines = text.split("\n");
|
|
438
|
+
const sections = [];
|
|
439
|
+
let current = null;
|
|
440
|
+
|
|
441
|
+
const isNewer = (a, b) =>
|
|
442
|
+
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }) > 0;
|
|
443
|
+
|
|
444
|
+
for (const line of lines) {
|
|
445
|
+
const match = line.match(/^##\s+\[([^\]]+)\]/);
|
|
446
|
+
if (match) {
|
|
447
|
+
if (current) sections.push(current);
|
|
448
|
+
current = { version: match[1], bodyLines: [] };
|
|
449
|
+
} else if (current) {
|
|
450
|
+
current.bodyLines.push(line);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (current) sections.push(current);
|
|
454
|
+
|
|
455
|
+
return sections
|
|
456
|
+
.filter((s) => /^\d+\.\d+\.\d+/.test(s.version)) // skip "Unreleased"
|
|
457
|
+
.filter((s) => {
|
|
458
|
+
const newerThanFrom = !fromVersion || isNewer(s.version, fromVersion);
|
|
459
|
+
const notNewerThanTo = !toVersion || !isNewer(s.version, toVersion);
|
|
460
|
+
return newerThanFrom && notNewerThanTo;
|
|
461
|
+
})
|
|
462
|
+
.map((s) => ({ version: s.version, body: s.bodyLines.join("\n").trim() }));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Print a concise summary of what changed between two versions, sourced from the
|
|
466
|
+
// installed package's CHANGELOG.md.
|
|
467
|
+
function printUpdateChangeSummary(packageDir, fromVersion, toVersion) {
|
|
468
|
+
if (!packageDir || !fromVersion || !toVersion) return;
|
|
469
|
+
|
|
470
|
+
if (fromVersion === toVersion) {
|
|
471
|
+
console.log(
|
|
472
|
+
`\n${colors.cyan}Already on the latest version (${toVersion}). No changelog to show.${colors.reset}`
|
|
473
|
+
);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const changelogPath = path.join(packageDir, "CHANGELOG.md");
|
|
478
|
+
const sections = changelogSectionsBetween(changelogPath, fromVersion, toVersion);
|
|
479
|
+
|
|
480
|
+
console.log(
|
|
481
|
+
`\n${colors.cyan}What changed (${fromVersion} → ${toVersion}):${colors.reset}`
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
if (sections.length === 0) {
|
|
485
|
+
console.log(` (No changelog entries found for this range.)`);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
for (const section of sections) {
|
|
490
|
+
console.log(`\n${colors.green}v${section.version}${colors.reset}`);
|
|
491
|
+
const body = section.body || " (No details recorded.)";
|
|
492
|
+
// Indent each line slightly for readability.
|
|
493
|
+
console.log(
|
|
494
|
+
body
|
|
495
|
+
.split("\n")
|
|
496
|
+
.map((l) => (l.length ? ` ${l}` : l))
|
|
497
|
+
.join("\n")
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
401
502
|
function runUpdate(args) {
|
|
402
503
|
const installType = detectInstallType();
|
|
403
504
|
|
|
@@ -410,6 +511,9 @@ function runUpdate(args) {
|
|
|
410
511
|
return;
|
|
411
512
|
}
|
|
412
513
|
|
|
514
|
+
// Capture the version before updating so we can show what changed afterward.
|
|
515
|
+
const versionBefore = currentVersion;
|
|
516
|
+
|
|
413
517
|
console.log(`\n${colors.yellow}Updating npm package...${colors.reset}`);
|
|
414
518
|
|
|
415
519
|
try {
|
|
@@ -428,6 +532,13 @@ function runUpdate(args) {
|
|
|
428
532
|
console.log(`\n${colors.yellow}Reinstalling files with --force...${colors.reset}`);
|
|
429
533
|
args.force = true;
|
|
430
534
|
runInstall(args);
|
|
535
|
+
|
|
536
|
+
// After reinstalling, read the freshly installed version and show the changelog
|
|
537
|
+
// between the old and new versions. The running process still has the old code
|
|
538
|
+
// loaded, so we read version + CHANGELOG from the installed package on disk.
|
|
539
|
+
const packageDir = resolveInstalledPackageDir(installType);
|
|
540
|
+
const versionAfter = packageDir ? readInstalledVersion(packageDir) : null;
|
|
541
|
+
printUpdateChangeSummary(packageDir, versionBefore, versionAfter);
|
|
431
542
|
}
|
|
432
543
|
|
|
433
544
|
function runInstall(args) {
|
package/docs/cli.md
CHANGED
|
@@ -51,7 +51,7 @@ akili install --tool both --local
|
|
|
51
51
|
|---|---|
|
|
52
52
|
| `akili init` | Interactive setup wizard for installation |
|
|
53
53
|
| `akili install` | Install commands, skills, and helper resources |
|
|
54
|
-
| `akili update` |
|
|
54
|
+
| `akili update` | Update the npm package to the latest version, reinstall files, and print a changelog summary of what changed |
|
|
55
55
|
| `akili list` | List packaged commands, skills, and helper resources |
|
|
56
56
|
| `akili doctor` | Check whether expected files are installed |
|
|
57
57
|
| `akili help` | Show help |
|
package/package.json
CHANGED