@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/index.js
CHANGED
|
@@ -163,6 +163,9 @@ async function memSave(input, ctx) {
|
|
|
163
163
|
);
|
|
164
164
|
}
|
|
165
165
|
const existing = existsSync4(ctx.paths.memoriesDir) ? await loadMemoriesFromDir2(ctx.paths.memoriesDir) : [];
|
|
166
|
+
const invalidPaths = input.paths.filter(
|
|
167
|
+
(p) => !existsSync4(path3.resolve(ctx.paths.root, p))
|
|
168
|
+
);
|
|
166
169
|
const incomingHash = bodyHash(input.body);
|
|
167
170
|
const hashDuplicate = existing.find(
|
|
168
171
|
({ memory }) => bodyHash(memory.body) === incomingHash && memory.frontmatter.scope === input.scope
|
|
@@ -199,7 +202,8 @@ async function memSave(input, ctx) {
|
|
|
199
202
|
scope: fm.scope,
|
|
200
203
|
file_path: topicMatch.filePath,
|
|
201
204
|
action: "updated",
|
|
202
|
-
revision_count: newFrontmatter.revision_count
|
|
205
|
+
revision_count: newFrontmatter.revision_count,
|
|
206
|
+
...invalidPaths.length > 0 ? { invalid_paths: invalidPaths, warning: `Anchor path(s) not found in project: ${invalidPaths.join(", ")}. They will be marked stale by haive sync.` } : {}
|
|
203
207
|
};
|
|
204
208
|
}
|
|
205
209
|
}
|
|
@@ -240,13 +244,18 @@ async function memSave(input, ctx) {
|
|
|
240
244
|
}
|
|
241
245
|
}
|
|
242
246
|
await writeFile2(file, serializeMemory({ frontmatter, body: input.body }), "utf8");
|
|
247
|
+
const finalWarning = [
|
|
248
|
+
invalidPaths.length > 0 ? `Anchor path(s) not found in project: ${invalidPaths.join(", ")}. They will be marked stale by \`haive sync\`.` : null,
|
|
249
|
+
warning ?? null
|
|
250
|
+
].filter(Boolean).join(" \u2014 ") || void 0;
|
|
243
251
|
return {
|
|
244
252
|
id: frontmatter.id,
|
|
245
253
|
scope: frontmatter.scope,
|
|
246
254
|
file_path: file,
|
|
247
255
|
action: "created",
|
|
248
|
-
...
|
|
249
|
-
...similar_found ? { similar_found } : {}
|
|
256
|
+
...finalWarning ? { warning: finalWarning } : {},
|
|
257
|
+
...similar_found ? { similar_found } : {},
|
|
258
|
+
...invalidPaths.length > 0 ? { invalid_paths: invalidPaths } : {}
|
|
250
259
|
};
|
|
251
260
|
}
|
|
252
261
|
|
|
@@ -1081,6 +1090,12 @@ async function memSessionEnd(input, ctx) {
|
|
|
1081
1090
|
}
|
|
1082
1091
|
const body = buildBody(input);
|
|
1083
1092
|
const topic = recapTopic(input.scope, input.module);
|
|
1093
|
+
const invalidPaths = input.files_touched.filter(
|
|
1094
|
+
(p) => !existsSync16(path7.resolve(ctx.paths.root, p))
|
|
1095
|
+
);
|
|
1096
|
+
if (invalidPaths.length > 0) {
|
|
1097
|
+
console.warn(`[haive] session end: anchor path(s) not found: ${invalidPaths.join(", ")}`);
|
|
1098
|
+
}
|
|
1084
1099
|
const existing = existsSync16(ctx.paths.memoriesDir) ? await loadMemoriesFromDir12(ctx.paths.memoriesDir) : [];
|
|
1085
1100
|
const topicMatch = existing.find(
|
|
1086
1101
|
({ memory }) => memory.frontmatter.topic === topic && memory.frontmatter.scope === input.scope && (!input.module || memory.frontmatter.module === input.module)
|
|
@@ -1149,9 +1164,11 @@ import {
|
|
|
1149
1164
|
isDecaying,
|
|
1150
1165
|
literalMatchesAllTokens as literalMatchesAllTokens2,
|
|
1151
1166
|
literalMatchesAnyToken as literalMatchesAnyToken2,
|
|
1167
|
+
loadCodeMap,
|
|
1152
1168
|
loadMemoriesFromDir as loadMemoriesFromDir13,
|
|
1153
1169
|
loadUsageIndex as loadUsageIndex7,
|
|
1154
1170
|
memoryMatchesAnchorPaths as memoryMatchesAnchorPaths2,
|
|
1171
|
+
queryCodeMap,
|
|
1155
1172
|
tokenizeQuery as tokenizeQuery2,
|
|
1156
1173
|
trackReads as trackReads3,
|
|
1157
1174
|
truncateToTokens
|
|
@@ -1175,6 +1192,9 @@ var GetBriefingInputSchema = {
|
|
|
1175
1192
|
track: z17.boolean().default(true).describe("Increment read_count on returned memories"),
|
|
1176
1193
|
format: z17.enum(["full", "compact"]).default("full").describe(
|
|
1177
1194
|
"Output format: 'full' returns complete memory bodies; 'compact' returns id + 1-line summary only (call mem_get for details)."
|
|
1195
|
+
),
|
|
1196
|
+
symbols: z17.array(z17.string()).default([]).describe(
|
|
1197
|
+
"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."
|
|
1178
1198
|
)
|
|
1179
1199
|
};
|
|
1180
1200
|
async function getBriefing(input, ctx) {
|
|
@@ -1236,6 +1256,7 @@ async function getBriefing(input, ctx) {
|
|
|
1236
1256
|
tags: fm.tags,
|
|
1237
1257
|
status: fm.status,
|
|
1238
1258
|
confidence: deriveConfidence4(fm, u),
|
|
1259
|
+
...fm.status === "draft" || fm.status === "proposed" ? { unverified: true } : {},
|
|
1239
1260
|
read_count: u.read_count,
|
|
1240
1261
|
reasons: [reason],
|
|
1241
1262
|
match_quality: matchQuality ?? "partial",
|
|
@@ -1299,7 +1320,20 @@ async function getBriefing(input, ctx) {
|
|
|
1299
1320
|
await trackReads3(ctx.paths, memories.map((m) => m.id));
|
|
1300
1321
|
}
|
|
1301
1322
|
}
|
|
1302
|
-
const
|
|
1323
|
+
const projectContextRaw = input.include_project_context && existsSync17(ctx.paths.projectContext) ? await readFile3(ctx.paths.projectContext, "utf8") : "";
|
|
1324
|
+
const isTemplateContext = projectContextRaw.includes("TODO \u2014 high-level overview") || projectContextRaw.includes("Generated by `haive init`");
|
|
1325
|
+
const projectContext = isTemplateContext ? "" : projectContextRaw;
|
|
1326
|
+
const setupWarnings = [];
|
|
1327
|
+
if (isTemplateContext) {
|
|
1328
|
+
setupWarnings.push(
|
|
1329
|
+
"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."
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
if (!existsSync17(ctx.paths.projectContext)) {
|
|
1333
|
+
setupWarnings.push(
|
|
1334
|
+
"No project-context.md found. Run `haive init` then invoke the bootstrap_project MCP prompt."
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1303
1337
|
const moduleContents = input.include_module_contexts ? await loadModuleContexts2(ctx, inferred) : [];
|
|
1304
1338
|
const memoriesText = memories.map((m) => {
|
|
1305
1339
|
const unverified = m.status === "proposed" ? " [UNVERIFIED \u2014 not yet validated]" : "";
|
|
@@ -1361,15 +1395,52 @@ ${m.content}`).join("\n\n---\n\n"),
|
|
|
1361
1395
|
if (isDecaying(u, createdAt)) decayWarnings.push(m.id);
|
|
1362
1396
|
}
|
|
1363
1397
|
const outputMemories = input.format === "compact" ? trimmedMemories.map((m) => ({ ...m, body: compactSummary(m.body) })) : trimmedMemories;
|
|
1398
|
+
let symbolLocations;
|
|
1399
|
+
const symbolsToLookup = new Set(input.symbols);
|
|
1400
|
+
for (const m of outputMemories) {
|
|
1401
|
+
const loaded = byId.get(m.id);
|
|
1402
|
+
for (const sym of loaded?.memory.frontmatter.anchor.symbols ?? []) {
|
|
1403
|
+
symbolsToLookup.add(sym);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
if (symbolsToLookup.size > 0) {
|
|
1407
|
+
const codeMap = await loadCodeMap(ctx.paths);
|
|
1408
|
+
if (codeMap) {
|
|
1409
|
+
symbolLocations = [];
|
|
1410
|
+
for (const sym of symbolsToLookup) {
|
|
1411
|
+
const { files } = queryCodeMap(codeMap, { symbol: sym });
|
|
1412
|
+
if (files.length > 0) {
|
|
1413
|
+
symbolLocations.push({
|
|
1414
|
+
symbol: sym,
|
|
1415
|
+
locations: files.flatMap(
|
|
1416
|
+
(f) => f.entry.exports.filter((e) => e.name.toLowerCase().includes(sym.toLowerCase())).map((e) => ({
|
|
1417
|
+
file: f.path,
|
|
1418
|
+
kind: e.kind,
|
|
1419
|
+
line: e.line,
|
|
1420
|
+
...e.description ? { description: e.description } : {}
|
|
1421
|
+
}))
|
|
1422
|
+
)
|
|
1423
|
+
});
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
if (symbolLocations.length === 0) symbolLocations = void 0;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1364
1429
|
return {
|
|
1365
1430
|
...input.task ? { task: input.task } : {},
|
|
1366
1431
|
search_mode: searchMode,
|
|
1367
1432
|
inferred_modules: inferred,
|
|
1368
1433
|
...lastSession ? { last_session: lastSession } : {},
|
|
1369
|
-
project_context:
|
|
1434
|
+
project_context: projectContextRaw ? {
|
|
1435
|
+
content: projectSlice.text,
|
|
1436
|
+
truncated: projectSlice.truncated,
|
|
1437
|
+
...isTemplateContext ? { is_template: true } : {}
|
|
1438
|
+
} : null,
|
|
1370
1439
|
module_contexts: trimmedModules,
|
|
1371
1440
|
memories: outputMemories,
|
|
1441
|
+
...symbolLocations ? { symbol_locations: symbolLocations } : {},
|
|
1372
1442
|
decay_warnings: decayWarnings,
|
|
1443
|
+
setup_warnings: setupWarnings,
|
|
1373
1444
|
estimated_tokens: totalTokens,
|
|
1374
1445
|
budget: {
|
|
1375
1446
|
max_tokens: input.max_tokens,
|
|
@@ -1417,7 +1488,7 @@ async function loadModuleContexts2(ctx, modules) {
|
|
|
1417
1488
|
}
|
|
1418
1489
|
|
|
1419
1490
|
// src/tools/code-map.ts
|
|
1420
|
-
import { loadCodeMap, queryCodeMap } from "@hiveai/core";
|
|
1491
|
+
import { loadCodeMap as loadCodeMap2, queryCodeMap as queryCodeMap2 } from "@hiveai/core";
|
|
1421
1492
|
import { z as z18 } from "zod";
|
|
1422
1493
|
var CodeMapInputSchema = {
|
|
1423
1494
|
file: z18.string().optional().describe("Filter to files whose path contains this substring"),
|
|
@@ -1425,7 +1496,7 @@ var CodeMapInputSchema = {
|
|
|
1425
1496
|
max_files: z18.number().int().positive().default(40).describe("Cap on returned files")
|
|
1426
1497
|
};
|
|
1427
1498
|
async function codeMapTool(input, ctx) {
|
|
1428
|
-
const map = await
|
|
1499
|
+
const map = await loadCodeMap2(ctx.paths);
|
|
1429
1500
|
if (!map) {
|
|
1430
1501
|
return {
|
|
1431
1502
|
available: false,
|
|
@@ -1433,7 +1504,7 @@ async function codeMapTool(input, ctx) {
|
|
|
1433
1504
|
notice: "No code map found. Run `haive index code` to generate `.ai/code-map.json`."
|
|
1434
1505
|
};
|
|
1435
1506
|
}
|
|
1436
|
-
const { files } =
|
|
1507
|
+
const { files } = queryCodeMap2(map, { file: input.file, symbol: input.symbol });
|
|
1437
1508
|
return {
|
|
1438
1509
|
available: true,
|
|
1439
1510
|
generated_at: map.generated_at,
|
|
@@ -1735,7 +1806,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
1735
1806
|
|
|
1736
1807
|
// src/server.ts
|
|
1737
1808
|
var SERVER_NAME = "haive";
|
|
1738
|
-
var SERVER_VERSION = "0.
|
|
1809
|
+
var SERVER_VERSION = "0.3.0";
|
|
1739
1810
|
function jsonResult(data) {
|
|
1740
1811
|
return {
|
|
1741
1812
|
content: [
|