karajan-code 4.6.0 → 4.6.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/package.json
CHANGED
|
@@ -81,6 +81,8 @@ architect, tester, security, audit, board) · \`kj hu add|move|list\` ·
|
|
|
81
81
|
|
|
82
82
|
Hit a kj bug or friction? Diagnose it and file it upstream with
|
|
83
83
|
\`kj report-issue\` (sanitized; ask your user before \`--publish\`).
|
|
84
|
+
kj announces a newer version? Tell your user what it brings and ask —
|
|
85
|
+
never run \`kj update\` on your own.
|
|
84
86
|
`;
|
|
85
87
|
|
|
86
88
|
export function renderPlaybook({ stateBackend = "hu-board", boardName = null } = {}) {
|
|
@@ -5,8 +5,38 @@ import { isSea } from "node:sea";
|
|
|
5
5
|
import { getKarajanHome } from "./paths.js";
|
|
6
6
|
|
|
7
7
|
const CACHE_FILE = "update-check.json";
|
|
8
|
-
|
|
8
|
+
// KJC-TSK-0690: 6h — kj can ship several releases a day; a session should
|
|
9
|
+
// not work a full day blind. KJ_NO_UPDATE_CHECK=1 opts out (CI).
|
|
10
|
+
const CACHE_TTL_MS = 6 * 60 * 60 * 1000;
|
|
9
11
|
const PACKAGE_NAME = "karajan-code";
|
|
12
|
+
const CHANGELOG_URL = "https://raw.githubusercontent.com/manufosela/karajan-code/main/CHANGELOG.md";
|
|
13
|
+
const HIGHLIGHT_MAX = 160;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* First paragraph of a version's CHANGELOG section — the release headline
|
|
17
|
+
* ("Minor. **The method, enforced.** …"), bold stripped, truncated. Pure.
|
|
18
|
+
*/
|
|
19
|
+
export function parseChangelogHighlight(markdown, version) {
|
|
20
|
+
const section = String(markdown).split(new RegExp(`^## \\[${version.replaceAll(".", "\\.")}\\][^\\n]*$`, "m"))[1];
|
|
21
|
+
if (!section) return null;
|
|
22
|
+
const firstLine = section.split(/^##|^###/m)[0].split("\n").map((l) => l.trim()).find(Boolean);
|
|
23
|
+
if (!firstLine) return null;
|
|
24
|
+
const clean = firstLine.replaceAll("**", "");
|
|
25
|
+
return clean.length > HIGHLIGHT_MAX ? `${clean.slice(0, HIGHLIGHT_MAX - 1)}…` : clean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function fetchHighlight(version) {
|
|
29
|
+
try {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
32
|
+
const res = await fetch(CHANGELOG_URL, { signal: controller.signal });
|
|
33
|
+
clearTimeout(timeout);
|
|
34
|
+
if (!res.ok) return null;
|
|
35
|
+
return parseChangelogHighlight(await res.text(), version);
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
10
40
|
|
|
11
41
|
const RAW_BASE = "https://raw.githubusercontent.com/manufosela/karajan-code/main/scripts";
|
|
12
42
|
export const INSTALL_SH_URL = `${RAW_BASE}/install-binary.sh`;
|
|
@@ -48,6 +78,7 @@ export function detectInstallChannel() {
|
|
|
48
78
|
* Returns { updateAvailable, latest, current } or null if check fails/cached.
|
|
49
79
|
*/
|
|
50
80
|
export async function checkForUpdate(currentVersion) {
|
|
81
|
+
if (process.env.KJ_NO_UPDATE_CHECK === "1") return null;
|
|
51
82
|
try {
|
|
52
83
|
const cachePath = path.join(getKarajanHome(), CACHE_FILE);
|
|
53
84
|
|
|
@@ -59,7 +90,7 @@ export async function checkForUpdate(currentVersion) {
|
|
|
59
90
|
if (!cache.latest || cache.latest === currentVersion) return null;
|
|
60
91
|
// Only show update if latest is actually NEWER than current
|
|
61
92
|
if (compareVersions(cache.latest, currentVersion) > 0) {
|
|
62
|
-
return { updateAvailable: true, latest: cache.latest, current: currentVersion };
|
|
93
|
+
return { updateAvailable: true, latest: cache.latest, current: currentVersion, highlight: cache.highlight || null };
|
|
63
94
|
}
|
|
64
95
|
return null;
|
|
65
96
|
}
|
|
@@ -78,14 +109,16 @@ export async function checkForUpdate(currentVersion) {
|
|
|
78
109
|
const data = await res.json();
|
|
79
110
|
const latest = data.version;
|
|
80
111
|
|
|
112
|
+
// KJC-TSK-0690: a NEWER version also fetches its headline once — the
|
|
113
|
+
// notice tells the user what it brings, not just that it exists.
|
|
114
|
+
const newer = latest !== currentVersion && compareVersions(latest, currentVersion) > 0;
|
|
115
|
+
const highlight = newer ? await fetchHighlight(latest) : null;
|
|
116
|
+
|
|
81
117
|
// Save cache
|
|
82
118
|
await fs.mkdir(getKarajanHome(), { recursive: true });
|
|
83
|
-
await fs.writeFile(cachePath, JSON.stringify({ latest, checkedAt: Date.now() }), "utf8");
|
|
119
|
+
await fs.writeFile(cachePath, JSON.stringify({ latest, checkedAt: Date.now(), highlight }), "utf8");
|
|
84
120
|
|
|
85
|
-
if (latest
|
|
86
|
-
if (compareVersions(latest, currentVersion) > 0) {
|
|
87
|
-
return { updateAvailable: true, latest, current: currentVersion };
|
|
88
|
-
}
|
|
121
|
+
if (newer) return { updateAvailable: true, latest, current: currentVersion, highlight };
|
|
89
122
|
return null;
|
|
90
123
|
} catch {
|
|
91
124
|
return null; // Network error, offline, etc. Never block.
|
|
@@ -100,7 +133,9 @@ export async function printUpdateNotice(currentVersion) {
|
|
|
100
133
|
if (result?.updateAvailable) {
|
|
101
134
|
const channel = detectInstallChannel();
|
|
102
135
|
console.log(`\n Update available: v${result.current} → v${result.latest}`);
|
|
103
|
-
console.log(` ${
|
|
136
|
+
if (result.highlight) console.log(` What it brings: ${result.highlight}`);
|
|
137
|
+
console.log(` ${updateInstruction({ channel })}`);
|
|
138
|
+
console.log(" Agent: tell your user and ask before updating — never update on your own.\n");
|
|
104
139
|
}
|
|
105
140
|
}
|
|
106
141
|
|