@geminilight/mindos 1.1.6 → 1.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 (59) hide show
  1. package/dist/server/handlers/agent-activity.d.ts +1 -1
  2. package/dist/server/handlers/agent-activity.d.ts.map +1 -1
  3. package/dist/server/handlers/agent-activity.js +8 -6
  4. package/dist/server/handlers/agent-activity.js.map +1 -1
  5. package/dist/server/handlers/ask-sessions.d.ts.map +1 -1
  6. package/dist/server/handlers/ask-sessions.js +150 -23
  7. package/dist/server/handlers/ask-sessions.js.map +1 -1
  8. package/dist/server/handlers/audit-log.d.ts +12 -0
  9. package/dist/server/handlers/audit-log.d.ts.map +1 -0
  10. package/dist/server/handlers/audit-log.js +265 -0
  11. package/dist/server/handlers/audit-log.js.map +1 -0
  12. package/dist/server/handlers/change-log-store.d.ts +13 -0
  13. package/dist/server/handlers/change-log-store.d.ts.map +1 -0
  14. package/dist/server/handlers/change-log-store.js +167 -0
  15. package/dist/server/handlers/change-log-store.js.map +1 -0
  16. package/dist/server/handlers/changes.d.ts +1 -1
  17. package/dist/server/handlers/changes.d.ts.map +1 -1
  18. package/dist/server/handlers/changes.js +27 -15
  19. package/dist/server/handlers/changes.js.map +1 -1
  20. package/dist/server/handlers/file.d.ts.map +1 -1
  21. package/dist/server/handlers/file.js +3 -48
  22. package/dist/server/handlers/file.js.map +1 -1
  23. package/dist/server/handlers/graph.d.ts +2 -5
  24. package/dist/server/handlers/graph.d.ts.map +1 -1
  25. package/dist/server/handlers/graph.js +6 -115
  26. package/dist/server/handlers/graph.js.map +1 -1
  27. package/dist/server/handlers/jsonl-log.d.ts +56 -0
  28. package/dist/server/handlers/jsonl-log.d.ts.map +1 -0
  29. package/dist/server/handlers/jsonl-log.js +153 -0
  30. package/dist/server/handlers/jsonl-log.js.map +1 -0
  31. package/dist/server/handlers/monitoring.d.ts +8 -0
  32. package/dist/server/handlers/monitoring.d.ts.map +1 -1
  33. package/dist/server/handlers/monitoring.js +25 -2
  34. package/dist/server/handlers/monitoring.js.map +1 -1
  35. package/dist/server/handlers/sync.d.ts +1 -0
  36. package/dist/server/handlers/sync.d.ts.map +1 -1
  37. package/dist/server/handlers/sync.js +35 -4
  38. package/dist/server/handlers/sync.js.map +1 -1
  39. package/dist/server/http.d.ts +4 -0
  40. package/dist/server/http.d.ts.map +1 -1
  41. package/dist/server/http.js +22 -5
  42. package/dist/server/http.js.map +1 -1
  43. package/dist/server/index.d.ts +1 -1
  44. package/dist/server/index.d.ts.map +1 -1
  45. package/dist/server/index.js +1 -1
  46. package/dist/server/index.js.map +1 -1
  47. package/dist/server/link-index.d.ts +29 -0
  48. package/dist/server/link-index.d.ts.map +1 -0
  49. package/dist/server/link-index.js +137 -0
  50. package/dist/server/link-index.js.map +1 -0
  51. package/dist/server/runtime.d.ts +4 -0
  52. package/dist/server/runtime.d.ts.map +1 -1
  53. package/dist/server/runtime.js +1 -1
  54. package/dist/server/runtime.js.map +1 -1
  55. package/dist/server/tree-cache.d.ts +35 -0
  56. package/dist/server/tree-cache.d.ts.map +1 -0
  57. package/dist/server/tree-cache.js +0 -0
  58. package/dist/server/tree-cache.js.map +1 -0
  59. package/package.json +9 -9
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { extname, posix } from 'node:path';
2
+ import { posix } from 'node:path';
3
3
  import { queryValue } from '../context.js';
