context-vault 3.1.6 → 3.1.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.
Files changed (82) hide show
  1. package/bin/cli.js +1369 -1774
  2. package/node_modules/@context-vault/core/dist/capture.d.ts +1 -1
  3. package/node_modules/@context-vault/core/dist/capture.d.ts.map +1 -1
  4. package/node_modules/@context-vault/core/dist/capture.js +34 -47
  5. package/node_modules/@context-vault/core/dist/capture.js.map +1 -1
  6. package/node_modules/@context-vault/core/dist/categories.js +30 -30
  7. package/node_modules/@context-vault/core/dist/config.d.ts +1 -1
  8. package/node_modules/@context-vault/core/dist/config.d.ts.map +1 -1
  9. package/node_modules/@context-vault/core/dist/config.js +37 -43
  10. package/node_modules/@context-vault/core/dist/config.js.map +1 -1
  11. package/node_modules/@context-vault/core/dist/constants.d.ts.map +1 -1
  12. package/node_modules/@context-vault/core/dist/constants.js +4 -4
  13. package/node_modules/@context-vault/core/dist/constants.js.map +1 -1
  14. package/node_modules/@context-vault/core/dist/db.d.ts +2 -2
  15. package/node_modules/@context-vault/core/dist/db.d.ts.map +1 -1
  16. package/node_modules/@context-vault/core/dist/db.js +21 -20
  17. package/node_modules/@context-vault/core/dist/db.js.map +1 -1
  18. package/node_modules/@context-vault/core/dist/embed.d.ts.map +1 -1
  19. package/node_modules/@context-vault/core/dist/embed.js +11 -11
  20. package/node_modules/@context-vault/core/dist/embed.js.map +1 -1
  21. package/node_modules/@context-vault/core/dist/files.d.ts.map +1 -1
  22. package/node_modules/@context-vault/core/dist/files.js +12 -13
  23. package/node_modules/@context-vault/core/dist/files.js.map +1 -1
  24. package/node_modules/@context-vault/core/dist/formatters.js +5 -5
  25. package/node_modules/@context-vault/core/dist/frontmatter.d.ts.map +1 -1
  26. package/node_modules/@context-vault/core/dist/frontmatter.js +23 -23
  27. package/node_modules/@context-vault/core/dist/frontmatter.js.map +1 -1
  28. package/node_modules/@context-vault/core/dist/index.d.ts +1 -1
  29. package/node_modules/@context-vault/core/dist/index.d.ts.map +1 -1
  30. package/node_modules/@context-vault/core/dist/index.js +58 -46
  31. package/node_modules/@context-vault/core/dist/index.js.map +1 -1
  32. package/node_modules/@context-vault/core/dist/ingest-url.d.ts.map +1 -1
  33. package/node_modules/@context-vault/core/dist/ingest-url.js +30 -33
  34. package/node_modules/@context-vault/core/dist/ingest-url.js.map +1 -1
  35. package/node_modules/@context-vault/core/dist/main.d.ts +13 -13
  36. package/node_modules/@context-vault/core/dist/main.d.ts.map +1 -1
  37. package/node_modules/@context-vault/core/dist/main.js +12 -12
  38. package/node_modules/@context-vault/core/dist/main.js.map +1 -1
  39. package/node_modules/@context-vault/core/dist/search.d.ts +1 -1
  40. package/node_modules/@context-vault/core/dist/search.d.ts.map +1 -1
  41. package/node_modules/@context-vault/core/dist/search.js +20 -22
  42. package/node_modules/@context-vault/core/dist/search.js.map +1 -1
  43. package/node_modules/@context-vault/core/dist/types.d.ts +1 -1
  44. package/node_modules/@context-vault/core/package.json +1 -1
  45. package/node_modules/@context-vault/core/src/capture.ts +44 -81
  46. package/node_modules/@context-vault/core/src/categories.ts +30 -30
  47. package/node_modules/@context-vault/core/src/config.ts +45 -60
  48. package/node_modules/@context-vault/core/src/constants.ts +8 -10
  49. package/node_modules/@context-vault/core/src/db.ts +37 -56
  50. package/node_modules/@context-vault/core/src/embed.ts +15 -26
  51. package/node_modules/@context-vault/core/src/files.ts +13 -16
  52. package/node_modules/@context-vault/core/src/formatters.ts +5 -5
  53. package/node_modules/@context-vault/core/src/frontmatter.ts +26 -30
  54. package/node_modules/@context-vault/core/src/index.ts +94 -100
  55. package/node_modules/@context-vault/core/src/ingest-url.ts +56 -93
  56. package/node_modules/@context-vault/core/src/main.ts +13 -18
  57. package/node_modules/@context-vault/core/src/search.ts +34 -56
  58. package/node_modules/@context-vault/core/src/types.ts +1 -1
  59. package/package.json +2 -2
  60. package/scripts/postinstall.js +18 -25
  61. package/scripts/prepack.js +13 -19
  62. package/src/archive.js +211 -0
  63. package/src/error-log.js +7 -7
  64. package/src/helpers.js +11 -13
  65. package/src/linking.js +8 -11
  66. package/src/migrate-dirs.js +139 -0
  67. package/src/register-tools.js +46 -48
  68. package/src/server.js +73 -99
  69. package/src/status.js +35 -71
  70. package/src/telemetry.js +18 -22
  71. package/src/temporal.js +19 -30
  72. package/src/tools/clear-context.js +15 -18
  73. package/src/tools/context-status.js +37 -57
  74. package/src/tools/create-snapshot.js +45 -57
  75. package/src/tools/delete-context.js +11 -12
  76. package/src/tools/get-context.js +112 -160
  77. package/src/tools/ingest-project.js +66 -86
  78. package/src/tools/ingest-url.js +25 -41
  79. package/src/tools/list-buckets.js +19 -25
  80. package/src/tools/list-context.js +35 -58
  81. package/src/tools/save-context.js +126 -182
  82. package/src/tools/session-start.js +46 -62
