@hiveai/mcp 0.2.15 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +80 -9
- package/dist/index.js.map +1 -1
- package/dist/server.js +80 -9
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -158,6 +158,9 @@ async function memSave(input, ctx) {
|
|
|
158
158
|
);
|
|
159
159
|
}
|
|
160
160
|
const existing = existsSync4(ctx.paths.memoriesDir) ? await loadMemoriesFromDir2(ctx.paths.memoriesDir) : [];
|
|
161
|
+
const invalidPaths = input.paths.filter(
|
|
162
|
+
(p) => !existsSync4(path3.resolve(ctx.paths.root, p))
|
|
163
|
+
);
|
|
161
164
|
const incomingHash = bodyHash(input.body);
|
|
162
165
|
const hashDuplicate = existing.find(
|
|
163
166
|
({ memory }) => bodyHash(memory.body) === incomingHash && memory.frontmatter.scope === input.scope
|
|
@@ -194,7 +197,8 @@ async function memSave(input, ctx) {
|
|
|
194
197
|
scope: fm.scope,
|
|
195
198
|
file_path: topicMatch.filePath,
|
|
196
199
|
action: "updated",
|
|
197
|
-
revision_count: newFrontmatter.revision_count
|
|
200
|
+
revision_count: newFrontmatter.revision_count,
|
|
201
|
+
...invalidPaths.length > 0 ? { invalid_paths: invalidPaths, warning: `Anchor path(s) not found in project: ${invalidPaths.join(", ")}. They will be marked stale by haive sync.` } : {}
|
|
198
202
|
};
|
|
199
203
|
}
|
|
200
204
|
}
|
|
@@ -235,13 +239,18 @@ async function memSave(input, ctx) {
|
|
|
235
239
|
}
|
|
236
240
|
}
|
|
237
241
|
await writeFile2(file, serializeMemory({ frontmatter, body: input.body }), "utf8");
|
|
242
|
+
const finalWarning = [
|
|
243
|
+
invalidPaths.length > 0 ? `Anchor path(s) not found in project: ${invalidPaths.join(", ")}. They will be marked stale by \`haive sync\`.` : null,
|
|
244
|
+
warning ?? null
|
|
245
|
+
].filter(Boolean).join(" \u2014 ") || void 0;
|
|
238
246
|
return {
|
|
239
247
|
id: frontmatter.id,
|
|
240
248
|
scope: frontmatter.scope,
|
|
241
249
|
file_path: file,
|
|
242
250
|
action: "created",
|
|
243
|
-
...
|
|
244
|
-
...similar_found ? { similar_found } : {}
|
|
251
|
+
...finalWarning ? { warning: finalWarning } : {},
|
|
252
|
+
...similar_found ? { similar_found } : {},
|
|
253
|
+
...invalidPaths.length > 0 ? { invalid_paths: invalidPaths } : {}
|
|
245
254
|
};
|
|
246
255
|
}
|
|
247
256
|
|
|
@@ -1076,6 +1085,12 @@ async function memSessionEnd(input, ctx) {
|
|
|
1076
1085
|
}
|
|
1077
1086
|
const body = buildBody(input);
|
|
1078
1087
|
const topic = recapTopic(input.scope, input.module);
|
|
1088
|
+
const invalidPaths = input.files_touched.filter(
|
|
1089
|
+
(p) => !existsSync16(path7.resolve(ctx.paths.root, p))
|
|
1090
|
+
);
|
|
1091
|
+
if (invalidPaths.length > 0) {
|
|
1092
|
+
console.warn(`[haive] session end: anchor path(s) not found: ${invalidPaths.join(", ")}`);
|
|
1093
|
+
}
|
|
1079
1094
|
const existing = existsSync16(ctx.paths.memoriesDir) ? await loadMemoriesFromDir12(ctx.paths.memoriesDir) : [];
|
|
1080
1095
|
const topicMatch = existing.find(
|
|
1081
1096
|
({ memory }) => memory.frontmatter.topic === topic && memory.frontmatter.scope === input.scope && (!input.module || memory.frontmatter.module === input.module)
|
|
@@ -1144,9 +1159,11 @@ import {
|
|
|
1144
1159
|
isDecaying,
|
|
1145
1160
|
literalMatchesAllTokens as literalMatchesAllTokens2,
|
|
1146
1161
|
literalMatchesAnyToken as literalMatchesAnyToken2,
|
|
1162
|
+
loadCodeMap,
|
|
1147
1163
|
loadMemoriesFromDir as loadMemoriesFromDir13,
|
|
1148
1164
|
loadUsageIndex as loadUsageIndex7,
|
|
1149
1165
|
memoryMatchesAnchorPaths as memoryMatchesAnchorPaths2,
|
|
1166
|
+
queryCodeMap,
|
|
1150
1167
|
tokenizeQuery as tokenizeQuery2,
|
|
1151
1168
|
trackReads as trackReads3,
|
|
1152
1169
|
truncateToTokens
|
|
@@ -1170,6 +1187,9 @@ var GetBriefingInputSchema = {
|
|
|
1170
1187
|
track: z17.boolean().default(true).describe("Increment read_count on returned memories"),
|
|
1171
1188
|
format: z17.enum(["full", "compact"]).default("full").describe(
|
|
1172
1189
|
"Output format: 'full' returns complete memory bodies; 'compact' returns id + 1-line summary only (call mem_get for details)."
|
|
1190
|
+
),
|
|
1191
|
+
symbols: z17.array(z17.string()).default([]).describe(
|
|
1192
|
+
"Symbol names to look up in the code-map (e.g. ['PaymentService', 'TenantFilter']). Returns the file(s) exporting each symbol so agents don't need to grep. Requires `haive index code` to have been run."
|
|
1173
1193
|
)
|
|
1174
1194
|
};
|
|
1175
1195
|
async function getBriefing(input, ctx) {
|
|
@@ -1231,6 +1251,7 @@ async function getBriefing(input, ctx) {
|
|
|
1231
1251
|
tags: fm.tags,
|
|
1232
1252
|
status: fm.status,
|
|
1233
1253
|
confidence: deriveConfidence4(fm, u),
|
|
1254
|
+
...fm.status === "draft" || fm.status === "proposed" ? { unverified: true } : {},
|
|
1234
1255
|
read_count: u.read_count,
|
|
1235
1256
|
reasons: [reason],
|
|
1236
1257
|
match_quality: matchQuality ?? "partial",
|
|
@@ -1294,7 +1315,20 @@ async function getBriefing(input, ctx) {
|
|
|
1294
1315
|
await trackReads3(ctx.paths, memories.map((m) => m.id));
|
|
1295
1316
|
}
|
|
1296
1317
|
}
|
|
1297
|
-
const
|
|
1318
|
+
const projectContextRaw = input.include_project_context && existsSync17(ctx.paths.projectContext) ? await readFile3(ctx.paths.projectContext, "utf8") : "";
|
|
1319
|
+
const isTemplateContext = projectContextRaw.includes("TODO \u2014 high-level overview") || projectContextRaw.includes("Generated by `haive init`");
|
|
1320
|
+
const projectContext = isTemplateContext ? "" : projectContextRaw;
|
|
1321
|
+
const setupWarnings = [];
|
|
1322
|
+
if (isTemplateContext) {
|
|
1323
|
+
setupWarnings.push(
|
|
1324
|
+
"project-context.md still contains the default template. Invoke the bootstrap_project MCP prompt to auto-fill it from your codebase. Until then, get_briefing returns no project context."
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
if (!existsSync17(ctx.paths.projectContext)) {
|
|
1328
|
+
setupWarnings.push(
|
|
1329
|
+
"No project-context.md found. Run `haive init` then invoke the bootstrap_project MCP prompt."
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1298
1332
|
const moduleContents = input.include_module_contexts ? await loadModuleContexts2(ctx, inferred) : [];
|
|
1299
1333
|
const memoriesText = memories.map((m) => {
|
|
1300
1334
|
const unverified = m.status === "proposed" ? " [UNVERIFIED \u2014 not yet validated]" : "";
|
|
@@ -1356,15 +1390,52 @@ ${m.content}`).join("\n\n---\n\n"),
|
|
|
1356
1390
|
if (isDecaying(u, createdAt)) decayWarnings.push(m.id);
|
|
1357
1391
|
}
|
|
1358
1392
|
const outputMemories = input.format === "compact" ? trimmedMemories.map((m) => ({ ...m, body: compactSummary(m.body) })) : trimmedMemories;
|
|
1393
|
+
let symbolLocations;
|
|
1394
|
+
const symbolsToLookup = new Set(input.symbols);
|
|
1395
|
+
for (const m of outputMemories) {
|
|
1396
|
+
const loaded = byId.get(m.id);
|
|
1397
|
+
for (const sym of loaded?.memory.frontmatter.anchor.symbols ?? []) {
|
|
1398
|
+
symbolsToLookup.add(sym);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
if (symbolsToLookup.size > 0) {
|
|
1402
|
+
const codeMap = await loadCodeMap(ctx.paths);
|
|
1403
|
+
if (codeMap) {
|
|
1404
|
+
symbolLocations = [];
|
|
1405
|
+
for (const sym of symbolsToLookup) {
|
|
1406
|
+
const { files } = queryCodeMap(codeMap, { symbol: sym });
|
|
1407
|
+
if (files.length > 0) {
|
|
1408
|
+
symbolLocations.push({
|
|
1409
|
+
symbol: sym,
|
|
1410
|
+
locations: files.flatMap(
|
|
1411
|
+
(f) => f.entry.exports.filter((e) => e.name.toLowerCase().includes(sym.toLowerCase())).map((e) => ({
|
|
1412
|
+
file: f.path,
|
|
1413
|
+
kind: e.kind,
|
|
1414
|
+
line: e.line,
|
|
1415
|
+
...e.description ? { description: e.description } : {}
|
|
1416
|
+
}))
|
|
1417
|
+
)
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
if (symbolLocations.length === 0) symbolLocations = void 0;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1359
1424
|
return {
|
|
1360
1425
|
...input.task ? { task: input.task } : {},
|
|
1361
1426
|
search_mode: searchMode,
|
|
1362
1427
|
inferred_modules: inferred,
|
|
1363
1428
|
...lastSession ? { last_session: lastSession } : {},
|
|
1364
|
-
project_context:
|
|
1429
|
+
project_context: projectContextRaw ? {
|
|
1430
|
+
content: projectSlice.text,
|
|
1431
|
+
truncated: projectSlice.truncated,
|
|
1432
|
+
...isTemplateContext ? { is_template: true } : {}
|
|
1433
|
+
} : null,
|
|
1365
1434
|
module_contexts: trimmedModules,
|
|
1366
1435
|
memories: outputMemories,
|
|
1436
|
+
...symbolLocations ? { symbol_locations: symbolLocations } : {},
|
|
1367
1437
|
decay_warnings: decayWarnings,
|
|
1438
|
+
setup_warnings: setupWarnings,
|
|
1368
1439
|
estimated_tokens: totalTokens,
|
|
1369
1440
|
budget: {
|
|
1370
1441
|
max_tokens: input.max_tokens,
|
|
@@ -1412,7 +1483,7 @@ async function loadModuleContexts2(ctx, modules) {
|
|
|
1412
1483
|
}
|
|
1413
1484
|
|
|
1414
1485
|
// src/tools/code-map.ts
|
|
1415
|
-
import { loadCodeMap, queryCodeMap } from "@hiveai/core";
|
|
1486
|
+
import { loadCodeMap as loadCodeMap2, queryCodeMap as queryCodeMap2 } from "@hiveai/core";
|
|
1416
1487
|
import { z as z18 } from "zod";
|
|
1417
1488
|
var CodeMapInputSchema = {
|
|
1418
1489
|
file: z18.string().optional().describe("Filter to files whose path contains this substring"),
|
|
@@ -1420,7 +1491,7 @@ var CodeMapInputSchema = {
|
|
|
1420
1491
|
max_files: z18.number().int().positive().default(40).describe("Cap on returned files")
|
|
1421
1492
|
};
|
|
1422
1493
|
async function codeMapTool(input, ctx) {
|
|
1423
|
-
const map = await
|
|
1494
|
+
const map = await loadCodeMap2(ctx.paths);
|
|
1424
1495
|
if (!map) {
|
|
1425
1496
|
return {
|
|
1426
1497
|
available: false,
|
|
@@ -1428,7 +1499,7 @@ async function codeMapTool(input, ctx) {
|
|
|
1428
1499
|
notice: "No code map found. Run `haive index code` to generate `.ai/code-map.json`."
|
|
1429
1500
|
};
|
|
1430
1501
|
}
|
|
1431
|
-
const { files } =
|
|
1502
|
+
const { files } = queryCodeMap2(map, { file: input.file, symbol: input.symbol });
|
|
1432
1503
|
return {
|
|
1433
1504
|
available: true,
|
|
1434
1505
|
generated_at: map.generated_at,
|
|
@@ -1730,7 +1801,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
1730
1801
|
|
|
1731
1802
|
// src/server.ts
|
|
1732
1803
|
var SERVER_NAME = "haive";
|
|
1733
|
-
var SERVER_VERSION = "0.
|
|
1804
|
+
var SERVER_VERSION = "0.3.0";
|
|
1734
1805
|
function jsonResult(data) {
|
|
1735
1806
|
return {
|
|
1736
1807
|
content: [
|