@plur-ai/mcp 0.21.1 → 0.21.2

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-O2NJFMNP.js";
3
+ } from "./chunk-OQDR6UF6.js";
4
4
 
5
5
  // src/telemetry.ts
6
6
  import { recordEvent, flushIfNeeded, registerFlushOnExit } from "@plur-ai/core";
@@ -17,7 +17,7 @@ function recordTelemetry(event) {
17
17
  import { existsSync, unlinkSync } from "fs";
18
18
  import { join, dirname, resolve } from "path";
19
19
  import { homedir } from "os";
20
- import { extractMetaEngrams, validateMetaEngram, confidenceBand, generateProfile, getProfileForInjection, selectModelForOperation, getCachedUpdateCheck, minorVersionsBehind, scanForTensions, CapabilityCanary, NO_SESSION, findProjectConfigPath, readProjectConfigFromPath, isSharedScope, resolveRerankerName, getReranker, classifyRerankerFailure, hfCacheDirName, SUGGEST_DISPLAY_MIN_CONFIDENCE, mcpRemoteWarningLine, doctorRemoteRemediation, normalizeEndpointUrl, REMOTE_STATUS_TTL_MS, PROBE_CLEARABLE_STATES, summariseProvenance, formatLayer3, renderProvenanceSummary, describeNeedsAction, summarizeOutbox, folderMapProblem, tokenEnvUnsetDetail, tokenEnvUnsetFix } from "@plur-ai/core";
20
+ import { extractMetaEngrams, validateMetaEngram, confidenceBand, generateProfile, getProfileForInjection, selectModelForOperation, getCachedUpdateCheck, minorVersionsBehind, scanForTensions, CapabilityCanary, NO_SESSION, findProjectConfigPath, readProjectConfigFromPath, isSharedScope, resolveRerankerName, getReranker, classifyRerankerFailure, hfCacheDirName, SUGGEST_DISPLAY_MIN_CONFIDENCE, mcpRemoteWarningLine, doctorRemoteRemediation, normalizeEndpointUrl, REMOTE_STATUS_TTL_MS, PROBE_CLEARABLE_STATES, summariseProvenance, formatLayer3, renderProvenanceSummary, describeNeedsAction, summarizeOutbox, folderMapProblem, tokenEnvUnsetDetail, tokenEnvUnsetFix, resolveRecallDeadlineMs } from "@plur-ai/core";
21
21
 
22
22
  // src/folder-map-advice.ts
23
23
  import { folderRepairCommand } from "@plur-ai/core";
@@ -71,6 +71,22 @@ function formatAge(ageMs) {
71
71
  if (h < 24) return `${h}h ago`;
72
72
  return `${Math.floor(h / 24)}d ago`;
73
73
  }
74
+ function attachRecallReport(response, meta) {
75
+ const remote = meta.remote ?? { state: "not_dialed", hosts: [] };
76
+ response.remote = remote;
77
+ response.results_complete = meta.results_complete ?? true;
78
+ const notes = [];
79
+ if (meta.local_complete === false) {
80
+ notes.push("Local search did not finish within the recall deadline \u2014 results are incomplete; retrying is fine.");
81
+ }
82
+ if (remote.hosts.some((h) => h.detail === "recall_deadline")) {
83
+ notes.push("The server did not answer within the recall deadline \u2014 results may be missing team engrams this call.");
84
+ }
85
+ if (notes.length > 0) {
86
+ const line = notes.join(" ");
87
+ response.warning = typeof response.warning === "string" && response.warning.length > 0 ? `${response.warning} ${line}` : line;
88
+ }
89
+ }
74
90
  function attachRemoteStoreDegradation(response, plur) {
75
91
  let status;
76
92
  try {
@@ -89,14 +105,16 @@ function attachRemoteStoreDegradation(response, plur) {
89
105
  response.warning = typeof response.warning === "string" && response.warning.length > 0 ? `${response.warning} ${line}` : line;
90
106
  }
91
107
  var recallHandler = async (args, plur) => {
108
+ const deadline_at = Date.now() + resolveRecallDeadlineMs();
92
109
  const mode = args.mode ?? "hybrid";
93
110
  if (mode === "keyword") {
94
- const results = await plur.recall(args.query, {
111
+ const kwMeta = await plur.recallWithMeta(args.query, {
95
112
  scope: args.scope,
96
113
  domain: args.domain,
97
114
  limit: args.limit,
98
115
  remote_timeout_ms: 2e3,
99
116
  // MCP recall remote budget (#776)
117
+ deadline_at,
100
118
  // #243: session default scope (incl. mid-session plur_session_scope
101
119
  // changes) establishes the remote dialing org context when no explicit
102
120
  // scope filter is passed. Same rule as writes (E7, formal R2): not
@@ -105,6 +123,7 @@ var recallHandler = async (args, plur) => {
105
123
  // of its own, the workspace's scope — the one resolver writes use.
106
124
  session: await _readSession(args, plur)
107
125
  });
126
+ const results = kwMeta.engrams;
108
127
  const response2 = {
109
128
  results: results.map((e) => {
110
129
  const supersededBy = e.relations?.superseded_by;
@@ -138,6 +157,7 @@ var recallHandler = async (args, plur) => {
138
157
  mode: "keyword"
139
158
  };
140
159
  attachRemoteStoreDegradation(response2, plur);
160
+ attachRecallReport(response2, kwMeta);
141
161
  return response2;
142
162
  }
143
163
  const budget = args.budget;
@@ -149,6 +169,7 @@ var recallHandler = async (args, plur) => {
149
169
  limit: fetchLimit,
150
170
  remote_timeout_ms: 2e3,
151
171
  // MCP recall remote budget (#776)
172
+ deadline_at,
152
173
  // #243: session default scope (incl. mid-session plur_session_scope
153
174
  // changes) establishes the remote dialing org context when no explicit
154
175
  // scope filter is passed. Same rule as writes (E7, formal R2), and the
@@ -205,8 +226,9 @@ var recallHandler = async (args, plur) => {
205
226
  mode: meta.mode
206
227
  };
207
228
  if (meta.mode === "hybrid-degraded") {
208
- response.warning = `Embedding layer unavailable \u2014 results are BM25-only. Run plur_doctor for diagnosis. Last error: ${meta.embedderError ?? "unknown"}`;
229
+ response.warning = meta.degraded_reason ? meta.embedderError ?? meta.degraded_reason : `Embedding layer unavailable \u2014 results are BM25-only. Run plur_doctor for diagnosis. Last error: ${meta.embedderError ?? "unknown"}`;
209
230
  }
231
+ if (meta.degraded_reason) response.degraded_reason = meta.degraded_reason;
210
232
  if (resolveRerankerName() !== "off") {
211
233
  response.reranked = meta.reranked ?? 0;
212
234
  const rr = plur.rerankerStatus();
@@ -216,6 +238,7 @@ var recallHandler = async (args, plur) => {
216
238
  }
217
239
  }
218
240
  attachRemoteStoreDegradation(response, plur);
241
+ attachRecallReport(response, meta);
219
242
  return response;
220
243
  };
221
244
  var RECALL_HYBRID_DEPRECATION = "plur_recall_hybrid is deprecated since 0.16 \u2014 use plur_recall (mode defaults to hybrid). This alias will be removed in 0.18.";
@@ -1312,12 +1335,14 @@ function getAllToolDefinitions() {
1312
1335
  required: ["task"]
1313
1336
  },
1314
1337
  handler: async (args, plur) => {
1338
+ const deadline_at = Date.now() + resolveRecallDeadlineMs();
1315
1339
  const session_id = _resolveWriteSession(args);
1316
1340
  const result = await plur.injectHybrid(args.task, {
1317
1341
  budget: args.budget,
1318
1342
  scope: args.scope,
1319
1343
  source: "inject",
1320
1344
  session_id,
1345
+ deadline_at,
1321
1346
  // #1566: the dialing context follows the same rule as writes — the
1322
1347
  // workspace's scope when the session has no default of its own.
1323
1348
  // session_id above stays the caller's for attribution.
@@ -1330,7 +1355,11 @@ function getAllToolDefinitions() {
1330
1355
  count: result.count,
1331
1356
  tokens_used: result.tokens_used,
1332
1357
  injected_ids: result.injected_ids,
1333
- mode: "hybrid",
1358
+ // #1586 round 4: a degraded injection says so, instead of a fixed 'hybrid'.
1359
+ // (Kept as 'hybrid' otherwise, as this reply always said.)
1360
+ mode: result.mode === "hybrid-degraded" ? "hybrid-degraded" : "hybrid",
1361
+ ...result.degraded_reason ? { degraded_reason: result.degraded_reason } : {},
1362
+ ...(result.mode === "hybrid-degraded" || result.degraded_reason) && result.embedder_error ? { embedder_error: result.embedder_error } : {},
1334
1363
  // #181: unresolved-tension warnings — flag contradicted context
1335
1364
  ...result.warnings ? { warnings: result.warnings } : {},
1336
1365
  // #1142: pinned engrams that did not fit. `pinned: true` reads as a
@@ -1339,6 +1368,7 @@ function getAllToolDefinitions() {
1339
1368
  ...result.omitted_pinned?.length ? { omitted_pinned: result.omitted_pinned } : {}
1340
1369
  };
1341
1370
  attachRemoteStoreDegradation(response, plur);
1371
+ attachRecallReport(response, result);
1342
1372
  return response;
1343
1373
  }
1344
1374
  },
@@ -2426,6 +2456,7 @@ function getAllToolDefinitions() {
2426
2456
  required: ["task"]
2427
2457
  },
2428
2458
  handler: async (args, plur) => {
2459
+ const deadline_at = Date.now() + resolveRecallDeadlineMs();
2429
2460
  mcpCanary.reset();
2430
2461
  mcpCanary.signal("session_start_hook");
2431
2462
  const crypto = await import("crypto");
@@ -2497,15 +2528,23 @@ function getAllToolDefinitions() {
2497
2528
  await plur.warmRemoteCaches().catch(() => {
2498
2529
  });
2499
2530
  let engrams = null;
2531
+ let injectionReport = {};
2500
2532
  try {
2501
2533
  const result = await plur.injectHybrid(task, {
2502
2534
  scope: tags?.length ? `tags:${tags.join(",")}` : void 0,
2503
2535
  session_id,
2504
2536
  // stamped on the co_injection provenance event (#452)
2505
2537
  source: "session_start",
2506
- remote_timeout_ms: 5e3
2538
+ remote_timeout_ms: 5e3,
2507
2539
  // session_start warm budget (#776)
2540
+ deadline_at
2508
2541
  });
2542
+ injectionReport = {
2543
+ remote: result.remote,
2544
+ results_complete: result.results_complete,
2545
+ ...result.degraded_reason ? { degraded_reason: result.degraded_reason } : {},
2546
+ ...(result.mode === "hybrid-degraded" || result.degraded_reason) && result.embedder_error ? { embedder_error: result.embedder_error } : {}
2547
+ };
2509
2548
  _recordInjectionTelemetry(session_id, result.injected_packs);
2510
2549
  if (result.count > 0) {
2511
2550
  const lines = [];
@@ -2656,6 +2695,11 @@ Tool profile "${session_tool_profile}": most plur_* tools are not exposed by nam
2656
2695
  ...default_scope ? { default_scope, scope_source } : {},
2657
2696
  ...default_domain ? { default_domain, domain_source: "project-config" } : {},
2658
2697
  ...projectConfig.warning ? { project_config_warning: projectConfig.warning } : {},
2698
+ // #1586 audit L6: the injection's per-call remote report (added fields).
2699
+ remote: injectionReport.remote ?? { state: "not_dialed", hosts: [] },
2700
+ results_complete: injectionReport.results_complete ?? false,
2701
+ ...injectionReport.degraded_reason ? { degraded_reason: injectionReport.degraded_reason } : {},
2702
+ ...injectionReport.embedder_error ? { embedder_error: injectionReport.embedder_error } : {},
2659
2703
  // Ask LLM to check back — MCP can't push, but we can request a follow-up
2660
2704
  follow_up: store_stats.engram_count === 0 ? "This is a fresh store with 0 engrams. After your first exchange with the user, review what you learned and call plur_learn for any corrections, preferences, or patterns. Build the memory from this session." : void 0,
2661
2705
  // On fresh install, suggest hook setup for reliable injection
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.21.1";
2
+ var VERSION = "0.21.2";
3
3
 
4
4
  export {
5
5
  VERSION
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-O2NJFMNP.js";
4
+ } from "./chunk-OQDR6UF6.js";
5
5
 
6
6
  // src/index.ts
7
7
  import { existsSync, readFileSync as readFileSync2, writeFileSync, mkdirSync, readdirSync, statSync } from "fs";
@@ -485,7 +485,7 @@ if (arg === "packs") {
485
485
  process.exit(0);
486
486
  }
487
487
  if (arg === "serve" || arg === void 0) {
488
- const { runStdio } = await import("./server-EHKHU4JH.js");
488
+ const { runStdio } = await import("./server-QOHVV2Z7.js");
489
489
  runStdio().catch((err) => {
490
490
  console.error("Failed to start PLUR MCP server:", err);
491
491
  process.exit(1);
@@ -9,10 +9,10 @@ import {
9
9
  resolveToolProfile,
10
10
  setActiveToolProfile,
11
11
  validateToolArgs
12
- } from "./chunk-OETJSRYE.js";
12
+ } from "./chunk-22X2SQNV.js";
13
13
  import {
14
14
  VERSION
15
- } from "./chunk-O2NJFMNP.js";
15
+ } from "./chunk-OQDR6UF6.js";
16
16
 
17
17
  // src/server.ts
18
18
  import { Server, ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/server";
@@ -20,7 +20,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
20
20
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
21
21
  import { join as join2 } from "path";
22
22
  import { homedir } from "os";
23
- import { Plur, checkForUpdate, VERSION_CHECK_SUCCESS_TTL_MS } from "@plur-ai/core";
23
+ import { Plur, checkForUpdate, VERSION_CHECK_SUCCESS_TTL_MS, allowBackgroundModelLoad } from "@plur-ai/core";
24
24
 
25
25
  // src/drop-log.ts
26
26
  import { appendFileSync, existsSync, mkdirSync, readFileSync } from "fs";
@@ -958,6 +958,7 @@ async function runStdio() {
958
958
  }
959
959
  const profile = resolveToolProfile();
960
960
  const server = await createServer(void 0, { profile });
961
+ allowBackgroundModelLoad(true);
961
962
  registerFlushOnExit({});
962
963
  try {
963
964
  writeFileSync(serverPidPath(), String(process.pid));
@@ -2,8 +2,8 @@ import {
2
2
  CURSOR_CORE_TOOL_NAMES,
3
3
  getToolDefinitions,
4
4
  validateToolArgs
5
- } from "./chunk-OETJSRYE.js";
6
- import "./chunk-O2NJFMNP.js";
5
+ } from "./chunk-22X2SQNV.js";
6
+ import "./chunk-OQDR6UF6.js";
7
7
 
8
8
  // src/tools-export.ts
9
9
  function getToolSchemas(profile) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plur-ai/mcp",
3
3
  "mcpName": "io.github.plur-ai/plur",
4
- "version": "0.21.1",
4
+ "version": "0.21.2",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "plur-mcp": "dist/index.js"
@@ -16,7 +16,7 @@
16
16
  "@modelcontextprotocol/client": "2.0.0-beta.4",
17
17
  "@modelcontextprotocol/core": "2.0.0-beta.4",
18
18
  "zod": "^3.23.0",
19
- "@plur-ai/core": "0.21.1"
19
+ "@plur-ai/core": "0.21.2"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^25.5.0"