@geminilight/mindos 1.1.6 → 1.1.8
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/server/handlers/agent-activity.d.ts +1 -1
- package/dist/server/handlers/agent-activity.d.ts.map +1 -1
- package/dist/server/handlers/agent-activity.js +8 -6
- package/dist/server/handlers/agent-activity.js.map +1 -1
- package/dist/server/handlers/ask-sessions.d.ts.map +1 -1
- package/dist/server/handlers/ask-sessions.js +150 -23
- package/dist/server/handlers/ask-sessions.js.map +1 -1
- package/dist/server/handlers/audit-log.d.ts +12 -0
- package/dist/server/handlers/audit-log.d.ts.map +1 -0
- package/dist/server/handlers/audit-log.js +265 -0
- package/dist/server/handlers/audit-log.js.map +1 -0
- package/dist/server/handlers/change-log-store.d.ts +13 -0
- package/dist/server/handlers/change-log-store.d.ts.map +1 -0
- package/dist/server/handlers/change-log-store.js +167 -0
- package/dist/server/handlers/change-log-store.js.map +1 -0
- package/dist/server/handlers/changes.d.ts +1 -1
- package/dist/server/handlers/changes.d.ts.map +1 -1
- package/dist/server/handlers/changes.js +27 -15
- package/dist/server/handlers/changes.js.map +1 -1
- package/dist/server/handlers/file.d.ts.map +1 -1
- package/dist/server/handlers/file.js +3 -48
- package/dist/server/handlers/file.js.map +1 -1
- package/dist/server/handlers/graph.d.ts +2 -5
- package/dist/server/handlers/graph.d.ts.map +1 -1
- package/dist/server/handlers/graph.js +6 -115
- package/dist/server/handlers/graph.js.map +1 -1
- package/dist/server/handlers/jsonl-log.d.ts +56 -0
- package/dist/server/handlers/jsonl-log.d.ts.map +1 -0
- package/dist/server/handlers/jsonl-log.js +153 -0
- package/dist/server/handlers/jsonl-log.js.map +1 -0
- package/dist/server/handlers/monitoring.d.ts +8 -0
- package/dist/server/handlers/monitoring.d.ts.map +1 -1
- package/dist/server/handlers/monitoring.js +25 -2
- package/dist/server/handlers/monitoring.js.map +1 -1
- package/dist/server/handlers/sync.d.ts +1 -0
- package/dist/server/handlers/sync.d.ts.map +1 -1
- package/dist/server/handlers/sync.js +35 -4
- package/dist/server/handlers/sync.js.map +1 -1
- package/dist/server/http.d.ts +4 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +22 -5
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/link-index.d.ts +29 -0
- package/dist/server/link-index.d.ts.map +1 -0
- package/dist/server/link-index.js +137 -0
- package/dist/server/link-index.js.map +1 -0
- package/dist/server/runtime.d.ts +4 -0
- package/dist/server/runtime.d.ts.map +1 -1
- package/dist/server/runtime.js +1 -1
- package/dist/server/runtime.js.map +1 -1
- package/dist/server/tree-cache.d.ts +35 -0
- package/dist/server/tree-cache.d.ts.map +1 -0
- package/dist/server/tree-cache.js +0 -0
- package/dist/server/tree-cache.js.map +1 -0
- package/package.json +9 -9
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { posix } from 'node:path';
|
|
3
3
|
import { queryValue } from '../context.js';
|
|
4
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
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;
|
|
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 =
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAe,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"monitoring.js","sourceRoot":"","sources":["../../../src/server/handlers/monitoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/sync.ts"],"names":[],"mappings":"AAMA,OAAO,EAAQ,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;
|
|
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: { ...
|
|
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
|
-
|
|
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,
|