package/src/status.js CHANGED
@@ -1,11 +1,11 @@
1
- import { existsSync, readdirSync, statSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { walkDir } from "@context-vault/core/files";
4
- import { isEmbedAvailable } from "@context-vault/core/embed";
5
- import { KIND_STALENESS_DAYS } from "@context-vault/core/categories";
1
+ import { existsSync, readdirSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { walkDir } from '@context-vault/core/files';
4
+ import { isEmbedAvailable } from '@context-vault/core/embed';
5
+ import { KIND_STALENESS_DAYS } from '@context-vault/core/categories';
6
6
 
7
7
  function countArchivedEntries(vaultDir) {
8
- const archRoot = join(vaultDir, "_archive");
8
+ const archRoot = join(vaultDir, '_archive');
9
9
  if (!existsSync(archRoot)) return 0;
10
10
  try {
11
11
  return walkDir(archRoot).length;
@@ -37,9 +37,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
37
37
 
38
38
  let kindCounts = [];
39
39
  try {
40
- kindCounts = db
41
- .prepare(`SELECT kind, COUNT(*) as c FROM vault GROUP BY kind`)
42
- .all();
40
+ kindCounts = db.prepare(`SELECT kind, COUNT(*) as c FROM vault GROUP BY kind`).all();
43
41
  } catch (e) {
44
42
  errors.push(`Kind count query failed: ${e.message}`);
45
43
  }
@@ -53,7 +51,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
53
51
  errors.push(`Category count query failed: ${e.message}`);
54
52
  }
55
53
 
56
- let dbSize = "n/a";
54
+ let dbSize = 'n/a';
57
55
  let dbSizeBytes = 0;
58
56
  try {
59
57
  if (existsSync(config.dbPath)) {
@@ -71,9 +69,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
71
69
  let staleCount = 0;
72
70
  try {
73
71
  const result = db
74
- .prepare(
75
- `SELECT COUNT(*) as c FROM vault WHERE file_path NOT LIKE ? || '%'`,
76
- )
72
+ .prepare(`SELECT COUNT(*) as c FROM vault WHERE file_path NOT LIKE ? || '%'`)
77
73
  .get(config.vaultDir);
78
74
  staleCount = result.c;
79
75
  stalePaths = staleCount > 0;
@@ -85,7 +81,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
85
81
  try {
86
82
  expiredCount = db
87
83
  .prepare(
88
- `SELECT COUNT(*) as c FROM vault WHERE expires_at IS NOT NULL AND expires_at <= datetime('now')`,
84
+ `SELECT COUNT(*) as c FROM vault WHERE expires_at IS NOT NULL AND expires_at <= datetime('now')`
89
85
  )
90
86
  .get().c;
91
87
  } catch (e) {
@@ -94,9 +90,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
94
90
 
95
91
  let eventCount = 0;
96
92
  try {
97
- eventCount = db
98
- .prepare(`SELECT COUNT(*) as c FROM vault WHERE category = 'event'`)
99
- .get().c;
93
+ eventCount = db.prepare(`SELECT COUNT(*) as c FROM vault WHERE category = 'event'`).get().c;
100
94
  } catch (e) {
101
95
  errors.push(`Event count failed: ${e.message}`);
102
96
  }
@@ -104,9 +98,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
104
98
  let eventsWithoutTtlCount = 0;
105
99
  try {
106
100
  eventsWithoutTtlCount = db
107
- .prepare(
108
- `SELECT COUNT(*) as c FROM vault WHERE category = 'event' AND expires_at IS NULL`,
109
- )
101
+ .prepare(`SELECT COUNT(*) as c FROM vault WHERE category = 'event' AND expires_at IS NULL`)
110
102
  .get().c;
111
103
  } catch (e) {
112
104
  errors.push(`Events without TTL count failed: ${e.message}`);
@@ -116,9 +108,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
116
108
  try {
117
109
  const total = db.prepare(`SELECT COUNT(*) as c FROM vault`).get().c;
118
110
  const indexed = db
119
- .prepare(
120
- `SELECT COUNT(*) as c FROM vault WHERE rowid IN (SELECT rowid FROM vault_vec)`,
121
- )
111
+ .prepare(`SELECT COUNT(*) as c FROM vault WHERE rowid IN (SELECT rowid FROM vault_vec)`)
122
112
  .get().c;
123
113
  embeddingStatus = { indexed, total, missing: total - indexed };
124
114
  } catch (e) {
@@ -131,7 +121,7 @@ export function gatherVaultStatus(ctx, opts = {}) {
131
121
  try {
132
122
  autoCapturedFeedbackCount = db
133
123
  .prepare(
134
- `SELECT COUNT(*) as c FROM vault WHERE kind = 'feedback' AND tags LIKE '%"auto-captured"%'`,
124
+ `SELECT COUNT(*) as c FROM vault WHERE kind = 'feedback' AND tags LIKE '%"auto-captured"%'`
135
125
  )
136
126
  .get().c;
137
127
  } catch (e) {
@@ -152,12 +142,12 @@ export function gatherVaultStatus(ctx, opts = {}) {
152
142
  const kindClauses = stalenessKinds
153
143
  .map(
154
144
  ([kind, days]) =>
155
- `(kind = '${kind}' AND COALESCE(updated_at, created_at) <= datetime('now', '-${days} days'))`,
145
+ `(kind = '${kind}' AND COALESCE(updated_at, created_at) <= datetime('now', '-${days} days'))`
156
146
  )
157
- .join(" OR ");
147
+ .join(' OR ');
158
148
  staleKnowledge = db
159
149
  .prepare(
160
- `SELECT kind, title, COALESCE(updated_at, created_at) as last_updated FROM vault WHERE category = 'knowledge' AND (${kindClauses}) AND (expires_at IS NULL OR expires_at > datetime('now')) ORDER BY last_updated ASC LIMIT 10`,
150
+ `SELECT kind, title, COALESCE(updated_at, created_at) as last_updated FROM vault WHERE category = 'knowledge' AND (${kindClauses}) AND (expires_at IS NULL OR expires_at > datetime('now')) ORDER BY last_updated ASC LIMIT 10`
161
151
  )
162
152
  .all();
163
153
  }
@@ -202,84 +192,62 @@ export function computeGrowthWarnings(status, thresholds) {
202
192
  const actions = [];
203
193
 
204
194
  const total = status.embeddingStatus?.total ?? 0;
205
- const {
206
- eventCount = 0,
207
- eventsWithoutTtlCount = 0,
208
- expiredCount = 0,
209
- dbSizeBytes = 0,
210
- } = status;
195
+ const { eventCount = 0, eventsWithoutTtlCount = 0, expiredCount = 0, dbSizeBytes = 0 } = status;
211
196
 
212
197
  let totalExceeded = false;
213
198
 
214
199
  if (t.totalEntries?.critical != null && total >= t.totalEntries.critical) {
215
200
  totalExceeded = true;
216
201
  warnings.push({
217
- level: "critical",
202
+ level: 'critical',
218
203
  message: `Total entries: ${total.toLocaleString()} (exceeds critical limit of ${t.totalEntries.critical.toLocaleString()})`,
219
204
  });
220
205
  } else if (t.totalEntries?.warn != null && total >= t.totalEntries.warn) {
221
206
  totalExceeded = true;
222
207
  warnings.push({
223
- level: "warn",
208
+ level: 'warn',
224
209
  message: `Total entries: ${total.toLocaleString()} (exceeds recommended ${t.totalEntries.warn.toLocaleString()})`,
225
210
  });
226
211
  }
227
212
 
228
- if (
229
- t.eventEntries?.critical != null &&
230
- eventCount >= t.eventEntries.critical
231
- ) {
213
+ if (t.eventEntries?.critical != null && eventCount >= t.eventEntries.critical) {
232
214
  warnings.push({
233
- level: "critical",
215
+ level: 'critical',
234
216
  message: `Event entries: ${eventCount.toLocaleString()} (exceeds critical limit of ${t.eventEntries.critical.toLocaleString()})`,
235
217
  });
236
- } else if (
237
- t.eventEntries?.warn != null &&
238
- eventCount >= t.eventEntries.warn
239
- ) {
218
+ } else if (t.eventEntries?.warn != null && eventCount >= t.eventEntries.warn) {
240
219
  const ttlNote =
241
- eventsWithoutTtlCount > 0
242
- ? ` (${eventsWithoutTtlCount.toLocaleString()} without TTL)`
243
- : "";
220
+ eventsWithoutTtlCount > 0 ? ` (${eventsWithoutTtlCount.toLocaleString()} without TTL)` : '';
244
221
  warnings.push({
245
- level: "warn",
222
+ level: 'warn',
246
223
  message: `Event entries: ${eventCount.toLocaleString()}${ttlNote} (exceeds recommended ${t.eventEntries.warn.toLocaleString()})`,
247
224
  });
248
225
  }
249
226
 
250
- if (
251
- t.vaultSizeBytes?.critical != null &&
252
- dbSizeBytes >= t.vaultSizeBytes.critical
253
- ) {
227
+ if (t.vaultSizeBytes?.critical != null && dbSizeBytes >= t.vaultSizeBytes.critical) {
254
228
  warnings.push({
255
- level: "critical",
229
+ level: 'critical',
256
230
  message: `Database size: ${(dbSizeBytes / 1024 / 1024).toFixed(1)}MB (exceeds critical limit of ${(t.vaultSizeBytes.critical / 1024 / 1024).toFixed(0)}MB)`,
257
231
  });
258
- } else if (
259
- t.vaultSizeBytes?.warn != null &&
260
- dbSizeBytes >= t.vaultSizeBytes.warn
261
- ) {
232
+ } else if (t.vaultSizeBytes?.warn != null && dbSizeBytes >= t.vaultSizeBytes.warn) {
262
233
  warnings.push({
263
- level: "warn",
234
+ level: 'warn',
264
235
  message: `Database size: ${(dbSizeBytes / 1024 / 1024).toFixed(1)}MB (exceeds recommended ${(t.vaultSizeBytes.warn / 1024 / 1024).toFixed(0)}MB)`,
265
236
  });
266
237
  }
267
238
 
268
- if (
269
- t.eventsWithoutTtl?.warn != null &&
270
- eventsWithoutTtlCount >= t.eventsWithoutTtl.warn
271
- ) {
239
+ if (t.eventsWithoutTtl?.warn != null && eventsWithoutTtlCount >= t.eventsWithoutTtl.warn) {
272
240
  warnings.push({
273
- level: "warn",
241
+ level: 'warn',
274
242
  message: `Event entries without expires_at: ${eventsWithoutTtlCount.toLocaleString()} (exceeds recommended ${t.eventsWithoutTtl.warn.toLocaleString()})`,
275
243
  });
276
244
  }
277
245
 
278
- const hasCritical = warnings.some((w) => w.level === "critical");
246
+ const hasCritical = warnings.some((w) => w.level === 'critical');
279
247
 
280
248
  if (expiredCount > 0) {
281
249
  actions.push(
282
- `Run \`context-vault prune\` to remove ${expiredCount} expired event entr${expiredCount === 1 ? "y" : "ies"}`,
250
+ `Run \`context-vault prune\` to remove ${expiredCount} expired event entr${expiredCount === 1 ? 'y' : 'ies'}`
283
251
  );
284
252
  }
285
253
  if (
@@ -287,14 +255,10 @@ export function computeGrowthWarnings(status, thresholds) {
287
255
  (eventCount >= (t.eventEntries?.warn ?? Infinity) ||
288
256
  eventsWithoutTtlCount >= (t.eventsWithoutTtl?.warn ?? Infinity))
289
257
  ) {
290
- actions.push(
291
- "Add `expires_at` to event/session entries to enable automatic cleanup",
292
- );
258
+ actions.push('Add `expires_at` to event/session entries to enable automatic cleanup');
293
259
  }
294
260
  if (total >= (t.totalEntries?.warn ?? Infinity)) {
295
- actions.push(
296
- "Run `context-vault archive` to move old ephemeral/event entries to _archive/",
297
- );
261
+ actions.push('Run `context-vault archive` to move old ephemeral/event entries to _archive/');
298
262
  }
299
263
 
300
264
  const kindBreakdown =
package/src/telemetry.js CHANGED
@@ -1,18 +1,14 @@
1
- import { existsSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import {
4
- API_URL,
5
- MARKETING_URL,
6
- GITHUB_ISSUES_URL,
7
- } from "@context-vault/core/constants";
1
+ import { existsSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { API_URL, MARKETING_URL, GITHUB_ISSUES_URL } from '@context-vault/core/constants';
8
4
 
9
5
  const TELEMETRY_ENDPOINT = `${API_URL}/telemetry`;
10
- const NOTICE_MARKER = ".telemetry-notice-shown";
11
- const FEEDBACK_PROMPT_MARKER = ".feedback-prompt-shown";
6
+ const NOTICE_MARKER = '.telemetry-notice-shown';
7
+ const FEEDBACK_PROMPT_MARKER = '.feedback-prompt-shown';
12
8
 
13
9
  export function isTelemetryEnabled(config) {
14
10
  const envVal = process.env.CONTEXT_VAULT_TELEMETRY;
15
- if (envVal !== undefined) return envVal === "1" || envVal === "true";
11
+ if (envVal !== undefined) return envVal === '1' || envVal === 'true';
16
12
  return config?.telemetry === true;
17
13
  }
18
14
 
@@ -31,8 +27,8 @@ export function sendTelemetryEvent(config, payload) {
31
27
  };
32
28
 
33
29
  fetch(TELEMETRY_ENDPOINT, {
34
- method: "POST",
35
- headers: { "Content-Type": "application/json" },
30
+ method: 'POST',
31
+ headers: { 'Content-Type': 'application/json' },
36
32
  body: JSON.stringify(event),
37
33
  signal: AbortSignal.timeout(5000),
38
34
  }).catch(() => {});
@@ -42,21 +38,21 @@ export function maybeShowTelemetryNotice(dataDir) {
42
38
  try {
43
39
  const markerPath = join(dataDir, NOTICE_MARKER);
44
40
  if (existsSync(markerPath)) return;
45
- writeFileSync(markerPath, new Date().toISOString() + "\n");
41
+ writeFileSync(markerPath, new Date().toISOString() + '\n');
46
42
  } catch {
47
43
  return;
48
44
  }
49
45
 
50
46
  const lines = [
51
- "[context-vault] Telemetry: disabled by default.",
52
- "[context-vault] To help improve context-vault, you can opt in to anonymous error reporting.",
53
- "[context-vault] Reports contain only: event type, error code, tool name, version, node version, platform, arch, timestamp.",
54
- "[context-vault] No vault content, file paths, or personal data is ever sent.",
47
+ '[context-vault] Telemetry: disabled by default.',
48
+ '[context-vault] To help improve context-vault, you can opt in to anonymous error reporting.',
49
+ '[context-vault] Reports contain only: event type, error code, tool name, version, node version, platform, arch, timestamp.',
50
+ '[context-vault] No vault content, file paths, or personal data is ever sent.',
55
51
  '[context-vault] Opt in: set "telemetry": true in ~/.context-mcp/config.json or set CONTEXT_VAULT_TELEMETRY=1.',
56
52
  `[context-vault] Full payload schema: ${MARKETING_URL}/telemetry`,
57
53
  ];
58
54
  for (const line of lines) {
59
- process.stderr.write(line + "\n");
55
+ process.stderr.write(line + '\n');
60
56
  }
61
57
  }
62
58
 
@@ -64,17 +60,17 @@ export function maybeShowFeedbackPrompt(dataDir) {
64
60
  try {
65
61
  const markerPath = join(dataDir, FEEDBACK_PROMPT_MARKER);
66
62
  if (existsSync(markerPath)) return;
67
- writeFileSync(markerPath, new Date().toISOString() + "\n");
63
+ writeFileSync(markerPath, new Date().toISOString() + '\n');
68
64
  } catch {
69
65
  return;
70
66
  }
71
67
 
72
68
  const lines = [
73
- "[context-vault] First entry saved — nice work!",
74
- "[context-vault] Got feedback, a bug, or a feature request?",
69
+ '[context-vault] First entry saved — nice work!',
70
+ '[context-vault] Got feedback, a bug, or a feature request?',
75
71
  `[context-vault] Open an issue: ${GITHUB_ISSUES_URL}`,
76
72
  ];
77
73
  for (const line of lines) {
78
- process.stderr.write(line + "\n");
74
+ process.stderr.write(line + '\n');
79
75
  }
80
76
  }
package/src/temporal.js CHANGED
@@ -7,12 +7,12 @@ function startOfToday(now) {
7
7
  }
8
8
 
9
9
  export function resolveTemporalShortcut(role, value, now = new Date()) {
10
- if (!value || typeof value !== "string") return value;
11
- const trimmed = value.trim().toLowerCase().replace(/\s+/g, "_");
10
+ if (!value || typeof value !== 'string') return value;
11
+ const trimmed = value.trim().toLowerCase().replace(/\s+/g, '_');
12
12
 
13
- if (trimmed === "today") {
13
+ if (trimmed === 'today') {
14
14
  const start = startOfToday(now);
15
- if (role === "until") {
15
+ if (role === 'until') {
16
16
  const end = new Date(start);
17
17
  end.setUTCDate(end.getUTCDate() + 1);
18
18
  return end.toISOString();
@@ -20,42 +20,40 @@ export function resolveTemporalShortcut(role, value, now = new Date()) {
20
20
  return start.toISOString();
21
21
  }
22
22
 
23
- if (trimmed === "yesterday") {
23
+ if (trimmed === 'yesterday') {
24
24
  const todayStart = startOfToday(now);
25
25
  const yesterdayStart = new Date(todayStart);
26
26
  yesterdayStart.setUTCDate(yesterdayStart.getUTCDate() - 1);
27
- if (role === "since") return yesterdayStart.toISOString();
27
+ if (role === 'since') return yesterdayStart.toISOString();
28
28
  return todayStart.toISOString();
29
29
  }
30
30
 
31
- if (trimmed === "this_week") {
31
+ if (trimmed === 'this_week') {
32
32
  const todayStart = startOfToday(now);
33
33
  const dayOfWeek = todayStart.getUTCDay();
34
34
  const daysFromMonday = (dayOfWeek + 6) % 7;
35
35
  const monday = new Date(todayStart);
36
36
  monday.setUTCDate(monday.getUTCDate() - daysFromMonday);
37
- if (role === "since") return monday.toISOString();
37
+ if (role === 'since') return monday.toISOString();
38
38
  const endOfToday = new Date(todayStart);
39
39
  endOfToday.setUTCDate(endOfToday.getUTCDate() + 1);
40
40
  return endOfToday.toISOString();
41
41
  }
42
42
 
43
- if (trimmed === "this_month") {
43
+ if (trimmed === 'this_month') {
44
44
  const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
45
- if (role === "since") return d.toISOString();
46
- const endOfMonth = new Date(
47
- Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1),
48
- );
45
+ if (role === 'since') return d.toISOString();
46
+ const endOfMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1));
49
47
  return endOfMonth.toISOString();
50
48
  }
51
49
 
52
50
  const m = SHORTCUT_RE.exec(trimmed);
53
51
  if (m) {
54
52
  const n = parseInt(m[1], 10);
55
- const unit = m[2].replace(/s$/, "");
53
+ const unit = m[2].replace(/s$/, '');
56
54
  let ms;
57
- if (unit === "day") ms = n * 86400000;
58
- else if (unit === "week") ms = n * 7 * 86400000;
55
+ if (unit === 'day') ms = n * 86400000;
56
+ else if (unit === 'week') ms = n * 7 * 86400000;
59
57
  else ms = n * 30 * 86400000;
60
58
  const target = new Date(now.getTime() - ms);
61
59
  target.setUTCHours(0, 0, 0, 0);
@@ -68,23 +66,14 @@ export function resolveTemporalShortcut(role, value, now = new Date()) {
68
66
  export function resolveTemporalParams(params, now = new Date()) {
69
67
  let { since, until } = params;
70
68
 
71
- if (
72
- since?.trim().toLowerCase() === "yesterday" &&
73
- (until === undefined || until === null)
74
- ) {
75
- since = resolveTemporalShortcut("since", since, now);
76
- until = resolveTemporalShortcut("until", "yesterday", now);
69
+ if (since?.trim().toLowerCase() === 'yesterday' && (until === undefined || until === null)) {
70
+ since = resolveTemporalShortcut('since', since, now);
71
+ until = resolveTemporalShortcut('until', 'yesterday', now);
77
72
  return { since, until };
78
73
  }
79
74
 
80
75
  return {
81
- since:
82
- since !== undefined
83
- ? resolveTemporalShortcut("since", since, now)
84
- : since,
85
- until:
86
- until !== undefined
87
- ? resolveTemporalShortcut("until", until, now)
88
- : until,
76
+ since: since !== undefined ? resolveTemporalShortcut('since', since, now) : since,
77
+ until: until !== undefined ? resolveTemporalShortcut('until', until, now) : until,
89
78
  };
90
79
  }
@@ -1,17 +1,17 @@
1
- import { z } from "zod";
2
- import { ok } from "../helpers.js";
1
+ import { z } from 'zod';
2
+ import { ok } from '../helpers.js';
3
3
 
4
- export const name = "clear_context";
4
+ export const name = 'clear_context';
5
5
 
6
6
  export const description =
7
- "Reset active in-memory session context without deleting vault entries. Call this when switching projects or topics mid-session. With `scope`, all subsequent get_context calls should filter to that tag/project. Vault data is never modified.";
7
+ 'Reset active in-memory session context without deleting vault entries. Call this when switching projects or topics mid-session. With `scope`, all subsequent get_context calls should filter to that tag/project. Vault data is never modified.';
8
8
 
9
9
  export const inputSchema = {
10
10
  scope: z
11
11
  .string()
12
12
  .optional()
13
13
  .describe(
14
- "Optional tag or project name to focus on going forward. When provided, treat subsequent get_context calls as if filtered to this tag.",
14
+ 'Optional tag or project name to focus on going forward. When provided, treat subsequent get_context calls as if filtered to this tag.'
15
15
  ),
16
16
  };
17
17
 
@@ -21,27 +21,24 @@ export const inputSchema = {
21
21
  */
22
22
  export function handler({ scope } = {}) {
23
23
  const lines = [
24
- "## Context Reset",
25
- "",
26
- "Active session context has been cleared. All previous context from this session should be disregarded.",
27
- "",
28
- "Vault entries are unchanged — no data was deleted.",
24
+ '## Context Reset',
25
+ '',
26
+ 'Active session context has been cleared. All previous context from this session should be disregarded.',
27
+ '',
28
+ 'Vault entries are unchanged — no data was deleted.',
29
29
  ];
30
30
 
31
31
  if (scope?.trim()) {
32
32
  const trimmed = scope.trim();
33
33
  lines.push(
34
- "",
34
+ '',
35
35
  `### Active Scope: \`${trimmed}\``,
36
- "",
37
- `Going forward, treat \`get_context\` calls as scoped to the tag or project **"${trimmed}"** unless the user explicitly requests a different scope or passes their own tag filters.`,
36
+ '',
37
+ `Going forward, treat \`get_context\` calls as scoped to the tag or project **"${trimmed}"** unless the user explicitly requests a different scope or passes their own tag filters.`
38
38
  );
39
39
  } else {
40
- lines.push(
41
- "",
42
- "No scope set. Use `get_context` normally — all vault entries are accessible.",
43
- );
40
+ lines.push('', 'No scope set. Use `get_context` normally — all vault entries are accessible.');
44
41
  }
45
42
 
46
- return ok(lines.join("\n"));
43
+ return ok(lines.join('\n'));
47
44
  }