@novare-technologies/nvaid 0.2.0 → 0.2.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/README.md +21 -0
- package/dist/cli.js +83 -4
- package/package.json +1 -1
- package/templates/nvaid/config.yml +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,27 @@ nvaid init --owning-repo frontend # preset the config's owning_repo
|
|
|
31
31
|
nvaid init --yes # non-interactive (defaults to the AGENTS.md catch-all)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Upgrading
|
|
35
|
+
|
|
36
|
+
Upgrading is **two steps**, because `nvaid update` re-syncs a repo to the version of the
|
|
37
|
+
tool installed on your machine — it does not upgrade the tool itself:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 1. upgrade the tool (once per machine, when a new version ships)
|
|
41
|
+
npm i -g @novare-technologies/nvaid@latest
|
|
42
|
+
|
|
43
|
+
# 2. re-sync each repo to the new version (run inside each repo)
|
|
44
|
+
nvaid update
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
nvaid checks npm (at most once a day, cached, non-blocking) and prints a one-line nudge
|
|
48
|
+
when a newer version is available — it never upgrades itself (the package manager owns the
|
|
49
|
+
tool's lifecycle). Silence the check with `NVAID_NO_UPDATE_CHECK=1`.
|
|
50
|
+
|
|
51
|
+
Note: `nvaid update` never touches hand-owned files (`config.yml`, `PROJECT-RULES.md`,
|
|
52
|
+
`DESIGN-CODE-DICTIONARY.md`, `intents/`). If a new version adds a config field, add it to
|
|
53
|
+
your `config.yml` by hand — the changelog will call these out.
|
|
54
|
+
|
|
34
55
|
## How it works
|
|
35
56
|
|
|
36
57
|
- **Full skill set, no profiles.** `init` injects every skill into each selected agent. A
|
package/dist/cli.js
CHANGED
|
@@ -109,8 +109,8 @@ var NVAID_DIR_NAME = "nvaid";
|
|
|
109
109
|
var CONFIG_FILE = "config.yml";
|
|
110
110
|
var AIDLC_ROOT_TOKEN = "{{AIDLC_ROOT}}";
|
|
111
111
|
async function nvaidVersion() {
|
|
112
|
-
const { readFile:
|
|
113
|
-
const pkg = JSON.parse(await
|
|
112
|
+
const { readFile: readFile4 } = await import("fs/promises");
|
|
113
|
+
const pkg = JSON.parse(await readFile4(resolve(TEMPLATES_DIR, "..", "package.json"), "utf8"));
|
|
114
114
|
return pkg.version;
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -460,6 +460,81 @@ async function runValidate() {
|
|
|
460
460
|
return 0;
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
+
// src/updateNotifier.ts
|
|
464
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
465
|
+
import { homedir, tmpdir } from "os";
|
|
466
|
+
import { join as join4 } from "path";
|
|
467
|
+
import pc4 from "picocolors";
|
|
468
|
+
var PKG = "@novare-technologies/nvaid";
|
|
469
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
470
|
+
var FETCH_TIMEOUT_MS = 1500;
|
|
471
|
+
function cacheFile() {
|
|
472
|
+
const base = process.env.XDG_CACHE_HOME || join4(homedir(), ".cache");
|
|
473
|
+
return join4(base || tmpdir(), "nvaid", "update-check.json");
|
|
474
|
+
}
|
|
475
|
+
async function readCache() {
|
|
476
|
+
try {
|
|
477
|
+
return JSON.parse(await readFile3(cacheFile(), "utf8"));
|
|
478
|
+
} catch {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async function writeCache(c) {
|
|
483
|
+
try {
|
|
484
|
+
const f = cacheFile();
|
|
485
|
+
await mkdir3(join4(f, ".."), { recursive: true });
|
|
486
|
+
await writeFile3(f, JSON.stringify(c), "utf8");
|
|
487
|
+
} catch {
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
async function fetchLatest() {
|
|
491
|
+
try {
|
|
492
|
+
const ctrl = new AbortController();
|
|
493
|
+
const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
|
|
494
|
+
const res = await fetch(`https://registry.npmjs.org/${PKG}/latest`, {
|
|
495
|
+
signal: ctrl.signal
|
|
496
|
+
});
|
|
497
|
+
clearTimeout(timer);
|
|
498
|
+
if (!res.ok) return null;
|
|
499
|
+
const data = await res.json();
|
|
500
|
+
return data.version ?? null;
|
|
501
|
+
} catch {
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function isNewer(a, b) {
|
|
506
|
+
const pa = a.split(".").map((n) => parseInt(n, 10));
|
|
507
|
+
const pb = b.split(".").map((n) => parseInt(n, 10));
|
|
508
|
+
for (let i = 0; i < 3; i++) {
|
|
509
|
+
const x = pa[i] ?? 0;
|
|
510
|
+
const y = pb[i] ?? 0;
|
|
511
|
+
if (x > y) return true;
|
|
512
|
+
if (x < y) return false;
|
|
513
|
+
}
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
async function notifyIfOutdated() {
|
|
517
|
+
if (process.env.NVAID_NO_UPDATE_CHECK) return;
|
|
518
|
+
const current = await nvaidVersion();
|
|
519
|
+
const cache = await readCache();
|
|
520
|
+
const now = Date.now();
|
|
521
|
+
let latest = null;
|
|
522
|
+
if (cache && now - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
523
|
+
latest = cache.latest;
|
|
524
|
+
} else {
|
|
525
|
+
latest = await fetchLatest();
|
|
526
|
+
if (latest) await writeCache({ lastCheck: now, latest });
|
|
527
|
+
}
|
|
528
|
+
if (!latest || !isNewer(latest, current)) return;
|
|
529
|
+
const line = (s) => process.stderr.write(s + "\n");
|
|
530
|
+
line("");
|
|
531
|
+
line(pc4.yellow(` \u250C\u2500 nvaid update available \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
532
|
+
line(pc4.yellow(" \u2502 ") + `${pc4.dim(current)} \u2192 ${pc4.green(latest)}`);
|
|
533
|
+
line(pc4.yellow(" \u2502 ") + `run: ${pc4.cyan(`npm i -g ${PKG}@latest`)}`);
|
|
534
|
+
line(pc4.yellow(" \u2502 ") + pc4.dim(`then re-sync your repo: nvaid update`));
|
|
535
|
+
line(pc4.yellow(` \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
536
|
+
}
|
|
537
|
+
|
|
463
538
|
// src/cli.ts
|
|
464
539
|
var program = new Command();
|
|
465
540
|
program.name("nvaid").description("nvaid \u2014 install an AI-DLC skills + workflow toolkit into any coding agent").version(await nvaidVersion());
|
|
@@ -475,9 +550,13 @@ program.command("update").description("Re-sync agent files to the installed nvai
|
|
|
475
550
|
await runUpdate();
|
|
476
551
|
});
|
|
477
552
|
program.command("validate").description("Fail if generated agent files are stale or hand-edited").action(async () => {
|
|
478
|
-
|
|
553
|
+
const code = await runValidate();
|
|
554
|
+
await notifyIfOutdated();
|
|
555
|
+
process.exit(code);
|
|
479
556
|
});
|
|
480
|
-
program.parseAsync().
|
|
557
|
+
program.parseAsync().then(async () => {
|
|
558
|
+
await notifyIfOutdated();
|
|
559
|
+
}).catch((err) => {
|
|
481
560
|
console.error(err instanceof Error ? err.message : err);
|
|
482
561
|
process.exit(1);
|
|
483
562
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novare-technologies/nvaid",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "nvaid — one CLI that installs an AI-DLC skills-and-workflow toolkit into any coding agent, and houses intents, config, and the design-code dictionary in a single nvaid/ folder.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|