@a13xu/lucid 1.12.0 → 1.13.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/build/index.js +26 -2
- package/build/tools/init.js +46 -10
- package/build/tools/updater.d.ts +11 -0
- package/build/tools/updater.js +133 -0
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { handleGetContext, GetContextSchema, handleGetRecent, GetRecentSchema, }
|
|
|
21
21
|
import { handleReward, RewardSchema, handlePenalize, PenalizeSchema, handleShowRewards, ShowRewardsSchema, } from "./tools/reward.js";
|
|
22
22
|
import { handleGetCodingRules, handleCheckCodeQuality, CheckCodeQualitySchema, } from "./tools/coding-guard.js";
|
|
23
23
|
import { handlePlanCreate, PlanCreateSchema, handlePlanList, PlanListSchema, handlePlanGet, PlanGetSchema, handlePlanUpdateTask, PlanUpdateTaskSchema, } from "./tools/plan.js";
|
|
24
|
+
import { UpdateLucidSchema, handleUpdateLucid, checkForUpdatesOnStartup, getCurrentVersion, } from "./tools/updater.js";
|
|
24
25
|
import { GenerateComponentSchema, handleGenerateComponent, ScaffoldPageSchema, handleScaffoldPage, SeoMetaSchema, handleSeoMeta, AccessibilityAuditSchema, handleAccessibilityAudit, ApiClientSchema, handleApiClient, TestGeneratorSchema, handleTestGenerator, ResponsiveLayoutSchema, handleResponsiveLayout, SecurityScanSchema, handleSecurityScan, DesignTokensSchema, handleDesignTokens, PerfHintsSchema, handlePerfHints, } from "./tools/webdev/index.js";
|
|
25
26
|
// ---------------------------------------------------------------------------
|
|
26
27
|
// Init DB
|
|
@@ -54,7 +55,7 @@ else {
|
|
|
54
55
|
// ---------------------------------------------------------------------------
|
|
55
56
|
// MCP Server
|
|
56
57
|
// ---------------------------------------------------------------------------
|
|
57
|
-
const server = new Server({ name: "lucid", version: "1.
|
|
58
|
+
const server = new Server({ name: "lucid", version: "1.13.0" }, { capabilities: { tools: {} } });
|
|
58
59
|
// ---------------------------------------------------------------------------
|
|
59
60
|
// Tool definitions
|
|
60
61
|
// ---------------------------------------------------------------------------
|
|
@@ -393,6 +394,23 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
393
394
|
required: ["task_id", "status"],
|
|
394
395
|
},
|
|
395
396
|
},
|
|
397
|
+
// ── Updater ──────────────────────────────────────────────────────────────
|
|
398
|
+
{
|
|
399
|
+
name: "update_lucid",
|
|
400
|
+
description: "Check for a newer version of Lucid on npm and update automatically. " +
|
|
401
|
+
"For global npm installs: runs npm install -g @a13xu/lucid@latest. " +
|
|
402
|
+
"For local source installs: shows git pull + npm run build instructions. " +
|
|
403
|
+
"After updating, restart Claude Code to load the new version.",
|
|
404
|
+
inputSchema: {
|
|
405
|
+
type: "object",
|
|
406
|
+
properties: {
|
|
407
|
+
force: {
|
|
408
|
+
type: "boolean",
|
|
409
|
+
description: "Force reinstall even if already on latest version (default false)",
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
396
414
|
// ── Web Dev Skills ───────────────────────────────────────────────────────
|
|
397
415
|
{
|
|
398
416
|
name: "generate_component",
|
|
@@ -654,6 +672,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
654
672
|
case "plan_update_task":
|
|
655
673
|
text = handlePlanUpdateTask(stmts, PlanUpdateTaskSchema.parse(args));
|
|
656
674
|
break;
|
|
675
|
+
// Updater
|
|
676
|
+
case "update_lucid":
|
|
677
|
+
text = await handleUpdateLucid(UpdateLucidSchema.parse(args));
|
|
678
|
+
break;
|
|
657
679
|
// Web Dev Skills
|
|
658
680
|
case "generate_component":
|
|
659
681
|
text = handleGenerateComponent(GenerateComponentSchema.parse(args));
|
|
@@ -703,4 +725,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
703
725
|
// ---------------------------------------------------------------------------
|
|
704
726
|
const transport = new StdioServerTransport();
|
|
705
727
|
await server.connect(transport);
|
|
706
|
-
console.error(
|
|
728
|
+
console.error(`[lucid] Server v${getCurrentVersion()} started on stdio.`);
|
|
729
|
+
// Non-blocking — logs to stderr if update is available
|
|
730
|
+
checkForUpdatesOnStartup().catch(() => { });
|
package/build/tools/init.js
CHANGED
|
@@ -29,6 +29,7 @@ export const InitProjectSchema = z.object({
|
|
|
29
29
|
projectName: z.string().optional(),
|
|
30
30
|
});
|
|
31
31
|
const LUCID_MARKER = "Lucid: call sync_file";
|
|
32
|
+
const LUCID_UPDATE_MARKER = "lucid-update-check";
|
|
32
33
|
const LUCID_HOOK = {
|
|
33
34
|
matcher: "Write|Edit|NotebookEdit",
|
|
34
35
|
hooks: [
|
|
@@ -38,7 +39,27 @@ const LUCID_HOOK = {
|
|
|
38
39
|
},
|
|
39
40
|
],
|
|
40
41
|
};
|
|
41
|
-
|
|
42
|
+
// SessionStart hook: checks npm registry and notifies if update is available.
|
|
43
|
+
// Uses only Node.js built-in https module — no external dependencies required.
|
|
44
|
+
const LUCID_UPDATE_HOOK = {
|
|
45
|
+
hooks: [
|
|
46
|
+
{
|
|
47
|
+
type: "command",
|
|
48
|
+
command: `node -e "const h=require('https');` +
|
|
49
|
+
`h.get('https://registry.npmjs.org/@a13xu/lucid/latest',` +
|
|
50
|
+
`function(r){var d='';r.on('data',function(c){d+=c});` +
|
|
51
|
+
`r.on('end',function(){` +
|
|
52
|
+
`try{var v=JSON.parse(d).version;` +
|
|
53
|
+
`var s=require('child_process').execSync(` +
|
|
54
|
+
`'npm list -g @a13xu/lucid --depth=0 2>/dev/null',{encoding:'utf8'});` +
|
|
55
|
+
`var m=s.match(/lucid@([\\d.]+)/);` +
|
|
56
|
+
`if(m&&m[1]&&v!==m[1])` +
|
|
57
|
+
`console.log('[Lucid] Update available: v'+m[1]+' → v'+v+'. Call update_lucid().')}` +
|
|
58
|
+
`catch(e){}})}).on('error',function(){})" 2>/dev/null || true`,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
function installHooks(dir) {
|
|
42
63
|
const claudeDir = join(dir, ".claude");
|
|
43
64
|
const settingsPath = join(claudeDir, "settings.json");
|
|
44
65
|
let settings = {};
|
|
@@ -51,20 +72,34 @@ function installHook(dir) {
|
|
|
51
72
|
}
|
|
52
73
|
}
|
|
53
74
|
const hooks = (settings["hooks"] ?? {});
|
|
75
|
+
let changed = false;
|
|
76
|
+
// ── PostToolUse: sync_file reminder ──────────────────────────────────────
|
|
54
77
|
const postToolUse = hooks["PostToolUse"] ?? [];
|
|
55
|
-
|
|
56
|
-
const alreadyInstalled = postToolUse.some((h) => {
|
|
78
|
+
const syncAlreadyInstalled = postToolUse.some((h) => {
|
|
57
79
|
const cmd = h.command ?? h.hooks?.[0]?.command ?? "";
|
|
58
80
|
return cmd.includes(LUCID_MARKER);
|
|
59
81
|
});
|
|
60
|
-
if (
|
|
82
|
+
if (!syncAlreadyInstalled) {
|
|
83
|
+
hooks["PostToolUse"] = [...postToolUse, LUCID_HOOK];
|
|
84
|
+
changed = true;
|
|
85
|
+
}
|
|
86
|
+
// ── SessionStart: version check ───────────────────────────────────────────
|
|
87
|
+
const sessionStart = hooks["SessionStart"] ?? [];
|
|
88
|
+
const updateAlreadyInstalled = sessionStart.some((h) => {
|
|
89
|
+
const cmd = h.command ?? h.hooks?.[0]?.command ?? "";
|
|
90
|
+
return cmd.includes(LUCID_UPDATE_MARKER);
|
|
91
|
+
});
|
|
92
|
+
if (!updateAlreadyInstalled) {
|
|
93
|
+
hooks["SessionStart"] = [...sessionStart, LUCID_UPDATE_HOOK];
|
|
94
|
+
changed = true;
|
|
95
|
+
}
|
|
96
|
+
if (!changed) {
|
|
61
97
|
return { installed: false, reason: "already installed" };
|
|
62
98
|
}
|
|
63
|
-
hooks["PostToolUse"] = [...postToolUse, LUCID_HOOK];
|
|
64
99
|
settings["hooks"] = hooks;
|
|
65
100
|
mkdirSync(claudeDir, { recursive: true });
|
|
66
101
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
67
|
-
return { installed: true, reason: "
|
|
102
|
+
return { installed: true, reason: "hooks added to .claude/settings.json" };
|
|
68
103
|
}
|
|
69
104
|
// ---------------------------------------------------------------------------
|
|
70
105
|
// Adaugă instrucțiune în CLAUDE.md
|
|
@@ -111,13 +146,14 @@ export async function handleInitProject(stmts, input) {
|
|
|
111
146
|
}
|
|
112
147
|
// ── Hook PostToolUse ──────────────────────────────────────────────────────
|
|
113
148
|
lines.push(``);
|
|
114
|
-
const hookResult =
|
|
149
|
+
const hookResult = installHooks(dir);
|
|
115
150
|
if (hookResult.installed) {
|
|
116
|
-
lines.push(`🔗 Claude Code
|
|
117
|
-
lines.push(`
|
|
151
|
+
lines.push(`🔗 Claude Code hooks installed (.claude/settings.json)`);
|
|
152
|
+
lines.push(` PostToolUse: reminder to call sync_file() after every Write/Edit`);
|
|
153
|
+
lines.push(` SessionStart: auto-check for Lucid updates on session start`);
|
|
118
154
|
}
|
|
119
155
|
else {
|
|
120
|
-
lines.push(`🔗
|
|
156
|
+
lines.push(`🔗 Hooks: ${hookResult.reason}`);
|
|
121
157
|
}
|
|
122
158
|
// ── Skills ────────────────────────────────────────────────────────────────
|
|
123
159
|
const skillsResult = installSkills(dir);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare function getCurrentVersion(): string;
|
|
3
|
+
export declare function checkForUpdatesOnStartup(): Promise<void>;
|
|
4
|
+
export declare const UpdateLucidSchema: z.ZodObject<{
|
|
5
|
+
force: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
force?: boolean | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
force?: boolean | undefined;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function handleUpdateLucid(args: z.infer<typeof UpdateLucidSchema>): Promise<string>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { readFileSync, existsSync } from "fs";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Package root resolution
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// build/tools/updater.js → ../../ = package root
|
|
10
|
+
const PACKAGE_ROOT = join(fileURLToPath(new URL(".", import.meta.url)), "../..");
|
|
11
|
+
export function getCurrentVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(join(PACKAGE_ROOT, "package.json"), "utf-8"));
|
|
14
|
+
return pkg.version ?? "unknown";
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return "unknown";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// npm registry check
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
async function fetchLatestVersion() {
|
|
24
|
+
try {
|
|
25
|
+
const res = await fetch("https://registry.npmjs.org/@a13xu/lucid/latest", { signal: AbortSignal.timeout(5000) });
|
|
26
|
+
if (!res.ok)
|
|
27
|
+
return null;
|
|
28
|
+
const data = (await res.json());
|
|
29
|
+
return data.version ?? null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function compareVersions(a, b) {
|
|
36
|
+
const pa = a.split(".").map(Number);
|
|
37
|
+
const pb = b.split(".").map(Number);
|
|
38
|
+
for (let i = 0; i < 3; i++) {
|
|
39
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
40
|
+
if (diff !== 0)
|
|
41
|
+
return diff;
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Install method detection
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
function detectInstallMethod() {
|
|
49
|
+
// If the package root is inside node_modules, it's npm-installed
|
|
50
|
+
if (PACKAGE_ROOT.includes("node_modules")) {
|
|
51
|
+
return "global-npm";
|
|
52
|
+
}
|
|
53
|
+
// Check if there's a .git folder — local source checkout
|
|
54
|
+
if (existsSync(join(PACKAGE_ROOT, ".git"))) {
|
|
55
|
+
return "local-source";
|
|
56
|
+
}
|
|
57
|
+
return "global-npm";
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Startup check (non-blocking — call from index.ts without await)
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
export async function checkForUpdatesOnStartup() {
|
|
63
|
+
const current = getCurrentVersion();
|
|
64
|
+
const latest = await fetchLatestVersion();
|
|
65
|
+
if (latest && compareVersions(latest, current) > 0) {
|
|
66
|
+
console.error(`[lucid] ⬆️ Update available: v${current} → v${latest}. ` +
|
|
67
|
+
`Call update_lucid() to update, or: npm install -g @a13xu/lucid@latest`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Schema & handler
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
export const UpdateLucidSchema = z.object({
|
|
74
|
+
force: z
|
|
75
|
+
.boolean()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe("Force reinstall even if already on latest version"),
|
|
78
|
+
});
|
|
79
|
+
// Example call:
|
|
80
|
+
// handleUpdateLucid({ force: false })
|
|
81
|
+
export async function handleUpdateLucid(args) {
|
|
82
|
+
const current = getCurrentVersion();
|
|
83
|
+
const lines = [`🔍 Checking for updates... (current: v${current})`];
|
|
84
|
+
const latest = await fetchLatestVersion();
|
|
85
|
+
if (!latest) {
|
|
86
|
+
return lines.concat("❌ Could not reach npm registry. Check your internet connection.").join("\n");
|
|
87
|
+
}
|
|
88
|
+
lines.push(`📦 Latest on npm: v${latest}`);
|
|
89
|
+
const upToDate = compareVersions(latest, current) <= 0;
|
|
90
|
+
if (upToDate && !args.force) {
|
|
91
|
+
lines.push(`✅ Lucid is up to date.`);
|
|
92
|
+
return lines.join("\n");
|
|
93
|
+
}
|
|
94
|
+
if (upToDate && args.force) {
|
|
95
|
+
lines.push(`⚠️ Already on v${latest}, reinstalling (force=true)...`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
lines.push(`🔄 Updating v${current} → v${latest}...`);
|
|
99
|
+
}
|
|
100
|
+
const method = detectInstallMethod();
|
|
101
|
+
if (method === "local-source") {
|
|
102
|
+
lines.push(``);
|
|
103
|
+
lines.push(`📁 Local source installation detected (${PACKAGE_ROOT}).`);
|
|
104
|
+
lines.push(`Run these commands to update:`);
|
|
105
|
+
lines.push(` cd "${PACKAGE_ROOT}"`);
|
|
106
|
+
lines.push(` git pull`);
|
|
107
|
+
lines.push(` npm run build`);
|
|
108
|
+
lines.push(`Then restart Claude Code.`);
|
|
109
|
+
return lines.join("\n");
|
|
110
|
+
}
|
|
111
|
+
// Global npm install
|
|
112
|
+
try {
|
|
113
|
+
lines.push(`Running: npm install -g @a13xu/lucid@${latest}`);
|
|
114
|
+
execSync(`npm install -g @a13xu/lucid@${latest}`, {
|
|
115
|
+
timeout: 120_000,
|
|
116
|
+
stdio: "pipe",
|
|
117
|
+
});
|
|
118
|
+
lines.push(`✅ Updated to v${latest}`);
|
|
119
|
+
lines.push(``);
|
|
120
|
+
lines.push(`⚠️ Restart Claude Code to load the new version:`);
|
|
121
|
+
lines.push(` • VS Code: Cmd/Ctrl+Shift+P → "Restart Claude Code"`);
|
|
122
|
+
lines.push(` • CLI: exit and re-run \`claude\``);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126
|
+
lines.push(`❌ Auto-update failed: ${msg}`);
|
|
127
|
+
lines.push(` Run manually: npm install -g @a13xu/lucid@${latest}`);
|
|
128
|
+
if (process.platform !== "win32") {
|
|
129
|
+
lines.push(` Or with sudo: sudo npm install -g @a13xu/lucid@${latest}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return lines.join("\n");
|
|
133
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a13xu/lucid",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Token-efficient memory, code indexing, and validation for Claude Code agents — SQLite + FTS5, TF-IDF + Qdrant retrieval, AST skeleton pruning, diff-aware context, Logic Guardian drift detection",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|