listing.mjs
88 lines 2.8 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 20 hours ago
1 /**
2 * Vault listing JSON for MCP resources (Issue #1 Phase A2).
3 */
4
5 import fs from 'fs';
6 import path from 'path';
7 import { runListNotes } from '../../lib/list-notes.mjs';
8 import { MCP_RESOURCE_PAGE_SIZE } from './pagination.mjs';
9
10 /**
11 * @param {import('../../lib/config.mjs').loadConfig extends () => infer R ? R : never} config
12 * @param {string} folderPrefix - vault-relative folder prefix (e.g. "", "inbox", "projects/foo", "captures")
13 */
14 export function buildVaultListing(config, folderPrefix = '') {
15 const folder = folderPrefix.replace(/\\/g, '/').replace(/\/$/, '') || undefined;
16 const out = runListNotes(config, {
17 folder,
18 limit: MCP_RESOURCE_PAGE_SIZE,
19 offset: 0,
20 order: 'date',
21 fields: 'path+metadata',
22 });
23 return {
24 folder: folder || '/',
25 notes: out.notes,
26 total: out.total,
27 limit: MCP_RESOURCE_PAGE_SIZE,
28 truncated: out.total > MCP_RESOURCE_PAGE_SIZE,
29 };
30 }
31
32 /**
33 * List non-markdown media files under vault-relative dir (audio/video).
34 * @param {string} vaultPath
35 * @param {string} relDir - e.g. media/audio
36 * @param {string[]} extensions - e.g. ['.mp3','.m4a']
37 */
38 export function listMediaFiles(vaultPath, relDir, extensions) {
39 const dir = path.join(vaultPath, relDir.replace(/\\/g, '/'));
40 if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
41 return { folder: relDir, files: [], total: 0 };
42 }
43 const files = [];
44 const walk = (d, prefix) => {
45 const entries = fs.readdirSync(d, { withFileTypes: true });
46 for (const e of entries) {
47 const full = path.join(d, e.name);
48 const rel = prefix ? `${prefix}/${e.name}` : e.name;
49 if (e.isDirectory()) walk(full, rel);
50 else if (e.isFile()) {
51 const ext = path.extname(e.name).toLowerCase();
52 if (extensions.includes(ext)) files.push(rel.replace(/\\/g, '/'));
53 }
54 }
55 };
56 walk(dir, '');
57 files.sort();
58 const slice = files.slice(0, MCP_RESOURCE_PAGE_SIZE);
59 return {
60 folder: relDir,
61 files: slice,
62 total: files.length,
63 limit: MCP_RESOURCE_PAGE_SIZE,
64 truncated: files.length > MCP_RESOURCE_PAGE_SIZE,
65 };
66 }
67
68 /**
69 * List .md files under vault/templates (not using global ignore for this resource).
70 */
71 export function listTemplateFiles(vaultPath) {
72 const tdir = path.join(vaultPath, 'templates');
73 if (!fs.existsSync(tdir) || !fs.statSync(tdir).isDirectory()) {
74 return { templates: [], total: 0 };
75 }
76 const md = [];
77 const walk = (d, prefix) => {
78 for (const e of fs.readdirSync(d, { withFileTypes: true })) {
79 const full = path.join(d, e.name);
80 const rel = prefix ? `${prefix}/${e.name}` : e.name;
81 if (e.isDirectory()) walk(full, rel);
82 else if (e.isFile() && e.name.endsWith('.md')) md.push(`templates/${rel.replace(/\\/g, '/')}`);
83 }
84 };
85 walk(tdir, '');
86 md.sort();
87 return { templates: md, total: md.length };
88 }
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 20 hours ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 1 day ago