4
- import { collectAllFilesFromMindRoot, readTextFileFromMindRoot } from '../runtime.js';
4
+ import { getLinkSnapshot, normalizeTargetPath } from '../link-index.js';
5
5
  import { json, publicCacheHeaders } from '../response.js';
6
6
  export function handleGraph(services) {
7
7
  const graph = buildGraphData(services);
@@ -13,7 +13,7 @@ export function handleBacklinks(query, services) {
13
13
  return json({ error: 'path required' }, { status: 400 });
14
14
  }
15
15
  const snippets = new Map();
16
- for (const hit of collectLinkHits(services)) {
16
+ for (const hit of getLinkSnapshot(services).hits) {
17
17
  if (hit.target !== target)
18
18
  continue;
19
19
  const list = snippets.get(hit.source) ?? [];
@@ -29,15 +29,15 @@ export function handleBacklinks(query, services) {
29
29
  return json(backlinks, { headers: publicCacheHeaders(300, generateETag(backlinks)) });
30
30
  }
31
31
  function buildGraphData(services) {
32
- const files = collectMarkdownFiles(services);
33
- const nodes = files.map((filePath) => ({
32
+ const snapshot = getLinkSnapshot(services);
33
+ const nodes = snapshot.files.map((filePath) => ({
34
34
  id: filePath,
35
35
  label: posix.basename(filePath, '.md'),
36
36
  folder: posix.dirname(filePath),
37
37
  }));
38
38
  const edgeKeys = new Set();
39
39
  const edges = [];
40
- for (const hit of collectLinkHits(services, files)) {
40
+ for (const hit of snapshot.hits) {
41
41
  if (hit.source === hit.target)
42
42
  continue;
43
43
  const key = `${hit.source}\0${hit.target}`;
@@ -49,115 +49,6 @@ function buildGraphData(services) {
49
49
  edges.sort((a, b) => a.source.localeCompare(b.source) || a.target.localeCompare(b.target));
50
50
  return { nodes, edges };
51
51
  }
52
- function collectLinkHits(services, markdownFiles = collectMarkdownFiles(services)) {
53
- const fileSet = new Set(markdownFiles);
54
- const basenameMap = buildBasenameMap(markdownFiles);
55
- const hits = [];
56
- for (const source of markdownFiles) {
57
- let content = '';
58
- try {
59
- content = readText(services, source);
60
- }
61
- catch {
62
- continue;
63
- }
64
- hits.push(...extractLinkHits(content, source, fileSet, basenameMap));
65
- }
66
- return hits;
67
- }
68
- function collectMarkdownFiles(services) {
69
- const files = services.collectAllFiles
70
- ? services.collectAllFiles()
71
- : services.mindRoot
72
- ? collectAllFilesFromMindRoot(services.mindRoot)
73
- : [];
74
- return files
75
- .filter((filePath) => extname(filePath).toLowerCase() === '.md')
76
- .map(normalizeTargetPath)
77
- .filter((filePath) => !!filePath)
78
- .sort((a, b) => a.localeCompare(b));
79
- }
80
- function readText(services, filePath) {
81
- if (services.readTextFile)
82
- return services.readTextFile(filePath);
83
- if (services.mindRoot)
84
- return readTextFileFromMindRoot(services.mindRoot, filePath);
85
- throw new Error('readTextFile service required');
86
- }
87
- function buildBasenameMap(files) {
88
- const map = new Map();
89
- for (const filePath of files) {
90
- const key = posix.basename(filePath).toLowerCase();
91
- const values = map.get(key) ?? [];
92
- values.push(filePath);
93
- map.set(key, values);
94
- }
95
- return map;
96
- }
97
- function extractLinkHits(content, source, fileSet, basenameMap) {
98
- const hits = [];
99
- const sourceDir = posix.dirname(source);
100
- const lines = content.split(/\r?\n/);
101
- for (const line of lines) {
102
- const snippet = line.trim();
103
- if (!snippet)
104
- continue;
105
- const wikiRe = /\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|[^\]]+)?\]\]/g;
106
- let match;
107
- while ((match = wikiRe.exec(line)) !== null) {
108
- const target = resolveLinkTarget(match[1], sourceDir, fileSet, basenameMap, false);
109
- if (target)
110
- hits.push({ source, target, snippet });
111
- }
112
- const markdownRe = /\[[^\]]+\]\(([^)#]+)(?:#[^)]+)?\)/g;
113
- while ((match = markdownRe.exec(line)) !== null) {
114
- const target = resolveLinkTarget(match[1], sourceDir, fileSet, basenameMap, true);
115
- if (target)
116
- hits.push({ source, target, snippet });
117
- }
118
- }
119
- return hits;
120
- }
121
- function resolveLinkTarget(rawTarget, sourceDir, fileSet, basenameMap, relativeToSource) {
122
- const target = normalizeTargetPath(rawTarget);
123
- if (!target || /^(https?:|mailto:|tel:)/i.test(target))
124
- return undefined;
125
- const candidates = new Set();
126
- candidates.add(target);
127
- candidates.add(target.endsWith('.md') ? target : `${target}.md`);
128
- if (relativeToSource) {
129
- candidates.add(posix.normalize(posix.join(sourceDir, target)));
130
- candidates.add(posix.normalize(posix.join(sourceDir, target.endsWith('.md') ? target : `${target}.md`)));
131
- }
132
- for (const candidate of candidates) {
133
- if (fileSet.has(candidate))
134
- return candidate;
135
- }
136
- const basename = posix.basename(target.endsWith('.md') ? target : `${target}.md`).toLowerCase();
137
- const basenameMatches = basenameMap.get(basename);
138
- if (basenameMatches?.length === 1)
139
- return basenameMatches[0];
140
- return undefined;
141
- }
142
- function normalizeTargetPath(value) {
143
- if (!value)
144
- return undefined;
145
- let normalized = value.trim();
146
- if (!normalized)
147
- return undefined;
148
- try {
149
- normalized = decodeURIComponent(normalized);
150
- }
151
- catch {
152
- // Keep the original value if it is not a valid URI component.
153
- }
154
- normalized = normalized.split('#')[0]?.trim() ?? '';
155
- normalized = normalized.replace(/\\/g, '/').replace(/^\/+/, '');
156
- normalized = posix.normalize(normalized);
157
- if (!normalized || normalized === '.' || normalized.startsWith('../') || normalized === '..')
158
- return undefined;
159
- return normalized;
160
- }
161
52
  function generateETag(value) {
162
53
  return `"${createHash('sha1').update(JSON.stringify(value)).digest('hex')}"`;
163
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../src/server/handlers/graph.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../src/server/handlers/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Generic append-only JSONL log store.
3
+ *
4
+ * Replaces the previous "read whole file -> unshift -> pretty-print rewrite"
5
+ * pattern (O(N) per event, O(N^2) per batch) with O(1) line appends plus an
6
+ * amortized size-capped compaction.
7
+ *
8
+ * On-disk layout:
9
+ * - `<file>`: one JSON object per line, oldest-first (newest at EOF).
10
+ * - `<metaFile>`: small sidecar `{ version: 2, lastSeenAt, legacy }`. Its
11
+ * presence marks that `<file>` is in JSONL format, so appends never need to
12
+ * re-read the log to detect the legacy pretty-printed format.
13
+ */
14
+ export interface JsonlLogMeta {
15
+ version: 2;
16
+ lastSeenAt: string | null;
17
+ legacy: Record<string, number | string | null>;
18
+ }
19
+ export interface JsonlCompactionConfig {
20
+ /** Newest entries kept when the log is compacted. */
21
+ maxEvents: number;
22
+ /** Compaction triggers once the file grows beyond this many bytes. */
23
+ maxBytes: number;
24
+ /** Compaction additionally drops oldest entries until at most this size. */
25
+ targetBytes: number;
26
+ }
27
+ export declare function readJsonlMeta(metaFile: string): JsonlLogMeta | null;
28
+ export declare function writeJsonlMeta(metaFile: string, meta: JsonlLogMeta): void;
29
+ /**
30
+ * Guarantees the log file is in JSONL format and returns its sidecar meta.
31
+ *
32
+ * On first contact with a legacy pretty-printed `{ events: [...] }` state file
33
+ * it rewrites the log once as JSONL. Legacy arrays are newest-first; on disk we
34
+ * store oldest-first so plain appends keep chronological order. `lastSeenAt`
35
+ * and legacy import counters are carried into the meta sidecar.
36
+ *
37
+ * Pure reads on a store that needs no migration do not write anything unless
38
+ * `persistIfMissing` is set (used by appenders so later appends skip the scan).
39
+ */
40
+ export declare function ensureJsonlStore(file: string, metaFile: string, options?: {
41
+ persistIfMissing?: boolean;
42
+ }): JsonlLogMeta;
43
+ /** Appends events (oldest-first input order) as a single write, then compacts if oversized. */
44
+ export declare function appendJsonlEvents(file: string, metaFile: string, events: unknown[], config: JsonlCompactionConfig): void;
45
+ /** Returns parsed events newest-first; corrupted lines are skipped. */
46
+ export declare function readJsonlEvents(file: string, metaFile: string): {
47
+ events: unknown[];
48
+ meta: JsonlLogMeta;
49
+ };
50
+ /**
51
+ * Rewrites the log keeping only the newest `maxEvents` entries (and at most
52
+ * `targetBytes` of them) once it grows past `maxBytes`. Amortized: appends stay
53
+ * O(1) and the occasional compaction is one bounded rewrite.
54
+ */
55
+ export declare function compactJsonlIfNeeded(file: string, config: JsonlCompactionConfig): void;
56
+ //# sourceMappingURL=jsonl-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-log.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/jsonl-log.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,qBAAqB;IACpC,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;CACrB;AAyCD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAenE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAEzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3C,YAAY,CAuBd;AAED,+FAA+F;AAC/F,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EAAE,EACjB,MAAM,EAAE,qBAAqB,GAC5B,IAAI,CAMN;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf;IAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAgB3C;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAmBtF"}
@@ -0,0 +1,153 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ function defaultMeta() {
4
+ return { version: 2, lastSeenAt: null, legacy: {} };
5
+ }
6
+ function parseLegacyStateFile(raw) {
7
+ try {
8
+ const parsed = JSON.parse(raw);
9
+ if (parsed
10
+ && typeof parsed === 'object'
11
+ && !Array.isArray(parsed)
12
+ && Array.isArray(parsed.events)) {
13
+ return parsed;
14
+ }
15
+ }
16
+ catch {
17
+ // Not a single JSON document: already JSONL (or corrupted lines we skip on read).
18
+ }
19
+ return null;
20
+ }
21
+ function atomicWrite(file, content) {
22
+ mkdirSync(dirname(file), { recursive: true });
23
+ const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
24
+ try {
25
+ writeFileSync(tmp, content, 'utf-8');
26
+ renameSync(tmp, file);
27
+ }
28
+ catch (error) {
29
+ try {
30
+ unlinkSync(tmp);
31
+ }
32
+ catch { /* ignore cleanup errors */ }
33
+ throw error;
34
+ }
35
+ }
36
+ export function readJsonlMeta(metaFile) {
37
+ try {
38
+ if (!existsSync(metaFile))
39
+ return null;
40
+ const parsed = JSON.parse(readFileSync(metaFile, 'utf-8'));
41
+ if (!parsed || typeof parsed !== 'object')
42
+ return null;
43
+ return {
44
+ version: 2,
45
+ lastSeenAt: typeof parsed.lastSeenAt === 'string' ? parsed.lastSeenAt : null,
46
+ legacy: parsed.legacy && typeof parsed.legacy === 'object' && !Array.isArray(parsed.legacy)
47
+ ? { ...parsed.legacy }
48
+ : {},
49
+ };
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ export function writeJsonlMeta(metaFile, meta) {
56
+ atomicWrite(metaFile, `${JSON.stringify(meta, null, 2)}\n`);
57
+ }
58
+ /**
59
+ * Guarantees the log file is in JSONL format and returns its sidecar meta.
60
+ *
61
+ * On first contact with a legacy pretty-printed `{ events: [...] }` state file
62
+ * it rewrites the log once as JSONL. Legacy arrays are newest-first; on disk we
63
+ * store oldest-first so plain appends keep chronological order. `lastSeenAt`
64
+ * and legacy import counters are carried into the meta sidecar.
65
+ *
66
+ * Pure reads on a store that needs no migration do not write anything unless
67
+ * `persistIfMissing` is set (used by appenders so later appends skip the scan).
68
+ */
69
+ export function ensureJsonlStore(file, metaFile, options = {}) {
70
+ const existing = readJsonlMeta(metaFile);
71
+ if (existing)
72
+ return existing;
73
+ const meta = defaultMeta();
74
+ let migrated = false;
75
+ if (existsSync(file)) {
76
+ const legacyState = parseLegacyStateFile(readFileSync(file, 'utf-8'));
77
+ if (legacyState) {
78
+ const lines = [...legacyState.events]
79
+ .reverse()
80
+ .filter((event) => event !== null && typeof event === 'object')
81
+ .map((event) => JSON.stringify(event));
82
+ if (typeof legacyState.lastSeenAt === 'string')
83
+ meta.lastSeenAt = legacyState.lastSeenAt;
84
+ if (legacyState.legacy && typeof legacyState.legacy === 'object' && !Array.isArray(legacyState.legacy)) {
85
+ meta.legacy = { ...legacyState.legacy };
86
+ }
87
+ atomicWrite(file, lines.length > 0 ? `${lines.join('\n')}\n` : '');
88
+ migrated = true;
89
+ }
90
+ }
91
+ if (migrated || options.persistIfMissing)
92
+ writeJsonlMeta(metaFile, meta);
93
+ return meta;
94
+ }
95
+ /** Appends events (oldest-first input order) as a single write, then compacts if oversized. */
96
+ export function appendJsonlEvents(file, metaFile, events, config) {
97
+ ensureJsonlStore(file, metaFile, { persistIfMissing: true });
98
+ if (events.length === 0)
99
+ return;
100
+ mkdirSync(dirname(file), { recursive: true });
101
+ appendFileSync(file, events.map((event) => `${JSON.stringify(event)}\n`).join(''), 'utf-8');
102
+ compactJsonlIfNeeded(file, config);
103
+ }
104
+ /** Returns parsed events newest-first; corrupted lines are skipped. */
105
+ export function readJsonlEvents(file, metaFile) {
106
+ const meta = ensureJsonlStore(file, metaFile);
107
+ if (!existsSync(file))
108
+ return { events: [], meta };
109
+ const events = [];
110
+ for (const line of readFileSync(file, 'utf-8').split('\n')) {
111
+ const trimmed = line.trim();
112
+ if (!trimmed)
113
+ continue;
114
+ try {
115
+ const parsed = JSON.parse(trimmed);
116
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed))
117
+ events.push(parsed);
118
+ }
119
+ catch {
120
+ // Skip corrupted line: a partial append must not poison the whole log.
121
+ }
122
+ }
123
+ events.reverse();
124
+ return { events, meta };
125
+ }
126
+ /**
127
+ * Rewrites the log keeping only the newest `maxEvents` entries (and at most
128
+ * `targetBytes` of them) once it grows past `maxBytes`. Amortized: appends stay
129
+ * O(1) and the occasional compaction is one bounded rewrite.
130
+ */
131
+ export function compactJsonlIfNeeded(file, config) {
132
+ let size;
133
+ try {
134
+ size = statSync(file).size;
135
+ }
136
+ catch {
137
+ return;
138
+ }
139
+ if (size <= config.maxBytes)
140
+ return;
141
+ const lines = readFileSync(file, 'utf-8').split('\n').filter((line) => line.trim().length > 0);
142
+ let kept = lines.slice(-config.maxEvents);
143
+ let bytes = kept.reduce((sum, line) => sum + Buffer.byteLength(line, 'utf-8') + 1, 0);
144
+ let drop = 0;
145
+ while (drop < kept.length - 1 && bytes > config.targetBytes) {
146
+ bytes -= Buffer.byteLength(kept[drop] ?? '', 'utf-8') + 1;
147
+ drop += 1;
148
+ }
149
+ if (drop > 0)
150
+ kept = kept.slice(drop);
151
+ atomicWrite(file, kept.length > 0 ? `${kept.join('\n')}\n` : '');
152
+ }
153
+ //# sourceMappingURL=jsonl-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-log.js","sourceRoot":"","sources":["../../../src/server/handlers/jsonl-log.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,13 @@ export type MonitoringHandlerServices = {
20
20
  };
21
21
  nodeVersion?: string;
22
22
  mcpPort?: number;
23
+ /**
24
+ * Monotonic tree version (e.g. the standalone server's tree cache or the
25
+ * web app's peekTreeVersion). When provided, the knowledge-base walk is
26
+ * cached until the version changes; otherwise a short TTL bounds the walk
27
+ * frequency.
28
+ */
29
+ getTreeVersion?: () => number;
23
30
  };
24
31
  export type MonitoringPayload = {
25
32
  system: {
@@ -43,4 +50,5 @@ export type MonitoringPayload = {
43
50
  };
44
51
  };
45
52
  export declare function handleMonitoringGet(services: MonitoringHandlerServices): MindosServerResponse<MonitoringPayload>;
53
+ export declare function resetMonitoringStatsCacheForTests(): void;
46
54
  //# sourceMappingURL=monitoring.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/monitoring.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGjE,MAAM,MAAM,yBAAyB,GAAG;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,yBAAyB,CAAC;IAClD,WAAW,CAAC,EAAE,MAAM;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7D,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,WAAW,EAAE,IAAI,CAAC,yBAAyB,EAAE,kBAAkB,CAAC,CAAC;IACjE,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,GAAG,EAAE;QACH,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,yBAAyB,GAClC,oBAAoB,CAAC,iBAAiB,CAAC,CAiCzC"}
1
+ {"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/monitoring.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGjE,MAAM,MAAM,yBAAyB,GAAG;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,yBAAyB,CAAC;IAClD,WAAW,CAAC,EAAE,MAAM;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,MAAM,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7D,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,WAAW,EAAE,IAAI,CAAC,yBAAyB,EAAE,kBAAkB,CAAC,CAAC;IACjE,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,GAAG,EAAE;QACH,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,yBAAyB,GAClC,oBAAoB,CAAC,iBAAiB,CAAC,CAiCzC;AA2BD,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
@@ -1,11 +1,11 @@
1
1
  import { existsSync, readdirSync, statSync } from 'node:fs';
2
- import { join } from 'node:path';
2
+ import { join, resolve } from 'node:path';
3
3
  import { json } from '../response.js';
4
4
  import { MINDOS_IGNORED_DIRS } from '../runtime.js';
5
5
  export function handleMonitoringGet(services) {
6
6
  const snapshot = (services.metricsSnapshot ?? defaultMetricsSnapshot)();
7
7
  const memory = (services.memoryUsage ?? process.memoryUsage)();
8
- const kbStats = walkStats(services.mindRoot);
8
+ const kbStats = getCachedStats(services.mindRoot, services.getTreeVersion);
9
9
  const mcpPort = services.mcpPort ?? (Number(process.env.MINDOS_MCP_PORT) || Number(process.env.MCP_PORT) || 8781);
10
10
  return json({
11
11
  system: {
@@ -45,6 +45,29 @@ function defaultMetricsSnapshot() {
45
45
  errors: 0,
46
46
  };
47
47
  }
48
+ // Bounds the full-library walk: monitoring is polled, but the stats only
49
+ // change when the tree does (version key) or, lacking a version source, at
50
+ // most once per TTL window.
51
+ const KB_STATS_TTL_MS = 30_000;
52
+ const kbStatsCache = new Map();
53
+ export function resetMonitoringStatsCacheForTests() {
54
+ kbStatsCache.clear();
55
+ }
56
+ function getCachedStats(root, getTreeVersion) {
57
+ const key = resolve(root);
58
+ const version = getTreeVersion ? getTreeVersion() : null;
59
+ const cached = kbStatsCache.get(key);
60
+ if (cached) {
61
+ const fresh = version !== null
62
+ ? cached.version === version
63
+ : Date.now() - cached.builtAt < KB_STATS_TTL_MS;
64
+ if (fresh)
65
+ return cached.value;
66
+ }
67
+ const value = walkStats(root);
68
+ kbStatsCache.set(key, { value, version, builtAt: Date.now() });
69
+ return value;
70
+ }
48
71
  function walkStats(root) {
49
72
  let fileCount = 0;
50
73
  let totalSizeBytes = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"monitoring.js","sourceRoot":"","sources":["../../../src/server/handlers/monitoring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"monitoring.js","sourceRoot":"","sources":["../../../src/server/handlers/monitoring.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { type MindosServerResponse } from '../response.js';
2
+ export declare function sanitizeGitEnv(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
2
3
  export type MindosSyncConfig = Record<string, any> & {
3
4
  mindRoot?: string;
4
5
  sync?: {
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/sync.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,29 @@ import { homedir, hostname } from 'node:os';
5
5
  import { dirname, join, resolve } from 'node:path';
6
6
  import { resolveExistingSafe } from '../../foundation/security/index.js';
7
7
  import { json } from '../response.js';
8
+ // Git hooks (pre-push etc.) export GIT_DIR — and may export GIT_WORK_TREE,
9
+ // GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY, GIT_PREFIX, GIT_QUARANTINE_PATH —
10
+ // pointing at the hook's own repository. Any git we spawn with that env and a
11
+ // different cwd silently operates on the hook's repo instead of mindRoot
12
+ // (real incident: a test run under pre-push committed onto the development
13
+ // worktree and deleted the tree). These vars are never legitimate input to
14
+ // MindOS sync; strip them from every spawned git's env. User-level git env
15
+ // (GIT_SSH_COMMAND, GIT_TERMINAL_PROMPT, GIT_AUTHOR_*) stays. Keep the list
16
+ // in sync with bin/lib/sync.js.
17
+ const GIT_REPO_TARGETING_VARS = new Set([
18
+ 'GIT_DIR',
19
+ 'GIT_WORK_TREE',
20
+ 'GIT_INDEX_FILE',
21
+ 'GIT_OBJECT_DIRECTORY',
22
+ 'GIT_ALTERNATE_OBJECT_DIRECTORIES',
23
+ 'GIT_COMMON_DIR',
24
+ 'GIT_NAMESPACE',
25
+ 'GIT_PREFIX',
26
+ 'GIT_QUARANTINE_PATH',
27
+ ]);
28
+ export function sanitizeGitEnv(base = process.env) {
29
+ return Object.fromEntries(Object.entries(base).filter(([key]) => !GIT_REPO_TARGETING_VARS.has(key)));
30
+ }
8
31
  const DEFAULT_MINDOS_DIR = join(homedir(), '.mindos');
9
32
  const DEFAULT_CONFIG_PATH = join(DEFAULT_MINDOS_DIR, 'config.json');
10
33
  const DEFAULT_SYNC_STATE_PATH = join(DEFAULT_MINDOS_DIR, 'sync-state.json');
@@ -453,6 +476,7 @@ function stopTrackingIgnoredFiles(mindRoot) {
453
476
  execFileSync('git', ['rm', '--cached', '--ignore-unmatch', '--', ...chunk], {
454
477
  cwd: mindRoot,
455
478
  stdio: 'pipe',
479
+ env: sanitizeGitEnv(),
456
480
  timeout: 60_000,
457
481
  });
458
482
  stoppedTracking.push(...chunk);
@@ -482,6 +506,7 @@ function commitAndPushResolvedSync(mindRoot, file) {
482
506
  execFileSync('git', ['commit', '--only', '-m', 'auto-sync: resolved sync conflict', '--', ...pathspecs], {
483
507
  cwd: mindRoot,
484
508
  stdio: 'pipe',
509
+ env: sanitizeGitEnv(),
485
510
  timeout: 60_000,
486
511
  });
487
512
  }
@@ -500,7 +525,7 @@ function commitAndPushResolvedSync(mindRoot, file) {
500
525
  execFileSync('git', ['push', '-u', 'origin', 'HEAD'], {
501
526
  cwd: mindRoot,
502
527
  stdio: 'pipe',
503
- env: { ...process.env, GIT_TERMINAL_PROMPT: '0', ...getGitSshEnvIfNeeded(remote) },
528
+ env: { ...sanitizeGitEnv(), GIT_TERMINAL_PROMPT: '0', ...getGitSshEnvIfNeeded(remote) },
504
529
  timeout: 60_000,
505
530
  });
506
531
  return { uploaded: true };
@@ -552,6 +577,7 @@ function isGitPathTracked(mindRoot, pathspec) {
552
577
  execFileSync('git', ['ls-files', '--error-unmatch', '--', pathspec], {
553
578
  cwd: mindRoot,
554
579
  stdio: ['ignore', 'ignore', 'ignore'],
580
+ env: sanitizeGitEnv(),
555
581
  timeout: 5000,
556
582
  });
557
583
  return true;
@@ -566,6 +592,7 @@ function listTrackedGitFiles(mindRoot) {
566
592
  cwd: mindRoot,
567
593
  encoding: 'utf-8',
568
594
  stdio: ['ignore', 'pipe', 'pipe'],
595
+ env: sanitizeGitEnv(),
569
596
  timeout: 30_000,
570
597
  }));
571
598
  }
@@ -583,6 +610,7 @@ function listIgnoredFilesFromTrackedSet(mindRoot, trackedFiles) {
583
610
  input,
584
611
  encoding: 'utf-8',
585
612
  stdio: ['pipe', 'pipe', 'pipe'],
613
+ env: sanitizeGitEnv(),
586
614
  timeout: 30_000,
587
615
  }));
588
616
  }
@@ -605,10 +633,10 @@ function chunkArray(items, chunkSize) {
605
633
  }
606
634
  function ensureServerGitIdentity(mindRoot) {
607
635
  if (!readServerGitConfig(mindRoot, 'user.email')) {
608
- execFileSync('git', ['config', 'user.email', 'mindos@local'], { cwd: mindRoot, stdio: 'pipe', timeout: 5000 });
636
+ execFileSync('git', ['config', 'user.email', 'mindos@local'], { cwd: mindRoot, stdio: 'pipe', env: sanitizeGitEnv(), timeout: 5000 });
609
637
  }
610
638
  if (!readServerGitConfig(mindRoot, 'user.name')) {
611
- execFileSync('git', ['config', 'user.name', 'MindOS'], { cwd: mindRoot, stdio: 'pipe', timeout: 5000 });
639
+ execFileSync('git', ['config', 'user.name', 'MindOS'], { cwd: mindRoot, stdio: 'pipe', env: sanitizeGitEnv(), timeout: 5000 });
612
640
  }
613
641
  }
614
642
  function readServerGitConfig(mindRoot, key) {
@@ -972,6 +1000,7 @@ function runGit(cwd, args) {
972
1000
  cwd,
973
1001
  encoding: 'utf-8',
974
1002
  stdio: ['ignore', 'pipe', 'ignore'],
1003
+ env: sanitizeGitEnv(),
975
1004
  }).trim();
976
1005
  }
977
1006
  export function redactGitRemote(remote) {
@@ -1026,7 +1055,9 @@ async function runCli(args, timeoutMs, services, envOverrides) {
1026
1055
  await services.runCli(args, timeoutMs, envOverrides);
1027
1056
  return;
1028
1057
  }
1029
- const env = { ...(services.env ?? process.env), ...(envOverrides ?? {}) };
1058
+ // The child CLI spawns its own git against mindRoot — repo-targeting vars
1059
+ // inherited from a git hook must not reach it either.
1060
+ const env = { ...sanitizeGitEnv(services.env ?? process.env), ...(envOverrides ?? {}) };
1030
1061
  const nodeBin = services.nodeBin ?? env.MINDOS_NODE_BIN ?? process.execPath;
1031
1062
  const cliPath = services.cliPath ?? resolveMindosCliPath({
1032
1063
  env,