@phren/cli 0.0.44 → 0.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/mcp/dist/cli-hooks-stop.js +2 -2
- package/mcp/dist/entrypoint.js +4 -1
- package/mcp/dist/generated/memory-ui-graph.browser.js +1 -1
- package/mcp/dist/link/doctor.js +43 -0
- package/mcp/dist/memory-ui-graph.runtime.js +1 -1
- package/mcp/dist/shared/index.js +52 -7
- package/mcp/dist/status.js +27 -0
- package/mcp/dist/ui/data.js +80 -54
- package/mcp/dist/ui/server.js +24 -4
- package/package.json +8 -8
package/mcp/dist/shared/index.js
CHANGED
|
@@ -4,6 +4,46 @@ import * as os from "os";
|
|
|
4
4
|
import * as crypto from "crypto";
|
|
5
5
|
import { globSync } from "glob";
|
|
6
6
|
import { debugLog, appendIndexEvent, getProjectDirs, collectNativeMemoryFiles, runtimeFile, homeDir, readRootManifest, } from "../shared.js";
|
|
7
|
+
/**
|
|
8
|
+
* Cached store project dirs to avoid repeated dynamic imports in sync code paths.
|
|
9
|
+
* Populated by `refreshStoreProjectDirs()`, consumed by `getAllStoreProjectDirs()`.
|
|
10
|
+
*/
|
|
11
|
+
let _cachedStoreProjectDirs = null;
|
|
12
|
+
let _cachedStorePhrenPath = null;
|
|
13
|
+
/**
|
|
14
|
+
* Gather project directories from the primary store AND all non-primary stores.
|
|
15
|
+
* This enables the FTS5 index to include team store projects alongside personal ones.
|
|
16
|
+
* Uses a sync cache populated by the async buildIndex path.
|
|
17
|
+
*/
|
|
18
|
+
function getAllStoreProjectDirs(phrenPath, profile) {
|
|
19
|
+
const dirs = [...getProjectDirs(phrenPath, profile)];
|
|
20
|
+
if (_cachedStoreProjectDirs && _cachedStorePhrenPath === phrenPath) {
|
|
21
|
+
dirs.push(..._cachedStoreProjectDirs);
|
|
22
|
+
}
|
|
23
|
+
return dirs;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Refresh the store project dirs cache. Called from async contexts (buildIndex, etc.)
|
|
27
|
+
* before sync code paths that need getAllStoreProjectDirs.
|
|
28
|
+
*/
|
|
29
|
+
async function refreshStoreProjectDirs(phrenPath, profile) {
|
|
30
|
+
try {
|
|
31
|
+
const { getNonPrimaryStores } = await import("../store-registry.js");
|
|
32
|
+
const otherStores = getNonPrimaryStores(phrenPath);
|
|
33
|
+
const dirs = [];
|
|
34
|
+
for (const store of otherStores) {
|
|
35
|
+
if (!fs.existsSync(store.path))
|
|
36
|
+
continue;
|
|
37
|
+
dirs.push(...getProjectDirs(store.path, profile));
|
|
38
|
+
}
|
|
39
|
+
_cachedStoreProjectDirs = dirs;
|
|
40
|
+
_cachedStorePhrenPath = phrenPath;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
_cachedStoreProjectDirs = [];
|
|
44
|
+
_cachedStorePhrenPath = phrenPath;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
7
47
|
import { getIndexPolicy, withFileLock } from "./governance.js";
|
|
8
48
|
import { stripTaskDoneSection } from "./content.js";
|
|
9
49
|
import { isInactiveFindingLine } from "../finding/lifecycle.js";
|
|
@@ -191,7 +231,7 @@ function touchSentinel(phrenPath) {
|
|
|
191
231
|
function computePhrenHash(phrenPath, profile, preGlobbed) {
|
|
192
232
|
const policy = getIndexPolicy(phrenPath);
|
|
193
233
|
const hash = crypto.createHash("sha1");
|
|
194
|
-
const topicConfigEntries =
|
|
234
|
+
const topicConfigEntries = getAllStoreProjectDirs(phrenPath, profile)
|
|
195
235
|
.map((dir) => path.join(dir, "topic-config.json"))
|
|
196
236
|
.filter((configPath) => fs.existsSync(configPath));
|
|
197
237
|
if (preGlobbed) {
|
|
@@ -215,9 +255,9 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
|
|
|
215
255
|
}
|
|
216
256
|
}
|
|
217
257
|
else {
|
|
218
|
-
const
|
|
258
|
+
const allProjectDirs = getAllStoreProjectDirs(phrenPath, profile);
|
|
219
259
|
const files = [];
|
|
220
|
-
for (const dir of
|
|
260
|
+
for (const dir of allProjectDirs) {
|
|
221
261
|
const projectName = path.basename(dir);
|
|
222
262
|
const config = readProjectConfig(phrenPath, projectName);
|
|
223
263
|
const ownership = getProjectOwnershipMode(phrenPath, projectName, config);
|
|
@@ -399,7 +439,7 @@ function getRepoManagedInstructionEntries(phrenPath, project) {
|
|
|
399
439
|
return entries;
|
|
400
440
|
}
|
|
401
441
|
function globAllFiles(phrenPath, profile) {
|
|
402
|
-
const projectDirs =
|
|
442
|
+
const projectDirs = getAllStoreProjectDirs(phrenPath, profile);
|
|
403
443
|
const indexPolicy = getIndexPolicy(phrenPath);
|
|
404
444
|
const entries = [];
|
|
405
445
|
const allAbsolutePaths = [];
|
|
@@ -826,7 +866,8 @@ function mergeManualLinks(db, phrenPath) {
|
|
|
826
866
|
}
|
|
827
867
|
async function buildIndexImpl(phrenPath, profile) {
|
|
828
868
|
const t0 = Date.now();
|
|
829
|
-
|
|
869
|
+
await refreshStoreProjectDirs(phrenPath, profile);
|
|
870
|
+
const projectDirs = getAllStoreProjectDirs(phrenPath, profile);
|
|
830
871
|
beginUserFragmentBuildCache(phrenPath, projectDirs.map(dir => path.basename(dir)));
|
|
831
872
|
try {
|
|
832
873
|
// ── Cache dir + hash sentinel ─────────────────────────────────────────────
|
|
@@ -1348,12 +1389,16 @@ export function detectProject(phrenPath, cwd, profile) {
|
|
|
1348
1389
|
if (manifest?.installMode === "project-local") {
|
|
1349
1390
|
return manifest.primaryProject || null;
|
|
1350
1391
|
}
|
|
1351
|
-
const projectDirs =
|
|
1392
|
+
const projectDirs = getAllStoreProjectDirs(phrenPath, profile);
|
|
1352
1393
|
const resolvedCwd = path.resolve(cwd);
|
|
1353
1394
|
let bestMatch = null;
|
|
1354
1395
|
for (const dir of projectDirs) {
|
|
1355
1396
|
const projectName = path.basename(dir);
|
|
1356
|
-
|
|
1397
|
+
// Try the project's own store path first (handles team store projects),
|
|
1398
|
+
// then fall back to primary phrenPath
|
|
1399
|
+
const storePhrenPath = path.dirname(dir);
|
|
1400
|
+
const sourcePath = getProjectSourcePath(storePhrenPath, projectName)
|
|
1401
|
+
|| getProjectSourcePath(phrenPath, projectName);
|
|
1357
1402
|
if (!sourcePath)
|
|
1358
1403
|
continue;
|
|
1359
1404
|
const matches = resolvedCwd === sourcePath || resolvedCwd.startsWith(sourcePath + path.sep);
|
package/mcp/dist/status.js
CHANGED
|
@@ -284,6 +284,33 @@ export async function runStatus() {
|
|
|
284
284
|
if (missingAgents.length > 0) {
|
|
285
285
|
console.log(` ${DIM} Not configured: ${missingAgents.join(", ")} — run phren init to add${RESET}`);
|
|
286
286
|
}
|
|
287
|
+
// Stores
|
|
288
|
+
try {
|
|
289
|
+
const { resolveAllStores } = await import("./store-registry.js");
|
|
290
|
+
const stores = resolveAllStores(phrenPath);
|
|
291
|
+
if (stores.length > 0) {
|
|
292
|
+
const primaryCount = stores.filter((s) => s.role === "primary").length;
|
|
293
|
+
const teamCount = stores.filter((s) => s.role === "team").length;
|
|
294
|
+
const readonlyCount = stores.filter((s) => s.role === "readonly").length;
|
|
295
|
+
const roleParts = [];
|
|
296
|
+
if (primaryCount > 0)
|
|
297
|
+
roleParts.push(`${primaryCount} primary`);
|
|
298
|
+
if (teamCount > 0)
|
|
299
|
+
roleParts.push(`${teamCount} team`);
|
|
300
|
+
if (readonlyCount > 0)
|
|
301
|
+
roleParts.push(`${readonlyCount} readonly`);
|
|
302
|
+
console.log(`\n ${BOLD}Stores${RESET} ${DIM}(${stores.length} stores: ${roleParts.join(", ")})${RESET}`);
|
|
303
|
+
for (const store of stores) {
|
|
304
|
+
const exists = fs.existsSync(store.path);
|
|
305
|
+
const existsLabel = exists ? `${GREEN}yes${RESET}` : `${RED}no${RESET}`;
|
|
306
|
+
console.log(` ${store.name} ${DIM}(${store.role}, ${store.sync})${RESET} path=${existsLabel}${store.remote ? ` remote=${DIM}${store.remote}${RESET}` : ""}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
if ((process.env.PHREN_DEBUG))
|
|
312
|
+
logger.debug("status", `statusStores: ${errorMessage(err)}`);
|
|
313
|
+
}
|
|
287
314
|
// Stats
|
|
288
315
|
const projectDirs = getProjectDirs(phrenPath, profile);
|
|
289
316
|
let totalFindings = 0;
|
package/mcp/dist/ui/data.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { createHash } from "crypto";
|
|
4
4
|
import { getProjectDirs, runtimeDir, runtimeHealthFile, memoryUsageLogFile, homePath, } from "../shared.js";
|
|
5
|
+
import { getNonPrimaryStores } from "../store-registry.js";
|
|
5
6
|
import { errorMessage } from "../utils.js";
|
|
6
7
|
import { readInstallPreferences } from "../init/preferences.js";
|
|
7
8
|
import { readCustomHooks } from "../hooks.js";
|
|
@@ -520,6 +521,66 @@ export function recentAccepted(phrenPath) {
|
|
|
520
521
|
const lines = fs.readFileSync(audit, "utf8").split("\n").filter((line) => line.includes("approve_memory"));
|
|
521
522
|
return lines.slice(-40).reverse();
|
|
522
523
|
}
|
|
524
|
+
function buildProjectInfo(basePath, project, store) {
|
|
525
|
+
const dir = path.join(basePath, project);
|
|
526
|
+
const findingsPath = path.join(dir, "FINDINGS.md");
|
|
527
|
+
const taskPath = resolveTaskFilePath(basePath, project);
|
|
528
|
+
const claudeMdPath = path.join(dir, "CLAUDE.md");
|
|
529
|
+
const summaryPath = path.join(dir, "summary.md");
|
|
530
|
+
const refPath = path.join(dir, "reference");
|
|
531
|
+
let findingCount = 0;
|
|
532
|
+
if (fs.existsSync(findingsPath)) {
|
|
533
|
+
const content = fs.readFileSync(findingsPath, "utf8");
|
|
534
|
+
findingCount = (content.match(/^- /gm) || []).length;
|
|
535
|
+
}
|
|
536
|
+
const sparkline = new Array(8).fill(0);
|
|
537
|
+
if (fs.existsSync(findingsPath)) {
|
|
538
|
+
const now = Date.now();
|
|
539
|
+
const weekMs = 7 * 24 * 60 * 60 * 1000;
|
|
540
|
+
const sparkContent = fs.readFileSync(findingsPath, "utf8");
|
|
541
|
+
const dateRe = /(?:created[_:]?\s*"?|created_at[":]+\s*)(\d{4}-\d{2}-\d{2})/g;
|
|
542
|
+
let match;
|
|
543
|
+
while ((match = dateRe.exec(sparkContent)) !== null) {
|
|
544
|
+
const age = now - new Date(match[1]).getTime();
|
|
545
|
+
const weekIdx = Math.floor(age / weekMs);
|
|
546
|
+
if (weekIdx >= 0 && weekIdx < 8)
|
|
547
|
+
sparkline[7 - weekIdx]++;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
let taskCount = 0;
|
|
551
|
+
if (taskPath && fs.existsSync(taskPath)) {
|
|
552
|
+
const content = fs.readFileSync(taskPath, "utf8");
|
|
553
|
+
const queueMatch = content.match(/## Queue[\s\S]*?(?=## |$)/);
|
|
554
|
+
if (queueMatch)
|
|
555
|
+
taskCount = (queueMatch[0].match(/^- /gm) || []).length;
|
|
556
|
+
}
|
|
557
|
+
let summaryText = "";
|
|
558
|
+
if (fs.existsSync(summaryPath)) {
|
|
559
|
+
summaryText = fs.readFileSync(summaryPath, "utf8").trim();
|
|
560
|
+
if (summaryText.length > 300)
|
|
561
|
+
summaryText = `${summaryText.slice(0, 300)}...`;
|
|
562
|
+
}
|
|
563
|
+
let githubUrl;
|
|
564
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
565
|
+
githubUrl = extractGithubUrl(fs.readFileSync(claudeMdPath, "utf8"));
|
|
566
|
+
}
|
|
567
|
+
if (!githubUrl && fs.existsSync(summaryPath)) {
|
|
568
|
+
githubUrl = extractGithubUrl(fs.readFileSync(summaryPath, "utf8"));
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
name: project,
|
|
572
|
+
storePath: basePath,
|
|
573
|
+
store,
|
|
574
|
+
findingCount,
|
|
575
|
+
taskCount,
|
|
576
|
+
hasClaudeMd: fs.existsSync(claudeMdPath),
|
|
577
|
+
hasSummary: fs.existsSync(summaryPath),
|
|
578
|
+
hasReference: fs.existsSync(refPath) && fs.statSync(refPath).isDirectory(),
|
|
579
|
+
summaryText,
|
|
580
|
+
githubUrl,
|
|
581
|
+
sparkline,
|
|
582
|
+
};
|
|
583
|
+
}
|
|
523
584
|
export function collectProjectsForUI(phrenPath, profile) {
|
|
524
585
|
const projects = getProjectDirs(phrenPath, profile).map((projectDir) => path.basename(projectDir)).filter((project) => project !== "global");
|
|
525
586
|
let allowedProjects = null;
|
|
@@ -539,65 +600,30 @@ export function collectProjectsForUI(phrenPath, profile) {
|
|
|
539
600
|
logger.debug("memory-ui", `memory-ui filterByProfile: ${errorMessage(err)}`);
|
|
540
601
|
}
|
|
541
602
|
const results = [];
|
|
603
|
+
const seen = new Set();
|
|
542
604
|
for (const project of projects) {
|
|
543
605
|
if (allowedProjects && !allowedProjects.has(project.toLowerCase()))
|
|
544
606
|
continue;
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const sparkContent = fs.readFileSync(findingsPath, "utf8");
|
|
561
|
-
const dateRe = /(?:created[_:]?\s*"?|created_at[":]+\s*)(\d{4}-\d{2}-\d{2})/g;
|
|
562
|
-
let match;
|
|
563
|
-
while ((match = dateRe.exec(sparkContent)) !== null) {
|
|
564
|
-
const age = now - new Date(match[1]).getTime();
|
|
565
|
-
const weekIdx = Math.floor(age / weekMs);
|
|
566
|
-
if (weekIdx >= 0 && weekIdx < 8)
|
|
567
|
-
sparkline[7 - weekIdx]++;
|
|
607
|
+
seen.add(project);
|
|
608
|
+
results.push(buildProjectInfo(phrenPath, project));
|
|
609
|
+
}
|
|
610
|
+
// Include projects from non-primary stores
|
|
611
|
+
try {
|
|
612
|
+
const teamStores = getNonPrimaryStores(phrenPath);
|
|
613
|
+
for (const store of teamStores) {
|
|
614
|
+
if (!fs.existsSync(store.path))
|
|
615
|
+
continue;
|
|
616
|
+
const teamProjects = getProjectDirs(store.path).map((d) => path.basename(d)).filter((p) => p !== "global");
|
|
617
|
+
for (const project of teamProjects) {
|
|
618
|
+
if (seen.has(project))
|
|
619
|
+
continue; // skip if same name exists in primary
|
|
620
|
+
seen.add(project);
|
|
621
|
+
results.push(buildProjectInfo(store.path, project, store.name));
|
|
568
622
|
}
|
|
569
623
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
const queueMatch = content.match(/## Queue[\s\S]*?(?=## |$)/);
|
|
574
|
-
if (queueMatch)
|
|
575
|
-
taskCount = (queueMatch[0].match(/^- /gm) || []).length;
|
|
576
|
-
}
|
|
577
|
-
let summaryText = "";
|
|
578
|
-
if (fs.existsSync(summaryPath)) {
|
|
579
|
-
summaryText = fs.readFileSync(summaryPath, "utf8").trim();
|
|
580
|
-
if (summaryText.length > 300)
|
|
581
|
-
summaryText = `${summaryText.slice(0, 300)}...`;
|
|
582
|
-
}
|
|
583
|
-
let githubUrl;
|
|
584
|
-
if (fs.existsSync(claudeMdPath)) {
|
|
585
|
-
githubUrl = extractGithubUrl(fs.readFileSync(claudeMdPath, "utf8"));
|
|
586
|
-
}
|
|
587
|
-
if (!githubUrl && fs.existsSync(summaryPath)) {
|
|
588
|
-
githubUrl = extractGithubUrl(fs.readFileSync(summaryPath, "utf8"));
|
|
589
|
-
}
|
|
590
|
-
results.push({
|
|
591
|
-
name: project,
|
|
592
|
-
findingCount,
|
|
593
|
-
taskCount,
|
|
594
|
-
hasClaudeMd: fs.existsSync(claudeMdPath),
|
|
595
|
-
hasSummary: fs.existsSync(summaryPath),
|
|
596
|
-
hasReference: fs.existsSync(refPath) && fs.statSync(refPath).isDirectory(),
|
|
597
|
-
summaryText,
|
|
598
|
-
githubUrl,
|
|
599
|
-
sparkline,
|
|
600
|
-
});
|
|
624
|
+
}
|
|
625
|
+
catch (err) {
|
|
626
|
+
logger.debug("memory-ui", `collectProjectsForUI team stores: ${errorMessage(err)}`);
|
|
601
627
|
}
|
|
602
628
|
return results.sort((a, b) => (b.findingCount + b.taskCount) - (a.findingCount + a.taskCount));
|
|
603
629
|
}
|
package/mcp/dist/ui/server.js
CHANGED
|
@@ -6,6 +6,7 @@ import * as path from "path";
|
|
|
6
6
|
import * as querystring from "querystring";
|
|
7
7
|
import { spawn, execFileSync } from "child_process";
|
|
8
8
|
import { computePhrenLiveStateToken, getProjectDirs, } from "../shared.js";
|
|
9
|
+
import { getNonPrimaryStores } from "../store-registry.js";
|
|
9
10
|
import { editFinding, readReviewQueue, removeFinding, readFindings, addFinding as addFindingStore, readTasksAcrossProjects, addTask as addTaskStore, completeTask as completeTaskStore, removeTask as removeTaskStore, updateTask as updateTaskStore, TASKS_FILENAME, } from "../data/access.js";
|
|
10
11
|
import { isValidProjectName, errorMessage, queueFilePath, safeProjectPath } from "../utils.js";
|
|
11
12
|
import { readInstallPreferences, writeInstallPreferences, writeGovernanceInstallPreferences } from "../init/preferences.js";
|
|
@@ -318,6 +319,20 @@ function handleGetHome(res, ctx) {
|
|
|
318
319
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
319
320
|
res.end(html);
|
|
320
321
|
}
|
|
322
|
+
/** Returns the store base path that contains the given project (primary or team store). */
|
|
323
|
+
function resolveProjectBasePath(phrenPath, project) {
|
|
324
|
+
const primaryDir = path.join(phrenPath, project);
|
|
325
|
+
if (fs.existsSync(primaryDir))
|
|
326
|
+
return phrenPath;
|
|
327
|
+
try {
|
|
328
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
329
|
+
if (fs.existsSync(path.join(store.path, project)))
|
|
330
|
+
return store.path;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch { /* fall through */ }
|
|
334
|
+
return phrenPath;
|
|
335
|
+
}
|
|
321
336
|
function handleGetProjects(res, ctx) {
|
|
322
337
|
jsonOk(res, collectProjectsForUI(ctx.phrenPath, ctx.profile));
|
|
323
338
|
}
|
|
@@ -342,7 +357,8 @@ function handleGetProjectContent(res, url, ctx) {
|
|
|
342
357
|
const allowedFiles = ["FINDINGS.md", TASKS_FILENAME, "CLAUDE.md", "summary.md"];
|
|
343
358
|
if (!allowedFiles.includes(file))
|
|
344
359
|
return jsonErr(res, `File not allowed: ${file}`, 400);
|
|
345
|
-
const
|
|
360
|
+
const basePath = resolveProjectBasePath(ctx.phrenPath, project);
|
|
361
|
+
const filePath = safeProjectPath(basePath, project, file);
|
|
346
362
|
if (!filePath)
|
|
347
363
|
return jsonErr(res, "Invalid project or file path", 400);
|
|
348
364
|
if (!fs.existsSync(filePath))
|
|
@@ -353,17 +369,21 @@ function handleGetProjectTopics(res, url, ctx) {
|
|
|
353
369
|
const project = String(parseQs(url).project || "");
|
|
354
370
|
if (!project || !isValidProjectName(project))
|
|
355
371
|
return jsonErr(res, "Invalid project", 400);
|
|
356
|
-
|
|
372
|
+
const basePath = resolveProjectBasePath(ctx.phrenPath, project);
|
|
373
|
+
jsonOk(res, { ok: true, ...getProjectTopicsResponse(basePath, project) });
|
|
357
374
|
}
|
|
358
375
|
function handleGetProjectReferenceList(res, url, ctx) {
|
|
359
376
|
const project = String(parseQs(url).project || "");
|
|
360
377
|
if (!project || !isValidProjectName(project))
|
|
361
378
|
return jsonErr(res, "Invalid project", 400);
|
|
362
|
-
|
|
379
|
+
const basePath = resolveProjectBasePath(ctx.phrenPath, project);
|
|
380
|
+
jsonOk(res, { ok: true, ...listProjectReferenceDocs(basePath, project) });
|
|
363
381
|
}
|
|
364
382
|
function handleGetProjectReferenceContent(res, url, ctx) {
|
|
365
383
|
const qs = parseQs(url);
|
|
366
|
-
const
|
|
384
|
+
const project = String(qs.project || "");
|
|
385
|
+
const basePath = resolveProjectBasePath(ctx.phrenPath, project);
|
|
386
|
+
const contentResult = readReferenceContent(basePath, project, String(qs.file || ""));
|
|
367
387
|
res.writeHead(contentResult.ok ? 200 : 400, { "content-type": "application/json; charset=utf-8" });
|
|
368
388
|
res.end(JSON.stringify(contentResult.ok ? { ok: true, content: contentResult.content } : { ok: false, error: contentResult.error }));
|
|
369
389
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phren/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.46",
|
|
4
4
|
"description": "Knowledge layer for AI agents. Phren learns and recalls.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"scripts/preuninstall.mjs"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
18
18
|
"chalk": "^5.6.2",
|
|
19
19
|
"glob": "^13.0.6",
|
|
20
20
|
"graphology": "^0.26.0",
|
|
@@ -26,17 +26,17 @@
|
|
|
26
26
|
"zod": "^4.3.6"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"esbuild": "^0.27.4",
|
|
30
29
|
"@playwright/test": "^1.58.2",
|
|
31
30
|
"@types/js-yaml": "^4.0.9",
|
|
32
31
|
"@types/node": "^25.5.0",
|
|
33
|
-
"@typescript-eslint/eslint-plugin": "^8.57.
|
|
34
|
-
"@typescript-eslint/parser": "^8.57.
|
|
35
|
-
"@vitest/coverage-v8": "^4.1.
|
|
32
|
+
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
|
33
|
+
"@typescript-eslint/parser": "^8.57.2",
|
|
34
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
35
|
+
"esbuild": "^0.27.4",
|
|
36
36
|
"eslint": "^10.1.0",
|
|
37
37
|
"tsx": "^4.21.0",
|
|
38
|
-
"typescript": "^
|
|
39
|
-
"vitest": "^4.1.
|
|
38
|
+
"typescript": "^6.0.2",
|
|
39
|
+
"vitest": "^4.1.2"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "node scripts/build.mjs",
|