eklavya 1.25.3 → 1.27.0
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/dist/artifacts.js +214 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/assets/artifact-template.html +144 -0
- package/dist/assets/dashboard.html +119 -2
- package/dist/assets/tutor/SKILL.md +7 -0
- package/dist/cli-memory.js +6 -3
- package/dist/cli-memory.js.map +1 -1
- package/dist/cli.js +185 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.js +10 -2
- package/dist/config.js.map +1 -1
- package/dist/dashboard.js +41 -1
- package/dist/dashboard.js.map +1 -1
- package/dist/hooks/memory-lib.js +1 -1
- package/dist/hooks/memory-lib.js.map +1 -1
- package/dist/hooks/session-start.js +34 -3
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/install-lock.js +155 -0
- package/dist/install-lock.js.map +1 -0
- package/dist/install.js +82 -60
- package/dist/install.js.map +1 -1
- package/dist/memory/reservation.js +15 -5
- package/dist/memory/reservation.js.map +1 -1
- package/dist/memory/worker.js +72 -31
- package/dist/memory/worker.js.map +1 -1
- package/dist/migrations/015_event_link_indexes.sql +24 -0
- package/dist/onboard.js +29 -15
- package/dist/onboard.js.map +1 -1
- package/dist/paths.js +8 -0
- package/dist/paths.js.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/agents/explainer.md +55 -0
- package/dist/plugin/agents/tutor.md +7 -0
- package/dist/plugin/hooks/CLAUDE.md +15 -3
- package/dist/plugin/hooks/run.mjs +104 -21
- package/dist/plugin/skills/CLAUDE.md +7 -0
- package/dist/plugin/skills/tutor/SKILL.md +7 -0
- package/dist/tools/config_tools.js +8 -0
- package/dist/tools/config_tools.js.map +1 -1
- package/dist/tools/record_attempt.js +25 -1
- package/dist/tools/record_attempt.js.map +1 -1
- package/dist/update.js +284 -0
- package/dist/update.js.map +1 -0
- package/dist/user-skill/eklavya/SKILL.md +18 -1
- package/dist/user-skill/eklavya-artifacts/SKILL.md +116 -0
- package/package.json +1 -1
|
@@ -33,12 +33,16 @@
|
|
|
33
33
|
* The same heal keeps rule 3 current. The plugin updates itself through Claude
|
|
34
34
|
* Code (a marketplace pull, `/plugin update`); the runtime only moves when npm
|
|
35
35
|
* runs. So when the runtime is older than the plugin pins, this run still uses
|
|
36
|
-
* it — never blocking — and a background install brings it up to the pin
|
|
37
|
-
|
|
36
|
+
* it — never blocking — and a background install brings it up to the pin,
|
|
37
|
+
* unless the machine opted out with `auto_update: false`. A MISSING runtime is
|
|
38
|
+
* installed whatever that setting says: without it nothing works, and
|
|
39
|
+
* installing the plugin was the request for it.
|
|
40
|
+
*
|
|
38
41
|
* Hard rule: a hook must never break a session. Everything here
|
|
39
42
|
* fails to exit 0 in silence.
|
|
40
43
|
*/
|
|
41
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
44
|
+
import { existsSync, linkSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
45
|
+
import { randomUUID } from 'node:crypto';
|
|
42
46
|
import { homedir } from 'node:os';
|
|
43
47
|
import path from 'node:path';
|
|
44
48
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
@@ -98,11 +102,27 @@ function olderThan(a, b) {
|
|
|
98
102
|
*/
|
|
99
103
|
function healIfBehind(entry) {
|
|
100
104
|
if (!entry.startsWith(path.join(runtimeHome, 'node_modules', 'eklavya') + path.sep)) return;
|
|
105
|
+
if (!autoUpdateEnabled()) return;
|
|
101
106
|
const installed = runtimeVersion();
|
|
102
107
|
const pinned = pinnedVersion();
|
|
103
108
|
if (installed && pinned && olderThan(installed, pinned)) healInBackground();
|
|
104
109
|
}
|
|
105
110
|
|
|
111
|
+
/**
|
|
112
|
+
* `auto_update` from the machine's config file — the global one only, as
|
|
113
|
+
* `autoUpdateEnabled` in the runtime's `update.ts` reads it: a project cannot
|
|
114
|
+
* opt the machine in or out. One small JSON read; anything unreadable is the
|
|
115
|
+
* default, which is on.
|
|
116
|
+
*/
|
|
117
|
+
function autoUpdateEnabled() {
|
|
118
|
+
try {
|
|
119
|
+
const home = process.env.EKLAVYA_HOME ?? path.join(homedir(), '.eklavya');
|
|
120
|
+
return JSON.parse(readFileSync(path.join(home, 'config.json'), 'utf8')).auto_update !== false;
|
|
121
|
+
} catch {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
106
126
|
/** The compiled entry point for `name`, or null if no build is reachable. */
|
|
107
127
|
function resolveEntry() {
|
|
108
128
|
const relative = name === 'server' ? ['dist', 'server.js'] : ['dist', 'hooks', `${name}.js`];
|
|
@@ -141,7 +161,9 @@ function healInBackground() {
|
|
|
141
161
|
} catch {
|
|
142
162
|
return;
|
|
143
163
|
}
|
|
144
|
-
|
|
164
|
+
const stamp = path.join(runtimeHome, '.installing');
|
|
165
|
+
const token = claimHeal(stamp);
|
|
166
|
+
if (!token) return;
|
|
145
167
|
|
|
146
168
|
try {
|
|
147
169
|
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
@@ -155,44 +177,105 @@ function healInBackground() {
|
|
|
155
177
|
// server this run goes on to import.
|
|
156
178
|
child.on('error', () => {});
|
|
157
179
|
child.unref();
|
|
180
|
+
// The claim now belongs to npm, which outlives this process: it is live
|
|
181
|
+
// exactly as long as npm runs. Nobody breaks a claim whose pid is alive,
|
|
182
|
+
// so the stamp is still this run's to rewrite.
|
|
183
|
+
if (child.pid) writeClaim(stamp, { pid: child.pid, token, at: new Date().toISOString() });
|
|
158
184
|
} catch {
|
|
159
185
|
/* A failed heal is a slow install, not a broken session. */
|
|
160
186
|
}
|
|
161
187
|
}
|
|
162
188
|
|
|
163
|
-
|
|
189
|
+
/** Shared with the runtime's `install-lock.ts`, which holds the same rules. */
|
|
190
|
+
const LOCK_TTL_MS = 60 * 60 * 1000;
|
|
191
|
+
const LEGACY_DATE_MS = 10 * 60 * 1000;
|
|
192
|
+
/** How often the heal may start npm, finished or not. */
|
|
193
|
+
const HEAL_EVERY_MS = 60 * 60 * 1000;
|
|
194
|
+
|
|
195
|
+
function ownerOf(text) {
|
|
196
|
+
const body = text.trim();
|
|
197
|
+
if (/^\d+$/.test(body)) return { pid: Number(body), token: null };
|
|
198
|
+
try {
|
|
199
|
+
const value = JSON.parse(body);
|
|
200
|
+
return { pid: typeof value.pid === 'number' ? value.pid : null, token: typeof value.token === 'string' ? value.token : null };
|
|
201
|
+
} catch {
|
|
202
|
+
return { pid: null, token: null };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function pidAlive(pid) {
|
|
207
|
+
try {
|
|
208
|
+
process.kill(pid, 0);
|
|
209
|
+
return true;
|
|
210
|
+
} catch (err) {
|
|
211
|
+
return err.code === 'EPERM';
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Is this stamp somebody's live claim on the runtime? */
|
|
216
|
+
function liveClaim(file, text) {
|
|
217
|
+
const age = Date.now() - statSync(file).mtimeMs;
|
|
218
|
+
if (age >= LOCK_TTL_MS) return false;
|
|
219
|
+
const { pid } = ownerOf(text);
|
|
220
|
+
return pid !== null ? pidAlive(pid) : age < LEGACY_DATE_MS;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Replaces the stamp in one step, so a reader never sees half of it. */
|
|
224
|
+
function writeClaim(stamp, owner) {
|
|
225
|
+
try {
|
|
226
|
+
const tmp = `${stamp}.${process.pid}.tmp`;
|
|
227
|
+
writeFileSync(tmp, JSON.stringify(owner));
|
|
228
|
+
renameSync(tmp, stamp);
|
|
229
|
+
} catch {
|
|
230
|
+
/* It still names this process, which is gone soon: the next claim breaks it. */
|
|
231
|
+
}
|
|
232
|
+
}
|
|
164
233
|
|
|
165
234
|
/**
|
|
166
|
-
* Take the `.installing` stamp
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
235
|
+
* Take the runtime lock — the `.installing` stamp `eklavya install` and the
|
|
236
|
+
* updater take too — and return its token, or null. The session's hooks and
|
|
237
|
+
* its server start within milliseconds of each other, so a stat followed by a
|
|
238
|
+
* write lets several through: creating with `wx` is the one step only one
|
|
239
|
+
* process can win.
|
|
240
|
+
*
|
|
241
|
+
* A stamp is broken only when it is not a live claim — its pid is dead, or it
|
|
242
|
+
* is past the hour — and, for the heal alone, only once it is an hour old: the
|
|
243
|
+
* stamp a finished or failed heal leaves behind is also what keeps a broken
|
|
244
|
+
* npm from being retried on every hook. Breaking is a rename (one winner), and
|
|
245
|
+
* a fresh claim renamed by mistake is put back with `link`, which never
|
|
246
|
+
* overwrites.
|
|
172
247
|
*/
|
|
173
248
|
function claimHeal(stamp) {
|
|
249
|
+
const token = randomUUID();
|
|
174
250
|
const create = () => {
|
|
175
251
|
try {
|
|
176
|
-
writeFileSync(stamp, new Date().toISOString(), { flag: 'wx' });
|
|
177
|
-
return
|
|
252
|
+
writeFileSync(stamp, JSON.stringify({ pid: process.pid, token, at: new Date().toISOString() }), { flag: 'wx' });
|
|
253
|
+
return token;
|
|
178
254
|
} catch {
|
|
179
|
-
return
|
|
255
|
+
return null;
|
|
180
256
|
}
|
|
181
257
|
};
|
|
182
|
-
if (create()) return
|
|
258
|
+
if (create()) return token;
|
|
259
|
+
const taken = `${stamp}.${process.pid}.${token}`;
|
|
183
260
|
try {
|
|
184
|
-
|
|
185
|
-
|
|
261
|
+
const judged = readFileSync(stamp, 'utf8');
|
|
262
|
+
if (liveClaim(stamp, judged) || Date.now() - statSync(stamp).mtimeMs < HEAL_EVERY_MS) return null;
|
|
186
263
|
renameSync(stamp, taken);
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
|
|
264
|
+
if (readFileSync(taken, 'utf8') !== judged) {
|
|
265
|
+
try {
|
|
266
|
+
linkSync(taken, stamp);
|
|
267
|
+
} catch {
|
|
268
|
+
/* someone else holds it now; theirs stands */
|
|
269
|
+
}
|
|
270
|
+
rmSync(taken, { force: true });
|
|
271
|
+
return null;
|
|
190
272
|
}
|
|
191
273
|
rmSync(taken, { force: true });
|
|
192
274
|
} catch {
|
|
193
275
|
// Cannot even read or move the stamp, so we cannot bound the retries.
|
|
194
276
|
// Doing nothing is the safe failure: the explicit installer still works.
|
|
195
|
-
|
|
277
|
+
rmSync(taken, { force: true });
|
|
278
|
+
return null;
|
|
196
279
|
}
|
|
197
280
|
return create();
|
|
198
281
|
}
|
|
@@ -56,6 +56,13 @@ by what it is, not loaded by trigger.
|
|
|
56
56
|
it, and it works where the plugin is not loaded. **Never move it under
|
|
57
57
|
`skills/`**: it would then register twice, once per surface. It drives the
|
|
58
58
|
`eklavya` CLI and the read/write config tools; it does not teach or quiz.
|
|
59
|
+
- **`user-skill/eklavya-artifacts/`** travels the same way (`USER_SKILLS` in
|
|
60
|
+
`install.ts`). It writes a page under `~/.eklavya/artifacts/<project>/`
|
|
61
|
+
through `eklavya artifacts new`, which owns the path, the metadata and the
|
|
62
|
+
template — the skill never writes a page from scratch. Its design rules and
|
|
63
|
+
`agents/explainer.md`'s summary of them describe one thing; change both.
|
|
64
|
+
- **`agents/explainer.md`** is the background page-writer `record_attempt`'s
|
|
65
|
+
`explain` block names. No Eklavya MCP tools at all: it cannot grade or log.
|
|
59
66
|
- **`agents/tutor.md`** is the subagent. It has the Eklavya MCP tools and
|
|
60
67
|
read-only file access — and **no `AskUserQuestion`** — so it renders the four
|
|
61
68
|
options as lettered text. Any change to
|
|
@@ -168,6 +168,13 @@ tool exists to prevent. **Read `references/grading.md` before you grade** — bo
|
|
|
168
168
|
scales, how long feedback may be, the sequence a blank earns, and what
|
|
169
169
|
`already_taught` changes.
|
|
170
170
|
|
|
171
|
+
**A missed answer can come back with `explain`.** That is `explain_on_wrong` at
|
|
172
|
+
work: follow its `instruction` exactly. The page is written in the background
|
|
173
|
+
and opens by itself, so give the verdict, say the page is on its way, and go
|
|
174
|
+
back to the task — no longer explanation, no waiting. When the developer asks
|
|
175
|
+
for something to be explained as a page ("explain this to me", "make me a page
|
|
176
|
+
on this"), start the same background explainer whatever the setting says.
|
|
177
|
+
|
|
171
178
|
## The dials
|
|
172
179
|
|
|
173
180
|
**Mode** is how hard to push, **focus** is what to teach, **cadence** is when to
|
|
@@ -110,6 +110,14 @@ export const setConfig = {
|
|
|
110
110
|
max_new_concepts_per_session: z.number().int().min(0).max(50).optional(),
|
|
111
111
|
max_stop_blocks_per_session: z.number().int().min(0).max(20).optional(),
|
|
112
112
|
quiet: z.boolean().optional(),
|
|
113
|
+
explain_on_wrong: z
|
|
114
|
+
.boolean()
|
|
115
|
+
.optional()
|
|
116
|
+
.describe('Whether a missed question also gets an explainer page, written in the background and opened (default false). Usually set per project.'),
|
|
117
|
+
auto_update: z
|
|
118
|
+
.boolean()
|
|
119
|
+
.optional()
|
|
120
|
+
.describe('Whether Eklavya updates itself in the background at session start (default true). Global scope only.'),
|
|
113
121
|
domains_enabled: z.array(z.string()).optional(),
|
|
114
122
|
// The namespaced half. Passed as objects rather than as dotted keys because
|
|
115
123
|
// the schema is what the model reads: a `memory` object with named fields
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config_tools.js","sourceRoot":"","sources":["../../src/tools/config_tools.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config_tools.js","sourceRoot":"","sources":["../../src/tools/config_tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,10 +6,18 @@ import { resolveSessionId } from '../session.js';
|
|
|
6
6
|
import { conceptBySlug, gradeConcept, hasAskedQuestion, levelStanding, logSessionConcept, promoteIfEarned, syncGate, MAX_MCQ_GRADE, } from '../store.js';
|
|
7
7
|
import { stripAskHeader } from '../ask.js';
|
|
8
8
|
import { CWD_HINT, LIMITS, SESSION_HINT } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* What the tutor does with an `explain` block. Non-blocking is the whole
|
|
11
|
+
* contract: the grade and the one-line verdict are already given, the page is
|
|
12
|
+
* written by a background agent, and the session goes back to the work.
|
|
13
|
+
*/
|
|
14
|
+
export function explainInstruction(name) {
|
|
15
|
+
return `Do not wait for this and do not explain further here. Start the eklavya-explainer agent (eklavya:eklavya-explainer when Eklavya is installed as a plugin) in the background, handing it the concept slug, the question, the learner's answer and the right answer; it writes an explainer page on ${name} and opens it. Tell the learner in one line that the page is on its way, then carry on with the task.`;
|
|
16
|
+
}
|
|
9
17
|
export const recordAttempt = {
|
|
10
18
|
name: 'record_attempt',
|
|
11
19
|
title: 'Record a quiz attempt',
|
|
12
|
-
description: 'Grade one answer on the 0-5 SM-2 scale and persist it. Updates mastery, the next review date, the session gate and this project\'s difficulty level. Record every response, including "I don\'t know" (grade 0, outcome dont_know, after you have taught it) and declines (grade 0, outcome declined). Pass format "mcq" and the options you offered — question takes the stem alone, which is what the repeat check hashes; the options go in options. Multiple choice is capped at grade 4: picking one of four cannot show you know why; omit format only when they typed a real explanation instead of picking. Returns level and level_progress, and level_up on the answer that earns a promotion — say that in one line and move on.',
|
|
20
|
+
description: 'Grade one answer on the 0-5 SM-2 scale and persist it. Updates mastery, the next review date, the session gate and this project\'s difficulty level. Record every response, including "I don\'t know" (grade 0, outcome dont_know, after you have taught it) and declines (grade 0, outcome declined). Pass format "mcq" and the options you offered — question takes the stem alone, which is what the repeat check hashes; the options go in options. Multiple choice is capped at grade 4: picking one of four cannot show you know why; omit format only when they typed a real explanation instead of picking. Returns level and level_progress, and level_up on the answer that earns a promotion — say that in one line and move on. Returns explain on a missed answer when explain_on_wrong is on: follow its instruction.',
|
|
13
21
|
inputSchema: {
|
|
14
22
|
session_id: z.string().max(LIMITS.sessionId).optional().describe(SESSION_HINT),
|
|
15
23
|
cwd: z.string().max(LIMITS.cwd).optional().describe(CWD_HINT),
|
|
@@ -120,6 +128,21 @@ export const recordAttempt = {
|
|
|
120
128
|
})();
|
|
121
129
|
const state = graded.state;
|
|
122
130
|
const gate = graded.gate;
|
|
131
|
+
// A missed answer, when the developer asked for pages on those. Decided
|
|
132
|
+
// here rather than left to a line in the tutor skill: the model follows a
|
|
133
|
+
// field it was handed far more reliably than a rule it has to remember, and
|
|
134
|
+
// the instruction is composed once, where the config is visible. A decline
|
|
135
|
+
// and a bare skip get nothing -- they asked to move on.
|
|
136
|
+
const missed = grade <= 2 && args.outcome !== 'declined' && (grade > 0 || args.outcome === 'dont_know');
|
|
137
|
+
const explain = config.explain_on_wrong && missed
|
|
138
|
+
? {
|
|
139
|
+
concept: concept.slug,
|
|
140
|
+
name: concept.name,
|
|
141
|
+
question,
|
|
142
|
+
answer: args.answer ?? null,
|
|
143
|
+
instruction: explainInstruction(concept.name),
|
|
144
|
+
}
|
|
145
|
+
: null;
|
|
123
146
|
const after = levelStanding(db, config, repoRoot);
|
|
124
147
|
const score = decayedScore(state.score, state.next_review, now);
|
|
125
148
|
return {
|
|
@@ -143,6 +166,7 @@ export const recordAttempt = {
|
|
|
143
166
|
// write would lose a real answer — but the tutor is told, so the next
|
|
144
167
|
// question can be a new one.
|
|
145
168
|
repeat_question: repeatQuestion,
|
|
169
|
+
...(explain ? { explain } : {}),
|
|
146
170
|
...(outcomeConflict
|
|
147
171
|
? {
|
|
148
172
|
outcome_conflict: 'You passed outcome "declined" and also feedback. A decline is dropped without explanation, so if you taught this concept it was a blank: record outcome "dont_know". It matters — a declined concept is never offered again, and in enforced mode that is the only way out of a blocked commit.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record_attempt.js","sourceRoot":"","sources":["../../src/tools/record_attempt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,QAAQ,EACR,aAAa,GAGd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAgB,MAAM,YAAY,CAAC;AAE1E,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,uBAAuB;IAC9B,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"record_attempt.js","sourceRoot":"","sources":["../../src/tools/record_attempt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,QAAQ,EACR,aAAa,GAGd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAgB,MAAM,YAAY,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,qSAAqS,IAAI,uGAAuG,CAAC;AAC1Z,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,uBAAuB;IAC9B,WAAW,EACT,qyBAAqyB;IACvyB,WAAW,EAAE;QACX,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC9E,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAC/E,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;aACpB,QAAQ,CACP,sPAAsP,CACvP;QACH,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;aAClB,QAAQ,EAAE;aACV,QAAQ,CACP,mIAAmI,CACpI;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,kGAAkG,CAAC;QAC/G,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,iEAAiE,CAAC;QACtH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACrG,MAAM,EAAE,CAAC;aACN,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,EAAE;aACV,QAAQ,CACP,oUAAoU,CACrU;QACH,OAAO,EAAE,CAAC;aACP,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;aACpC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;aACnB,QAAQ,EAAE;aACV,QAAQ,CAAC,2EAA2E,CAAC;QACxF,OAAO,EAAE,CAAC;aACP,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;aAC3C,QAAQ,EAAE;aACV,QAAQ,CACP,meAAme,CACpe;KACJ;IACD,OAAO,EAAE,CACP,IAYC,EACD,EAAE,EAAE,EAAE,EACN,EAAE;QACF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAElE,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,KAAK,EAAE,iBAAiB;gBACxB,IAAI;gBACJ,MAAM,EAAE,gFAAgF;aACzF,CAAC;QACJ,CAAC;QAED,gFAAgF;QAChF,6EAA6E;QAC7E,kDAAkD;QAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE/C,6EAA6E;QAC7E,oDAAoD;QACpD,MAAM,QAAQ,GAAG,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAErD,6EAA6E;QAC7E,MAAM,cAAc,GAAG,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAElE,2EAA2E;QAC3E,6EAA6E;QAC7E,4EAA4E;QAC5E,oCAAoC;QACpC,4EAA4E;QAC5E,0EAA0E;QAC1E,2EAA2E;QAC3E,0EAA0E;QAC1E,2EAA2E;QAC3E,0DAA0D;QAC1D,MAAM,eAAe,GACnB,IAAI,CAAC,OAAO,KAAK,UAAU,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAEtG,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC;QACnE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QAElD,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YACjC,uEAAuE;YACvE,wEAAwE;YACxE,2EAA2E;YAC3E,uEAAuE;YACvE,kCAAkC;YAClC,iBAAiB,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC7D,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,EAAE;gBAC5B,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,SAAS;gBACT,QAAQ;gBACR,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;gBAC3B,KAAK;gBACL,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;gBAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;gBAC3B,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;gBAC7B,uEAAuE;gBACvE,uEAAuE;gBACvE,wEAAwE;gBACxE,kDAAkD;gBAClD,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;gBAC7B,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,GAAG;aACJ,CAAC,CAAC;YAEH,oEAAoE;YACpE,yEAAyE;YACzE,iCAAiC;YACjC,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YAExD,0EAA0E;YAC1E,yEAAyE;YACzE,uEAAuE;YACvE,uEAAuE;YACvE,6CAA6C;YAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACjE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC1C,CAAC,CAAC,EAAE,CAAC;QAEL,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QAEzB,wEAAwE;QACxE,0EAA0E;QAC1E,4EAA4E;QAC5E,2EAA2E;QAC3E,wDAAwD;QACxD,MAAM,MAAM,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,KAAK,UAAU,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC;QACxG,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,IAAI,MAAM;YAC/C,CAAC,CAAC;gBACE,OAAO,EAAE,OAAO,CAAC,IAAI;gBACrB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ;gBACR,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;gBAC3B,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC;aAC9C;YACH,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,KAAK,GAAG,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAEhE,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,cAAc,EAAE,KAAK;YACrB,qEAAqE;YACrE,mBAAmB;YACnB,GAAG,CAAC,MAAM;gBACR,CAAC,CAAC;oBACE,YAAY,EAAE,IAAI;oBAClB,MAAM,EAAE,gCAAgC,aAAa,6EAA6E,KAAK,eAAe,IAAI,CAAC,KAAK,GAAG;iBACpK;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACzC,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,aAAa,EAAE,KAAK,CAAC,UAAU;YAC/B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACnC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAC3C,oEAAoE;YACpE,sEAAsE;YACtE,6BAA6B;YAC7B,eAAe,EAAE,cAAc;YAC/B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,eAAe;gBACjB,CAAC,CAAC;oBACE,gBAAgB,EACd,iSAAiS;iBACpS;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,IAAI;YACJ,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,0EAA0E;YAC1E,4DAA4D;YAC5D,cAAc,EAAE;gBACd,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;gBAC3B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;gBAC5B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBACnC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBAC/B,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBACtC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1D;YACD,GAAG,CAAC,MAAM,CAAC,SAAS;gBAClB,CAAC,CAAC;oBACE,QAAQ,EAAE;wBACR,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI;wBAC3B,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE;wBACvB,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM;wBACtC,QAAQ,EAAE,MAAM,CACd,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAC5F;wBACD,MAAM,EAAE,mEAAmE,MAAM,CAAC,SAAS,CAAC,IAAI,qDAAqD,MAAM,CAAC,SAAS,CAAC,EAAE,QAAQ;qBACjL;iBACF;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;CACF,CAAC"}
|
package/dist/update.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The auto-updater: Eklavya keeps itself current the way Claude Code does —
|
|
3
|
+
* a background check at session start, an install nobody waits on, one line
|
|
4
|
+
* when it worked, and one line naming the fix when it did not.
|
|
5
|
+
*
|
|
6
|
+
* What moves, and how:
|
|
7
|
+
*
|
|
8
|
+
* - The runtime (`~/.eklavya/runtime`) is the only thing npm installs. It is
|
|
9
|
+
* under the user's home, so an update never needs sudo — which is why the
|
|
10
|
+
* global `eklavya` command is not updated at all: `cli.ts` hands off to the
|
|
11
|
+
* runtime whenever the runtime is newer, so a stale global binary runs new
|
|
12
|
+
* code without anyone touching npm.
|
|
13
|
+
* - Everything else `eklavya install` sets up — the plugin files, the chat
|
|
14
|
+
* skill, the registration, the status line — is refreshed by running the
|
|
15
|
+
* NEW runtime's own `install --auto`. One code path for a manual install and
|
|
16
|
+
* an automatic one, so an update can never do less than an install would.
|
|
17
|
+
* `--auto` never asks a question and never changes a setting.
|
|
18
|
+
*
|
|
19
|
+
* `update.json` beside the database is the whole state: when it last checked,
|
|
20
|
+
* which version `install` last finished for, and the last failure. The
|
|
21
|
+
* SessionStart hook reads it to decide whether to start a run and what to say;
|
|
22
|
+
* `eklavya doctor` reads it to report.
|
|
23
|
+
*
|
|
24
|
+
* Deliberately light on imports: the SessionStart hook loads this module on
|
|
25
|
+
* every session, and only `runUpdate` (in its own background process) spawns
|
|
26
|
+
* anything slow.
|
|
27
|
+
*/
|
|
28
|
+
import fs from 'node:fs';
|
|
29
|
+
import path from 'node:path';
|
|
30
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
31
|
+
import { eklavyaHome } from './paths.js';
|
|
32
|
+
import { loadGlobalConfig } from './config.js';
|
|
33
|
+
import { claimInstall, releaseInstall } from './install-lock.js';
|
|
34
|
+
/** How often the background check runs, at most. Every session would ask npm otherwise. */
|
|
35
|
+
export const CHECK_EVERY_MS = 60 * 60 * 1000;
|
|
36
|
+
/** Offline is not a failure worth a line — until it has lasted this long. */
|
|
37
|
+
export const OFFLINE_GRACE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
38
|
+
export function statePath() {
|
|
39
|
+
return path.join(eklavyaHome(), 'update.json');
|
|
40
|
+
}
|
|
41
|
+
export function logPath() {
|
|
42
|
+
return path.join(eklavyaHome(), 'update.log');
|
|
43
|
+
}
|
|
44
|
+
/** The runtime this updater owns. Never an `EKLAVYA_RUNTIME` build: that one is pinned on purpose. */
|
|
45
|
+
function runtimeDir() {
|
|
46
|
+
return path.join(eklavyaHome(), 'runtime');
|
|
47
|
+
}
|
|
48
|
+
export function runtimeCli() {
|
|
49
|
+
return path.join(runtimeDir(), 'node_modules', 'eklavya', 'dist', 'cli.js');
|
|
50
|
+
}
|
|
51
|
+
export function runtimeVersion() {
|
|
52
|
+
try {
|
|
53
|
+
const pkg = path.join(runtimeDir(), 'node_modules', 'eklavya', 'package.json');
|
|
54
|
+
return JSON.parse(fs.readFileSync(pkg, 'utf8')).version ?? null;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function readState() {
|
|
61
|
+
try {
|
|
62
|
+
const value = JSON.parse(fs.readFileSync(statePath(), 'utf8'));
|
|
63
|
+
return value && typeof value === 'object' ? value : {};
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Merges `patch` in. Never throws: losing a state write costs one extra check, not a session. */
|
|
70
|
+
export function writeState(patch) {
|
|
71
|
+
try {
|
|
72
|
+
fs.mkdirSync(eklavyaHome(), { recursive: true });
|
|
73
|
+
const tmp = `${statePath()}.${process.pid}.tmp`;
|
|
74
|
+
fs.writeFileSync(tmp, `${JSON.stringify({ ...readState(), ...patch }, null, 2)}\n`);
|
|
75
|
+
fs.renameSync(tmp, statePath());
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
/* see above */
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** `auto_update`, from the global file only: a project cannot opt the machine out. */
|
|
82
|
+
export function autoUpdateEnabled() {
|
|
83
|
+
return loadGlobalConfig().auto_update;
|
|
84
|
+
}
|
|
85
|
+
/** -1, 0 or 1 over the numeric parts of two versions; a prerelease tag is ignored. */
|
|
86
|
+
export function compareVersions(a, b) {
|
|
87
|
+
const parts = (v) => v.split('-')[0].split('.').map((n) => Number(n) || 0);
|
|
88
|
+
const [x, y] = [parts(a), parts(b)];
|
|
89
|
+
for (let i = 0; i < Math.max(x.length, y.length); i++) {
|
|
90
|
+
const d = (x[i] ?? 0) - (y[i] ?? 0);
|
|
91
|
+
if (d !== 0)
|
|
92
|
+
return Math.sign(d);
|
|
93
|
+
}
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Should a session start a background run? Only for an installed runtime (a
|
|
98
|
+
* missing one is `run.mjs`'s heal), never under `EKLAVYA_RUNTIME`, and only
|
|
99
|
+
* when the last check is an hour old — or when the runtime moved without
|
|
100
|
+
* `install` following it, which is what the pinned heal in `run.mjs` does.
|
|
101
|
+
*/
|
|
102
|
+
export function updateDue(now = Date.now()) {
|
|
103
|
+
if (process.env.EKLAVYA_RUNTIME || !autoUpdateEnabled())
|
|
104
|
+
return false;
|
|
105
|
+
const installed = runtimeVersion();
|
|
106
|
+
if (!installed)
|
|
107
|
+
return false;
|
|
108
|
+
const state = readState();
|
|
109
|
+
const recent = now - (state.checked_at ? Date.parse(state.checked_at) : NaN) < CHECK_EVERY_MS;
|
|
110
|
+
// A failure waits out the hour too: a broken npm retried every session is
|
|
111
|
+
// a spawn per session for nothing.
|
|
112
|
+
return !recent || (state.applied !== installed && !state.error);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Starts `eklavya update --background` from the runtime, detached, when one is
|
|
116
|
+
* due. Returns at once; every failure is swallowed — the caller is a hook.
|
|
117
|
+
*/
|
|
118
|
+
export function startBackgroundUpdate() {
|
|
119
|
+
try {
|
|
120
|
+
if (!updateDue())
|
|
121
|
+
return;
|
|
122
|
+
fs.mkdirSync(eklavyaHome(), { recursive: true });
|
|
123
|
+
// stdio ignored: the run writes its own log, and only once it holds the
|
|
124
|
+
// claim, so a run that finds another in progress cannot wipe that log.
|
|
125
|
+
const child = spawn(process.execPath, [runtimeCli(), 'update', '--background'], {
|
|
126
|
+
detached: true,
|
|
127
|
+
stdio: 'ignore',
|
|
128
|
+
windowsHide: true,
|
|
129
|
+
});
|
|
130
|
+
// An async spawn failure lands here, after this hook has moved on. Without
|
|
131
|
+
// a listener it is an uncaught error and the hook exits 1.
|
|
132
|
+
child.on('error', () => { });
|
|
133
|
+
child.unref();
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
/* an update that cannot start is retried next session */
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The one line a session shows about updates, or null. "Updated" once per
|
|
141
|
+
* version; a failure every session until it clears, like Claude Code's own —
|
|
142
|
+
* except being offline, which says nothing until it has lasted a week.
|
|
143
|
+
*
|
|
144
|
+
* `announces` is set on the "updated" line: the caller passes it to
|
|
145
|
+
* `markAnnounced` once the line has actually gone out, so a session that
|
|
146
|
+
* returns early does not swallow it.
|
|
147
|
+
*/
|
|
148
|
+
export function updateNotice(now = Date.now()) {
|
|
149
|
+
const state = readState();
|
|
150
|
+
if (state.error) {
|
|
151
|
+
const lastOk = state.ok_at ? Date.parse(state.ok_at) : NaN;
|
|
152
|
+
const longOffline = !(now - lastOk < OFFLINE_GRACE_MS);
|
|
153
|
+
if (state.error_class !== 'network' || longOffline) {
|
|
154
|
+
return { text: `Eklavya can't update itself · ${state.error} · run: eklavya update` };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const version = state.applied;
|
|
158
|
+
if (version && version !== state.announced && version === runtimeVersion()) {
|
|
159
|
+
return { text: `Eklavya updated to ${version}`, announces: version };
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
export function markAnnounced(version) {
|
|
164
|
+
writeState({ announced: version });
|
|
165
|
+
}
|
|
166
|
+
// --- the run ----------------------------------------------------------------
|
|
167
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
168
|
+
function run(cmd, args, timeout) {
|
|
169
|
+
return spawnSync(cmd, args, {
|
|
170
|
+
encoding: 'utf8',
|
|
171
|
+
timeout,
|
|
172
|
+
shell: process.platform === 'win32',
|
|
173
|
+
windowsHide: true,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The line of a failed command that says why: a Node `…Error:` line, else an
|
|
178
|
+
* npm error code (`EACCES`, `ENOTFOUND`), else the last line that is not Node's
|
|
179
|
+
* `Node.js v…` trailer.
|
|
180
|
+
*/
|
|
181
|
+
function lastLine(text) {
|
|
182
|
+
const lines = (text ?? '').split('\n').map((l) => l.replace(/^npm (ERR!|error)\s*/, '').trim()).filter(Boolean);
|
|
183
|
+
const why = lines.find((l) => /^[A-Za-z]*Error:/.test(l)) ??
|
|
184
|
+
lines.find((l) => /\bE[A-Z]{3,}\b/.test(l)) ??
|
|
185
|
+
lines.filter((l) => !/^Node\.js v/.test(l)).at(-1);
|
|
186
|
+
return (why ?? 'unknown error').slice(0, 160);
|
|
187
|
+
}
|
|
188
|
+
const NETWORK = /ENOTFOUND|EAI_AGAIN|ETIMEDOUT|ECONNREFUSED|ECONNRESET|ENETUNREACH|network|socket hang up/i;
|
|
189
|
+
class UpdateError extends Error {
|
|
190
|
+
cls;
|
|
191
|
+
constructor(message, cls) {
|
|
192
|
+
super(message);
|
|
193
|
+
this.cls = cls;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* One update run: ask npm for the latest version, install it into the runtime
|
|
198
|
+
* if it is newer, then let the runtime's own `install --auto` refresh
|
|
199
|
+
* everything else. `say` is where progress goes — nowhere in the background.
|
|
200
|
+
*/
|
|
201
|
+
export async function runUpdate(opts) {
|
|
202
|
+
if (opts.background && !updateDue())
|
|
203
|
+
return { status: 'skipped' };
|
|
204
|
+
// The runtime lock `installRuntime` and the launcher's heal take too
|
|
205
|
+
// (`install-lock.ts`). The new runtime's `install --auto` below skips the
|
|
206
|
+
// runtime step, so it never asks for the lock this run is holding.
|
|
207
|
+
const claim = claimInstall(runtimeDir());
|
|
208
|
+
if (!claim)
|
|
209
|
+
return { status: 'busy' };
|
|
210
|
+
// The background run's log is this run's alone: truncated here, after the claim.
|
|
211
|
+
const log = (text) => {
|
|
212
|
+
if (!opts.background)
|
|
213
|
+
return;
|
|
214
|
+
try {
|
|
215
|
+
fs.appendFileSync(logPath(), text);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
/* a log is a courtesy */
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
if (opts.background) {
|
|
222
|
+
try {
|
|
223
|
+
fs.writeFileSync(logPath(), `${new Date().toISOString()} eklavya update\n`);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
/* see above */
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const say = (line) => {
|
|
230
|
+
log(`${line}\n`);
|
|
231
|
+
opts.say?.(line);
|
|
232
|
+
};
|
|
233
|
+
const now = new Date().toISOString();
|
|
234
|
+
const from = runtimeVersion();
|
|
235
|
+
try {
|
|
236
|
+
const view = run(npm, ['view', 'eklavya@latest', 'version'], 60_000);
|
|
237
|
+
if (view.error || view.status !== 0) {
|
|
238
|
+
const why = view.error?.message ?? lastLine(view.stderr);
|
|
239
|
+
throw new UpdateError(view.error?.code === 'ENOENT' ? 'npm not found on PATH' : `npm view failed: ${why}`, NETWORK.test(why) ? 'network' : 'npm');
|
|
240
|
+
}
|
|
241
|
+
const latest = view.stdout.trim();
|
|
242
|
+
// Anything else is npm talking (a warning on stdout, an .npmrc notice), and
|
|
243
|
+
// installing `eklavya@<that>` would fail in a way that names the wrong thing.
|
|
244
|
+
if (!/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(latest)) {
|
|
245
|
+
throw new UpdateError(`npm view returned no version: ${lastLine(latest || view.stderr)}`, 'npm');
|
|
246
|
+
}
|
|
247
|
+
say(`latest ${latest}, runtime ${from ?? 'not installed'}`);
|
|
248
|
+
if (!from || compareVersions(latest, from) > 0) {
|
|
249
|
+
say(`installing eklavya@${latest}…`);
|
|
250
|
+
const install = run(npm, ['install', `eklavya@${latest}`, '--prefix', runtimeDir(), '--omit=dev', '--no-audit', '--no-fund', '--loglevel=error'], 10 * 60_000);
|
|
251
|
+
if (install.error || install.status !== 0) {
|
|
252
|
+
const why = install.error?.message ?? lastLine(install.stderr);
|
|
253
|
+
throw new UpdateError(`npm install failed: ${why}`, NETWORK.test(why) ? 'network' : 'npm');
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const version = runtimeVersion();
|
|
257
|
+
if (!version)
|
|
258
|
+
throw new UpdateError('the runtime is missing after npm install', 'npm');
|
|
259
|
+
// The new runtime's install, so the plugin files, skill and registration
|
|
260
|
+
// match the code that will run them. Skipped when it already finished for
|
|
261
|
+
// this version: an hourly re-registration would rewrite Claude Code's files
|
|
262
|
+
// for nothing.
|
|
263
|
+
if (readState().applied !== version) {
|
|
264
|
+
say(`refreshing the plugin, skill and registration for ${version}…`);
|
|
265
|
+
const refresh = run(process.execPath, [runtimeCli(), 'install', '--auto'], 5 * 60_000);
|
|
266
|
+
log(`${refresh.stdout ?? ''}${refresh.stderr ?? ''}`);
|
|
267
|
+
if (refresh.error || refresh.status !== 0) {
|
|
268
|
+
throw new UpdateError(`eklavya install failed: ${lastLine(refresh.stderr || refresh.stdout)}`, 'install');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
writeState({ checked_at: now, ok_at: now, latest, applied: version, error: null, error_class: null });
|
|
272
|
+
return from === version ? { status: 'current', version } : { status: 'updated', from, to: version };
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
276
|
+
log(`failed: ${error}\n`);
|
|
277
|
+
writeState({ checked_at: now, error, error_class: err instanceof UpdateError ? err.cls : 'install' });
|
|
278
|
+
return { status: 'failed', error };
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
releaseInstall(claim);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=update.js.map
|