@hiveai/mcp 0.9.30 → 0.10.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 +44 -5
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +8 -0
- package/dist/server.js +44 -5
- package/dist/server.js.map +1 -1
- package/package.json +3 -3
package/dist/server.d.ts
CHANGED
|
@@ -158,6 +158,14 @@ interface BriefingOutput {
|
|
|
158
158
|
* Clients can use this flag to skip surfacing a near-empty briefing to the model.
|
|
159
159
|
*/
|
|
160
160
|
low_value?: true;
|
|
161
|
+
/**
|
|
162
|
+
* Whether this briefing carries knowledge a capable model could NOT have inferred on its own.
|
|
163
|
+
* - "high": at least one surfaced memory is arbitrary/team-specific (unguessable).
|
|
164
|
+
* - "low": nothing team-specific matched — a generic agent would reach the same answer.
|
|
165
|
+
* When "low" and the project context is still auto-generated/template, the adaptive briefing
|
|
166
|
+
* trims that inferable context to keep the call near-zero-cost (config: adaptiveBriefing).
|
|
167
|
+
*/
|
|
168
|
+
briefing_value?: "high" | "low";
|
|
161
169
|
/**
|
|
162
170
|
* Short, action-oriented hints surfaced to the agent based on the briefing payload.
|
|
163
171
|
* Examples: "haive is uninitialized — use Read/Grep directly", "gotcha memories present — read first".
|
package/dist/server.js
CHANGED
|
@@ -1074,6 +1074,7 @@ import { existsSync as existsSync15 } from "fs";
|
|
|
1074
1074
|
import path6 from "path";
|
|
1075
1075
|
import {
|
|
1076
1076
|
buildFrontmatter as buildFrontmatter3,
|
|
1077
|
+
isLikelyGuessable,
|
|
1077
1078
|
memoryFilePath as memoryFilePath3,
|
|
1078
1079
|
serializeMemory as serializeMemory7
|
|
1079
1080
|
} from "@hiveai/core";
|
|
@@ -1086,12 +1087,25 @@ var MemObserveInputSchema = {
|
|
|
1086
1087
|
scope: z15.enum(["personal", "team", "module"]).default("team").describe("Visibility scope \u2014 defaults to team since discoveries benefit everyone"),
|
|
1087
1088
|
module: z15.string().optional().describe("Module name (required when scope=module)"),
|
|
1088
1089
|
tags: z15.array(z15.string()).default([]).describe("Tags for filtering"),
|
|
1089
|
-
author: z15.string().optional().describe("Author handle or email")
|
|
1090
|
+
author: z15.string().optional().describe("Author handle or email"),
|
|
1091
|
+
force: z15.boolean().default(false).describe(
|
|
1092
|
+
"Save even if the observation looks like generic, guessable knowledge. By default, low-specificity observations (things a capable model already knows) are SKIPPED to keep the corpus high-signal \u2014 only unguessable, team-specific discoveries are worth storing."
|
|
1093
|
+
)
|
|
1090
1094
|
};
|
|
1091
1095
|
async function memObserve(input, ctx) {
|
|
1092
1096
|
if (!existsSync15(ctx.paths.haiveDir)) {
|
|
1093
1097
|
throw new Error(`No .ai/ directory at ${ctx.paths.root}. Run 'haive init' first.`);
|
|
1094
1098
|
}
|
|
1099
|
+
const signalText = [input.what, input.impact, input.fix ?? ""].join(" ");
|
|
1100
|
+
if (!input.force && isLikelyGuessable(signalText)) {
|
|
1101
|
+
return {
|
|
1102
|
+
id: "",
|
|
1103
|
+
scope: input.scope,
|
|
1104
|
+
file_path: "",
|
|
1105
|
+
skipped: true,
|
|
1106
|
+
reason: "Observation looks like generic, guessable knowledge (low specificity) \u2014 not saved. Capture only arbitrary, team-specific facts (exact names, values, formats). Pass force=true to override."
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1095
1109
|
const slug = input.what.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().split(/\s+/).slice(0, 6).join("-");
|
|
1096
1110
|
const anchorPaths = input.where.split(/[,\n]/).map((s) => s.trim()).filter(Boolean);
|
|
1097
1111
|
const baseFm = buildFrontmatter3({
|
|
@@ -1412,6 +1426,8 @@ import {
|
|
|
1412
1426
|
queryCodeMap,
|
|
1413
1427
|
resolveBriefingBudget,
|
|
1414
1428
|
serializeMemory as serializeMemory9,
|
|
1429
|
+
specificityScore,
|
|
1430
|
+
GUESSABLE_THRESHOLD,
|
|
1415
1431
|
tokenizeQuery as tokenizeQuery2,
|
|
1416
1432
|
trackReads as trackReads3,
|
|
1417
1433
|
truncateToTokens,
|
|
@@ -1837,6 +1853,14 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
1837
1853
|
const memoriesEmpty = outputMemories.length === 0;
|
|
1838
1854
|
const hasMemoriesDir = existsSync18(ctx.paths.memoriesDir);
|
|
1839
1855
|
const isColdStart = isTemplateContext && memoriesEmpty && !lastSession && !autoContextGenerated;
|
|
1856
|
+
const hasUnguessableSignal = outputMemories.some(
|
|
1857
|
+
(m) => (m.priority === "must_read" || m.priority === "useful") && specificityScore(m.body) >= GUESSABLE_THRESHOLD
|
|
1858
|
+
);
|
|
1859
|
+
const briefingValueLow = !hasUnguessableSignal;
|
|
1860
|
+
const adaptiveConfig = await loadConfig3(ctx.paths);
|
|
1861
|
+
const bootstrapUnfilled = /Auto-generated by `haive init/i.test(projectContextRaw) && (projectContextRaw.match(/TODO —/g)?.length ?? 0) >= 2;
|
|
1862
|
+
const contextIsInferable = isTemplateContext || autoContextGenerated || bootstrapUnfilled;
|
|
1863
|
+
const adaptiveTrim = adaptiveConfig.adaptiveBriefing !== false && briefingValueLow && contextIsInferable;
|
|
1840
1864
|
const hints = [];
|
|
1841
1865
|
if (isColdStart) {
|
|
1842
1866
|
hints.push(
|
|
@@ -1869,6 +1893,11 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
1869
1893
|
);
|
|
1870
1894
|
}
|
|
1871
1895
|
}
|
|
1896
|
+
if (adaptiveTrim) {
|
|
1897
|
+
hints.push(
|
|
1898
|
+
"No team-specific policy matched these files/task \u2014 nothing here a capable model can't infer. The auto-generated project context was trimmed to keep this briefing near-zero-cost; proceed with normal Read/Grep."
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1872
1901
|
if (existsSync18(ctx.paths.haiveDir)) {
|
|
1873
1902
|
await writeBriefingMarker(ctx.paths, {
|
|
1874
1903
|
sessionId: process.env.HAIVE_SESSION_ID,
|
|
@@ -1884,7 +1913,12 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
1884
1913
|
search_mode: searchMode,
|
|
1885
1914
|
inferred_modules: inferred,
|
|
1886
1915
|
...lastSession ? { last_session: lastSession } : {},
|
|
1887
|
-
project_context:
|
|
1916
|
+
project_context: adaptiveTrim ? {
|
|
1917
|
+
content: "(adaptive briefing: auto-generated context omitted \u2014 no team-specific policy matched, so a capable model needs nothing extra here)",
|
|
1918
|
+
truncated: false,
|
|
1919
|
+
...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
|
|
1920
|
+
...autoContextGenerated ? { auto_generated: true } : {}
|
|
1921
|
+
} : projectContextRaw || autoContextGenerated ? {
|
|
1888
1922
|
content: projectSlice.text,
|
|
1889
1923
|
truncated: projectSlice.truncated,
|
|
1890
1924
|
...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
|
|
@@ -1898,6 +1932,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
1898
1932
|
decay_warnings: decayWarnings,
|
|
1899
1933
|
setup_warnings: setupWarnings,
|
|
1900
1934
|
...isColdStart ? { low_value: true } : {},
|
|
1935
|
+
briefing_value: briefingValueLow ? "low" : "high",
|
|
1901
1936
|
...hints.length > 0 ? { hints } : {},
|
|
1902
1937
|
estimated_tokens: totalTokens,
|
|
1903
1938
|
budget: {
|
|
@@ -2473,8 +2508,12 @@ var CODE_STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
2473
2508
|
"console"
|
|
2474
2509
|
]);
|
|
2475
2510
|
function tokenizeDiffForLiteral(diff) {
|
|
2476
|
-
const
|
|
2477
|
-
const
|
|
2511
|
+
const lines = diff.split("\n");
|
|
2512
|
+
const looksLikeDiff = lines.some((l) => /^[+-]/.test(l));
|
|
2513
|
+
const addedOnly = looksLikeDiff ? lines.filter((l) => l.startsWith("+") && !l.startsWith("+++")).join("\n") : diff;
|
|
2514
|
+
const source = addedOnly.trim().length > 0 ? addedOnly : diff;
|
|
2515
|
+
const wsTokens = tokenizeQuery3(source);
|
|
2516
|
+
const wordTokens = source.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
|
|
2478
2517
|
return [.../* @__PURE__ */ new Set([...wsTokens, ...wordTokens])];
|
|
2479
2518
|
}
|
|
2480
2519
|
async function antiPatternsCheck(input, ctx) {
|
|
@@ -3825,7 +3864,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
3825
3864
|
// src/server.ts
|
|
3826
3865
|
import { loadConfigSync } from "@hiveai/core";
|
|
3827
3866
|
var SERVER_NAME = "haive";
|
|
3828
|
-
var SERVER_VERSION = "0.
|
|
3867
|
+
var SERVER_VERSION = "0.10.0";
|
|
3829
3868
|
function jsonResult(data) {
|
|
3830
3869
|
return {
|
|
3831
3870
|
content: [
|