@hiveai/mcp 0.9.5 → 0.9.7

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 CHANGED
@@ -1127,7 +1127,11 @@ import {
1127
1127
  import { z as z16 } from "zod";
1128
1128
 
1129
1129
  // src/session-tracker.ts
1130
- import { appendUsageEvent, loadConfig as loadConfig2 } from "@hiveai/core";
1130
+ import {
1131
+ appendUsageEvent,
1132
+ appendRuntimeJournalEntry,
1133
+ loadConfig as loadConfig2
1134
+ } from "@hiveai/core";
1131
1135
  import { mkdir as mkdir5, writeFile as writeFile9, rm } from "fs/promises";
1132
1136
  import { existsSync as existsSync16 } from "fs";
1133
1137
  import path7 from "path";
@@ -1200,6 +1204,14 @@ var SessionTracker = class {
1200
1204
  recapId = result.id;
1201
1205
  } catch {
1202
1206
  }
1207
+ void appendRuntimeJournalEntry(this.ctx.paths, {
1208
+ kind: "session_end",
1209
+ message: recapId ? `auto session close | ${toolSummary} | recap:${recapId}` : `auto session close | ${toolSummary}`,
1210
+ meta: {
1211
+ recap_id: recapId ?? null,
1212
+ total_tool_calls: totalCalls
1213
+ }
1214
+ });
1203
1215
  const ranPostTask = this.events.some(
1204
1216
  (e) => e.tool === "mem_session_end" && !e.summary?.startsWith("Auto-captured")
1205
1217
  );
@@ -1900,6 +1912,7 @@ var CodeMapInputSchema = {
1900
1912
  "Approximate token budget for the response. When the matching set exceeds it, files are ranked by export density (exports per LOC) and the highest-signal ones are kept first. Omit to disable budgeting (legacy behavior)."
1901
1913
  )
1902
1914
  };
