eminiar 0.10.1 → 0.11.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/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/mcp.json +11 -0
- package/.cursor-plugin/plugin.json +23 -0
- package/README.md +12 -8
- package/dist/cli.js +595 -401
- package/dist/hook.js +687 -463
- package/hooks/cursor.json +36 -0
- package/package.json +7 -4
- package/rules/eminiar.mdc +15 -0
package/dist/cli.js
CHANGED
|
@@ -23221,6 +23221,24 @@ var init_storage = __esm({
|
|
|
23221
23221
|
}
|
|
23222
23222
|
});
|
|
23223
23223
|
|
|
23224
|
+
// src/hooks/cursor.ts
|
|
23225
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
23226
|
+
import { homedir as homedir3 } from "os";
|
|
23227
|
+
import { join as join10 } from "path";
|
|
23228
|
+
function cursorDir() {
|
|
23229
|
+
return process.env.CURSOR_CONFIG_DIR || join10(homedir3(), ".cursor");
|
|
23230
|
+
}
|
|
23231
|
+
var PENDING_TTL_MS;
|
|
23232
|
+
var init_cursor = __esm({
|
|
23233
|
+
"src/hooks/cursor.ts"() {
|
|
23234
|
+
"use strict";
|
|
23235
|
+
init_esm_shims();
|
|
23236
|
+
init_context();
|
|
23237
|
+
init_paths();
|
|
23238
|
+
PENDING_TTL_MS = 10 * 6e4;
|
|
23239
|
+
}
|
|
23240
|
+
});
|
|
23241
|
+
|
|
23224
23242
|
// src/install/shell.ts
|
|
23225
23243
|
import { spawnSync } from "child_process";
|
|
23226
23244
|
import { createInterface } from "readline";
|
|
@@ -23269,194 +23287,20 @@ var init_shell = __esm({
|
|
|
23269
23287
|
}
|
|
23270
23288
|
});
|
|
23271
23289
|
|
|
23272
|
-
// src/install/materialize.ts
|
|
23273
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync6, rmSync as rmSync2 } from "fs";
|
|
23274
|
-
import { join as join10 } from "path";
|
|
23275
|
-
function stableRoot() {
|
|
23276
|
-
return join10(paths().plugin, "node_modules", "eminiar");
|
|
23277
|
-
}
|
|
23278
|
-
function stableVersion() {
|
|
23279
|
-
try {
|
|
23280
|
-
return JSON.parse(readFileSync6(join10(stableRoot(), "package.json"), "utf8")).version;
|
|
23281
|
-
} catch {
|
|
23282
|
-
return void 0;
|
|
23283
|
-
}
|
|
23284
|
-
}
|
|
23285
|
-
function materialize(spec, force = false) {
|
|
23286
|
-
const prefix = paths().plugin;
|
|
23287
|
-
mkdirSync5(prefix, { recursive: true });
|
|
23288
|
-
const root = stableRoot();
|
|
23289
|
-
const here = pluginRoot();
|
|
23290
|
-
if (!force && !spec && here === root) return { root, fromSpec: "self" };
|
|
23291
|
-
if (!force && !spec && stableVersion() === version2() && existsSync7(join10(root, "dist", "server.js"))) {
|
|
23292
|
-
log.ok(`stable copy already at v${version2()} (${root})`);
|
|
23293
|
-
return { root, fromSpec: `pack:${here}` };
|
|
23294
|
-
}
|
|
23295
|
-
let target = spec;
|
|
23296
|
-
if (!target) {
|
|
23297
|
-
if (!existsSync7(join10(here, "dist", "server.js"))) {
|
|
23298
|
-
throw new Error(`${here} has no dist/ \u2014 run \`npm run build\` first`);
|
|
23299
|
-
}
|
|
23300
|
-
const dest = paths().tmp;
|
|
23301
|
-
mkdirSync5(dest, { recursive: true });
|
|
23302
|
-
const pack = run(
|
|
23303
|
-
npmCli(),
|
|
23304
|
-
["pack", "--ignore-scripts", "--pack-destination", dest, "--silent"],
|
|
23305
|
-
{ cwd: here }
|
|
23306
|
-
);
|
|
23307
|
-
if (!pack.ok) throw new Error(`npm pack failed: ${pack.stderr || pack.stdout}`);
|
|
23308
|
-
const tarball = pack.stdout.trim().split("\n").pop();
|
|
23309
|
-
target = join10(dest, tarball);
|
|
23310
|
-
}
|
|
23311
|
-
const install2 = run(
|
|
23312
|
-
npmCli(),
|
|
23313
|
-
[
|
|
23314
|
-
"install",
|
|
23315
|
-
"--prefix",
|
|
23316
|
-
prefix,
|
|
23317
|
-
"--omit=dev",
|
|
23318
|
-
"--no-audit",
|
|
23319
|
-
"--no-fund",
|
|
23320
|
-
"--loglevel=error",
|
|
23321
|
-
target
|
|
23322
|
-
],
|
|
23323
|
-
{
|
|
23324
|
-
env: { ...process.env, npm_config_update_notifier: "false" }
|
|
23325
|
-
}
|
|
23326
|
-
);
|
|
23327
|
-
if (!install2.ok) throw new Error(`npm install failed: ${install2.stderr || install2.stdout}`);
|
|
23328
|
-
if (!spec && target.endsWith(".tgz")) rmSync2(target, { force: true });
|
|
23329
|
-
for (const must of [
|
|
23330
|
-
"dist/server.js",
|
|
23331
|
-
"dist/hook.js",
|
|
23332
|
-
"bin/em-hook",
|
|
23333
|
-
".claude-plugin/plugin.json",
|
|
23334
|
-
"hooks/hooks.json"
|
|
23335
|
-
]) {
|
|
23336
|
-
if (!existsSync7(join10(root, must))) throw new Error(`stable copy is missing ${must}`);
|
|
23337
|
-
}
|
|
23338
|
-
log.ok(
|
|
23339
|
-
`installed v${stableVersion()} into ${root} (${readdirSync3(join10(prefix, "node_modules")).length} packages)`
|
|
23340
|
-
);
|
|
23341
|
-
return { root, fromSpec: spec ?? `pack:${here}` };
|
|
23342
|
-
}
|
|
23343
|
-
function nativeCheck(node2, root) {
|
|
23344
|
-
const script = `
|
|
23345
|
-
const { createRequire } = require("node:module");
|
|
23346
|
-
const req = createRequire(${JSON.stringify(join10(root, "package.json"))});
|
|
23347
|
-
const out = [];
|
|
23348
|
-
for (const m of ["better-sqlite3", "sqlite-vec", "web-tree-sitter", "@huggingface/transformers"]) {
|
|
23349
|
-
try { const x = req(m); if (m === "better-sqlite3") { const db = new x(":memory:"); req("sqlite-vec").load(db); db.close(); } }
|
|
23350
|
-
catch (e) { out.push(m + ": " + (e && e.message ? e.message.split("\\n")[0] : e)); }
|
|
23351
|
-
}
|
|
23352
|
-
process.stdout.write(JSON.stringify(out));
|
|
23353
|
-
`;
|
|
23354
|
-
const r = run(node2, ["-e", script], { cwd: root });
|
|
23355
|
-
if (!r.ok) return [`native check could not run: ${r.stderr.trim().split("\n").pop()}`];
|
|
23356
|
-
try {
|
|
23357
|
-
return JSON.parse(r.stdout);
|
|
23358
|
-
} catch {
|
|
23359
|
-
return [`native check returned garbage: ${r.stdout.slice(0, 200)}`];
|
|
23360
|
-
}
|
|
23361
|
-
}
|
|
23362
|
-
function rebuildNative(root) {
|
|
23363
|
-
const r = run(
|
|
23364
|
-
npmCli(),
|
|
23365
|
-
["rebuild", "better-sqlite3", "--prefix", paths().plugin, "--loglevel=error"],
|
|
23366
|
-
{ cwd: root }
|
|
23367
|
-
);
|
|
23368
|
-
return r.ok;
|
|
23369
|
-
}
|
|
23370
|
-
function downloadModel(node2, root, model2) {
|
|
23371
|
-
const script = `
|
|
23372
|
-
(async () => {
|
|
23373
|
-
const tf = await import("@huggingface/transformers");
|
|
23374
|
-
tf.env.cacheDir = ${JSON.stringify(paths().models)};
|
|
23375
|
-
const p = await tf.pipeline("feature-extraction", ${JSON.stringify(model2)}, { dtype: "q8", device: "cpu" });
|
|
23376
|
-
const r = await p(["warm up"], { pooling: "cls", normalize: true });
|
|
23377
|
-
process.stdout.write(String(r.tolist()[0].length));
|
|
23378
|
-
})().catch((e) => { process.stderr.write(String(e && e.message || e)); process.exit(1); });
|
|
23379
|
-
`;
|
|
23380
|
-
const r = run(node2, ["--input-type=module", "-e", script], { cwd: root });
|
|
23381
|
-
return r.ok ? void 0 : r.stderr.trim().split("\n").pop();
|
|
23382
|
-
}
|
|
23383
|
-
var init_materialize = __esm({
|
|
23384
|
-
"src/install/materialize.ts"() {
|
|
23385
|
-
"use strict";
|
|
23386
|
-
init_esm_shims();
|
|
23387
|
-
init_paths();
|
|
23388
|
-
init_version();
|
|
23389
|
-
init_shell();
|
|
23390
|
-
}
|
|
23391
|
-
});
|
|
23392
|
-
|
|
23393
|
-
// src/install/node-resolve.ts
|
|
23394
|
-
import { accessSync as accessSync3, constants as constants3, existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
23395
|
-
import { join as join11 } from "path";
|
|
23396
|
-
function versionOf(bin) {
|
|
23397
|
-
const r = run(bin, ["-p", "process.versions.node"]);
|
|
23398
|
-
return r.ok ? r.stdout.trim() : void 0;
|
|
23399
|
-
}
|
|
23400
|
-
function nodeOk(version3) {
|
|
23401
|
-
const [maj = 0, min = 0] = version3.split(".").map(Number);
|
|
23402
|
-
return maj > 22 || maj === 22 && min >= 12;
|
|
23403
|
-
}
|
|
23404
|
-
function pinNode(explicit) {
|
|
23405
|
-
const candidate = explicit ?? process.execPath;
|
|
23406
|
-
accessSync3(candidate, constants3.X_OK);
|
|
23407
|
-
const version3 = versionOf(candidate);
|
|
23408
|
-
if (!version3) throw new Error(`${candidate} does not look like a node binary`);
|
|
23409
|
-
if (!nodeOk(version3))
|
|
23410
|
-
throw new Error(`node ${version3} at ${candidate} is too old; need >= 22.12`);
|
|
23411
|
-
writeFileSync4(ensureDirs().nodePathFile, candidate);
|
|
23412
|
-
return { path: candidate, version: version3 };
|
|
23413
|
-
}
|
|
23414
|
-
function pinnedNode() {
|
|
23415
|
-
try {
|
|
23416
|
-
const path3 = readFileSync7(ensureDirs().nodePathFile, "utf8").trim();
|
|
23417
|
-
const version3 = versionOf(path3);
|
|
23418
|
-
return version3 ? { path: path3, version: version3 } : void 0;
|
|
23419
|
-
} catch {
|
|
23420
|
-
return void 0;
|
|
23421
|
-
}
|
|
23422
|
-
}
|
|
23423
|
-
function pinRoot(root) {
|
|
23424
|
-
if (!existsSync8(join11(root, "dist", "server.js")))
|
|
23425
|
-
throw new Error(`${root} has no dist/server.js; cannot pin it as the stable root`);
|
|
23426
|
-
writeFileSync4(ensureDirs().rootPathFile, root);
|
|
23427
|
-
return root;
|
|
23428
|
-
}
|
|
23429
|
-
function pinnedRoot() {
|
|
23430
|
-
try {
|
|
23431
|
-
const root = readFileSync7(ensureDirs().rootPathFile, "utf8").trim();
|
|
23432
|
-
return root && existsSync8(join11(root, "dist", "server.js")) ? root : void 0;
|
|
23433
|
-
} catch {
|
|
23434
|
-
return void 0;
|
|
23435
|
-
}
|
|
23436
|
-
}
|
|
23437
|
-
var init_node_resolve = __esm({
|
|
23438
|
-
"src/install/node-resolve.ts"() {
|
|
23439
|
-
"use strict";
|
|
23440
|
-
init_esm_shims();
|
|
23441
|
-
init_paths();
|
|
23442
|
-
init_shell();
|
|
23443
|
-
}
|
|
23444
|
-
});
|
|
23445
|
-
|
|
23446
23290
|
// src/install/register.ts
|
|
23447
23291
|
import { createHash as createHash2 } from "crypto";
|
|
23448
|
-
import { cpSync, existsSync as
|
|
23449
|
-
import { join as
|
|
23292
|
+
import { cpSync, existsSync as existsSync8, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync7, rmSync as rmSync3 } from "fs";
|
|
23293
|
+
import { join as join11 } from "path";
|
|
23450
23294
|
function fileHash(file3) {
|
|
23451
23295
|
try {
|
|
23452
|
-
return createHash2("sha1").update(
|
|
23296
|
+
return createHash2("sha1").update(readFileSync7(file3)).digest("hex");
|
|
23453
23297
|
} catch {
|
|
23454
23298
|
return void 0;
|
|
23455
23299
|
}
|
|
23456
23300
|
}
|
|
23457
23301
|
function probeServer(root) {
|
|
23458
|
-
const bin =
|
|
23459
|
-
if (!
|
|
23302
|
+
const bin = join11(root, "bin", "em-server");
|
|
23303
|
+
if (!existsSync8(bin)) return "bin/em-server is missing";
|
|
23460
23304
|
const r = run(bin, ["--probe"], { timeoutMs: 2e4 });
|
|
23461
23305
|
if (r.ok && / ok /.test(r.stdout)) return void 0;
|
|
23462
23306
|
const lines = (r.stderr || r.stdout).trim().split("\n").filter(Boolean);
|
|
@@ -23466,11 +23310,11 @@ function probeServer(root) {
|
|
|
23466
23310
|
function pluginCacheStale(stable) {
|
|
23467
23311
|
const cache3 = pluginInstallPath("eminiar@eminiar");
|
|
23468
23312
|
if (!cache3 || cache3 === stable) return void 0;
|
|
23469
|
-
if (!
|
|
23313
|
+
if (!existsSync8(cache3)) return `${cache3} is missing`;
|
|
23470
23314
|
for (const rel of CACHE_FINGERPRINT) {
|
|
23471
|
-
if (fileHash(
|
|
23315
|
+
if (fileHash(join11(cache3, rel)) !== fileHash(join11(stable, rel))) return `${rel} differs`;
|
|
23472
23316
|
}
|
|
23473
|
-
if (
|
|
23317
|
+
if (existsSync8(join11(cache3, ".mcp.json")) && !existsSync8(join11(stable, ".mcp.json")))
|
|
23474
23318
|
return ".mcp.json is present in the cache but not in the stable copy";
|
|
23475
23319
|
const probe3 = probeServer(cache3);
|
|
23476
23320
|
if (probe3) return `cached copy ${probe3}`;
|
|
@@ -23527,7 +23371,7 @@ function isOurs(cmd2, stable) {
|
|
|
23527
23371
|
function registerSettings(stable) {
|
|
23528
23372
|
const settings = readJson2(settingsPath());
|
|
23529
23373
|
const hooks = settings.hooks ?? {};
|
|
23530
|
-
const hookCmd = `"${
|
|
23374
|
+
const hookCmd = `"${join11(stable, "bin", "em-hook")}"`;
|
|
23531
23375
|
for (const ev2 of HOOK_EVENTS) {
|
|
23532
23376
|
const list2 = hooks[ev2] ?? [];
|
|
23533
23377
|
const filtered = list2.filter(
|
|
@@ -23548,17 +23392,17 @@ function registerSettings(stable) {
|
|
|
23548
23392
|
const servers = cj.mcpServers ?? {};
|
|
23549
23393
|
servers.eminiar = {
|
|
23550
23394
|
type: "stdio",
|
|
23551
|
-
command:
|
|
23395
|
+
command: join11(stable, "bin", "em-server"),
|
|
23552
23396
|
args: [],
|
|
23553
23397
|
env: { EMINIAR_PLUGIN_ROOT: stable }
|
|
23554
23398
|
};
|
|
23555
23399
|
cj.mcpServers = servers;
|
|
23556
23400
|
writeJsonWithBackup(claudeJsonPath(), cj);
|
|
23557
23401
|
const skills = [];
|
|
23558
|
-
const skillsDir =
|
|
23402
|
+
const skillsDir = join11(settingsPath(), "..", "skills");
|
|
23559
23403
|
mkdirSync6(skillsDir, { recursive: true });
|
|
23560
|
-
for (const name of
|
|
23561
|
-
cpSync(
|
|
23404
|
+
for (const name of readdirSync3(join11(stable, "skills"))) {
|
|
23405
|
+
cpSync(join11(stable, "skills", name), join11(skillsDir, name), { recursive: true });
|
|
23562
23406
|
skills.push(name);
|
|
23563
23407
|
}
|
|
23564
23408
|
return { hookEvents: HOOK_EVENTS, mcpServer: true, skills };
|
|
@@ -23589,8 +23433,8 @@ function unregisterSettings(stable, wrote) {
|
|
|
23589
23433
|
}
|
|
23590
23434
|
}
|
|
23591
23435
|
for (const name of wrote.skills ?? []) {
|
|
23592
|
-
const dir =
|
|
23593
|
-
if (
|
|
23436
|
+
const dir = join11(settingsPath(), "..", "skills", name);
|
|
23437
|
+
if (existsSync8(dir)) rmSync3(dir, { recursive: true, force: true });
|
|
23594
23438
|
}
|
|
23595
23439
|
}
|
|
23596
23440
|
function setStatusline(stable) {
|
|
@@ -23604,7 +23448,7 @@ function setStatusline(stable) {
|
|
|
23604
23448
|
}
|
|
23605
23449
|
settings.statusLine = {
|
|
23606
23450
|
type: "command",
|
|
23607
|
-
command: `"${
|
|
23451
|
+
command: `"${join11(stable, "bin", "eminiar")}" statusline`
|
|
23608
23452
|
};
|
|
23609
23453
|
writeJsonWithBackup(settingsPath(), settings);
|
|
23610
23454
|
return true;
|
|
@@ -23646,14 +23490,304 @@ var init_register = __esm({
|
|
|
23646
23490
|
}
|
|
23647
23491
|
});
|
|
23648
23492
|
|
|
23493
|
+
// src/install/cursor.ts
|
|
23494
|
+
import { cpSync as cpSync2, existsSync as existsSync9, mkdirSync as mkdirSync7, readdirSync as readdirSync4, readFileSync as readFileSync8, rmSync as rmSync4 } from "fs";
|
|
23495
|
+
import { join as join12 } from "path";
|
|
23496
|
+
function cursorPresent() {
|
|
23497
|
+
return existsSync9(cursorDir()) || existsSync9("/Applications/Cursor.app") || !!findOnPath("cursor") || !!findOnPath("cursor-agent");
|
|
23498
|
+
}
|
|
23499
|
+
function cursorHookCommand(stable) {
|
|
23500
|
+
return `"${join12(stable, "bin", "em-hook")}" --client cursor`;
|
|
23501
|
+
}
|
|
23502
|
+
function registerCursor(stable) {
|
|
23503
|
+
const cfg = readJson2(cursorHooksPath());
|
|
23504
|
+
if (typeof cfg.version !== "number") cfg.version = 1;
|
|
23505
|
+
const hooks = cfg.hooks ?? {};
|
|
23506
|
+
const command = cursorHookCommand(stable);
|
|
23507
|
+
for (const ev2 of CURSOR_HOOK_EVENTS) {
|
|
23508
|
+
const list2 = (Array.isArray(hooks[ev2]) ? hooks[ev2] : []).filter(
|
|
23509
|
+
(h) => !isOurs(h.command, stable)
|
|
23510
|
+
);
|
|
23511
|
+
const entry = { command, timeout: TIMEOUTS[ev2] ?? 5 };
|
|
23512
|
+
if (ev2 === "preToolUse") entry.matcher = CURSOR_PRE_TOOL_MATCHER;
|
|
23513
|
+
list2.push(entry);
|
|
23514
|
+
hooks[ev2] = list2;
|
|
23515
|
+
}
|
|
23516
|
+
cfg.hooks = hooks;
|
|
23517
|
+
writeJsonWithBackup(cursorHooksPath(), cfg);
|
|
23518
|
+
const mcp = readJson2(cursorMcpPath());
|
|
23519
|
+
const servers = mcp.mcpServers ?? {};
|
|
23520
|
+
servers.eminiar = {
|
|
23521
|
+
command: join12(stable, "bin", "em-server"),
|
|
23522
|
+
args: [],
|
|
23523
|
+
env: { EMINIAR_PLUGIN_ROOT: stable }
|
|
23524
|
+
};
|
|
23525
|
+
mcp.mcpServers = servers;
|
|
23526
|
+
writeJsonWithBackup(cursorMcpPath(), mcp);
|
|
23527
|
+
const skills = [];
|
|
23528
|
+
const src = join12(stable, "skills");
|
|
23529
|
+
if (existsSync9(src)) {
|
|
23530
|
+
mkdirSync7(cursorSkillsDir(), { recursive: true });
|
|
23531
|
+
for (const name of readdirSync4(src)) {
|
|
23532
|
+
cpSync2(join12(src, name), join12(cursorSkillsDir(), name), { recursive: true });
|
|
23533
|
+
skills.push(name);
|
|
23534
|
+
}
|
|
23535
|
+
}
|
|
23536
|
+
return { hookEvents: [...CURSOR_HOOK_EVENTS], mcpServer: true, skills };
|
|
23537
|
+
}
|
|
23538
|
+
function unregisterCursor(stable, wrote) {
|
|
23539
|
+
if (!wrote) return;
|
|
23540
|
+
if (wrote.hookEvents.length && existsSync9(cursorHooksPath())) {
|
|
23541
|
+
const cfg = readJson2(cursorHooksPath());
|
|
23542
|
+
const hooks = cfg.hooks ?? {};
|
|
23543
|
+
for (const ev2 of wrote.hookEvents) {
|
|
23544
|
+
if (!Array.isArray(hooks[ev2])) continue;
|
|
23545
|
+
const kept = hooks[ev2].filter((h) => !isOurs(h.command, stable));
|
|
23546
|
+
if (kept.length) hooks[ev2] = kept;
|
|
23547
|
+
else delete hooks[ev2];
|
|
23548
|
+
}
|
|
23549
|
+
cfg.hooks = hooks;
|
|
23550
|
+
writeJsonWithBackup(cursorHooksPath(), cfg);
|
|
23551
|
+
}
|
|
23552
|
+
if (wrote.mcpServer && existsSync9(cursorMcpPath())) {
|
|
23553
|
+
const mcp = readJson2(cursorMcpPath());
|
|
23554
|
+
const servers = mcp.mcpServers;
|
|
23555
|
+
if (servers?.eminiar && isOurs(servers.eminiar.command, stable)) {
|
|
23556
|
+
delete servers.eminiar;
|
|
23557
|
+
writeJsonWithBackup(cursorMcpPath(), mcp);
|
|
23558
|
+
}
|
|
23559
|
+
}
|
|
23560
|
+
for (const name of wrote.skills) {
|
|
23561
|
+
const dir = join12(cursorSkillsDir(), name);
|
|
23562
|
+
if (existsSync9(dir)) rmSync4(dir, { recursive: true, force: true });
|
|
23563
|
+
}
|
|
23564
|
+
}
|
|
23565
|
+
function cursorStatus() {
|
|
23566
|
+
const read2 = (f) => existsSync9(f) ? readFileSync8(f, "utf8") : "";
|
|
23567
|
+
const hooksRaw = read2(cursorHooksPath());
|
|
23568
|
+
let events = [];
|
|
23569
|
+
try {
|
|
23570
|
+
const cfg = hooksRaw ? JSON.parse(hooksRaw) : {};
|
|
23571
|
+
const hooks = cfg.hooks ?? {};
|
|
23572
|
+
events = Object.keys(hooks).filter(
|
|
23573
|
+
(ev2) => Array.isArray(hooks[ev2]) && hooks[ev2].some(
|
|
23574
|
+
(h) => typeof h.command === "string" && h.command.includes("em-hook")
|
|
23575
|
+
)
|
|
23576
|
+
);
|
|
23577
|
+
} catch {
|
|
23578
|
+
}
|
|
23579
|
+
return { hooks: events.length > 0, mcp: read2(cursorMcpPath()).includes("em-server"), events };
|
|
23580
|
+
}
|
|
23581
|
+
var cursorHooksPath, cursorMcpPath, cursorSkillsDir, CURSOR_HOOK_EVENTS, CURSOR_PRE_TOOL_MATCHER, TIMEOUTS;
|
|
23582
|
+
var init_cursor2 = __esm({
|
|
23583
|
+
"src/install/cursor.ts"() {
|
|
23584
|
+
"use strict";
|
|
23585
|
+
init_esm_shims();
|
|
23586
|
+
init_cursor();
|
|
23587
|
+
init_languages();
|
|
23588
|
+
init_claude_config();
|
|
23589
|
+
init_register();
|
|
23590
|
+
cursorHooksPath = () => join12(cursorDir(), "hooks.json");
|
|
23591
|
+
cursorMcpPath = () => join12(cursorDir(), "mcp.json");
|
|
23592
|
+
cursorSkillsDir = () => join12(cursorDir(), "skills");
|
|
23593
|
+
CURSOR_HOOK_EVENTS = [
|
|
23594
|
+
"sessionStart",
|
|
23595
|
+
"beforeSubmitPrompt",
|
|
23596
|
+
"preToolUse",
|
|
23597
|
+
"postToolUse",
|
|
23598
|
+
"postToolUseFailure",
|
|
23599
|
+
"subagentStop",
|
|
23600
|
+
"preCompact",
|
|
23601
|
+
"afterAgentResponse",
|
|
23602
|
+
"sessionEnd"
|
|
23603
|
+
];
|
|
23604
|
+
CURSOR_PRE_TOOL_MATCHER = "Shell|Read|Write|Edit|Grep|Glob|WebFetch|WebSearch|Task";
|
|
23605
|
+
TIMEOUTS = { sessionStart: 10, preCompact: 15, postToolUse: 10 };
|
|
23606
|
+
}
|
|
23607
|
+
});
|
|
23608
|
+
|
|
23609
|
+
// src/install/materialize.ts
|
|
23610
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync9, rmSync as rmSync5 } from "fs";
|
|
23611
|
+
import { join as join13 } from "path";
|
|
23612
|
+
function stableRoot() {
|
|
23613
|
+
return join13(paths().plugin, "node_modules", "eminiar");
|
|
23614
|
+
}
|
|
23615
|
+
function stableVersion() {
|
|
23616
|
+
try {
|
|
23617
|
+
return JSON.parse(readFileSync9(join13(stableRoot(), "package.json"), "utf8")).version;
|
|
23618
|
+
} catch {
|
|
23619
|
+
return void 0;
|
|
23620
|
+
}
|
|
23621
|
+
}
|
|
23622
|
+
function materialize(spec, force = false) {
|
|
23623
|
+
const prefix = paths().plugin;
|
|
23624
|
+
mkdirSync8(prefix, { recursive: true });
|
|
23625
|
+
const root = stableRoot();
|
|
23626
|
+
const here = pluginRoot();
|
|
23627
|
+
if (!force && !spec && here === root) return { root, fromSpec: "self" };
|
|
23628
|
+
if (!force && !spec && stableVersion() === version2() && existsSync10(join13(root, "dist", "server.js"))) {
|
|
23629
|
+
log.ok(`stable copy already at v${version2()} (${root})`);
|
|
23630
|
+
return { root, fromSpec: `pack:${here}` };
|
|
23631
|
+
}
|
|
23632
|
+
let target = spec;
|
|
23633
|
+
if (!target) {
|
|
23634
|
+
if (!existsSync10(join13(here, "dist", "server.js"))) {
|
|
23635
|
+
throw new Error(`${here} has no dist/ \u2014 run \`npm run build\` first`);
|
|
23636
|
+
}
|
|
23637
|
+
const dest = paths().tmp;
|
|
23638
|
+
mkdirSync8(dest, { recursive: true });
|
|
23639
|
+
const pack = run(
|
|
23640
|
+
npmCli(),
|
|
23641
|
+
["pack", "--ignore-scripts", "--pack-destination", dest, "--silent"],
|
|
23642
|
+
{ cwd: here }
|
|
23643
|
+
);
|
|
23644
|
+
if (!pack.ok) throw new Error(`npm pack failed: ${pack.stderr || pack.stdout}`);
|
|
23645
|
+
const tarball = pack.stdout.trim().split("\n").pop();
|
|
23646
|
+
target = join13(dest, tarball);
|
|
23647
|
+
}
|
|
23648
|
+
const install2 = run(
|
|
23649
|
+
npmCli(),
|
|
23650
|
+
[
|
|
23651
|
+
"install",
|
|
23652
|
+
"--prefix",
|
|
23653
|
+
prefix,
|
|
23654
|
+
"--omit=dev",
|
|
23655
|
+
"--no-audit",
|
|
23656
|
+
"--no-fund",
|
|
23657
|
+
"--loglevel=error",
|
|
23658
|
+
target
|
|
23659
|
+
],
|
|
23660
|
+
{
|
|
23661
|
+
env: { ...process.env, npm_config_update_notifier: "false" }
|
|
23662
|
+
}
|
|
23663
|
+
);
|
|
23664
|
+
if (!install2.ok) throw new Error(`npm install failed: ${install2.stderr || install2.stdout}`);
|
|
23665
|
+
if (!spec && target.endsWith(".tgz")) rmSync5(target, { force: true });
|
|
23666
|
+
for (const must of [
|
|
23667
|
+
"dist/server.js",
|
|
23668
|
+
"dist/hook.js",
|
|
23669
|
+
"bin/em-hook",
|
|
23670
|
+
".claude-plugin/plugin.json",
|
|
23671
|
+
"hooks/hooks.json"
|
|
23672
|
+
]) {
|
|
23673
|
+
if (!existsSync10(join13(root, must))) throw new Error(`stable copy is missing ${must}`);
|
|
23674
|
+
}
|
|
23675
|
+
log.ok(
|
|
23676
|
+
`installed v${stableVersion()} into ${root} (${readdirSync5(join13(prefix, "node_modules")).length} packages)`
|
|
23677
|
+
);
|
|
23678
|
+
return { root, fromSpec: spec ?? `pack:${here}` };
|
|
23679
|
+
}
|
|
23680
|
+
function nativeCheck(node2, root) {
|
|
23681
|
+
const script = `
|
|
23682
|
+
const { createRequire } = require("node:module");
|
|
23683
|
+
const req = createRequire(${JSON.stringify(join13(root, "package.json"))});
|
|
23684
|
+
const out = [];
|
|
23685
|
+
for (const m of ["better-sqlite3", "sqlite-vec", "web-tree-sitter", "@huggingface/transformers"]) {
|
|
23686
|
+
try { const x = req(m); if (m === "better-sqlite3") { const db = new x(":memory:"); req("sqlite-vec").load(db); db.close(); } }
|
|
23687
|
+
catch (e) { out.push(m + ": " + (e && e.message ? e.message.split("\\n")[0] : e)); }
|
|
23688
|
+
}
|
|
23689
|
+
process.stdout.write(JSON.stringify(out));
|
|
23690
|
+
`;
|
|
23691
|
+
const r = run(node2, ["-e", script], { cwd: root });
|
|
23692
|
+
if (!r.ok) return [`native check could not run: ${r.stderr.trim().split("\n").pop()}`];
|
|
23693
|
+
try {
|
|
23694
|
+
return JSON.parse(r.stdout);
|
|
23695
|
+
} catch {
|
|
23696
|
+
return [`native check returned garbage: ${r.stdout.slice(0, 200)}`];
|
|
23697
|
+
}
|
|
23698
|
+
}
|
|
23699
|
+
function rebuildNative(root) {
|
|
23700
|
+
const r = run(
|
|
23701
|
+
npmCli(),
|
|
23702
|
+
["rebuild", "better-sqlite3", "--prefix", paths().plugin, "--loglevel=error"],
|
|
23703
|
+
{ cwd: root }
|
|
23704
|
+
);
|
|
23705
|
+
return r.ok;
|
|
23706
|
+
}
|
|
23707
|
+
function downloadModel(node2, root, model2) {
|
|
23708
|
+
const script = `
|
|
23709
|
+
(async () => {
|
|
23710
|
+
const tf = await import("@huggingface/transformers");
|
|
23711
|
+
tf.env.cacheDir = ${JSON.stringify(paths().models)};
|
|
23712
|
+
const p = await tf.pipeline("feature-extraction", ${JSON.stringify(model2)}, { dtype: "q8", device: "cpu" });
|
|
23713
|
+
const r = await p(["warm up"], { pooling: "cls", normalize: true });
|
|
23714
|
+
process.stdout.write(String(r.tolist()[0].length));
|
|
23715
|
+
})().catch((e) => { process.stderr.write(String(e && e.message || e)); process.exit(1); });
|
|
23716
|
+
`;
|
|
23717
|
+
const r = run(node2, ["--input-type=module", "-e", script], { cwd: root });
|
|
23718
|
+
return r.ok ? void 0 : r.stderr.trim().split("\n").pop();
|
|
23719
|
+
}
|
|
23720
|
+
var init_materialize = __esm({
|
|
23721
|
+
"src/install/materialize.ts"() {
|
|
23722
|
+
"use strict";
|
|
23723
|
+
init_esm_shims();
|
|
23724
|
+
init_paths();
|
|
23725
|
+
init_version();
|
|
23726
|
+
init_shell();
|
|
23727
|
+
}
|
|
23728
|
+
});
|
|
23729
|
+
|
|
23730
|
+
// src/install/node-resolve.ts
|
|
23731
|
+
import { accessSync as accessSync3, constants as constants3, existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
|
|
23732
|
+
import { join as join14 } from "path";
|
|
23733
|
+
function versionOf(bin) {
|
|
23734
|
+
const r = run(bin, ["-p", "process.versions.node"]);
|
|
23735
|
+
return r.ok ? r.stdout.trim() : void 0;
|
|
23736
|
+
}
|
|
23737
|
+
function nodeOk(version3) {
|
|
23738
|
+
const [maj = 0, min = 0] = version3.split(".").map(Number);
|
|
23739
|
+
return maj > 22 || maj === 22 && min >= 12;
|
|
23740
|
+
}
|
|
23741
|
+
function pinNode(explicit) {
|
|
23742
|
+
const candidate = explicit ?? process.execPath;
|
|
23743
|
+
accessSync3(candidate, constants3.X_OK);
|
|
23744
|
+
const version3 = versionOf(candidate);
|
|
23745
|
+
if (!version3) throw new Error(`${candidate} does not look like a node binary`);
|
|
23746
|
+
if (!nodeOk(version3))
|
|
23747
|
+
throw new Error(`node ${version3} at ${candidate} is too old; need >= 22.12`);
|
|
23748
|
+
writeFileSync5(ensureDirs().nodePathFile, candidate);
|
|
23749
|
+
return { path: candidate, version: version3 };
|
|
23750
|
+
}
|
|
23751
|
+
function pinnedNode() {
|
|
23752
|
+
try {
|
|
23753
|
+
const path3 = readFileSync10(ensureDirs().nodePathFile, "utf8").trim();
|
|
23754
|
+
const version3 = versionOf(path3);
|
|
23755
|
+
return version3 ? { path: path3, version: version3 } : void 0;
|
|
23756
|
+
} catch {
|
|
23757
|
+
return void 0;
|
|
23758
|
+
}
|
|
23759
|
+
}
|
|
23760
|
+
function pinRoot(root) {
|
|
23761
|
+
if (!existsSync11(join14(root, "dist", "server.js")))
|
|
23762
|
+
throw new Error(`${root} has no dist/server.js; cannot pin it as the stable root`);
|
|
23763
|
+
writeFileSync5(ensureDirs().rootPathFile, root);
|
|
23764
|
+
return root;
|
|
23765
|
+
}
|
|
23766
|
+
function pinnedRoot() {
|
|
23767
|
+
try {
|
|
23768
|
+
const root = readFileSync10(ensureDirs().rootPathFile, "utf8").trim();
|
|
23769
|
+
return root && existsSync11(join14(root, "dist", "server.js")) ? root : void 0;
|
|
23770
|
+
} catch {
|
|
23771
|
+
return void 0;
|
|
23772
|
+
}
|
|
23773
|
+
}
|
|
23774
|
+
var init_node_resolve = __esm({
|
|
23775
|
+
"src/install/node-resolve.ts"() {
|
|
23776
|
+
"use strict";
|
|
23777
|
+
init_esm_shims();
|
|
23778
|
+
init_paths();
|
|
23779
|
+
init_shell();
|
|
23780
|
+
}
|
|
23781
|
+
});
|
|
23782
|
+
|
|
23649
23783
|
// src/install/doctor.ts
|
|
23650
23784
|
var doctor_exports = {};
|
|
23651
23785
|
__export(doctor_exports, {
|
|
23652
23786
|
fullDoctor: () => fullDoctor
|
|
23653
23787
|
});
|
|
23654
23788
|
import { spawn } from "child_process";
|
|
23655
|
-
import { existsSync as
|
|
23656
|
-
import { join as
|
|
23789
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
23790
|
+
import { join as join15 } from "path";
|
|
23657
23791
|
function mcpHandshake(bin, ms = 15e3) {
|
|
23658
23792
|
return new Promise((resolve9) => {
|
|
23659
23793
|
const child = spawn(bin, [], { stdio: ["pipe", "pipe", "pipe"] });
|
|
@@ -23688,8 +23822,8 @@ function mcpHandshake(bin, ms = 15e3) {
|
|
|
23688
23822
|
async function fullDoctor(opts = {}) {
|
|
23689
23823
|
const rec = readInstallRecord();
|
|
23690
23824
|
const stable = rec?.stableRoot ?? stableRoot();
|
|
23691
|
-
const hasStable =
|
|
23692
|
-
const bins = hasStable ? stable :
|
|
23825
|
+
const hasStable = existsSync12(join15(stable, "dist", "server.js"));
|
|
23826
|
+
const bins = hasStable ? stable : join15(process.argv[1] ?? "", "..", "..");
|
|
23693
23827
|
const fixed = [];
|
|
23694
23828
|
if (opts.fix && hasStable) {
|
|
23695
23829
|
try {
|
|
@@ -23714,7 +23848,7 @@ async function fullDoctor(opts = {}) {
|
|
|
23714
23848
|
checks.push({
|
|
23715
23849
|
name: "install",
|
|
23716
23850
|
ok: !!rec,
|
|
23717
|
-
detail: rec ? `v${rec.version} via ${rec.method} at ${rec.installedAt.slice(0, 10)} (${rec.stableRoot})` : "not installed (run `npx eminiar install`)"
|
|
23851
|
+
detail: rec ? `v${rec.version} via ${rec.method === "none" ? "cursor" : rec.method}${rec.wrote.cursor && rec.method !== "none" ? " + cursor" : ""} at ${rec.installedAt.slice(0, 10)} (${rec.stableRoot})` : "not installed (run `npx eminiar install`)"
|
|
23718
23852
|
});
|
|
23719
23853
|
const pinned = pinnedNode();
|
|
23720
23854
|
checks.push({
|
|
@@ -23751,14 +23885,29 @@ async function fullDoctor(opts = {}) {
|
|
|
23751
23885
|
detail: `${lines.join(" \xB7 ")}${drift}${liveOk ? "" : " \u2014 run `eminiar doctor --fix`, then `eminiar upgrade` if it still fails"}`
|
|
23752
23886
|
});
|
|
23753
23887
|
}
|
|
23754
|
-
} else {
|
|
23755
|
-
const s =
|
|
23888
|
+
} else if (rec.method === "settings") {
|
|
23889
|
+
const s = existsSync12(join15(process.env.HOME ?? "", ".claude", "settings.json")) ? readFileSync11(join15(process.env.HOME ?? "", ".claude", "settings.json"), "utf8") : "";
|
|
23756
23890
|
checks.push({
|
|
23757
23891
|
name: "hooks in settings.json",
|
|
23758
23892
|
ok: s.includes("em-hook"),
|
|
23759
23893
|
detail: s.includes("em-hook") ? "present" : "missing"
|
|
23760
23894
|
});
|
|
23761
23895
|
}
|
|
23896
|
+
if (rec?.wrote.cursor || cursorPresent()) {
|
|
23897
|
+
const cs = cursorStatus();
|
|
23898
|
+
const registered = !!rec?.wrote.cursor;
|
|
23899
|
+
checks.push({
|
|
23900
|
+
name: "Cursor",
|
|
23901
|
+
ok: registered ? cs.hooks && cs.mcp : true,
|
|
23902
|
+
detail: registered ? `${cs.hooks ? `hooks on ${cs.events.length} events` : "hooks missing from ~/.cursor/hooks.json"} \xB7 ${cs.mcp ? "MCP server in ~/.cursor/mcp.json" : "MCP server missing from ~/.cursor/mcp.json"}${cs.hooks && cs.mcp ? "" : " \u2014 run `npx eminiar install --cursor`"}` : cs.hooks || cs.mcp ? "partly configured by hand; `npx eminiar install --cursor` completes and tracks it" : "installed but not registered; `npx eminiar install --cursor` adds hooks, MCP server and skills"
|
|
23903
|
+
});
|
|
23904
|
+
if (registered && rec?.method === "settings")
|
|
23905
|
+
checks.push({
|
|
23906
|
+
name: "Cursor third-party import",
|
|
23907
|
+
ok: false,
|
|
23908
|
+
detail: "Cursor also runs the Claude Code hooks in ~/.claude/settings.json (Settings \u2192 Agents \u2192 Third-Party Imports, on by default), so each event fires twice there; turn that setting off or reinstall Claude Code with `--method plugin`"
|
|
23909
|
+
});
|
|
23910
|
+
}
|
|
23762
23911
|
const failed = needsAuthEntry();
|
|
23763
23912
|
if (failed && opts.fix && clearNeedsAuthEntry()) fixed.push("cached launch failure cleared");
|
|
23764
23913
|
const stillFailed = needsAuthEntry();
|
|
@@ -23769,8 +23918,8 @@ async function fullDoctor(opts = {}) {
|
|
|
23769
23918
|
});
|
|
23770
23919
|
if (opts.fix)
|
|
23771
23920
|
checks.push({ name: "fix", ok: true, detail: fixed.join(", ") || "nothing to fix" });
|
|
23772
|
-
const hookBin =
|
|
23773
|
-
if (
|
|
23921
|
+
const hookBin = join15(bins, "bin", "em-hook");
|
|
23922
|
+
if (existsSync12(hookBin)) {
|
|
23774
23923
|
const r = run(hookBin, ["--selftest"], { env: { ...process.env } });
|
|
23775
23924
|
checks.push({
|
|
23776
23925
|
name: "hook self-test",
|
|
@@ -23778,8 +23927,8 @@ async function fullDoctor(opts = {}) {
|
|
|
23778
23927
|
detail: r.ok ? r.stdout.trim() : r.stderr.trim().slice(-200) || "failed"
|
|
23779
23928
|
});
|
|
23780
23929
|
}
|
|
23781
|
-
const serverBin =
|
|
23782
|
-
if (
|
|
23930
|
+
const serverBin = join15(bins, "bin", "em-server");
|
|
23931
|
+
if (existsSync12(serverBin)) {
|
|
23783
23932
|
const reply = await mcpHandshake(serverBin);
|
|
23784
23933
|
checks.push({ name: "MCP handshake", ok: /^eminiar v|^ok$/.test(reply), detail: reply });
|
|
23785
23934
|
}
|
|
@@ -23791,10 +23940,10 @@ async function fullDoctor(opts = {}) {
|
|
|
23791
23940
|
ok: true,
|
|
23792
23941
|
detail: `${ctx.root} \xB7 ${db.countDocuments()} docs \xB7 ${db.memoryCount()} memories \xB7 graph ${db.graphCounts().nodes} nodes`
|
|
23793
23942
|
});
|
|
23794
|
-
const cfgFile =
|
|
23795
|
-
if (
|
|
23943
|
+
const cfgFile = join15(ctx.root, "eminiar.config.json");
|
|
23944
|
+
if (existsSync12(cfgFile)) {
|
|
23796
23945
|
try {
|
|
23797
|
-
const parsed = ConfigSchema.safeParse(JSON.parse(
|
|
23946
|
+
const parsed = ConfigSchema.safeParse(JSON.parse(readFileSync11(cfgFile, "utf8")));
|
|
23798
23947
|
checks.push({
|
|
23799
23948
|
name: "eminiar.config.json",
|
|
23800
23949
|
ok: parsed.success,
|
|
@@ -23817,9 +23966,9 @@ async function fullDoctor(opts = {}) {
|
|
|
23817
23966
|
ok: true,
|
|
23818
23967
|
detail: live2.length ? `running for this project (pid ${live2.join(", ")})` : "none running for this project right now; enforce routing annotates instead of denying until one connects"
|
|
23819
23968
|
});
|
|
23820
|
-
const projectMcp =
|
|
23821
|
-
if (
|
|
23822
|
-
const raw =
|
|
23969
|
+
const projectMcp = join15(ctx.root, ".mcp.json");
|
|
23970
|
+
if (existsSync12(projectMcp)) {
|
|
23971
|
+
const raw = readFileSync11(projectMcp, "utf8");
|
|
23823
23972
|
const bad = raw.includes(`\${CLAUDE_PLUGIN_ROOT}`) && raw.includes("em-server");
|
|
23824
23973
|
checks.push({
|
|
23825
23974
|
name: "project .mcp.json",
|
|
@@ -23849,6 +23998,7 @@ var init_doctor2 = __esm({
|
|
|
23849
23998
|
init_server_alive();
|
|
23850
23999
|
init_storage();
|
|
23851
24000
|
init_claude_config();
|
|
24001
|
+
init_cursor2();
|
|
23852
24002
|
init_materialize();
|
|
23853
24003
|
init_node_resolve();
|
|
23854
24004
|
init_register();
|
|
@@ -23949,8 +24099,8 @@ __export(install_exports, {
|
|
|
23949
24099
|
install: () => install,
|
|
23950
24100
|
writeTeamFiles: () => writeTeamFiles
|
|
23951
24101
|
});
|
|
23952
|
-
import { existsSync as
|
|
23953
|
-
import { join as
|
|
24102
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
24103
|
+
import { join as join16 } from "path";
|
|
23954
24104
|
async function install(opts) {
|
|
23955
24105
|
console.log(`eminiar v${version2()} installer`);
|
|
23956
24106
|
log.step("node");
|
|
@@ -23980,8 +24130,8 @@ async function install(opts) {
|
|
|
23980
24130
|
}
|
|
23981
24131
|
log.step("data directory");
|
|
23982
24132
|
const p = ensureDirs();
|
|
23983
|
-
if (!
|
|
23984
|
-
|
|
24133
|
+
if (!existsSync13(p.configFile))
|
|
24134
|
+
writeFileSync6(p.configFile, `${JSON.stringify(ConfigSchema.parse({}), null, 2)}
|
|
23985
24135
|
`);
|
|
23986
24136
|
globalDb();
|
|
23987
24137
|
log.ok(p.home);
|
|
@@ -23991,18 +24141,23 @@ async function install(opts) {
|
|
|
23991
24141
|
if (err) log.warn(`download failed (${err}); it will be retried lazily on first hybrid search`);
|
|
23992
24142
|
else log.ok("ready");
|
|
23993
24143
|
}
|
|
23994
|
-
|
|
23995
|
-
const
|
|
24144
|
+
const claude = claudeCli();
|
|
24145
|
+
const wantClaude = !opts.cursor || !!claude || !!opts.method;
|
|
24146
|
+
const method = opts.method ?? (claude ? "plugin" : "settings");
|
|
24147
|
+
const targets = [wantClaude ? `Claude Code (${method} method)` : "", opts.cursor ? "Cursor" : ""].filter(Boolean).join(" and ");
|
|
24148
|
+
log.step(`register with ${targets}`);
|
|
24149
|
+
if (opts.cursor && !cursorPresent())
|
|
24150
|
+
log.warn(`${cursorDirHint()} not found; Cursor files are written anyway for its first launch`);
|
|
23996
24151
|
if (!await confirm(
|
|
23997
|
-
`Register eminiar with
|
|
24152
|
+
`Register eminiar with ${targets}? This edits your user-level ${[wantClaude ? "Claude" : "", opts.cursor ? "Cursor" : ""].filter(Boolean).join(" and ")} config.`,
|
|
23998
24153
|
!!opts.yes
|
|
23999
24154
|
)) {
|
|
24000
24155
|
log.warn("skipped registration; re-run with --yes or confirm interactively");
|
|
24001
24156
|
return 1;
|
|
24002
24157
|
}
|
|
24003
24158
|
let wrote = {};
|
|
24004
|
-
let usedMethod = method;
|
|
24005
|
-
if (
|
|
24159
|
+
let usedMethod = wantClaude ? method : "none";
|
|
24160
|
+
if (usedMethod === "plugin") {
|
|
24006
24161
|
const r = registerPlugin(stable);
|
|
24007
24162
|
if (r.ok) {
|
|
24008
24163
|
log.ok(r.detail);
|
|
@@ -24018,15 +24173,27 @@ async function install(opts) {
|
|
|
24018
24173
|
"hooks written to ~/.claude/settings.json, MCP server to ~/.claude.json, skills to ~/.claude/skills"
|
|
24019
24174
|
);
|
|
24020
24175
|
}
|
|
24021
|
-
if (
|
|
24022
|
-
|
|
24023
|
-
|
|
24024
|
-
|
|
24025
|
-
if (
|
|
24026
|
-
|
|
24027
|
-
|
|
24176
|
+
if (wantClaude) {
|
|
24177
|
+
if (needsAuthEntry() && clearNeedsAuthEntry())
|
|
24178
|
+
log.ok("cleared Claude Code's cached connection failure for the plugin server");
|
|
24179
|
+
const wantStatusline = opts.statusline ?? (!!opts.yes && !opts.team);
|
|
24180
|
+
if (wantStatusline) {
|
|
24181
|
+
if (setStatusline(stable)) {
|
|
24182
|
+
wrote.statusline = true;
|
|
24183
|
+
log.ok("statusLine set to `eminiar statusline`");
|
|
24184
|
+
}
|
|
24028
24185
|
}
|
|
24029
24186
|
}
|
|
24187
|
+
if (opts.cursor) {
|
|
24188
|
+
wrote.cursor = registerCursor(stable);
|
|
24189
|
+
log.ok(
|
|
24190
|
+
`hooks written to ${cursorDirHint()}/hooks.json, MCP server to ${cursorDirHint()}/mcp.json, skills to ${cursorDirHint()}/skills`
|
|
24191
|
+
);
|
|
24192
|
+
if (usedMethod === "settings")
|
|
24193
|
+
log.warn(
|
|
24194
|
+
"Cursor also imports Claude Code hooks from ~/.claude/settings.json (Settings \u2192 Agents \u2192 Third-Party Imports); turn that off or each event fires twice in Cursor"
|
|
24195
|
+
);
|
|
24196
|
+
}
|
|
24030
24197
|
writeInstallRecord({
|
|
24031
24198
|
version: version2(),
|
|
24032
24199
|
method: usedMethod,
|
|
@@ -24038,21 +24205,25 @@ async function install(opts) {
|
|
|
24038
24205
|
});
|
|
24039
24206
|
if (opts.team) {
|
|
24040
24207
|
log.step("team defaults");
|
|
24041
|
-
writeTeamFiles(resolveProjectRoot(), opts.marketplace);
|
|
24208
|
+
writeTeamFiles(resolveProjectRoot(), opts.marketplace, { cursor: !!opts.cursor, stable });
|
|
24042
24209
|
}
|
|
24043
24210
|
log.step("doctor");
|
|
24044
24211
|
const checks = await fullDoctor();
|
|
24045
24212
|
console.log(formatDoctor(checks));
|
|
24213
|
+
const restart = [wantClaude ? "Claude Code" : "", opts.cursor ? "Cursor" : ""].filter(Boolean).join(" and ");
|
|
24046
24214
|
console.log(
|
|
24047
24215
|
`
|
|
24048
|
-
Restart
|
|
24216
|
+
Restart ${restart} to load eminiar. Try ${wantClaude ? "/em-doctor, then " : ""}em_execute with an intent.`
|
|
24049
24217
|
);
|
|
24050
24218
|
return checks.every((c) => c.ok) ? 0 : 1;
|
|
24051
24219
|
}
|
|
24052
|
-
function
|
|
24053
|
-
|
|
24054
|
-
|
|
24055
|
-
|
|
24220
|
+
function cursorDirHint() {
|
|
24221
|
+
return process.env.CURSOR_CONFIG_DIR || "~/.cursor";
|
|
24222
|
+
}
|
|
24223
|
+
function writeTeamFiles(root, marketplace, extra = {}) {
|
|
24224
|
+
const cfg = join16(root, "eminiar.config.json");
|
|
24225
|
+
if (!existsSync13(cfg)) {
|
|
24226
|
+
writeFileSync6(
|
|
24056
24227
|
cfg,
|
|
24057
24228
|
`${JSON.stringify(
|
|
24058
24229
|
{
|
|
@@ -24082,7 +24253,7 @@ function writeTeamFiles(root, marketplace) {
|
|
|
24082
24253
|
}
|
|
24083
24254
|
if (marketplace) {
|
|
24084
24255
|
const m = /^github:(.+)$/.exec(marketplace);
|
|
24085
|
-
const file3 =
|
|
24256
|
+
const file3 = join16(root, ".claude", "settings.json");
|
|
24086
24257
|
const settings = readJson2(file3);
|
|
24087
24258
|
const known = settings.extraKnownMarketplaces ?? {};
|
|
24088
24259
|
known.eminiar = m ? { source: { source: "github", repo: m[1] } } : { source: { source: "url", url: marketplace } };
|
|
@@ -24095,7 +24266,19 @@ function writeTeamFiles(root, marketplace) {
|
|
|
24095
24266
|
`${file3}: marketplace + enabledPlugins added \u2014 teammates are prompted to install on next launch`
|
|
24096
24267
|
);
|
|
24097
24268
|
} else {
|
|
24098
|
-
log.info(
|
|
24269
|
+
log.info(
|
|
24270
|
+
`teammates: \`npx eminiar install${extra.cursor ? " --cursor" : ""}\` (reads the committed eminiar.config.json)`
|
|
24271
|
+
);
|
|
24272
|
+
}
|
|
24273
|
+
if (extra.cursor) {
|
|
24274
|
+
const src = join16(extra.stable ?? "", "rules", "eminiar.mdc");
|
|
24275
|
+
const dst = join16(root, ".cursor", "rules", "eminiar.mdc");
|
|
24276
|
+
if (existsSync13(dst)) log.ok(`${dst} already exists`);
|
|
24277
|
+
else if (existsSync13(src)) {
|
|
24278
|
+
mkdirSync9(join16(root, ".cursor", "rules"), { recursive: true });
|
|
24279
|
+
copyFileSync2(src, dst);
|
|
24280
|
+
log.ok(`wrote ${dst} \u2014 commit it`);
|
|
24281
|
+
}
|
|
24099
24282
|
}
|
|
24100
24283
|
}
|
|
24101
24284
|
var init_install = __esm({
|
|
@@ -24109,6 +24292,7 @@ var init_install = __esm({
|
|
|
24109
24292
|
init_global();
|
|
24110
24293
|
init_version();
|
|
24111
24294
|
init_claude_config();
|
|
24295
|
+
init_cursor2();
|
|
24112
24296
|
init_doctor2();
|
|
24113
24297
|
init_materialize();
|
|
24114
24298
|
init_node_resolve();
|
|
@@ -24131,12 +24315,14 @@ async function upgrade() {
|
|
|
24131
24315
|
const fromCheckout = rec.fromSpec.startsWith("pack:") || rec.fromSpec === "self";
|
|
24132
24316
|
return install({
|
|
24133
24317
|
yes: true,
|
|
24134
|
-
|
|
24318
|
+
// "none" means Cursor-only last time; let install() decide again from what is present.
|
|
24319
|
+
method: rec.method === "none" ? void 0 : rec.method,
|
|
24135
24320
|
noModel: false,
|
|
24136
24321
|
spec: fromCheckout ? void 0 : "eminiar@latest",
|
|
24137
24322
|
force: fromCheckout,
|
|
24138
24323
|
node: rec.node,
|
|
24139
|
-
statusline: !!rec.wrote.statusline
|
|
24324
|
+
statusline: !!rec.wrote.statusline,
|
|
24325
|
+
cursor: !!rec.wrote.cursor
|
|
24140
24326
|
});
|
|
24141
24327
|
}
|
|
24142
24328
|
var init_upgrade = __esm({
|
|
@@ -24154,13 +24340,14 @@ var uninstall_exports = {};
|
|
|
24154
24340
|
__export(uninstall_exports, {
|
|
24155
24341
|
uninstall: () => uninstall
|
|
24156
24342
|
});
|
|
24157
|
-
import { existsSync as
|
|
24343
|
+
import { existsSync as existsSync14, rmSync as rmSync6 } from "fs";
|
|
24158
24344
|
async function uninstall(opts) {
|
|
24159
24345
|
const rec = readInstallRecord();
|
|
24160
24346
|
const p = paths();
|
|
24161
24347
|
const plan = [
|
|
24162
24348
|
rec?.method === "plugin" || !rec ? "claude plugin uninstall eminiar@eminiar + marketplace remove" : "",
|
|
24163
24349
|
rec?.method === "settings" ? "remove eminiar hook entries from ~/.claude/settings.json, mcpServers.eminiar from ~/.claude.json, em-* skills" : "",
|
|
24350
|
+
rec?.wrote.cursor ? "remove eminiar hook entries from ~/.cursor/hooks.json, mcpServers.eminiar from ~/.cursor/mcp.json, em-* skills from ~/.cursor/skills" : "",
|
|
24164
24351
|
rec?.wrote.statusline ? "clear the eminiar statusLine" : "",
|
|
24165
24352
|
`delete ${p.plugin}`,
|
|
24166
24353
|
opts.purgeData ? `delete ${p.home} (ALL indexes, memories, stats)` : `keep ${p.home} (indexes, memories, stats)`
|
|
@@ -24171,11 +24358,13 @@ async function uninstall(opts) {
|
|
|
24171
24358
|
const stable = rec?.stableRoot ?? `${p.plugin}/node_modules/eminiar`;
|
|
24172
24359
|
if (!rec || rec.method === "plugin") unregisterPlugin();
|
|
24173
24360
|
if (rec?.method === "settings") unregisterSettings(stable, rec.wrote);
|
|
24361
|
+
if (rec?.wrote.cursor) unregisterCursor(stable, rec.wrote.cursor);
|
|
24174
24362
|
if (rec?.wrote.statusline) clearStatusline(stable);
|
|
24175
|
-
if (
|
|
24176
|
-
if (opts.purgeData)
|
|
24177
|
-
else if (
|
|
24178
|
-
|
|
24363
|
+
if (existsSync14(p.plugin)) rmSync6(p.plugin, { recursive: true, force: true });
|
|
24364
|
+
if (opts.purgeData) rmSync6(p.home, { recursive: true, force: true });
|
|
24365
|
+
else if (existsSync14(p.installFile)) rmSync6(p.installFile, { force: true });
|
|
24366
|
+
const from = [rec?.method !== "none" ? "Claude Code" : "", rec?.wrote.cursor ? "Cursor" : ""].filter(Boolean).join(" and ");
|
|
24367
|
+
log.ok(`eminiar removed from ${from || "Claude Code"}; restart it to finish`);
|
|
24179
24368
|
return 0;
|
|
24180
24369
|
}
|
|
24181
24370
|
var init_uninstall = __esm({
|
|
@@ -24184,6 +24373,7 @@ var init_uninstall = __esm({
|
|
|
24184
24373
|
init_esm_shims();
|
|
24185
24374
|
init_paths();
|
|
24186
24375
|
init_claude_config();
|
|
24376
|
+
init_cursor2();
|
|
24187
24377
|
init_register();
|
|
24188
24378
|
init_shell();
|
|
24189
24379
|
}
|
|
@@ -30631,7 +30821,7 @@ __export(indexer_exports, {
|
|
|
30631
30821
|
indexContent: () => indexContent,
|
|
30632
30822
|
indexPath: () => indexPath
|
|
30633
30823
|
});
|
|
30634
|
-
import { readFileSync as
|
|
30824
|
+
import { readFileSync as readFileSync12, statSync } from "fs";
|
|
30635
30825
|
import { relative, resolve as resolve2 } from "path";
|
|
30636
30826
|
function indexContent(db, input2) {
|
|
30637
30827
|
const kind = input2.kind ?? (input2.contentType === "code" ? "code" : input2.contentType === "json" ? "json" : void 0);
|
|
@@ -30713,7 +30903,7 @@ function indexPath(db, root, target, opts = {}) {
|
|
|
30713
30903
|
summary.skipped.push({ path: rel, reason: `too large (${size} bytes)` });
|
|
30714
30904
|
continue;
|
|
30715
30905
|
}
|
|
30716
|
-
const content =
|
|
30906
|
+
const content = readFileSync12(file3, "utf8");
|
|
30717
30907
|
if (content.includes("\0")) {
|
|
30718
30908
|
summary.skipped.push({ path: rel, reason: "binary" });
|
|
30719
30909
|
continue;
|
|
@@ -32328,8 +32518,8 @@ var init_routes = __esm({
|
|
|
32328
32518
|
});
|
|
32329
32519
|
|
|
32330
32520
|
// src/graph/languages/parser.ts
|
|
32331
|
-
import { existsSync as
|
|
32332
|
-
import { extname as extname2, join as
|
|
32521
|
+
import { existsSync as existsSync15 } from "fs";
|
|
32522
|
+
import { extname as extname2, join as join17 } from "path";
|
|
32333
32523
|
function grammarFor(path3) {
|
|
32334
32524
|
switch (extname2(path3).toLowerCase()) {
|
|
32335
32525
|
case ".ts":
|
|
@@ -32362,8 +32552,8 @@ async function getParser(grammar) {
|
|
|
32362
32552
|
}
|
|
32363
32553
|
let lang = languages.get(grammar);
|
|
32364
32554
|
if (!lang) {
|
|
32365
|
-
const file3 =
|
|
32366
|
-
if (!
|
|
32555
|
+
const file3 = join17(pluginRoot(), "vendor", "grammars", `${grammar}.wasm`);
|
|
32556
|
+
if (!existsSync15(file3)) throw new Error(`grammar missing: ${file3}`);
|
|
32367
32557
|
lang = await parserMod.Language.load(file3);
|
|
32368
32558
|
languages.set(grammar, lang);
|
|
32369
32559
|
}
|
|
@@ -32421,8 +32611,8 @@ var init_parser = __esm({
|
|
|
32421
32611
|
});
|
|
32422
32612
|
|
|
32423
32613
|
// src/graph/languages/go.ts
|
|
32424
|
-
import { existsSync as
|
|
32425
|
-
import { dirname as dirname4, join as
|
|
32614
|
+
import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
|
|
32615
|
+
import { dirname as dirname4, join as join18, normalize, relative as relative2, resolve as resolve3 } from "path";
|
|
32426
32616
|
function goModule(root, fromAbs) {
|
|
32427
32617
|
let dir = dirname4(fromAbs);
|
|
32428
32618
|
while (dir.startsWith(root)) {
|
|
@@ -32430,9 +32620,9 @@ function goModule(root, fromAbs) {
|
|
|
32430
32620
|
if (hit !== void 0) {
|
|
32431
32621
|
if (hit) return hit;
|
|
32432
32622
|
} else {
|
|
32433
|
-
const file3 =
|
|
32434
|
-
if (
|
|
32435
|
-
const m = /^module\s+(\S+)/m.exec(
|
|
32623
|
+
const file3 = join18(dir, "go.mod");
|
|
32624
|
+
if (existsSync16(file3)) {
|
|
32625
|
+
const m = /^module\s+(\S+)/m.exec(readFileSync13(file3, "utf8"));
|
|
32436
32626
|
const info = m ? { module: m[1], dir } : null;
|
|
32437
32627
|
goModCache.set(dir, info);
|
|
32438
32628
|
if (info) return info;
|
|
@@ -32449,11 +32639,11 @@ function resolveGoPackage(root, fromRel, importPath) {
|
|
|
32449
32639
|
let dir;
|
|
32450
32640
|
if (importPath === mod.module) dir = mod.dir;
|
|
32451
32641
|
else if (importPath.startsWith(`${mod.module}/`))
|
|
32452
|
-
dir =
|
|
32453
|
-
if (!dir || !
|
|
32642
|
+
dir = join18(mod.dir, importPath.slice(mod.module.length + 1));
|
|
32643
|
+
if (!dir || !existsSync16(dir)) return [];
|
|
32454
32644
|
try {
|
|
32455
|
-
return
|
|
32456
|
-
(f) => normalize(relative2(root,
|
|
32645
|
+
return readdirSync6(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).sort().map(
|
|
32646
|
+
(f) => normalize(relative2(root, join18(dir, f))).split("\\").join("/")
|
|
32457
32647
|
);
|
|
32458
32648
|
} catch {
|
|
32459
32649
|
return [];
|
|
@@ -32855,13 +33045,13 @@ var init_go = __esm({
|
|
|
32855
33045
|
});
|
|
32856
33046
|
|
|
32857
33047
|
// src/graph/languages/php.ts
|
|
32858
|
-
import { readdirSync as
|
|
32859
|
-
import { dirname as dirname5, join as
|
|
33048
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync14, statSync as statSync2 } from "fs";
|
|
33049
|
+
import { dirname as dirname5, join as join19, normalize as normalize2, relative as relative3, resolve as resolve4 } from "path";
|
|
32860
33050
|
function readComposer(dir) {
|
|
32861
|
-
const file3 =
|
|
33051
|
+
const file3 = join19(dir, "composer.json");
|
|
32862
33052
|
if (!isFile(file3)) return null;
|
|
32863
33053
|
try {
|
|
32864
|
-
const json3 = JSON.parse(
|
|
33054
|
+
const json3 = JSON.parse(readFileSync14(file3, "utf8"));
|
|
32865
33055
|
const info = { dir, psr4: [], psr0: [], classmap: [], files: [], require: [] };
|
|
32866
33056
|
for (const key of ["autoload", "autoload-dev"]) {
|
|
32867
33057
|
const section = json3[key];
|
|
@@ -32903,7 +33093,7 @@ function phpFilesUnder(abs, budget) {
|
|
|
32903
33093
|
if (isFile(abs)) return abs.endsWith(".php") ? [abs] : [];
|
|
32904
33094
|
let entries;
|
|
32905
33095
|
try {
|
|
32906
|
-
entries =
|
|
33096
|
+
entries = readdirSync7(abs, { recursive: true, encoding: "utf8" });
|
|
32907
33097
|
} catch {
|
|
32908
33098
|
return [];
|
|
32909
33099
|
}
|
|
@@ -32911,7 +33101,7 @@ function phpFilesUnder(abs, budget) {
|
|
|
32911
33101
|
for (const e of entries) {
|
|
32912
33102
|
if (budget.left <= 0) break;
|
|
32913
33103
|
if (!e.endsWith(".php") || e.split(/[\\/]/).includes("vendor")) continue;
|
|
32914
|
-
out.push(
|
|
33104
|
+
out.push(join19(abs, e));
|
|
32915
33105
|
budget.left--;
|
|
32916
33106
|
}
|
|
32917
33107
|
return out;
|
|
@@ -32921,11 +33111,11 @@ function classmapClasses(root, auto) {
|
|
|
32921
33111
|
const classes = /* @__PURE__ */ new Map();
|
|
32922
33112
|
const budget = { left: CLASSMAP_MAX_FILES };
|
|
32923
33113
|
for (const entry of auto.classmap) {
|
|
32924
|
-
for (const f of phpFilesUnder(
|
|
33114
|
+
for (const f of phpFilesUnder(join19(auto.dir, entry), budget)) {
|
|
32925
33115
|
if (relative3(root, f).startsWith("..")) continue;
|
|
32926
33116
|
let code;
|
|
32927
33117
|
try {
|
|
32928
|
-
code =
|
|
33118
|
+
code = readFileSync14(f, "utf8");
|
|
32929
33119
|
} catch {
|
|
32930
33120
|
continue;
|
|
32931
33121
|
}
|
|
@@ -32945,11 +33135,11 @@ function autoloadedFunctions(root, auto) {
|
|
|
32945
33135
|
if (auto.functions) return auto.functions;
|
|
32946
33136
|
const functions = /* @__PURE__ */ new Map();
|
|
32947
33137
|
for (const entry of auto.files) {
|
|
32948
|
-
const f =
|
|
33138
|
+
const f = join19(auto.dir, entry);
|
|
32949
33139
|
if (!isFile(f) || relative3(root, f).startsWith("..")) continue;
|
|
32950
33140
|
let code;
|
|
32951
33141
|
try {
|
|
32952
|
-
code =
|
|
33142
|
+
code = readFileSync14(f, "utf8");
|
|
32953
33143
|
} catch {
|
|
32954
33144
|
continue;
|
|
32955
33145
|
}
|
|
@@ -32969,14 +33159,14 @@ function resolvePhpClass(root, fromRel, fqcn) {
|
|
|
32969
33159
|
for (const { prefix, dirs } of auto.psr4) {
|
|
32970
33160
|
if (!name.startsWith(prefix)) continue;
|
|
32971
33161
|
const rest2 = name.slice(prefix.length).split("\\");
|
|
32972
|
-
for (const d of dirs) candidates2.push(
|
|
33162
|
+
for (const d of dirs) candidates2.push(join19(auto.dir, d, ...rest2));
|
|
32973
33163
|
}
|
|
32974
33164
|
for (const { prefix, dirs } of auto.psr0) {
|
|
32975
33165
|
if (!name.startsWith(prefix)) continue;
|
|
32976
33166
|
const cut = name.lastIndexOf("\\");
|
|
32977
33167
|
const ns = cut === -1 ? [] : name.slice(0, cut).split("\\");
|
|
32978
33168
|
const cls = name.slice(cut + 1).split("_");
|
|
32979
|
-
for (const d of dirs) candidates2.push(
|
|
33169
|
+
for (const d of dirs) candidates2.push(join19(auto.dir, d, ...ns, ...cls));
|
|
32980
33170
|
}
|
|
32981
33171
|
} else {
|
|
32982
33172
|
const parts = name.split("\\");
|
|
@@ -33213,7 +33403,7 @@ async function parsePhp(root, rel, code) {
|
|
|
33213
33403
|
for (let i = left.includes("__FILE__") ? 1 : 0; i < Number(up[1] ?? 1); i++)
|
|
33214
33404
|
base = dirname5(base);
|
|
33215
33405
|
}
|
|
33216
|
-
if (base && right !== void 0) candidates2.push(
|
|
33406
|
+
if (base && right !== void 0) candidates2.push(join19(base, right));
|
|
33217
33407
|
}
|
|
33218
33408
|
const hit = candidates2.find((c) => isFile(c) && !relative3(root, c).startsWith(".."));
|
|
33219
33409
|
if (!hit) continue;
|
|
@@ -33922,25 +34112,25 @@ var init_php = __esm({
|
|
|
33922
34112
|
});
|
|
33923
34113
|
|
|
33924
34114
|
// src/graph/languages/python.ts
|
|
33925
|
-
import { existsSync as
|
|
33926
|
-
import { dirname as dirname6, join as
|
|
34115
|
+
import { existsSync as existsSync17, statSync as statSync3 } from "fs";
|
|
34116
|
+
import { dirname as dirname6, join as join20, normalize as normalize3, relative as relative4, resolve as resolve5 } from "path";
|
|
33927
34117
|
function resolvePython(root, fromRel, module, level) {
|
|
33928
34118
|
const parts = module ? module.split(".") : [];
|
|
33929
34119
|
const candidates2 = [];
|
|
33930
34120
|
if (level > 0) {
|
|
33931
34121
|
let base = dirname6(resolve5(root, fromRel));
|
|
33932
34122
|
for (let i = 1; i < level; i++) base = dirname6(base);
|
|
33933
|
-
candidates2.push(
|
|
34123
|
+
candidates2.push(join20(base, ...parts));
|
|
33934
34124
|
} else {
|
|
33935
34125
|
candidates2.push(resolve5(root, ...parts), resolve5(root, "src", ...parts));
|
|
33936
34126
|
let dir = dirname6(resolve5(root, fromRel));
|
|
33937
34127
|
while (dir.startsWith(root) && dir !== root) {
|
|
33938
|
-
candidates2.push(
|
|
34128
|
+
candidates2.push(join20(dir, ...parts));
|
|
33939
34129
|
dir = dirname6(dir);
|
|
33940
34130
|
}
|
|
33941
34131
|
}
|
|
33942
34132
|
for (const c of candidates2) {
|
|
33943
|
-
for (const f of [`${c}.py`,
|
|
34133
|
+
for (const f of [`${c}.py`, join20(c, "__init__.py"), `${c}.pyi`]) {
|
|
33944
34134
|
if (isFile2(f) && !relative4(root, f).startsWith(".."))
|
|
33945
34135
|
return normalize3(relative4(root, f)).split("\\").join("/");
|
|
33946
34136
|
}
|
|
@@ -33979,7 +34169,7 @@ async function parsePython(root, rel, code) {
|
|
|
33979
34169
|
walkRefs(stmt);
|
|
33980
34170
|
}
|
|
33981
34171
|
edges.push(...refs.edges());
|
|
33982
|
-
if (!
|
|
34172
|
+
if (!existsSync17(join20(root, rel))) {
|
|
33983
34173
|
}
|
|
33984
34174
|
const errors = tree.rootNode.hasError ? tree.rootNode.descendantsOfType("ERROR").length : 0;
|
|
33985
34175
|
fileNode.meta = {
|
|
@@ -34326,16 +34516,16 @@ var init_python = __esm({
|
|
|
34326
34516
|
});
|
|
34327
34517
|
|
|
34328
34518
|
// src/graph/resolve.ts
|
|
34329
|
-
import { existsSync as
|
|
34330
|
-
import { dirname as dirname7, join as
|
|
34519
|
+
import { existsSync as existsSync18, readdirSync as readdirSync8, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
|
|
34520
|
+
import { dirname as dirname7, join as join21, normalize as normalize4, relative as relative5, resolve as resolve6 } from "path";
|
|
34331
34521
|
function loadTsPaths(root) {
|
|
34332
34522
|
const hit = tsPathsCache.get(root);
|
|
34333
34523
|
if (hit !== void 0) return hit;
|
|
34334
34524
|
let out = null;
|
|
34335
34525
|
try {
|
|
34336
|
-
const file3 =
|
|
34337
|
-
if (
|
|
34338
|
-
const raw =
|
|
34526
|
+
const file3 = join21(root, "tsconfig.json");
|
|
34527
|
+
if (existsSync18(file3)) {
|
|
34528
|
+
const raw = readFileSync15(file3, "utf8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
|
|
34339
34529
|
const cfg = JSON.parse(raw);
|
|
34340
34530
|
const co = cfg.compilerOptions ?? {};
|
|
34341
34531
|
if (co.paths) {
|
|
@@ -34373,16 +34563,16 @@ function probe(abs) {
|
|
|
34373
34563
|
if (tryFile(abs + ext)) return abs + ext;
|
|
34374
34564
|
}
|
|
34375
34565
|
for (const ext of EXTS) {
|
|
34376
|
-
const idx =
|
|
34566
|
+
const idx = join21(abs, `index${ext}`);
|
|
34377
34567
|
if (tryFile(idx)) return idx;
|
|
34378
34568
|
}
|
|
34379
34569
|
return void 0;
|
|
34380
34570
|
}
|
|
34381
34571
|
function readPackageJson(dir) {
|
|
34382
34572
|
try {
|
|
34383
|
-
const file3 =
|
|
34384
|
-
if (!
|
|
34385
|
-
return JSON.parse(
|
|
34573
|
+
const file3 = join21(dir, "package.json");
|
|
34574
|
+
if (!existsSync18(file3)) return void 0;
|
|
34575
|
+
return JSON.parse(readFileSync15(file3, "utf8"));
|
|
34386
34576
|
} catch {
|
|
34387
34577
|
return void 0;
|
|
34388
34578
|
}
|
|
@@ -34398,9 +34588,9 @@ function loadWorkspaces(root) {
|
|
|
34398
34588
|
if (Array.isArray(ws)) globs.push(...ws);
|
|
34399
34589
|
else if (ws?.packages) globs.push(...ws.packages);
|
|
34400
34590
|
try {
|
|
34401
|
-
const yaml =
|
|
34402
|
-
if (
|
|
34403
|
-
for (const m of
|
|
34591
|
+
const yaml = join21(root, "pnpm-workspace.yaml");
|
|
34592
|
+
if (existsSync18(yaml)) {
|
|
34593
|
+
for (const m of readFileSync15(yaml, "utf8").matchAll(/^\s*-\s*['"]?([^'"\n#]+?)['"]?\s*$/gm))
|
|
34404
34594
|
globs.push(m[1].trim());
|
|
34405
34595
|
}
|
|
34406
34596
|
} catch {
|
|
@@ -34413,8 +34603,8 @@ function loadWorkspaces(root) {
|
|
|
34413
34603
|
else {
|
|
34414
34604
|
const base = resolve6(root, g.slice(0, star));
|
|
34415
34605
|
try {
|
|
34416
|
-
for (const d of
|
|
34417
|
-
if (d.isDirectory()) dirs.push(
|
|
34606
|
+
for (const d of readdirSync8(base, { withFileTypes: true })) {
|
|
34607
|
+
if (d.isDirectory()) dirs.push(join21(base, d.name));
|
|
34418
34608
|
}
|
|
34419
34609
|
} catch {
|
|
34420
34610
|
}
|
|
@@ -35557,8 +35747,8 @@ var init_link = __esm({
|
|
|
35557
35747
|
});
|
|
35558
35748
|
|
|
35559
35749
|
// src/graph/reindex.ts
|
|
35560
|
-
import { readFileSync as
|
|
35561
|
-
import { join as
|
|
35750
|
+
import { readFileSync as readFileSync16, statSync as statSync5 } from "fs";
|
|
35751
|
+
import { join as join22 } from "path";
|
|
35562
35752
|
function listCodeFiles(ctx) {
|
|
35563
35753
|
return import_fast_glob2.default.sync(ctx.config.graph.include, {
|
|
35564
35754
|
cwd: ctx.root,
|
|
@@ -35569,7 +35759,7 @@ function listCodeFiles(ctx) {
|
|
|
35569
35759
|
});
|
|
35570
35760
|
}
|
|
35571
35761
|
async function indexOne(ctx, db, rel, force) {
|
|
35572
|
-
const abs =
|
|
35762
|
+
const abs = join22(ctx.root, rel);
|
|
35573
35763
|
const st = statSync5(abs);
|
|
35574
35764
|
const backend = getCodeBackend(ctx);
|
|
35575
35765
|
const language = backend.languageOf(rel) ?? null;
|
|
@@ -35589,7 +35779,7 @@ async function indexOne(ctx, db, rel, force) {
|
|
|
35589
35779
|
}
|
|
35590
35780
|
return "skipped";
|
|
35591
35781
|
}
|
|
35592
|
-
const code =
|
|
35782
|
+
const code = readFileSync16(abs, "utf8");
|
|
35593
35783
|
const hash2 = hashText(code);
|
|
35594
35784
|
const prev = db.fileIndexGet(rel);
|
|
35595
35785
|
if (!force && prev?.hash === hash2 && prev.status !== "skipped") return "unchanged";
|
|
@@ -35670,7 +35860,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
35670
35860
|
summary.unsupported++;
|
|
35671
35861
|
if (db.fileIndexGet(rel)?.status === "unsupported") continue;
|
|
35672
35862
|
try {
|
|
35673
|
-
const st = statSync5(
|
|
35863
|
+
const st = statSync5(join22(ctx.root, rel));
|
|
35674
35864
|
db.fileIndexSet({
|
|
35675
35865
|
path: rel,
|
|
35676
35866
|
hash: "",
|
|
@@ -35686,7 +35876,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
35686
35876
|
}
|
|
35687
35877
|
for (const rel of targets) {
|
|
35688
35878
|
try {
|
|
35689
|
-
if (!statSafe(
|
|
35879
|
+
if (!statSafe(join22(ctx.root, rel))) {
|
|
35690
35880
|
if (db.fileIndexGet(rel)) {
|
|
35691
35881
|
removeOne(db, rel);
|
|
35692
35882
|
summary.removed++;
|
|
@@ -35698,7 +35888,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
35698
35888
|
const error62 = err.message;
|
|
35699
35889
|
summary.errors.push({ path: rel, error: error62 });
|
|
35700
35890
|
try {
|
|
35701
|
-
const st = statSync5(
|
|
35891
|
+
const st = statSync5(join22(ctx.root, rel));
|
|
35702
35892
|
db.fileIndexSet({
|
|
35703
35893
|
path: rel,
|
|
35704
35894
|
hash: "",
|
|
@@ -35801,10 +35991,10 @@ function indexFreshness(ctx, db) {
|
|
|
35801
35991
|
const dirty = [];
|
|
35802
35992
|
for (const r of rows.slice(0, 400)) {
|
|
35803
35993
|
try {
|
|
35804
|
-
const abs =
|
|
35994
|
+
const abs = join22(ctx.root, r.path);
|
|
35805
35995
|
const st = statSync5(abs);
|
|
35806
35996
|
if (r.mtime !== null && Math.abs(st.mtimeMs - r.mtime) < 1 && st.size === r.size) continue;
|
|
35807
|
-
if (hashText(
|
|
35997
|
+
if (hashText(readFileSync16(abs, "utf8")) !== r.hash) dirty.push(r.path);
|
|
35808
35998
|
} catch {
|
|
35809
35999
|
dirty.push(r.path);
|
|
35810
36000
|
}
|
|
@@ -35838,10 +36028,10 @@ var init_reindex = __esm({
|
|
|
35838
36028
|
});
|
|
35839
36029
|
|
|
35840
36030
|
// src/session/current.ts
|
|
35841
|
-
import { readFileSync as
|
|
35842
|
-
import { join as
|
|
36031
|
+
import { readFileSync as readFileSync17, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
36032
|
+
import { join as join23 } from "path";
|
|
35843
36033
|
function file2(ctx) {
|
|
35844
|
-
return
|
|
36034
|
+
return join23(projectDir(ctx.id), "current-session");
|
|
35845
36035
|
}
|
|
35846
36036
|
function getCurrentSession(ctx) {
|
|
35847
36037
|
if (process.env.EMINIAR_SESSION_ID) return process.env.EMINIAR_SESSION_ID;
|
|
@@ -35853,7 +36043,7 @@ function getCurrentSession(ctx) {
|
|
|
35853
36043
|
return "unknown";
|
|
35854
36044
|
}
|
|
35855
36045
|
if (cached4 && cached4.file === f && cached4.mtimeMs === mtimeMs) return cached4.id;
|
|
35856
|
-
const id =
|
|
36046
|
+
const id = readFileSync17(f, "utf8").trim() || "unknown";
|
|
35857
36047
|
cached4 = { file: f, mtimeMs, id };
|
|
35858
36048
|
return id;
|
|
35859
36049
|
}
|
|
@@ -36024,15 +36214,15 @@ __export(store_exports, {
|
|
|
36024
36214
|
write: () => write
|
|
36025
36215
|
});
|
|
36026
36216
|
import {
|
|
36027
|
-
existsSync as
|
|
36028
|
-
mkdirSync as
|
|
36029
|
-
readFileSync as
|
|
36217
|
+
existsSync as existsSync19,
|
|
36218
|
+
mkdirSync as mkdirSync10,
|
|
36219
|
+
readFileSync as readFileSync18,
|
|
36030
36220
|
renameSync,
|
|
36031
36221
|
statSync as statSync7,
|
|
36032
36222
|
unlinkSync,
|
|
36033
|
-
writeFileSync as
|
|
36223
|
+
writeFileSync as writeFileSync8
|
|
36034
36224
|
} from "fs";
|
|
36035
|
-
import { dirname as dirname8, join as
|
|
36225
|
+
import { dirname as dirname8, join as join24, relative as relative6, sep } from "path";
|
|
36036
36226
|
function isStatus(s) {
|
|
36037
36227
|
return typeof s === "string" && MEMORY_STATUSES.includes(s);
|
|
36038
36228
|
}
|
|
@@ -36046,13 +36236,13 @@ function memoriesRel(ctx) {
|
|
|
36046
36236
|
return ctx.config.memories.dir.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
36047
36237
|
}
|
|
36048
36238
|
function memoriesDir(ctx) {
|
|
36049
|
-
return
|
|
36239
|
+
return join24(ctx.root, memoriesRel(ctx));
|
|
36050
36240
|
}
|
|
36051
36241
|
function relOf(ctx, name) {
|
|
36052
36242
|
return `${memoriesRel(ctx)}/${name}.md`;
|
|
36053
36243
|
}
|
|
36054
36244
|
function absOf(ctx, name) {
|
|
36055
|
-
return
|
|
36245
|
+
return join24(ctx.root, relOf(ctx, name));
|
|
36056
36246
|
}
|
|
36057
36247
|
function nameOfFile(ctx, abs) {
|
|
36058
36248
|
const rel = relative6(memoriesDir(ctx), abs).split(sep).join("/");
|
|
@@ -36110,7 +36300,7 @@ function impliedFileLinks(root, body, skipPrefix) {
|
|
|
36110
36300
|
if (!p || p.startsWith("..") || out.has(p) || skipPrefix && p.startsWith(`${skipPrefix}/`))
|
|
36111
36301
|
continue;
|
|
36112
36302
|
try {
|
|
36113
|
-
if (statSync7(
|
|
36303
|
+
if (statSync7(join24(root, p)).isFile()) out.add(p);
|
|
36114
36304
|
} catch {
|
|
36115
36305
|
}
|
|
36116
36306
|
if (out.size >= 30) break;
|
|
@@ -36119,8 +36309,8 @@ function impliedFileLinks(root, body, skipPrefix) {
|
|
|
36119
36309
|
}
|
|
36120
36310
|
function writeMemoryFile(ctx, name, meta4, body) {
|
|
36121
36311
|
const abs = absOf(ctx, name);
|
|
36122
|
-
|
|
36123
|
-
|
|
36312
|
+
mkdirSync10(dirname8(abs), { recursive: true });
|
|
36313
|
+
writeFileSync8(abs, serializeMemoryFile(meta4, `
|
|
36124
36314
|
${body.trim()}
|
|
36125
36315
|
`));
|
|
36126
36316
|
}
|
|
@@ -36158,13 +36348,13 @@ function forgetInDb(db, name, rel) {
|
|
|
36158
36348
|
function syncFile(ctx, db, name, opts = {}) {
|
|
36159
36349
|
const abs = absOf(ctx, name);
|
|
36160
36350
|
const rel = relOf(ctx, name);
|
|
36161
|
-
if (!
|
|
36351
|
+
if (!existsSync19(abs)) return void 0;
|
|
36162
36352
|
let st = statSync7(abs);
|
|
36163
36353
|
const row = db.memoryGetByName(name);
|
|
36164
36354
|
const mtime = Math.floor(st.mtimeMs);
|
|
36165
36355
|
if (!opts.force && row && row.file_mtime === mtime && row.file_size === st.size)
|
|
36166
36356
|
return { changed: false, row };
|
|
36167
|
-
let text3 =
|
|
36357
|
+
let text3 = readFileSync18(abs, "utf8");
|
|
36168
36358
|
let hash2 = hashText(text3);
|
|
36169
36359
|
if (!opts.force && row && row.file_hash === hash2) {
|
|
36170
36360
|
db.memoryUpsertByName({
|
|
@@ -36202,7 +36392,7 @@ function syncFile(ctx, db, name, opts = {}) {
|
|
|
36202
36392
|
parsed.hadFrontmatter ? parsed.body : `
|
|
36203
36393
|
${parsed.body.replace(/^\s*\n/, "")}`
|
|
36204
36394
|
);
|
|
36205
|
-
|
|
36395
|
+
writeFileSync8(abs, text3);
|
|
36206
36396
|
st = statSync7(abs);
|
|
36207
36397
|
hash2 = hashText(text3);
|
|
36208
36398
|
}
|
|
@@ -36244,15 +36434,15 @@ tags: ${tags.join(", ")}` : ""}`,
|
|
|
36244
36434
|
}
|
|
36245
36435
|
function setMeta(ctx, db, name, patch) {
|
|
36246
36436
|
const abs = absOf(ctx, name);
|
|
36247
|
-
if (!
|
|
36248
|
-
const parsed = parseMemoryFile(
|
|
36437
|
+
if (!existsSync19(abs)) return false;
|
|
36438
|
+
const parsed = parseMemoryFile(readFileSync18(abs, "utf8"));
|
|
36249
36439
|
const meta4 = { ...parsed.meta };
|
|
36250
36440
|
for (const [k, v] of Object.entries(patch)) {
|
|
36251
36441
|
if (v === void 0) delete meta4[k];
|
|
36252
36442
|
else meta4[k] = v;
|
|
36253
36443
|
}
|
|
36254
36444
|
meta4.updated = (/* @__PURE__ */ new Date()).toISOString();
|
|
36255
|
-
|
|
36445
|
+
writeFileSync8(abs, serializeMemoryFile(meta4, parsed.body));
|
|
36256
36446
|
syncFile(ctx, db, name, { force: true });
|
|
36257
36447
|
return true;
|
|
36258
36448
|
}
|
|
@@ -36261,10 +36451,10 @@ function migrateLegacy(ctx, db) {
|
|
|
36261
36451
|
for (const row of db.memoryLegacyRows()) {
|
|
36262
36452
|
const kind = isKind(row.kind) ? row.kind : "note";
|
|
36263
36453
|
const base = `${kind}/${slugify2(row.content)}`;
|
|
36264
|
-
const taken =
|
|
36454
|
+
const taken = existsSync19(absOf(ctx, base)) || !!db.memoryGetByName(base);
|
|
36265
36455
|
const name = taken ? `${base}-${row.id}` : base;
|
|
36266
36456
|
const created = new Date(row.created_at).toISOString();
|
|
36267
|
-
if (!
|
|
36457
|
+
if (!existsSync19(absOf(ctx, name))) {
|
|
36268
36458
|
writeMemoryFile(
|
|
36269
36459
|
ctx,
|
|
36270
36460
|
name,
|
|
@@ -36289,7 +36479,7 @@ function reconcile(ctx, db) {
|
|
|
36289
36479
|
const out = { files: 0, synced: 0, removed: 0, migrated: 0, skipped: [] };
|
|
36290
36480
|
out.migrated = migrateLegacy(ctx, db);
|
|
36291
36481
|
const dir = memoriesDir(ctx);
|
|
36292
|
-
const files =
|
|
36482
|
+
const files = existsSync19(dir) ? import_fast_glob3.default.sync("**/*.md", { cwd: dir, absolute: true, onlyFiles: true, dot: true }) : [];
|
|
36293
36483
|
const seen = /* @__PURE__ */ new Set();
|
|
36294
36484
|
for (const f of files) {
|
|
36295
36485
|
const name = nameOfFile(ctx, f);
|
|
@@ -36317,7 +36507,7 @@ function write(ctx, db, input2) {
|
|
|
36317
36507
|
);
|
|
36318
36508
|
const abs = absOf(ctx, name);
|
|
36319
36509
|
const prev = db.memoryGetByName(name);
|
|
36320
|
-
const exists = !!prev ||
|
|
36510
|
+
const exists = !!prev || existsSync19(abs);
|
|
36321
36511
|
if (exists && !input2.replace)
|
|
36322
36512
|
throw new Error(
|
|
36323
36513
|
`memory "${name}" already exists; pass replace: true to overwrite it, or em_memory {action: "edit"} to change part of it`
|
|
@@ -36326,7 +36516,7 @@ function write(ctx, db, input2) {
|
|
|
36326
36516
|
let extra = {};
|
|
36327
36517
|
if (exists) {
|
|
36328
36518
|
try {
|
|
36329
|
-
extra = parseMemoryFile(
|
|
36519
|
+
extra = parseMemoryFile(readFileSync18(abs, "utf8")).meta;
|
|
36330
36520
|
} catch {
|
|
36331
36521
|
}
|
|
36332
36522
|
}
|
|
@@ -36353,7 +36543,7 @@ function write(ctx, db, input2) {
|
|
|
36353
36543
|
function read(ctx, db, name) {
|
|
36354
36544
|
const synced = syncFile(ctx, db, name);
|
|
36355
36545
|
if (!synced) return void 0;
|
|
36356
|
-
const parsed = parseMemoryFile(
|
|
36546
|
+
const parsed = parseMemoryFile(readFileSync18(absOf(ctx, name), "utf8"));
|
|
36357
36547
|
return {
|
|
36358
36548
|
name,
|
|
36359
36549
|
kind: synced.row.kind,
|
|
@@ -36378,14 +36568,14 @@ function escapeRe(s) {
|
|
|
36378
36568
|
}
|
|
36379
36569
|
function edit(ctx, db, name, opts) {
|
|
36380
36570
|
const abs = absOf(ctx, name);
|
|
36381
|
-
if (!
|
|
36571
|
+
if (!existsSync19(abs)) throw new Error(`memory "${name}" does not exist`);
|
|
36382
36572
|
syncFile(ctx, db, name);
|
|
36383
|
-
const parsed = parseMemoryFile(
|
|
36573
|
+
const parsed = parseMemoryFile(readFileSync18(abs, "utf8"));
|
|
36384
36574
|
const re = new RegExp(opts.regex ? opts.find : escapeRe(opts.find), "g");
|
|
36385
36575
|
const count = (parsed.body.match(re) ?? []).length;
|
|
36386
36576
|
if (!count) return 0;
|
|
36387
36577
|
const body = parsed.body.replace(re, opts.replace);
|
|
36388
|
-
|
|
36578
|
+
writeFileSync8(
|
|
36389
36579
|
abs,
|
|
36390
36580
|
serializeMemoryFile({ ...parsed.meta, updated: (/* @__PURE__ */ new Date()).toISOString() }, body)
|
|
36391
36581
|
);
|
|
@@ -36396,12 +36586,12 @@ function rename(ctx, db, from, to) {
|
|
|
36396
36586
|
if (!isValidName(to)) throw new Error(`invalid memory name "${to}"`);
|
|
36397
36587
|
const absFrom = absOf(ctx, from);
|
|
36398
36588
|
const absTo = absOf(ctx, to);
|
|
36399
|
-
if (!
|
|
36400
|
-
if (
|
|
36401
|
-
|
|
36589
|
+
if (!existsSync19(absFrom)) throw new Error(`memory "${from}" does not exist`);
|
|
36590
|
+
if (existsSync19(absTo) || db.memoryGetByName(to)) throw new Error(`memory "${to}" already exists`);
|
|
36591
|
+
mkdirSync10(dirname8(absTo), { recursive: true });
|
|
36402
36592
|
renameSync(absFrom, absTo);
|
|
36403
|
-
const parsed = parseMemoryFile(
|
|
36404
|
-
|
|
36593
|
+
const parsed = parseMemoryFile(readFileSync18(absTo, "utf8"));
|
|
36594
|
+
writeFileSync8(
|
|
36405
36595
|
absTo,
|
|
36406
36596
|
serializeMemoryFile(
|
|
36407
36597
|
{ ...parsed.meta, name: to, updated: (/* @__PURE__ */ new Date()).toISOString() },
|
|
@@ -36415,11 +36605,11 @@ function rename(ctx, db, from, to) {
|
|
|
36415
36605
|
for (const row of db.memoryList({ limit: 1e5 })) {
|
|
36416
36606
|
if (!row.name || row.name === to) continue;
|
|
36417
36607
|
const abs = absOf(ctx, row.name);
|
|
36418
|
-
if (!
|
|
36419
|
-
const text3 =
|
|
36608
|
+
if (!existsSync19(abs)) continue;
|
|
36609
|
+
const text3 = readFileSync18(abs, "utf8");
|
|
36420
36610
|
if (!ref.test(text3)) continue;
|
|
36421
36611
|
ref.lastIndex = 0;
|
|
36422
|
-
|
|
36612
|
+
writeFileSync8(abs, text3.replace(ref, `mem:${to}`));
|
|
36423
36613
|
syncFile(ctx, db, row.name, { force: true });
|
|
36424
36614
|
refsUpdated++;
|
|
36425
36615
|
}
|
|
@@ -36427,19 +36617,19 @@ function rename(ctx, db, from, to) {
|
|
|
36427
36617
|
}
|
|
36428
36618
|
function remove(ctx, db, name) {
|
|
36429
36619
|
const abs = absOf(ctx, name);
|
|
36430
|
-
const existed =
|
|
36431
|
-
if (
|
|
36620
|
+
const existed = existsSync19(abs) || !!db.memoryGetByName(name);
|
|
36621
|
+
if (existsSync19(abs)) unlinkSync(abs);
|
|
36432
36622
|
forgetInDb(db, name, relOf(ctx, name));
|
|
36433
36623
|
return existed;
|
|
36434
36624
|
}
|
|
36435
36625
|
function gitignoreHint(ctx) {
|
|
36436
36626
|
if (hinted.has(ctx.root)) return void 0;
|
|
36437
36627
|
hinted.add(ctx.root);
|
|
36438
|
-
const file3 =
|
|
36439
|
-
if (!
|
|
36628
|
+
const file3 = join24(ctx.root, ".gitignore");
|
|
36629
|
+
if (!existsSync19(file3)) return void 0;
|
|
36440
36630
|
const dir = memoriesRel(ctx);
|
|
36441
36631
|
const top2 = dir.split("/")[0];
|
|
36442
|
-
const ignored =
|
|
36632
|
+
const ignored = readFileSync18(file3, "utf8").split(/\r?\n/).map((l) => l.trim().replace(/^\//, "").replace(/\/$/, "")).some((l) => l === top2 || l === dir || l === `${top2}/**` || l === `${dir}/**`);
|
|
36443
36633
|
return ignored ? `note: .gitignore ignores ${dir}, so memories stay local to this machine (remove that line to share them with the team)` : void 0;
|
|
36444
36634
|
}
|
|
36445
36635
|
var import_fast_glob3, MEMORY_KINDS, SEGMENT, NAME_RE, MEM_LINK_RE, PATH_RE, hinted;
|
|
@@ -37069,12 +37259,12 @@ var init_em_graph_changes = __esm({
|
|
|
37069
37259
|
});
|
|
37070
37260
|
|
|
37071
37261
|
// src/graph/architecture.ts
|
|
37072
|
-
import { existsSync as
|
|
37073
|
-
import { join as
|
|
37262
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
|
|
37263
|
+
import { join as join25 } from "path";
|
|
37074
37264
|
function pkgJson(root) {
|
|
37075
37265
|
try {
|
|
37076
|
-
const f =
|
|
37077
|
-
return
|
|
37266
|
+
const f = join25(root, "package.json");
|
|
37267
|
+
return existsSync20(f) ? JSON.parse(readFileSync19(f, "utf8")) : {};
|
|
37078
37268
|
} catch {
|
|
37079
37269
|
return {};
|
|
37080
37270
|
}
|
|
@@ -38426,8 +38616,8 @@ var init_catalog = __esm({
|
|
|
38426
38616
|
});
|
|
38427
38617
|
|
|
38428
38618
|
// src/docs/manifest.ts
|
|
38429
|
-
import { existsSync as
|
|
38430
|
-
import { dirname as dirname9, join as
|
|
38619
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync9 } from "fs";
|
|
38620
|
+
import { dirname as dirname9, join as join26 } from "path";
|
|
38431
38621
|
function docsTag(name) {
|
|
38432
38622
|
return `${DOCS_PREFIX}${name}`;
|
|
38433
38623
|
}
|
|
@@ -38442,7 +38632,7 @@ function slugify3(input2) {
|
|
|
38442
38632
|
return (s || "source").slice(0, 64);
|
|
38443
38633
|
}
|
|
38444
38634
|
function manifestPathAt(root, rel = ".eminiar/docs.json") {
|
|
38445
|
-
return
|
|
38635
|
+
return join26(root, rel);
|
|
38446
38636
|
}
|
|
38447
38637
|
function manifestPath(ctx) {
|
|
38448
38638
|
return manifestPathAt(ctx.root, ctx.config.docs.manifest);
|
|
@@ -38470,9 +38660,9 @@ function normalize5(raw) {
|
|
|
38470
38660
|
return { version: 1, sources: out };
|
|
38471
38661
|
}
|
|
38472
38662
|
function readManifestAt(file3) {
|
|
38473
|
-
if (!
|
|
38663
|
+
if (!existsSync21(file3)) return empty();
|
|
38474
38664
|
try {
|
|
38475
|
-
return normalize5(JSON.parse(
|
|
38665
|
+
return normalize5(JSON.parse(readFileSync20(file3, "utf8")));
|
|
38476
38666
|
} catch {
|
|
38477
38667
|
return empty();
|
|
38478
38668
|
}
|
|
@@ -38482,12 +38672,12 @@ function readManifest(ctx) {
|
|
|
38482
38672
|
}
|
|
38483
38673
|
function writeManifest(ctx, m) {
|
|
38484
38674
|
const file3 = manifestPath(ctx);
|
|
38485
|
-
|
|
38675
|
+
mkdirSync11(dirname9(file3), { recursive: true });
|
|
38486
38676
|
const sorted = {
|
|
38487
38677
|
version: 1,
|
|
38488
38678
|
sources: [...m.sources].sort((a, b) => a.name.localeCompare(b.name))
|
|
38489
38679
|
};
|
|
38490
|
-
|
|
38680
|
+
writeFileSync9(file3, `${JSON.stringify(sorted, null, 2)}
|
|
38491
38681
|
`);
|
|
38492
38682
|
return file3;
|
|
38493
38683
|
}
|
|
@@ -38583,11 +38773,11 @@ var init_manifest = __esm({
|
|
|
38583
38773
|
});
|
|
38584
38774
|
|
|
38585
38775
|
// src/docs/discover.ts
|
|
38586
|
-
import { existsSync as
|
|
38587
|
-
import { basename, join as
|
|
38776
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21, statSync as statSync8 } from "fs";
|
|
38777
|
+
import { basename, join as join27, relative as relative7 } from "path";
|
|
38588
38778
|
function readText(file3) {
|
|
38589
38779
|
try {
|
|
38590
|
-
return
|
|
38780
|
+
return readFileSync21(file3, "utf8");
|
|
38591
38781
|
} catch {
|
|
38592
38782
|
return void 0;
|
|
38593
38783
|
}
|
|
@@ -38641,7 +38831,7 @@ function findProjects(root, opts) {
|
|
|
38641
38831
|
const found = /* @__PURE__ */ new Set();
|
|
38642
38832
|
for (const m of markers) {
|
|
38643
38833
|
for (const f of glob(root, [`*/${m}`, `*/*/${m}`], 3)) {
|
|
38644
|
-
const dir =
|
|
38834
|
+
const dir = join27(f, "..");
|
|
38645
38835
|
const rel = relative7(root, dir);
|
|
38646
38836
|
if (!rel || rel.split("/").some((p) => p.startsWith(".") || p === "node_modules")) continue;
|
|
38647
38837
|
found.add(dir);
|
|
@@ -38650,7 +38840,7 @@ function findProjects(root, opts) {
|
|
|
38650
38840
|
const max = opts.maxProjects ?? 40;
|
|
38651
38841
|
const seenNames = /* @__PURE__ */ new Set();
|
|
38652
38842
|
const nameOf = (dir) => {
|
|
38653
|
-
const pkg = readJson3(
|
|
38843
|
+
const pkg = readJson3(join27(dir, "package.json"));
|
|
38654
38844
|
return typeof pkg?.name === "string" ? pkg.name : void 0;
|
|
38655
38845
|
};
|
|
38656
38846
|
const rootName = nameOf(root);
|
|
@@ -38668,7 +38858,7 @@ function findProjects(root, opts) {
|
|
|
38668
38858
|
return out;
|
|
38669
38859
|
}
|
|
38670
38860
|
function npmSignals(dir, includeDev, project) {
|
|
38671
|
-
const pkg = readJson3(
|
|
38861
|
+
const pkg = readJson3(join27(dir, "package.json"));
|
|
38672
38862
|
if (!pkg) return [];
|
|
38673
38863
|
const sections = ["dependencies", ...includeDev ? ["devDependencies"] : []];
|
|
38674
38864
|
const out = [];
|
|
@@ -38685,13 +38875,13 @@ function npmSignals(dir, includeDev, project) {
|
|
|
38685
38875
|
}
|
|
38686
38876
|
function pythonSignals(dir, project) {
|
|
38687
38877
|
const out = [];
|
|
38688
|
-
const py = readText(
|
|
38878
|
+
const py = readText(join27(dir, "pyproject.toml"));
|
|
38689
38879
|
if (py) {
|
|
38690
38880
|
const block = /dependencies\s*=\s*\[([\s\S]*?)\]/.exec(py)?.[1] ?? "";
|
|
38691
38881
|
for (const m of block.matchAll(/["']([A-Za-z0-9_.-]+)/g))
|
|
38692
38882
|
out.push({ kind: "pypi", key: m[1].toLowerCase(), project });
|
|
38693
38883
|
}
|
|
38694
|
-
const req = readText(
|
|
38884
|
+
const req = readText(join27(dir, "requirements.txt"));
|
|
38695
38885
|
if (req) {
|
|
38696
38886
|
for (const line of req.split("\n")) {
|
|
38697
38887
|
const name = /^\s*([A-Za-z0-9_.-]+)/.exec(line)?.[1];
|
|
@@ -38702,7 +38892,7 @@ function pythonSignals(dir, project) {
|
|
|
38702
38892
|
return out;
|
|
38703
38893
|
}
|
|
38704
38894
|
function goSignals(dir, project) {
|
|
38705
|
-
const mod = readText(
|
|
38895
|
+
const mod = readText(join27(dir, "go.mod"));
|
|
38706
38896
|
if (!mod) return [];
|
|
38707
38897
|
const out = [];
|
|
38708
38898
|
const block = /require\s*\(([\s\S]*?)\)/g;
|
|
@@ -38899,8 +39089,8 @@ function localCandidates(root, dir, project, isRegistered) {
|
|
|
38899
39089
|
why: "project readme and top-level guides"
|
|
38900
39090
|
});
|
|
38901
39091
|
for (const d of ["docs", "doc", "documentation"]) {
|
|
38902
|
-
const abs =
|
|
38903
|
-
if (!
|
|
39092
|
+
const abs = join27(dir, d);
|
|
39093
|
+
if (!existsSync22(abs)) continue;
|
|
38904
39094
|
const files = glob(abs, ["**/*.md", "**/*.mdx", "**/*.rst", "**/*.txt"]).filter(
|
|
38905
39095
|
(f) => !SKIP_EXT.has(f.slice(f.lastIndexOf(".")))
|
|
38906
39096
|
);
|
|
@@ -38923,8 +39113,8 @@ function localCandidates(root, dir, project, isRegistered) {
|
|
|
38923
39113
|
"docs/decisions",
|
|
38924
39114
|
"decisions"
|
|
38925
39115
|
]) {
|
|
38926
|
-
const abs =
|
|
38927
|
-
if (!
|
|
39116
|
+
const abs = join27(dir, d);
|
|
39117
|
+
if (!existsSync22(abs)) continue;
|
|
38928
39118
|
if (out.some((c) => c.path && rel(abs).startsWith(`${c.path}/`))) break;
|
|
38929
39119
|
const files = glob(abs, ["**/*.md"]);
|
|
38930
39120
|
push({
|
|
@@ -39721,7 +39911,7 @@ var init_category = __esm({
|
|
|
39721
39911
|
});
|
|
39722
39912
|
|
|
39723
39913
|
// src/docs/graph.ts
|
|
39724
|
-
import { existsSync as
|
|
39914
|
+
import { existsSync as existsSync23, statSync as statSync9 } from "fs";
|
|
39725
39915
|
import { dirname as dirname10, posix, relative as relative8, sep as sep2 } from "path";
|
|
39726
39916
|
function manifestRel(ctx) {
|
|
39727
39917
|
return relative8(ctx.root, manifestPath(ctx)).split(sep2).join("/");
|
|
@@ -39819,7 +40009,7 @@ function localDocPages(ctx, db) {
|
|
|
39819
40009
|
}
|
|
39820
40010
|
function stampOf(ctx, db) {
|
|
39821
40011
|
const file3 = manifestPath(ctx);
|
|
39822
|
-
const st =
|
|
40012
|
+
const st = existsSync23(file3) ? statSync9(file3) : void 0;
|
|
39823
40013
|
const counts = db.graphNodeCounts();
|
|
39824
40014
|
const syncs = readManifest(ctx).sources.map((s) => syncState(db, s.name)?.at ?? 0).join(",");
|
|
39825
40015
|
return `${st ? `${Math.floor(st.mtimeMs)}:${st.size}` : "none"}|${counts.file ?? 0}|${counts.package ?? 0}|${syncs}`;
|
|
@@ -44386,14 +44576,14 @@ __export(ingest_exports, {
|
|
|
44386
44576
|
usageEnabled: () => usageEnabled
|
|
44387
44577
|
});
|
|
44388
44578
|
import { createHash as createHash4 } from "crypto";
|
|
44389
|
-
import { closeSync, existsSync as
|
|
44390
|
-
import { homedir as
|
|
44391
|
-
import { basename as basename2, dirname as dirname11, join as
|
|
44579
|
+
import { closeSync, existsSync as existsSync24, openSync, readdirSync as readdirSync9, readSync, statSync as statSync10 } from "fs";
|
|
44580
|
+
import { homedir as homedir4 } from "os";
|
|
44581
|
+
import { basename as basename2, dirname as dirname11, join as join28, resolve as resolve7, sep as sep3 } from "path";
|
|
44392
44582
|
function isValidSessionId(id) {
|
|
44393
44583
|
return SESSION_ID_RE.test(id);
|
|
44394
44584
|
}
|
|
44395
44585
|
function claudeDir2() {
|
|
44396
|
-
return process.env.EMINIAR_CLAUDE_DIR ||
|
|
44586
|
+
return process.env.EMINIAR_CLAUDE_DIR || join28(homedir4(), ".claude");
|
|
44397
44587
|
}
|
|
44398
44588
|
function insideDir(path3, dir) {
|
|
44399
44589
|
const d = resolve7(dir);
|
|
@@ -44412,7 +44602,7 @@ function transcriptSlug(root) {
|
|
|
44412
44602
|
return root.replace(/[^A-Za-z0-9]/g, "-");
|
|
44413
44603
|
}
|
|
44414
44604
|
function transcriptDirFor(root) {
|
|
44415
|
-
return
|
|
44605
|
+
return join28(claudeDir2(), "projects", transcriptSlug(root));
|
|
44416
44606
|
}
|
|
44417
44607
|
function usageEnabled(ctx) {
|
|
44418
44608
|
return ctx.config.usage.enabled !== false;
|
|
@@ -44582,7 +44772,7 @@ function add(a, b) {
|
|
|
44582
44772
|
}
|
|
44583
44773
|
function listJsonl(dir) {
|
|
44584
44774
|
try {
|
|
44585
|
-
return
|
|
44775
|
+
return readdirSync9(dir).filter((f) => f.endsWith(".jsonl")).map((f) => join28(dir, f));
|
|
44586
44776
|
} catch {
|
|
44587
44777
|
return [];
|
|
44588
44778
|
}
|
|
@@ -44602,7 +44792,7 @@ function firstEntrySessionId(path3) {
|
|
|
44602
44792
|
function sidechainFilesFor(db, dir, sessionId) {
|
|
44603
44793
|
if (!isValidSessionId(sessionId)) return [];
|
|
44604
44794
|
const inside = (p) => insideDir(p, dir) && p.endsWith(".jsonl");
|
|
44605
|
-
const out = listJsonl(
|
|
44795
|
+
const out = listJsonl(join28(dir, sessionId, "subagents")).filter(inside);
|
|
44606
44796
|
for (const path3 of listJsonl(dir)) {
|
|
44607
44797
|
if (!inside(path3) || !basename2(path3).startsWith("agent-")) continue;
|
|
44608
44798
|
const known = db.transcriptFileGet(path3)?.session_id;
|
|
@@ -44646,11 +44836,11 @@ function ingestSession(db, root, sessionId, transcriptPath, opts = {}) {
|
|
|
44646
44836
|
function ingestProject(db, root, opts = {}) {
|
|
44647
44837
|
const dir = transcriptDirFor(root);
|
|
44648
44838
|
const files = new Set(listJsonl(dir));
|
|
44649
|
-
if (
|
|
44839
|
+
if (existsSync24(dir)) {
|
|
44650
44840
|
try {
|
|
44651
|
-
for (const entry of
|
|
44841
|
+
for (const entry of readdirSync9(dir, { withFileTypes: true })) {
|
|
44652
44842
|
if (entry.isDirectory())
|
|
44653
|
-
for (const sub of listJsonl(
|
|
44843
|
+
for (const sub of listJsonl(join28(dir, entry.name, "subagents"))) files.add(sub);
|
|
44654
44844
|
}
|
|
44655
44845
|
} catch {
|
|
44656
44846
|
}
|
|
@@ -46004,14 +46194,14 @@ var init_em_search = __esm({
|
|
|
46004
46194
|
});
|
|
46005
46195
|
|
|
46006
46196
|
// src/ui/api.ts
|
|
46007
|
-
import { existsSync as
|
|
46008
|
-
import { join as
|
|
46197
|
+
import { existsSync as existsSync25, readdirSync as readdirSync10 } from "fs";
|
|
46198
|
+
import { join as join29, relative as relative9 } from "path";
|
|
46009
46199
|
function listProjects() {
|
|
46010
46200
|
const dir = paths().projects;
|
|
46011
46201
|
const out = [];
|
|
46012
|
-
for (const id of
|
|
46202
|
+
for (const id of readdirSync10(dir, { withFileTypes: true })) {
|
|
46013
46203
|
if (!id.isDirectory()) continue;
|
|
46014
|
-
const db =
|
|
46204
|
+
const db = join29(dir, id.name, "eminiar.db");
|
|
46015
46205
|
try {
|
|
46016
46206
|
const a = new SqliteAdapter(db, { vectors: false });
|
|
46017
46207
|
out.push({ id: id.name, root: a.sessionLatest()?.project_root ?? null });
|
|
@@ -46037,8 +46227,8 @@ function statsPayload(ctx) {
|
|
|
46037
46227
|
const db = getStorage(ctx);
|
|
46038
46228
|
const sessionId = getCurrentSession(ctx);
|
|
46039
46229
|
const g = globalDb();
|
|
46040
|
-
const onboardingDir =
|
|
46041
|
-
const onboarding =
|
|
46230
|
+
const onboardingDir = join29(memoriesDir(ctx), "onboarding");
|
|
46231
|
+
const onboarding = existsSync25(onboardingDir) ? readdirSync10(onboardingDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)) : [];
|
|
46042
46232
|
return {
|
|
46043
46233
|
project: ctx.root,
|
|
46044
46234
|
projectId: ctx.id,
|
|
@@ -46640,8 +46830,8 @@ var init_namepath = __esm({
|
|
|
46640
46830
|
});
|
|
46641
46831
|
|
|
46642
46832
|
// src/code/symbols.ts
|
|
46643
|
-
import { existsSync as
|
|
46644
|
-
import { join as
|
|
46833
|
+
import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
|
|
46834
|
+
import { join as join30 } from "path";
|
|
46645
46835
|
function isExported2(n) {
|
|
46646
46836
|
if (!n.meta) return false;
|
|
46647
46837
|
try {
|
|
@@ -46677,7 +46867,7 @@ var init_symbols2 = __esm({
|
|
|
46677
46867
|
});
|
|
46678
46868
|
|
|
46679
46869
|
// src/ui/graph-api.ts
|
|
46680
|
-
import { readFileSync as
|
|
46870
|
+
import { readFileSync as readFileSync23, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
|
|
46681
46871
|
import { relative as relative10, resolve as resolve8 } from "path";
|
|
46682
46872
|
function metaOf2(row) {
|
|
46683
46873
|
if (!row?.meta) return {};
|
|
@@ -46763,7 +46953,7 @@ function filePayload(ctx, rel) {
|
|
|
46763
46953
|
}));
|
|
46764
46954
|
if (st.size > MAX_CODE_BYTES)
|
|
46765
46955
|
return { path: clean, tooLarge: true, size: st.size, status: row?.status ?? null, symbols };
|
|
46766
|
-
const content =
|
|
46956
|
+
const content = readFileSync23(real, "utf8");
|
|
46767
46957
|
return {
|
|
46768
46958
|
path: clean,
|
|
46769
46959
|
size: st.size,
|
|
@@ -47449,8 +47639,8 @@ var init_lineage = __esm({
|
|
|
47449
47639
|
});
|
|
47450
47640
|
|
|
47451
47641
|
// src/ui/history-graph-api.ts
|
|
47452
|
-
import { existsSync as
|
|
47453
|
-
import { join as
|
|
47642
|
+
import { existsSync as existsSync27 } from "fs";
|
|
47643
|
+
import { join as join31 } from "path";
|
|
47454
47644
|
function parseList(raw) {
|
|
47455
47645
|
if (!raw) return [];
|
|
47456
47646
|
try {
|
|
@@ -47689,7 +47879,7 @@ function buildHistoryGraph(ctx, db, m, opts = {}) {
|
|
|
47689
47879
|
path: p,
|
|
47690
47880
|
line: null,
|
|
47691
47881
|
root: id === focusId,
|
|
47692
|
-
missing:
|
|
47882
|
+
missing: existsSync27(join31(ctx.root, p)) ? void 0 : true,
|
|
47693
47883
|
risk: h?.risk,
|
|
47694
47884
|
fixes: h?.fixes
|
|
47695
47885
|
});
|
|
@@ -48048,9 +48238,9 @@ __export(server_exports, {
|
|
|
48048
48238
|
uiDir: () => uiDir
|
|
48049
48239
|
});
|
|
48050
48240
|
import { spawn as spawn2 } from "child_process";
|
|
48051
|
-
import { existsSync as
|
|
48241
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24, statSync as statSync12 } from "fs";
|
|
48052
48242
|
import { createServer } from "http";
|
|
48053
|
-
import { extname as extname3, join as
|
|
48243
|
+
import { extname as extname3, join as join32, normalize as normalize6 } from "path";
|
|
48054
48244
|
import { URL as URL2 } from "url";
|
|
48055
48245
|
function json2(res, status, body) {
|
|
48056
48246
|
res.writeHead(status, {
|
|
@@ -48072,7 +48262,7 @@ function strList(v) {
|
|
|
48072
48262
|
return void 0;
|
|
48073
48263
|
}
|
|
48074
48264
|
function uiDir() {
|
|
48075
|
-
return process.env.EMINIAR_UI_DIR ||
|
|
48265
|
+
return process.env.EMINIAR_UI_DIR || join32(pluginRoot(), "dist", "ui");
|
|
48076
48266
|
}
|
|
48077
48267
|
function originAllowed(req, port) {
|
|
48078
48268
|
const host = req.headers.host ?? "";
|
|
@@ -48096,25 +48286,25 @@ function originAllowed(req, port) {
|
|
|
48096
48286
|
function serveStatic(res, p) {
|
|
48097
48287
|
const dir = uiDir();
|
|
48098
48288
|
const rel = p === "/" ? "index.html" : p.replace(/^\/+/, "");
|
|
48099
|
-
const file3 = normalize6(
|
|
48289
|
+
const file3 = normalize6(join32(dir, rel));
|
|
48100
48290
|
if (!file3.startsWith(normalize6(dir))) return false;
|
|
48101
|
-
if (!
|
|
48291
|
+
if (!existsSync28(file3) || !statSync12(file3).isFile()) return false;
|
|
48102
48292
|
const type = MIME[extname3(file3).toLowerCase()] ?? "application/octet-stream";
|
|
48103
48293
|
if (rel === "index.html") {
|
|
48104
48294
|
const stamp = (name) => {
|
|
48105
48295
|
try {
|
|
48106
|
-
return `/${name}?v=${Math.floor(statSync12(
|
|
48296
|
+
return `/${name}?v=${Math.floor(statSync12(join32(dir, name)).mtimeMs)}`;
|
|
48107
48297
|
} catch {
|
|
48108
48298
|
return `/${name}`;
|
|
48109
48299
|
}
|
|
48110
48300
|
};
|
|
48111
|
-
const html =
|
|
48301
|
+
const html = readFileSync24(file3, "utf8").replace('"/app.global.js"', `"${stamp("app.global.js")}"`).replace('"/styles.css"', `"${stamp("styles.css")}"`);
|
|
48112
48302
|
res.writeHead(200, { "content-type": type, "cache-control": "no-store" });
|
|
48113
48303
|
res.end(html);
|
|
48114
48304
|
return true;
|
|
48115
48305
|
}
|
|
48116
48306
|
res.writeHead(200, { "content-type": type, "cache-control": "no-cache" });
|
|
48117
|
-
res.end(
|
|
48307
|
+
res.end(readFileSync24(file3));
|
|
48118
48308
|
return true;
|
|
48119
48309
|
}
|
|
48120
48310
|
async function serve(opts) {
|
|
@@ -48553,7 +48743,7 @@ __export(statusline_exports, {
|
|
|
48553
48743
|
renderStatusline: () => renderStatusline,
|
|
48554
48744
|
usageSegments: () => usageSegments
|
|
48555
48745
|
});
|
|
48556
|
-
import { existsSync as
|
|
48746
|
+
import { existsSync as existsSync29, readFileSync as readFileSync25, writeFileSync as writeFileSync10 } from "fs";
|
|
48557
48747
|
function epochMs(v) {
|
|
48558
48748
|
if (typeof v === "number" && Number.isFinite(v)) return v < 1e12 ? v * 1e3 : v;
|
|
48559
48749
|
if (typeof v === "string") {
|
|
@@ -48615,8 +48805,8 @@ function renderStatusline(raw) {
|
|
|
48615
48805
|
const key = cacheKey(input2);
|
|
48616
48806
|
const cache3 = paths().statuslineCache;
|
|
48617
48807
|
try {
|
|
48618
|
-
if (
|
|
48619
|
-
const c = JSON.parse(
|
|
48808
|
+
if (existsSync29(cache3)) {
|
|
48809
|
+
const c = JSON.parse(readFileSync25(cache3, "utf8"));
|
|
48620
48810
|
if (Date.now() - c.at < CACHE_TTL_MS && c.key === key) return c.line;
|
|
48621
48811
|
}
|
|
48622
48812
|
} catch {
|
|
@@ -48647,7 +48837,7 @@ function renderStatusline(raw) {
|
|
|
48647
48837
|
line = `eminiar \xB7 unavailable (${err.message.slice(0, 40)})`;
|
|
48648
48838
|
}
|
|
48649
48839
|
try {
|
|
48650
|
-
|
|
48840
|
+
writeFileSync10(cache3, JSON.stringify({ at: Date.now(), line, key }));
|
|
48651
48841
|
} catch {
|
|
48652
48842
|
}
|
|
48653
48843
|
return line;
|
|
@@ -48681,9 +48871,11 @@ var USAGE = `eminiar v${version2()} \u2014 local-first context, memory & knowled
|
|
|
48681
48871
|
Usage: eminiar <command> [options]
|
|
48682
48872
|
|
|
48683
48873
|
Setup
|
|
48684
|
-
install [--no-model] [--method plugin|settings] [--team] [--yes] [--force]
|
|
48874
|
+
install [--no-model] [--method plugin|settings] [--cursor] [--team] [--yes] [--force]
|
|
48875
|
+
Install into Claude Code; --cursor also registers with Cursor
|
|
48876
|
+
(hooks, MCP server, skills under ~/.cursor)
|
|
48685
48877
|
upgrade Update to the latest version and re-register
|
|
48686
|
-
uninstall [--purge-data] Remove from Claude Code (data kept unless --purge-data)
|
|
48878
|
+
uninstall [--purge-data] Remove from Claude Code and Cursor (data kept unless --purge-data)
|
|
48687
48879
|
doctor [--json] [--fix] Check installation health; --fix re-pins node/root and clears
|
|
48688
48880
|
Claude Code's cached launch failure
|
|
48689
48881
|
replace-context-mode [--yes] Remove the context-mode plugin after parity sign-off
|
|
@@ -48711,7 +48903,7 @@ Use
|
|
|
48711
48903
|
ui [--port 7331] [--no-open] Web dashboard: stats, memories, graph, search, sessions, actions
|
|
48712
48904
|
(alias: serve)
|
|
48713
48905
|
statusline Claude Code statusLine command (reads JSON on stdin)
|
|
48714
|
-
hook [--event E]
|
|
48906
|
+
hook [--event E] [--client claude|cursor] Run the hook handler manually (reads JSON on stdin)
|
|
48715
48907
|
version | help
|
|
48716
48908
|
`;
|
|
48717
48909
|
function text2(r) {
|
|
@@ -48741,6 +48933,7 @@ var commands = {
|
|
|
48741
48933
|
node: { type: "string" },
|
|
48742
48934
|
yes: { type: "boolean" },
|
|
48743
48935
|
statusline: { type: "boolean" },
|
|
48936
|
+
cursor: { type: "boolean" },
|
|
48744
48937
|
force: { type: "boolean" }
|
|
48745
48938
|
},
|
|
48746
48939
|
strict: false
|
|
@@ -48748,6 +48941,7 @@ var commands = {
|
|
|
48748
48941
|
const { install: install2 } = await Promise.resolve().then(() => (init_install(), install_exports));
|
|
48749
48942
|
return install2({
|
|
48750
48943
|
force: !!values.force,
|
|
48944
|
+
cursor: !!values.cursor,
|
|
48751
48945
|
noModel: !!values["no-model"],
|
|
48752
48946
|
method: values.method === "settings" ? "settings" : values.method === "plugin" ? "plugin" : void 0,
|
|
48753
48947
|
team: !!values.team,
|