context-vault 2.11.0 → 2.12.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/bin/cli.js CHANGED
@@ -25,6 +25,7 @@ import { join, resolve, dirname } from "node:path";
25
25
  import { homedir, platform } from "node:os";
26
26
  import { execSync, execFile, execFileSync } from "node:child_process";
27
27
  import { fileURLToPath } from "node:url";
28
+ import { APP_URL, API_URL, MARKETING_URL } from "@context-vault/core/constants";
28
29
 
29
30
  const __filename = fileURLToPath(import.meta.url);
30
31
  const __dirname = dirname(__filename);
@@ -272,9 +273,39 @@ async function runSetup() {
272
273
  existingVault = cfg.vaultDir || existingVault;
273
274
  } catch {}
274
275
 
276
+ // Version check against npm registry (5s timeout, fail silently if offline)
277
+ let latestVersion = null;
278
+ try {
279
+ latestVersion = execSync("npm view context-vault version", {
280
+ encoding: "utf-8",
281
+ stdio: ["pipe", "pipe", "pipe"],
282
+ timeout: 5000,
283
+ }).trim();
284
+ } catch {}
285
+
286
+ if (latestVersion === VERSION) {
287
+ console.log(
288
+ green(` ✓ context-vault v${VERSION} is up to date`) +
289
+ dim(` (vault: ${existingVault})`),
290
+ );
291
+ console.log();
292
+ return;
293
+ }
294
+
275
295
  console.log(yellow(` Existing installation detected`));
276
296
  console.log(dim(` Vault: ${existingVault}`));
277
- console.log(dim(` Config: ${existingConfig}`));
297
+ if (latestVersion) {
298
+ console.log();
299
+ console.log(` Current: ${dim(VERSION)}`);
300
+ console.log(` Latest: ${green(latestVersion)}`);
301
+ const upgradeCmd = isNpx()
302
+ ? "npx context-vault@latest setup"
303
+ : "npm install -g context-vault";
304
+ console.log();
305
+ console.log(dim(` To upgrade: ${upgradeCmd}`));
306
+ } else {
307
+ console.log(dim(` Config: ${existingConfig}`));
308
+ }
278
309
  console.log();
279
310
  console.log(` 1) Full reconfigure`);
280
311
  console.log(` 2) Update tool configs only ${dim("(skip vault setup)")}`);
@@ -354,6 +385,7 @@ async function runSetup() {
354
385
 
355
386
  console.log();
356
387
  console.log(green(" ✓ Tool configs updated."));
388
+ console.log(dim(" Restart your AI tools to apply the changes."));
357
389
  console.log();
358
390
  return;
359
391
  }