1915
+ var CodeMapInputZod = z18.object(CodeMapInputSchema);
1903
1916
  async function codeMapTool(input, ctx) {
1904
1917
  const map = await loadCodeMap2(ctx.paths);
1905
1918
  if (!map) {
@@ -3070,19 +3083,27 @@ function gitFileDiff(root, file, sinceDays) {
3070
3083
 
3071
3084
  // src/tools/mem-conflict-candidates.ts
3072
3085
  import { existsSync as existsSync27 } from "fs";
3073
- import { findLexicalConflictPairs, loadMemoriesFromDir as loadMemoriesFromDir21 } from "@hiveai/core";
3086
+ import {
3087
+ findLexicalConflictPairs,
3088
+ findTopicStatusConflictPairs,
3089
+ loadMemoriesFromDir as loadMemoriesFromDir21
3090
+ } from "@hiveai/core";
3074
3091
  import { z as z30 } from "zod";
3075
3092
  var MemConflictCandidatesInputSchema = {
3076
3093
  since_days: z30.number().int().positive().max(3650).default(365).describe("Only memories created since N days ago"),
3077
3094
  types: z30.array(z30.enum(["decision", "architecture", "convention", "gotcha"])).default(["decision", "architecture"]).describe("Memory types scanned for pairwise lexical overlap"),
3078
3095
  min_jaccard: z30.number().min(0).max(1).default(0.45).describe("Minimum Jaccard token similarity to surface as a candidate pair"),
3079
3096
  max_pairs: z30.number().int().positive().max(100).default(20).describe("Cap pairs returned"),
3080
- max_scan: z30.number().int().positive().max(2e3).default(500).describe("Maximum memories sampled for O(n\xB2) scan \u2014 excess dropped after chronological sort.")
3097
+ max_scan: z30.number().int().positive().max(2e3).default(500).describe("Maximum memories sampled for O(n\xB2) scan \u2014 excess dropped after chronological sort."),
3098
+ max_topic_pairs: z30.number().int().positive().max(100).default(20).describe(
3099
+ "Cap for extra signal: memories sharing the same topic with validated vs rejected status."
3100
+ )
3081
3101
  };
3082
3102
  async function memConflictCandidates(input, ctx) {
3083
3103
  if (!existsSync27(ctx.paths.memoriesDir)) {
3084
3104
  return {
3085
3105
  pairs: [],
3106
+ topic_status_pairs: [],
3086
3107
  scanned: 0,
3087
3108
  truncated: false,
3088
3109
  notice: "No .ai/memories directory."
@@ -3096,8 +3117,9 @@ async function memConflictCandidates(input, ctx) {
3096
3117
  maxPairs: input.max_pairs,
3097
3118
  maxScan: input.max_scan
3098
3119
  });
3099
- const notice = pairs.length === 0 ? "No lexical candidate pairs \u2265 threshold \u2014 try lowering min_jaccard or widen since_days/types." : void 0;
3100
- return { pairs, scanned, truncated, notice };
3120
+ const topicStatusPairs = findTopicStatusConflictPairs(all, input.max_topic_pairs);
3121
+ const notice = pairs.length === 0 && topicStatusPairs.length === 0 ? "No lexical or topic-status candidates \u2014 widen since_days/types or lower min_jaccard." : void 0;
3122
+ return { pairs, topic_status_pairs: topicStatusPairs, scanned, truncated, notice };
3101
3123
  }
3102
3124
 
3103
3125
  // src/tools/mem-resolve-project.ts
@@ -3151,13 +3173,47 @@ async function memTimeline(input, ctx) {
3151
3173
  return { entries, total: entries.length, notice };
3152
3174
  }
3153
3175
 
3154
- // src/prompts/bootstrap-project.ts
3176
+ // src/tools/runtime-journal-append.ts
3177
+ import { appendRuntimeJournalEntry as appendRuntimeJournalEntry2 } from "@hiveai/core";
3155
3178
  import { z as z34 } from "zod";
3179
+ var RuntimeJournalAppendInputSchema = {
3180
+ message: z34.string().min(1).describe("Short line to append to the runtime session journal"),
3181
+ kind: z34.enum(["note", "session_end", "mcp"]).default("note"),
3182
+ tool: z34.string().optional().describe("When kind=mcp, which tool name (optional)")
3183
+ };
3184
+ async function runtimeJournalAppend(input, ctx) {
3185
+ await appendRuntimeJournalEntry2(ctx.paths, {
3186
+ kind: input.kind,
3187
+ message: input.message,
3188
+ ...input.tool ? { tool: input.tool } : {}
3189
+ });
3190
+ return {
3191
+ ok: true,
3192
+ path_hint: `${ctx.paths.runtimeDir}/session-journal.ndjson`
3193
+ };
3194
+ }
3195
+
3196
+ // src/tools/runtime-journal-tail.ts
3197
+ import { readRuntimeJournalTail } from "@hiveai/core";
3198
+ import { z as z35 } from "zod";
3199
+ var RuntimeJournalTailInputSchema = {
3200
+ limit: z35.number().int().positive().max(500).default(30).describe("Last N journal entries to return")
3201
+ };
3202
+ async function runtimeJournalTail(input, ctx) {
3203
+ const entries = await readRuntimeJournalTail(ctx.paths, input.limit);
3204
+ if (entries.length === 0) {
3205
+ return { entries: [], empty: true };
3206
+ }
3207
+ return { entries };
3208
+ }
3209
+
3210
+ // src/prompts/bootstrap-project.ts
3211
+ import { z as z36 } from "zod";
3156
3212
  var BootstrapProjectArgsSchema = {
3157
- module: z34.string().optional().describe(
3213
+ module: z36.string().optional().describe(
3158
3214
  "Optional module name to scope the analysis to (writes to .ai/modules/<module>/context.md)"
3159
3215
  ),
3160
- focus: z34.string().optional().describe("Optional area to emphasize (e.g. 'data layer', 'API surface')")
3216
+ focus: z36.string().optional().describe("Optional area to emphasize (e.g. 'data layer', 'API surface')")
3161
3217
  };
3162
3218
  var ROOT_TEMPLATE = `# Project context
3163
3219
 
@@ -3239,10 +3295,10 @@ ${template}\`\`\`
3239
3295
  }
3240
3296
 
3241
3297
  // src/prompts/post-task.ts
3242
- import { z as z35 } from "zod";
3298
+ import { z as z37 } from "zod";
3243
3299
  var PostTaskArgsSchema = {
3244
- task_summary: z35.string().optional().describe("One sentence describing what you just did"),
3245
- files_touched: z35.array(z35.string()).optional().describe("Files you created or modified during the task")
3300
+ task_summary: z37.string().optional().describe("One sentence describing what you just did"),
3301
+ files_touched: z37.array(z37.string()).optional().describe("Files you created or modified during the task")
3246
3302
  };
3247
3303
  function postTaskPrompt(args, ctx) {
3248
3304
  const taskLine = args.task_summary ? `
@@ -3326,12 +3382,12 @@ When done, respond with a brief summary: "Saved N memories: [list of IDs]. Sessi
3326
3382
  }
3327
3383
 
3328
3384
  // src/prompts/import-docs.ts
3329
- import { z as z36 } from "zod";
3385
+ import { z as z38 } from "zod";
3330
3386
  var ImportDocsArgsSchema = {
3331
- content: z36.string().describe("The documentation content to analyze and import as memories (Markdown, README, ADR, etc.)"),
3332
- source: z36.string().optional().describe("Origin of the content (file path, URL, or document title) \u2014 used to anchor memories"),
3333
- scope: z36.enum(["personal", "team"]).default("team").describe("Scope to assign to created memories"),
3334
- dry_run: z36.boolean().default(false).describe("If true, describe what would be saved without actually calling mem_save")
3387
+ content: z38.string().describe("The documentation content to analyze and import as memories (Markdown, README, ADR, etc.)"),
3388
+ source: z38.string().optional().describe("Origin of the content (file path, URL, or document title) \u2014 used to anchor memories"),
3389
+ scope: z38.enum(["personal", "team"]).default("team").describe("Scope to assign to created memories"),
3390
+ dry_run: z38.boolean().default(false).describe("If true, describe what would be saved without actually calling mem_save")
3335
3391
  };
3336
3392
  function importDocsPrompt(args, ctx) {
3337
3393
  const sourceLine = args.source ? `
@@ -3396,7 +3452,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
3396
3452
 
3397
3453
  // src/server.ts
3398
3454
  var SERVER_NAME = "haive";
3399
- var SERVER_VERSION = "0.9.5";
3455
+ var SERVER_VERSION = "0.9.7";
3400
3456
  function jsonResult(data) {
3401
3457
  return {
3402
3458
  content: [
@@ -4079,14 +4135,17 @@ function createHaiveServer(options = {}) {
4079
4135
  server.tool(
4080
4136
  "mem_conflict_candidates",
4081
4137
  [
4082
- "Bulk lexical scan for decision/architecture-like pairs that look similar (Jaccard on tokens).",
4138
+ "Bulk scan for conflict CANDIDATES (not proof):",
4083
4139
  "",
4084
- "Advisory only \u2014 follow with mem_conflicts_with on specific ids for real contradiction checks.",
4140
+ " 1. Lexical similarity (Jaccard) on decision/architecture-like pairs",
4141
+ " 2. Same frontmatter.topic with validated vs rejected \u2014 quick human-review signal",
4142
+ "",
4143
+ "Advisory only \u2014 follow with mem_conflicts_with on specific ids.",
4085
4144
  "",
4086
4145
  "PARAMETERS:",
4087
- " since_days, types, min_jaccard, max_pairs, max_scan",
4146
+ " since_days, types, min_jaccard, max_pairs, max_scan, max_topic_pairs",
4088
4147
  "",
4089
- "RETURNS: { pairs: [{ id_a, id_b, jaccard }], scanned, truncated, notice? }"
4148
+ "RETURNS: { pairs, topic_status_pairs, scanned, truncated, notice? }"
4090
4149
  ].join("\n"),
4091
4150
  MemConflictCandidatesInputSchema,
4092
4151
  async (input) => {
@@ -4094,6 +4153,32 @@ function createHaiveServer(options = {}) {
4094
4153
  return jsonResult(await memConflictCandidates(input, context));
4095
4154
  }
4096
4155
  );
4156
+ server.tool(
4157
+ "runtime_journal_append",
4158
+ [
4159
+ "Append one line to `.ai/.runtime/session-journal.ndjson` \u2014 machine-local session continuity.",
4160
+ "",
4161
+ "Does NOT replace team memories; complements mem_session_end recaps for local traces.",
4162
+ "",
4163
+ "PARAMETERS: message, kind (note|session_end|mcp), optional tool",
4164
+ "",
4165
+ "RETURNS: { ok, path_hint }"
4166
+ ].join("\n"),
4167
+ RuntimeJournalAppendInputSchema,
4168
+ async (input) => jsonResult(await runtimeJournalAppend(input, context))
4169
+ );
4170
+ server.tool(
4171
+ "runtime_journal_tail",
4172
+ [
4173
+ "Read the last N entries from the runtime session journal (parsed JSON lines).",
4174
+ "",
4175
+ "PARAMETERS: limit (default 30, max 500)",
4176
+ "",
4177
+ "RETURNS: { entries: [...], empty?: true }"
4178
+ ].join("\n"),
4179
+ RuntimeJournalTailInputSchema,
4180
+ async (input) => jsonResult(await runtimeJournalTail(input, context))
4181
+ );
4097
4182
  server.tool(
4098
4183
  "pre_commit_check",
4099
4184
  [