@drewpayment/mink 0.10.0 → 0.10.1
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/README.md +62 -1
- package/dashboard/out/404.html +1 -1
- package/dashboard/out/action-log.html +1 -1
- package/dashboard/out/action-log.txt +1 -1
- package/dashboard/out/activity.html +1 -1
- package/dashboard/out/activity.txt +1 -1
- package/dashboard/out/bugs.html +1 -1
- package/dashboard/out/bugs.txt +1 -1
- package/dashboard/out/capture.html +1 -1
- package/dashboard/out/capture.txt +1 -1
- package/dashboard/out/config.html +1 -1
- package/dashboard/out/config.txt +1 -1
- package/dashboard/out/daemon.html +1 -1
- package/dashboard/out/daemon.txt +1 -1
- package/dashboard/out/design.html +1 -1
- package/dashboard/out/design.txt +1 -1
- package/dashboard/out/discord.html +1 -1
- package/dashboard/out/discord.txt +1 -1
- package/dashboard/out/file-index.html +1 -1
- package/dashboard/out/file-index.txt +1 -1
- package/dashboard/out/index.html +1 -1
- package/dashboard/out/index.txt +1 -1
- package/dashboard/out/insights.html +1 -1
- package/dashboard/out/insights.txt +1 -1
- package/dashboard/out/learning.html +1 -1
- package/dashboard/out/learning.txt +1 -1
- package/dashboard/out/overview.html +1 -1
- package/dashboard/out/overview.txt +1 -1
- package/dashboard/out/scheduler.html +1 -1
- package/dashboard/out/scheduler.txt +1 -1
- package/dashboard/out/sync.html +1 -1
- package/dashboard/out/sync.txt +1 -1
- package/dashboard/out/tokens.html +1 -1
- package/dashboard/out/tokens.txt +1 -1
- package/dashboard/out/waste.html +1 -1
- package/dashboard/out/waste.txt +1 -1
- package/dashboard/out/wiki.html +1 -1
- package/dashboard/out/wiki.txt +1 -1
- package/dist/cli.js +102 -31
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/scan.ts +29 -6
- package/src/commands/wiki.ts +19 -3
- package/src/core/note-index.ts +50 -1
- package/src/core/scanner.ts +19 -3
- package/src/types/note.ts +1 -0
- /package/dashboard/out/_next/static/{frTrvF6NV-Xl2bLk21NkY → e0QWU9rPMeSlJJLTwij89}/_buildManifest.js +0 -0
- /package/dashboard/out/_next/static/{frTrvF6NV-Xl2bLk21NkY → e0QWU9rPMeSlJJLTwij89}/_ssgManifest.js +0 -0
package/src/commands/scan.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
2
|
+
import { join, relative } from "path";
|
|
3
3
|
import { fileIndexPath, configPath } from "../core/paths";
|
|
4
4
|
import { atomicWriteJson, safeReadJson } from "../core/fs-utils";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
scanProject,
|
|
7
|
+
scanProjectWithStats,
|
|
8
|
+
loadConfig,
|
|
9
|
+
getExcludes,
|
|
10
|
+
} from "../core/scanner";
|
|
6
11
|
import { extractDescription } from "../core/description";
|
|
7
12
|
import { estimateTokens } from "../core/token-estimate";
|
|
8
13
|
import {
|
|
@@ -13,6 +18,11 @@ import {
|
|
|
13
18
|
} from "../core/index-store";
|
|
14
19
|
import type { FileIndex, FileIndexEntry } from "../types/file-index";
|
|
15
20
|
|
|
21
|
+
function configRelativePath(cfgPath: string, cwd: string): string {
|
|
22
|
+
const rel = relative(cwd, cfgPath);
|
|
23
|
+
return rel.startsWith("..") ? cfgPath : rel;
|
|
24
|
+
}
|
|
25
|
+
|
|
16
26
|
function loadExistingIndex(indexPath: string): FileIndex {
|
|
17
27
|
const raw = safeReadJson(indexPath);
|
|
18
28
|
if (isFileIndex(raw)) return raw;
|
|
@@ -64,7 +74,8 @@ export function scan(cwd: string, options: { check: boolean }): void {
|
|
|
64
74
|
const start = Date.now();
|
|
65
75
|
const index = loadExistingIndex(idxPath);
|
|
66
76
|
|
|
67
|
-
const
|
|
77
|
+
const stats = scanProjectWithStats(cwd, excludes, maxFiles);
|
|
78
|
+
const scanned = stats.files;
|
|
68
79
|
|
|
69
80
|
// Build new entries, preserving lifetime counters
|
|
70
81
|
const newIndex = createEmptyIndex();
|
|
@@ -95,7 +106,19 @@ export function scan(cwd: string, options: { check: boolean }): void {
|
|
|
95
106
|
atomicWriteJson(idxPath, newIndex);
|
|
96
107
|
|
|
97
108
|
const elapsed = Date.now() - start;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
if (stats.truncated > 0) {
|
|
110
|
+
console.log(
|
|
111
|
+
`[mink] scanned ${stats.totalScanned} files; indexed ${newIndex.header.totalFiles} most recent in ${elapsed}ms`
|
|
112
|
+
);
|
|
113
|
+
console.log(
|
|
114
|
+
` ${stats.truncated} files past maxFiles=${maxFiles} were not indexed`
|
|
115
|
+
);
|
|
116
|
+
console.log(
|
|
117
|
+
` raise the cap by setting "maxFiles" in ${configRelativePath(cfgPath, cwd)}`
|
|
118
|
+
);
|
|
119
|
+
} else {
|
|
120
|
+
console.log(
|
|
121
|
+
`[mink] indexed ${newIndex.header.totalFiles} files in ${elapsed}ms`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
101
124
|
}
|
package/src/commands/wiki.ts
CHANGED
|
@@ -14,7 +14,11 @@ import {
|
|
|
14
14
|
import { atomicWriteJson } from "../core/fs-utils";
|
|
15
15
|
import { setConfigValue } from "../core/global-config";
|
|
16
16
|
import { seedTemplates } from "../core/vault-templates";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
rebuildVaultIndex,
|
|
19
|
+
loadVaultIndex,
|
|
20
|
+
vaultIndexStaleness,
|
|
21
|
+
} from "../core/note-index";
|
|
18
22
|
import { updateMasterIndex } from "../core/note-linker";
|
|
19
23
|
import type { VaultManifest, NoteCategory } from "../types/note";
|
|
20
24
|
|
|
@@ -32,6 +36,7 @@ export async function wiki(
|
|
|
32
36
|
wikiStatus();
|
|
33
37
|
break;
|
|
34
38
|
case "rebuild-index":
|
|
39
|
+
case "scan":
|
|
35
40
|
wikiRebuildIndex();
|
|
36
41
|
break;
|
|
37
42
|
case "organize":
|
|
@@ -51,7 +56,8 @@ export async function wiki(
|
|
|
51
56
|
console.log();
|
|
52
57
|
console.log(" init Initialize the notes/wiki vault");
|
|
53
58
|
console.log(" status Show vault statistics");
|
|
54
|
-
console.log(" rebuild-index Full rescan and reindex of vault");
|
|
59
|
+
console.log(" rebuild-index Full rescan and reindex of vault (alias: scan)");
|
|
60
|
+
console.log(" scan Alias for rebuild-index");
|
|
55
61
|
console.log(" organize List inbox notes needing categorization");
|
|
56
62
|
console.log(" link <path> [name] Symlink external notes into the vault");
|
|
57
63
|
console.log(" unlink <name> Remove a symlinked directory from the vault");
|
|
@@ -174,6 +180,13 @@ function wikiStatus(): void {
|
|
|
174
180
|
}
|
|
175
181
|
|
|
176
182
|
const vaultPath = resolveVaultPath();
|
|
183
|
+
const staleness = vaultIndexStaleness();
|
|
184
|
+
if (staleness.isStale) {
|
|
185
|
+
console.log(
|
|
186
|
+
`[mink] vault index is stale (${staleness.reason}) — rebuilding...`
|
|
187
|
+
);
|
|
188
|
+
rebuildVaultIndex();
|
|
189
|
+
}
|
|
177
190
|
const index = loadVaultIndex();
|
|
178
191
|
|
|
179
192
|
const categoryCounts: Record<string, number> = {
|
|
@@ -200,7 +213,10 @@ function wikiStatus(): void {
|
|
|
200
213
|
}
|
|
201
214
|
console.log();
|
|
202
215
|
console.log(
|
|
203
|
-
` last
|
|
216
|
+
` last full scan: ${index.lastFullScanTimestamp || "never"}`
|
|
217
|
+
);
|
|
218
|
+
console.log(
|
|
219
|
+
` last update: ${index.lastScanTimestamp || "never"}`
|
|
204
220
|
);
|
|
205
221
|
|
|
206
222
|
const links = listLinks();
|
package/src/core/note-index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { VaultIndex, VaultIndexEntry, NoteCategory } from "../types/note";
|
|
|
7
7
|
export function createEmptyVaultIndex(): VaultIndex {
|
|
8
8
|
return {
|
|
9
9
|
lastScanTimestamp: "",
|
|
10
|
+
lastFullScanTimestamp: "",
|
|
10
11
|
totalNotes: 0,
|
|
11
12
|
entries: {},
|
|
12
13
|
};
|
|
@@ -182,7 +183,9 @@ export function rebuildVaultIndex(): VaultIndex {
|
|
|
182
183
|
}
|
|
183
184
|
}
|
|
184
185
|
|
|
185
|
-
|
|
186
|
+
const now = new Date().toISOString();
|
|
187
|
+
index.lastScanTimestamp = now;
|
|
188
|
+
index.lastFullScanTimestamp = now;
|
|
186
189
|
saveVaultIndex(index);
|
|
187
190
|
return index;
|
|
188
191
|
}
|
|
@@ -219,6 +222,52 @@ export function getRecentNotes(n: number): VaultIndexEntry[] {
|
|
|
219
222
|
.slice(0, n);
|
|
220
223
|
}
|
|
221
224
|
|
|
225
|
+
export interface VaultStaleness {
|
|
226
|
+
isStale: boolean;
|
|
227
|
+
reason: string | null;
|
|
228
|
+
diskCount: number;
|
|
229
|
+
indexCount: number;
|
|
230
|
+
lastFullScan: string | null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function vaultIndexStaleness(): VaultStaleness {
|
|
234
|
+
const index = loadVaultIndex();
|
|
235
|
+
const root = resolveVaultPath();
|
|
236
|
+
const diskCount = collectAllMarkdown(root).length;
|
|
237
|
+
const indexCount = Object.keys(index.entries).length;
|
|
238
|
+
const lastFullScan = index.lastFullScanTimestamp || null;
|
|
239
|
+
|
|
240
|
+
if (!lastFullScan) {
|
|
241
|
+
return {
|
|
242
|
+
isStale: true,
|
|
243
|
+
reason: "no full scan on record",
|
|
244
|
+
diskCount,
|
|
245
|
+
indexCount,
|
|
246
|
+
lastFullScan: null,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const delta = Math.abs(diskCount - indexCount);
|
|
251
|
+
const threshold = Math.max(5, Math.floor(diskCount * 0.05));
|
|
252
|
+
if (delta >= threshold) {
|
|
253
|
+
return {
|
|
254
|
+
isStale: true,
|
|
255
|
+
reason: `${diskCount} files on disk but ${indexCount} in index`,
|
|
256
|
+
diskCount,
|
|
257
|
+
indexCount,
|
|
258
|
+
lastFullScan,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
isStale: false,
|
|
264
|
+
reason: null,
|
|
265
|
+
diskCount,
|
|
266
|
+
indexCount,
|
|
267
|
+
lastFullScan,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
222
271
|
interface ScannedMarkdown {
|
|
223
272
|
absolutePath: string;
|
|
224
273
|
relativePath: string;
|
package/src/core/scanner.ts
CHANGED
|
@@ -87,13 +87,29 @@ export function getExcludes(config: ProjectConfig): string[] {
|
|
|
87
87
|
return [...DEFAULT_EXCLUDES, ...(config.excludePatterns ?? [])];
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
export
|
|
90
|
+
export interface ScanStats {
|
|
91
|
+
files: ScannedFile[];
|
|
92
|
+
totalScanned: number;
|
|
93
|
+
truncated: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function scanProjectWithStats(
|
|
91
97
|
projectRoot: string,
|
|
92
98
|
excludes: string[],
|
|
93
99
|
maxFiles: number = DEFAULT_MAX_FILES
|
|
94
|
-
):
|
|
100
|
+
): ScanStats {
|
|
95
101
|
const results: ScannedFile[] = [];
|
|
96
102
|
walkDirectory(projectRoot, projectRoot, excludes, results);
|
|
97
103
|
results.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
98
|
-
|
|
104
|
+
const totalScanned = results.length;
|
|
105
|
+
const files = results.slice(0, maxFiles);
|
|
106
|
+
return { files, totalScanned, truncated: totalScanned - files.length };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function scanProject(
|
|
110
|
+
projectRoot: string,
|
|
111
|
+
excludes: string[],
|
|
112
|
+
maxFiles: number = DEFAULT_MAX_FILES
|
|
113
|
+
): ScannedFile[] {
|
|
114
|
+
return scanProjectWithStats(projectRoot, excludes, maxFiles).files;
|
|
99
115
|
}
|
package/src/types/note.ts
CHANGED
|
File without changes
|
/package/dashboard/out/_next/static/{frTrvF6NV-Xl2bLk21NkY → e0QWU9rPMeSlJJLTwij89}/_ssgManifest.js
RENAMED
|
File without changes
|