@hiveai/mcp 0.9.31 → 0.10.1

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/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".
@@ -341,15 +349,13 @@ interface WhyThisFileOutput {
341
349
  */
342
350
  declare function whyThisFile(input: WhyThisFileInput, ctx: HaiveContext): Promise<WhyThisFileOutput>;
343
351
 
344
- declare const AntiPatternsCheckInputSchema: {
345
- diff: z.ZodOptional<z.ZodString>;
346
- paths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
347
- limit: z.ZodDefault<z.ZodNumber>;
348
- semantic: z.ZodDefault<z.ZodBoolean>;
349
- };
350
- type AntiPatternsCheckInput = {
351
- [K in keyof typeof AntiPatternsCheckInputSchema]: z.infer<(typeof AntiPatternsCheckInputSchema)[K]>;
352
- };
352
+ interface AntiPatternsCheckInput {
353
+ diff?: string;
354
+ paths: string[];
355
+ limit: number;
356
+ semantic: boolean;
357
+ min_semantic_score?: number;
358
+ }
353
359
  interface AntiPatternsWarning {
354
360
  id: string;
355
361
  type: "attempt" | "gotcha";
@@ -693,8 +699,8 @@ declare const SERVER_NAME = "haive";
693
699
  declare const SERVER_VERSION: string;
694
700
  type ToolProfile = "enforcement" | "maintenance" | "experimental" | "full";
695
701
  declare const ENFORCEMENT_PROFILE_TOOLS: readonly ["get_briefing", "mem_save", "mem_tried", "mem_search", "mem_get", "mem_verify", "mem_relevant_to", "code_map", "code_search", "pre_commit_check", "mem_session_end"];
696
- declare const MAINTENANCE_PROFILE_TOOLS: readonly ["get_briefing", "mem_save", "mem_tried", "mem_search", "mem_get", "mem_verify", "mem_relevant_to", "code_map", "code_search", "pre_commit_check", "mem_session_end", "mem_suggest_topic", "mem_for_files", "mem_list", "get_project_context", "bootstrap_project_save", "mem_resolve_project", "mem_update", "mem_approve", "mem_reject", "mem_pending", "mem_delete", "mem_diff", "get_recap", "code_search", "anti_patterns_check", "mem_distill", "mem_timeline", "mem_conflict_candidates"];
697
- declare const EXPERIMENTAL_PROFILE_TOOLS: readonly ["get_briefing", "mem_save", "mem_tried", "mem_search", "mem_get", "mem_verify", "mem_relevant_to", "code_map", "code_search", "pre_commit_check", "mem_session_end", "mem_suggest_topic", "mem_for_files", "mem_list", "get_project_context", "bootstrap_project_save", "mem_resolve_project", "mem_update", "mem_approve", "mem_reject", "mem_pending", "mem_delete", "mem_diff", "get_recap", "code_search", "anti_patterns_check", "mem_distill", "mem_timeline", "mem_conflict_candidates", "mem_observe", "why_this_file", "why_this_decision", "mem_conflicts_with", "pattern_detect", "runtime_journal_append", "runtime_journal_tail"];
702
+ declare const MAINTENANCE_PROFILE_TOOLS: readonly ["get_briefing", "mem_save", "mem_tried", "mem_search", "mem_get", "mem_verify", "mem_relevant_to", "code_map", "code_search", "pre_commit_check", "mem_session_end", "mem_suggest_topic", "mem_for_files", "mem_list", "get_project_context", "bootstrap_project_save", "mem_resolve_project", "mem_update", "mem_approve", "mem_reject", "mem_pending", "mem_delete", "mem_diff", "get_recap", "anti_patterns_check", "mem_distill", "mem_timeline", "mem_conflict_candidates"];
703
+ declare const EXPERIMENTAL_PROFILE_TOOLS: readonly ["get_briefing", "mem_save", "mem_tried", "mem_search", "mem_get", "mem_verify", "mem_relevant_to", "code_map", "code_search", "pre_commit_check", "mem_session_end", "mem_suggest_topic", "mem_for_files", "mem_list", "get_project_context", "bootstrap_project_save", "mem_resolve_project", "mem_update", "mem_approve", "mem_reject", "mem_pending", "mem_delete", "mem_diff", "get_recap", "anti_patterns_check", "mem_distill", "mem_timeline", "mem_conflict_candidates", "mem_observe", "why_this_file", "why_this_decision", "mem_conflicts_with", "pattern_detect", "runtime_journal_append", "runtime_journal_tail"];
698
704
  declare const TOOL_PROFILES: Record<Exclude<ToolProfile, "full">, ReadonlySet<string>>;
699
705
  declare function getAllowedToolsForProfile(profile: ToolProfile): ReadonlySet<string>;
700
706
  declare function createHaiveServer(options?: CreateContextOptions): {
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({
@@ -1398,6 +1412,7 @@ import {
1398
1412
  getUsage as getUsage5,
1399
1413
  inferModulesFromPaths as inferModulesFromPaths2,
1400
1414
  isGlobPath,
1415
+ isRetiredMemory,
1401
1416
  isAutoPromoteEligible,
1402
1417
  isDecaying,
1403
1418
  isStackPackSeed,
@@ -1412,6 +1427,8 @@ import {
1412
1427
  queryCodeMap,
1413
1428
  resolveBriefingBudget,
1414
1429
  serializeMemory as serializeMemory9,
1430
+ specificityScore,
1431
+ GUESSABLE_THRESHOLD,
1415
1432
  tokenizeQuery as tokenizeQuery2,
1416
1433
  trackReads as trackReads3,
1417
1434
  truncateToTokens,
@@ -1482,6 +1499,7 @@ async function getBriefing(input, ctx) {
1482
1499
  const s = memory.frontmatter.status;
1483
1500
  if (s === "rejected" || s === "deprecated") return false;
1484
1501
  if (!input.include_stale && s === "stale") return false;
1502
+ if (!input.include_stale && isRetiredMemory(memory.frontmatter, memory.body)) return false;
1485
1503
  if (memory.frontmatter.type === "session_recap") return false;
1486
1504
  return true;
1487
1505
  });
@@ -1837,6 +1855,14 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
1837
1855
  const memoriesEmpty = outputMemories.length === 0;
1838
1856
  const hasMemoriesDir = existsSync18(ctx.paths.memoriesDir);
1839
1857
  const isColdStart = isTemplateContext && memoriesEmpty && !lastSession && !autoContextGenerated;
1858
+ const hasUnguessableSignal = outputMemories.some(
1859
+ (m) => (m.priority === "must_read" || m.priority === "useful") && specificityScore(m.body) >= GUESSABLE_THRESHOLD
1860
+ );
1861
+ const briefingValueLow = !hasUnguessableSignal;
1862
+ const adaptiveConfig = await loadConfig3(ctx.paths);
1863
+ const bootstrapUnfilled = /Auto-generated by `haive init/i.test(projectContextRaw) && (projectContextRaw.match(/TODO —/g)?.length ?? 0) >= 2;
1864
+ const contextIsInferable = isTemplateContext || autoContextGenerated || bootstrapUnfilled;
1865
+ const adaptiveTrim = adaptiveConfig.adaptiveBriefing !== false && briefingValueLow && contextIsInferable;
1840
1866
  const hints = [];
1841
1867
  if (isColdStart) {
1842
1868
  hints.push(
@@ -1869,6 +1895,11 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
1869
1895
  );
1870
1896
  }
1871
1897
  }
1898
+ if (adaptiveTrim) {
1899
+ hints.push(
1900
+ "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."
1901
+ );
1902
+ }
1872
1903
  if (existsSync18(ctx.paths.haiveDir)) {
1873
1904
  await writeBriefingMarker(ctx.paths, {
1874
1905
  sessionId: process.env.HAIVE_SESSION_ID,
@@ -1884,7 +1915,12 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
1884
1915
  search_mode: searchMode,
1885
1916
  inferred_modules: inferred,
1886
1917
  ...lastSession ? { last_session: lastSession } : {},
1887
- project_context: projectContextRaw || autoContextGenerated ? {
1918
+ project_context: adaptiveTrim ? {
1919
+ content: "(adaptive briefing: auto-generated context omitted \u2014 no team-specific policy matched, so a capable model needs nothing extra here)",
1920
+ truncated: false,
1921
+ ...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
1922
+ ...autoContextGenerated ? { auto_generated: true } : {}
1923
+ } : projectContextRaw || autoContextGenerated ? {
1888
1924
  content: projectSlice.text,
1889
1925
  truncated: projectSlice.truncated,
1890
1926
  ...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
@@ -1898,6 +1934,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
1898
1934
  decay_warnings: decayWarnings,
1899
1935
  setup_warnings: setupWarnings,
1900
1936
  ...isColdStart ? { low_value: true } : {},
1937
+ briefing_value: briefingValueLow ? "low" : "high",
1901
1938
  ...hints.length > 0 ? { hints } : {},
1902
1939
  estimated_tokens: totalTokens,
1903
1940
  budget: {
@@ -2406,6 +2443,7 @@ import { existsSync as existsSync22 } from "fs";
2406
2443
  import {
2407
2444
  deriveConfidence as deriveConfidence6,
2408
2445
  getUsage as getUsage7,
2446
+ isRetiredMemory as isRetiredMemory2,
2409
2447
  loadMemoriesFromDir as loadMemoriesFromDir17,
2410
2448
  loadUsageIndex as loadUsageIndex9,
2411
2449
  literalMatchesAnyToken as literalMatchesAnyToken3,
@@ -2423,6 +2461,9 @@ var AntiPatternsCheckInputSchema = {
2423
2461
  limit: z24.number().int().positive().max(20).default(8).describe("Cap on returned warnings."),
2424
2462
  semantic: z24.boolean().default(true).describe(
2425
2463
  "When true, also use semantic search (requires @hiveai/embeddings + memory index) to find related anti-patterns."
2464
+ ),
2465
+ min_semantic_score: z24.number().min(0).max(1).default(0.45).describe(
2466
+ "Minimum cosine score for semantic-only anti-pattern hits. Anchor/literal matches still surface. Default 0.45 keeps broad, weakly-related memories out of review noise."
2426
2467
  )
2427
2468
  };
2428
2469
  var CODE_STOPWORDS = /* @__PURE__ */ new Set([
@@ -2473,8 +2514,12 @@ var CODE_STOPWORDS = /* @__PURE__ */ new Set([
2473
2514
  "console"
2474
2515
  ]);
2475
2516
  function tokenizeDiffForLiteral(diff) {
2476
- const wsTokens = tokenizeQuery3(diff);
2477
- const wordTokens = diff.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
2517
+ const lines = diff.split("\n");
2518
+ const looksLikeDiff = lines.some((l) => /^[+-]/.test(l));
2519
+ const addedOnly = looksLikeDiff ? lines.filter((l) => l.startsWith("+") && !l.startsWith("+++")).join("\n") : diff;
2520
+ const source = addedOnly.trim().length > 0 ? addedOnly : diff;
2521
+ const wsTokens = tokenizeQuery3(source);
2522
+ const wordTokens = source.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
2478
2523
  return [.../* @__PURE__ */ new Set([...wsTokens, ...wordTokens])];
2479
2524
  }
2480
2525
  async function antiPatternsCheck(input, ctx) {
@@ -2489,11 +2534,12 @@ async function antiPatternsCheck(input, ctx) {
2489
2534
  return { scanned: 0, warnings: [], notice: "No .ai/memories directory \u2014 nothing to check against." };
2490
2535
  }
2491
2536
  const all = await loadMemoriesFromDir17(ctx.paths.memoriesDir);
2537
+ const minSemanticScore = input.min_semantic_score ?? 0.45;
2492
2538
  const negative = all.filter(({ memory }) => {
2493
2539
  const t = memory.frontmatter.type;
2494
2540
  if (t !== "attempt" && t !== "gotcha") return false;
2495
2541
  const s = memory.frontmatter.status;
2496
- return s !== "rejected" && s !== "deprecated" && s !== "stale";
2542
+ return s !== "rejected" && s !== "deprecated" && s !== "stale" && !isRetiredMemory2(memory.frontmatter, memory.body);
2497
2543
  });
2498
2544
  if (negative.length === 0) {
2499
2545
  return { scanned: 0, warnings: [], notice: "No attempt/gotcha memories found yet." };
@@ -2547,6 +2593,7 @@ async function antiPatternsCheck(input, ctx) {
2547
2593
  const negativeIds = new Set(negative.map(({ memory }) => memory.frontmatter.id));
2548
2594
  for (const hit of result.hits) {
2549
2595
  if (!negativeIds.has(hit.id)) continue;
2596
+ if (hit.score < minSemanticScore && !seen.has(hit.id)) continue;
2550
2597
  const found = negative.find(({ memory }) => memory.frontmatter.id === hit.id);
2551
2598
  if (found) upsert(found.memory.frontmatter, found.memory.body, "semantic", hit.score);
2552
2599
  }
@@ -3825,7 +3872,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
3825
3872
  // src/server.ts
3826
3873
  import { loadConfigSync } from "@hiveai/core";
3827
3874
  var SERVER_NAME = "haive";
3828
- var SERVER_VERSION = "0.9.31";
3875
+ var SERVER_VERSION = "0.10.1";
3829
3876
  function jsonResult(data) {
3830
3877
  return {
3831
3878
  content: [
@@ -3864,7 +3911,6 @@ var MAINTENANCE_PROFILE_TOOLS = [
3864
3911
  "mem_delete",
3865
3912
  "mem_diff",
3866
3913
  "get_recap",
3867
- "code_search",
3868
3914
  "anti_patterns_check",
3869
3915
  "mem_distill",
3870
3916
  "mem_timeline",