gnosys 5.2.7 → 5.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +274 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +116 -32
- package/dist/index.js.map +1 -1
- package/dist/lib/db.d.ts +1 -0
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +3 -0
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/portfolio.d.ts +93 -0
- package/dist/lib/portfolio.d.ts.map +1 -0
- package/dist/lib/portfolio.js +618 -0
- package/dist/lib/portfolio.js.map +1 -0
- package/dist/lib/portfolioHtml.d.ts +9 -0
- package/dist/lib/portfolioHtml.d.ts.map +1 -0
- package/dist/lib/portfolioHtml.js +537 -0
- package/dist/lib/portfolioHtml.js.map +1 -0
- package/dist/postinstall.d.ts +3 -2
- package/dist/postinstall.d.ts.map +1 -1
- package/dist/postinstall.js +67 -21
- package/dist/postinstall.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -53,6 +53,7 @@ import { createProjectIdentity, readProjectIdentity } from "./lib/projectIdentit
|
|
|
53
53
|
import { setPreference, getPreference, getAllPreferences, deletePreference } from "./lib/preferences.js";
|
|
54
54
|
import { syncRules } from "./lib/rulesGen.js";
|
|
55
55
|
import { federatedSearch, detectAmbiguity, generateBriefing, generateAllBriefings, getWorkingSet, formatWorkingSet, detectCurrentProject } from "./lib/federated.js";
|
|
56
|
+
import { generatePortfolio, formatPortfolioCompact, formatPortfolioMarkdown, generateStatusPrompt } from "./lib/portfolio.js";
|
|
56
57
|
// Initialize resolver (discovers all layered stores)
|
|
57
58
|
const resolver = new GnosysResolver();
|
|
58
59
|
let config = DEFAULT_CONFIG;
|
|
@@ -815,27 +816,37 @@ server.tool("gnosys_update", "Update an existing memory's frontmatter and/or con
|
|
|
815
816
|
projectRoot: projectRootParam,
|
|
816
817
|
}, async ({ path: memPath, title, tags, status, confidence, relevance, supersedes, superseded_by, content: newContent, projectRoot, }) => {
|
|
817
818
|
const ctx = await resolveToolContext(projectRoot);
|
|
818
|
-
|
|
819
|
-
if (!memory) {
|
|
819
|
+
if (!ctx.centralDb?.isAvailable()) {
|
|
820
820
|
return {
|
|
821
|
-
content: [{ type: "text", text:
|
|
821
|
+
content: [{ type: "text", text: "Database not available. Cannot update memory." }],
|
|
822
822
|
isError: true,
|
|
823
823
|
};
|
|
824
824
|
}
|
|
825
|
-
//
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
if (
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
825
|
+
// DB-first lookup: resolve memory ID from central DB (mirrors gnosys_read pattern)
|
|
826
|
+
let memoryId;
|
|
827
|
+
let currentTitle;
|
|
828
|
+
const dbMem = ctx.centralDb.getMemory(memPath);
|
|
829
|
+
if (dbMem) {
|
|
830
|
+
memoryId = dbMem.id;
|
|
831
|
+
currentTitle = dbMem.title;
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
// Fallback to legacy file resolver
|
|
835
|
+
const memory = await ctx.resolver.readMemory(memPath);
|
|
836
|
+
if (!memory) {
|
|
837
|
+
return {
|
|
838
|
+
content: [{ type: "text", text: `Memory not found: ${memPath}` }],
|
|
839
|
+
isError: true,
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
if (!memory.frontmatter.id) {
|
|
843
|
+
return {
|
|
844
|
+
content: [{ type: "text", text: `Memory has no ID: ${memPath}` }],
|
|
845
|
+
isError: true,
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
memoryId = memory.frontmatter.id;
|
|
849
|
+
currentTitle = memory.frontmatter.title || memPath;
|
|
839
850
|
}
|
|
840
851
|
// Build updates object — only include defined fields
|
|
841
852
|
const updates = {};
|
|
@@ -853,20 +864,7 @@ server.tool("gnosys_update", "Update an existing memory's frontmatter and/or con
|
|
|
853
864
|
updates.supersedes = supersedes;
|
|
854
865
|
if (superseded_by !== undefined)
|
|
855
866
|
updates.superseded_by = superseded_by;
|
|
856
|
-
const fullContent = newContent ? `# ${title ||
|
|
857
|
-
const memoryId = memory.frontmatter.id;
|
|
858
|
-
if (!memoryId) {
|
|
859
|
-
return {
|
|
860
|
-
content: [{ type: "text", text: `Memory has no ID: ${memPath}` }],
|
|
861
|
-
isError: true,
|
|
862
|
-
};
|
|
863
|
-
}
|
|
864
|
-
if (!ctx.centralDb?.isAvailable()) {
|
|
865
|
-
return {
|
|
866
|
-
content: [{ type: "text", text: "Database not available. Cannot update memory." }],
|
|
867
|
-
isError: true,
|
|
868
|
-
};
|
|
869
|
-
}
|
|
867
|
+
const fullContent = newContent ? `# ${title || currentTitle}\n\n${newContent}` : undefined;
|
|
870
868
|
// Write update to DB only (SQLite is sole source of truth)
|
|
871
869
|
syncUpdateToDb(ctx.centralDb, memoryId, updates, fullContent);
|
|
872
870
|
auditToDb(ctx.centralDb, "write", memoryId, { tool: "gnosys_update", changed: Object.keys(updates) });
|
|
@@ -880,7 +878,7 @@ server.tool("gnosys_update", "Update an existing memory's frontmatter and/or con
|
|
|
880
878
|
const changedFields = Object.keys(updates);
|
|
881
879
|
if (newContent)
|
|
882
880
|
changedFields.push("content");
|
|
883
|
-
const updatedTitle = title ||
|
|
881
|
+
const updatedTitle = title || currentTitle;
|
|
884
882
|
return {
|
|
885
883
|
content: [
|
|
886
884
|
{
|
|
@@ -1101,6 +1099,30 @@ server.tool("gnosys_history", "View version history for a memory. Shows what cha
|
|
|
1101
1099
|
projectRoot: projectRootParam,
|
|
1102
1100
|
}, async ({ path: memPath, limit, projectRoot }) => {
|
|
1103
1101
|
const ctx = await resolveToolContext(projectRoot);
|
|
1102
|
+
// DB-first: resolve memory ID and show timestamps
|
|
1103
|
+
if (ctx.centralDb?.isAvailable()) {
|
|
1104
|
+
const dbMem = ctx.centralDb.getMemory(memPath);
|
|
1105
|
+
if (dbMem) {
|
|
1106
|
+
// Query audit_log for this memory
|
|
1107
|
+
const audits = ctx.centralDb.getAuditLog(dbMem.id, limit || 20);
|
|
1108
|
+
if (audits.length > 0) {
|
|
1109
|
+
const lines = audits.map((e) => `- ${e.timestamp.split("T")[0]} — ${e.operation}${e.details ? ` (${e.details})` : ""}`);
|
|
1110
|
+
return {
|
|
1111
|
+
content: [{
|
|
1112
|
+
type: "text",
|
|
1113
|
+
text: `History for **${dbMem.title}** (${dbMem.id}, ${audits.length} entries):\n\nCreated: ${dbMem.created}\nModified: ${dbMem.modified}\n\n${lines.join("\n")}`,
|
|
1114
|
+
}],
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
return {
|
|
1118
|
+
content: [{
|
|
1119
|
+
type: "text",
|
|
1120
|
+
text: `Memory found: **${dbMem.title}** (${dbMem.id})\nCreated: ${dbMem.created}\nModified: ${dbMem.modified}\nNo audit history recorded.`,
|
|
1121
|
+
}],
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
// Legacy file-based fallback
|
|
1104
1126
|
const memory = await ctx.resolver.readMemory(memPath);
|
|
1105
1127
|
if (!memory) {
|
|
1106
1128
|
return { content: [{ type: "text", text: `Memory not found: ${memPath}` }], isError: true };
|
|
@@ -1260,6 +1282,34 @@ server.tool("gnosys_links", "Show wikilinks for a specific memory — outgoing [
|
|
|
1260
1282
|
projectRoot: projectRootParam,
|
|
1261
1283
|
}, async ({ path: memPath, projectRoot }) => {
|
|
1262
1284
|
const ctx = await resolveToolContext(projectRoot);
|
|
1285
|
+
// DB-first: resolve memory ID and check relationships table
|
|
1286
|
+
if (ctx.centralDb?.isAvailable()) {
|
|
1287
|
+
const dbMem = ctx.centralDb.getMemory(memPath);
|
|
1288
|
+
if (dbMem) {
|
|
1289
|
+
const outRels = ctx.centralDb.getRelationshipsFrom(dbMem.id);
|
|
1290
|
+
const inRels = ctx.centralDb.getRelationshipsTo(dbMem.id);
|
|
1291
|
+
if (outRels.length > 0 || inRels.length > 0) {
|
|
1292
|
+
const parts = [`Links for **${dbMem.title}** (${dbMem.id}):\n`];
|
|
1293
|
+
if (outRels.length > 0) {
|
|
1294
|
+
parts.push(`Outgoing (${outRels.length}):`);
|
|
1295
|
+
for (const r of outRels) {
|
|
1296
|
+
const target = ctx.centralDb.getMemory(r.target_id);
|
|
1297
|
+
parts.push(` → ${r.rel_type} → ${target ? target.title : r.target_id}`);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
if (inRels.length > 0) {
|
|
1301
|
+
parts.push(`\nIncoming (${inRels.length}):`);
|
|
1302
|
+
for (const r of inRels) {
|
|
1303
|
+
const source = ctx.centralDb.getMemory(r.source_id);
|
|
1304
|
+
parts.push(` ← ${r.rel_type} ← ${source ? source.title : r.source_id}`);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return { content: [{ type: "text", text: parts.join("\n") }] };
|
|
1308
|
+
}
|
|
1309
|
+
return { content: [{ type: "text", text: `Memory found: **${dbMem.title}** (${dbMem.id})\nNo links or relationships recorded.` }] };
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
// Legacy file-based fallback
|
|
1263
1313
|
const memory = await ctx.resolver.readMemory(memPath);
|
|
1264
1314
|
if (!memory) {
|
|
1265
1315
|
return { content: [{ type: "text", text: `Memory not found: ${memPath}` }], isError: true };
|
|
@@ -2221,6 +2271,40 @@ server.tool("gnosys_briefing", "Generate a project briefing — a summary of mem
|
|
|
2221
2271
|
].join("\n");
|
|
2222
2272
|
return { content: [{ type: "text", text }] };
|
|
2223
2273
|
});
|
|
2274
|
+
// ─── Tool: gnosys_portfolio ─────────────────────────────────────────────
|
|
2275
|
+
server.tool("gnosys_portfolio", "Portfolio dashboard — shows all registered projects with memory counts, categories, status snapshots, roadmap items, and recent activity. Use for cross-project status overview.", {
|
|
2276
|
+
format: z.enum(["compact", "full"]).optional().describe("Output format: compact (default) or full markdown"),
|
|
2277
|
+
}, async ({ format }) => {
|
|
2278
|
+
if (!centralDb?.isAvailable()) {
|
|
2279
|
+
return { content: [{ type: "text", text: "Central DB not available." }], isError: true };
|
|
2280
|
+
}
|
|
2281
|
+
const report = generatePortfolio(centralDb);
|
|
2282
|
+
if (report.projects.length === 0) {
|
|
2283
|
+
return { content: [{ type: "text", text: "No projects with active memories found." }] };
|
|
2284
|
+
}
|
|
2285
|
+
const text = format === "full"
|
|
2286
|
+
? formatPortfolioMarkdown(report)
|
|
2287
|
+
: formatPortfolioCompact(report);
|
|
2288
|
+
return { content: [{ type: "text", text }] };
|
|
2289
|
+
});
|
|
2290
|
+
// ─── Tool: gnosys_update_status ─────────────────────────────────────────
|
|
2291
|
+
server.tool("gnosys_update_status", "Get the prompt/template for writing a dashboard-compatible status memory for this project. Returns instructions for creating a landscape memory with the correct heading format so the portfolio dashboard can parse it. Run this, then follow the instructions to analyze and write the status.", {
|
|
2292
|
+
projectRoot: z.string().optional().describe("Project root for auto-detection"),
|
|
2293
|
+
}, async ({ projectRoot }) => {
|
|
2294
|
+
if (!centralDb?.isAvailable()) {
|
|
2295
|
+
return { content: [{ type: "text", text: "Central DB not available." }], isError: true };
|
|
2296
|
+
}
|
|
2297
|
+
const pid = await detectCurrentProject(centralDb, projectRoot || undefined);
|
|
2298
|
+
if (!pid) {
|
|
2299
|
+
return { content: [{ type: "text", text: "No project detected from current directory." }], isError: true };
|
|
2300
|
+
}
|
|
2301
|
+
const project = centralDb.getProject(pid);
|
|
2302
|
+
if (!project) {
|
|
2303
|
+
return { content: [{ type: "text", text: `Project not found: ${pid}` }], isError: true };
|
|
2304
|
+
}
|
|
2305
|
+
const prompt = generateStatusPrompt(project.name, project.working_directory);
|
|
2306
|
+
return { content: [{ type: "text", text: prompt }] };
|
|
2307
|
+
});
|
|
2224
2308
|
// ─── Tool: gnosys_working_set ───────────────────────────────────────────
|
|
2225
2309
|
server.tool("gnosys_working_set", "Get the implicit working set — recently modified memories for the current project. These represent the active context and get boosted in federated search.", {
|
|
2226
2310
|
projectRoot: z.string().optional().describe("Project root for auto-detection"),
|