@@ -501,7 +533,7 @@ async function runSetup() {
501
533
  console.log(
502
534
  dim(" file paths, or personal data is ever sent. Off by default."),
503
535
  );
504
- console.log(dim(" Full schema: https://contextvault.dev/telemetry"));
536
+ console.log(dim(` Full schema: ${MARKETING_URL}/telemetry`));
505
537
  console.log();
506
538
 
507
539
  let telemetryEnabled = vaultConfig.telemetry === true;
@@ -541,7 +573,12 @@ async function runSetup() {
541
573
  console.log(
542
574
  `\n ${dim("[4/6]")}${bold(" Downloading embedding model...")}`,
543
575
  );
544
- console.log(dim(" all-MiniLM-L6-v2 (~22MB, one-time download)\n"));
576
+ console.log(dim(" all-MiniLM-L6-v2 (~22MB, one-time download)"));
577
+ console.log(
578
+ dim(
579
+ ` Slow connection? Re-run with --skip-embeddings (enables FTS-only mode)\n`,
580
+ ),
581
+ );
545
582
  {
546
583
  const spinnerFrames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
547
584
  let frame = 0;
@@ -731,7 +768,9 @@ async function runSetup() {
731
768
  const boxLines = [
732
769
  ` ✓ Setup complete — ${passed}/${checks.length} checks passed (${elapsed}s)`,
733
770
  ``,
734
- ` ${bold("AI Tools")} open ${toolName} and try:`,
771
+ ` ${bold("Next:")} restart ${toolName} to activate the vault`,
772
+ ``,
773
+ ` ${bold("AI Tools")} — once active, try:`,
735
774
  ` "Search my vault for getting started"`,
736
775
  ` "Save an insight about [topic]"`,
737
776
  ` "Show my vault status"`,
@@ -979,7 +1018,7 @@ This is an example entry showing the decision format. Feel free to delete it.
979
1018
 
980
1019
  async function runConnect() {
981
1020
  const apiKey = getFlag("--key");
982
- const hostedUrl = getFlag("--url") || "https://api.context-vault.com";
1021
+ const hostedUrl = getFlag("--url") || API_URL;
983
1022
 
984
1023
  if (!apiKey) {
985
1024
  console.log(`\n ${bold("context-vault connect")}\n`);
@@ -988,9 +1027,7 @@ async function runConnect() {
988
1027
  console.log(` context-vault connect --key cv_...\n`);
989
1028
  console.log(` Options:`);
990
1029
  console.log(` --key <key> API key (required)`);
991
- console.log(
992
- ` --url <url> Hosted server URL (default: https://api.context-vault.com)`,
993
- );
1030
+ console.log(` --url <url> Hosted server URL (default: ${API_URL})`);
994
1031
  console.log();
995
1032
  return;
996
1033
  }
@@ -1232,9 +1269,7 @@ async function runSwitch() {
1232
1269
  );
1233
1270
  console.log(` Options:`);
1234
1271
  console.log(` --key <key> API key for hosted mode (cv_...)`);
1235
- console.log(
1236
- ` --url <url> Hosted server URL (default: https://api.context-vault.com)\n`,
1237
- );
1272
+ console.log(` --url <url> Hosted server URL (default: ${API_URL})\n`);
1238
1273
  return;
1239
1274
  }
1240
1275
 
@@ -1291,10 +1326,7 @@ async function runSwitch() {
1291
1326
  console.log(dim(` Server: node ${launcherPath}`));
1292
1327
  console.log();
1293
1328
  } else {
1294
- const hostedUrl =
1295
- getFlag("--url") ||
1296
- vaultConfig.hostedUrl ||
1297
- "https://api.context-vault.com";
1329
+ const hostedUrl = getFlag("--url") || vaultConfig.hostedUrl || API_URL;
1298
1330
  const apiKey = getFlag("--key") || vaultConfig.apiKey;
1299
1331
 
1300
1332
  if (!apiKey) {
@@ -1674,15 +1706,13 @@ async function runMigrate() {
1674
1706
  ` context-vault migrate --to-local Download hosted vault to local files`,
1675
1707
  );
1676
1708
  console.log(`\n Options:`);
1677
- console.log(
1678
- ` --url <url> Hosted server URL (default: https://api.context-vault.com)`,
1679
- );
1709
+ console.log(` --url <url> Hosted server URL (default: ${API_URL})`);
1680
1710
  console.log(` --key <key> API key (cv_...)`);
1681
1711
  console.log();
1682
1712
  return;
1683
1713
  }
1684
1714
 
1685
- const hostedUrl = getFlag("--url") || "https://api.context-vault.com";
1715
+ const hostedUrl = getFlag("--url") || API_URL;
1686
1716
  const apiKey = getFlag("--key");
1687
1717
 
1688
1718
  if (!apiKey) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-vault/core",
3
- "version": "2.11.0",
3
+ "version": "2.12.0",
4
4
  "type": "module",
5
5
  "description": "Shared core: capture, index, retrieve, tools, and utilities for context-vault",
6
6
  "main": "src/index.js",
@@ -1,3 +1,9 @@
1
+ export const APP_URL = "https://app.context-vault.com";
2
+ export const API_URL = "https://api.context-vault.com";
3
+ export const MARKETING_URL = "https://contextvault.dev";
4
+ export const GITHUB_ISSUES_URL =
5
+ "https://github.com/fellanH/context-vault/issues";
6
+
1
7
  export const MAX_BODY_LENGTH = 100 * 1024; // 100KB
2
8
  export const MAX_TITLE_LENGTH = 500;
3
9
  export const MAX_KIND_LENGTH = 64;
@@ -1,8 +1,10 @@
1
1
  import { existsSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { API_URL, MARKETING_URL, GITHUB_ISSUES_URL } from "../constants.js";
3
4
 
4
- const TELEMETRY_ENDPOINT = "https://api.context-vault.com/telemetry";
5
+ const TELEMETRY_ENDPOINT = `${API_URL}/telemetry`;
5
6
  const NOTICE_MARKER = ".telemetry-notice-shown";
7
+ const FEEDBACK_PROMPT_MARKER = ".feedback-prompt-shown";
6
8
 
7
9
  export function isTelemetryEnabled(config) {
8
10
  const envVal = process.env.CONTEXT_VAULT_TELEMETRY;
@@ -56,7 +58,31 @@ export function maybeShowTelemetryNotice(dataDir) {
56
58
  "[context-vault] Reports contain only: event type, error code, tool name, version, node version, platform, arch, timestamp.",
57
59
  "[context-vault] No vault content, file paths, or personal data is ever sent.",
58
60
  '[context-vault] Opt in: set "telemetry": true in ~/.context-mcp/config.json or set CONTEXT_VAULT_TELEMETRY=1.',
59
- "[context-vault] Full payload schema: https://contextvault.dev/telemetry",
61
+ `[context-vault] Full payload schema: ${MARKETING_URL}/telemetry`,
62
+ ];
63
+ for (const line of lines) {
64
+ process.stderr.write(line + "\n");
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Print a one-time feedback prompt after the user's first successful save.
70
+ * Uses a marker file in dataDir to ensure it's only shown once.
71
+ * Never throws, never blocks.
72
+ */
73
+ export function maybeShowFeedbackPrompt(dataDir) {
74
+ try {
75
+ const markerPath = join(dataDir, FEEDBACK_PROMPT_MARKER);
76
+ if (existsSync(markerPath)) return;
77
+ writeFileSync(markerPath, new Date().toISOString() + "\n");
78
+ } catch {
79
+ return;
80
+ }
81
+
82
+ const lines = [
83
+ "[context-vault] First entry saved — nice work!",
84
+ "[context-vault] Got feedback, a bug, or a feature request?",
85
+ `[context-vault] Open an issue: ${GITHUB_ISSUES_URL}`,
60
86
  ];
61
87
  for (const line of lines) {
62
88
  process.stderr.write(line + "\n");
@@ -4,6 +4,7 @@ import { indexEntry } from "../../index/index.js";
4
4
  import { categoryFor } from "../../core/categories.js";
5
5
  import { normalizeKind } from "../../core/files.js";
6
6
  import { ok, err, ensureVaultExists, ensureValidKind } from "../helpers.js";
7
+ import { maybeShowFeedbackPrompt } from "../../core/telemetry.js";
7
8
  import {
8
9
  MAX_BODY_LENGTH,
9
10
  MAX_TITLE_LENGTH,
@@ -398,6 +399,11 @@ export async function handler(
398
399
  supersedes,
399
400
  userId,
400
401
  });
402
+
403
+ if (ctx.config?.dataDir) {
404
+ maybeShowFeedbackPrompt(ctx.config.dataDir);
405
+ }
406
+
401
407
  const relPath = entry.filePath
402
408
  ? entry.filePath.replace(config.vaultDir + "/", "")
403
409
  : entry.filePath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-vault",
3
- "version": "2.11.0",
3
+ "version": "2.12.0",
4
4
  "type": "module",
5
5
  "description": "Persistent memory for AI agents — saves and searches knowledge across sessions",
6
6
  "bin": {
@@ -55,7 +55,7 @@
55
55
  "@context-vault/core"
56
56
  ],
57
57
  "dependencies": {
58
- "@context-vault/core": "^2.11.0",
58
+ "@context-vault/core": "^2.12.0",
59
59
  "@modelcontextprotocol/sdk": "^1.26.0",
60
60
  "sqlite-vec": "^0.1.0"
61
61
  }