import.mjs
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠ breaking
1 day ago
| 1 | /** |
| 2 | * Import from external sources into vault. Phase 6. |
| 3 | * Each importer produces vault notes with SPEC §1-2 frontmatter. |
| 4 | */ |
| 5 | |
| 6 | import fs from 'fs'; |
| 7 | import path from 'path'; |
| 8 | import { loadConfig } from './config.mjs'; |
| 9 | import { writeNote } from './write.mjs'; |
| 10 | import { normalizeSlug } from './vault.mjs'; |
| 11 | import { IMPORT_SOURCE_TYPES, isValidImportSourceType } from './import-source-types.mjs'; |
| 12 | import { getRepoRoot } from './repo-root.mjs'; |
| 13 | |
| 14 | const projectRoot = getRepoRoot(); |
| 15 | |
| 16 | /** @typedef {{ |
| 17 | * project?: string, |
| 18 | * outputDir?: string, |
| 19 | * tags?: string[], |
| 20 | * dryRun?: boolean, |
| 21 | * vaultPath?: string, |
| 22 | * onProgress?: (p: { progress: number, total?: number, message?: string }) => void | Promise<void>, |
| 23 | * onMemoryEvent?: (data: object) => void, |
| 24 | * urlMode?: 'auto' | 'bookmark' | 'extract', |
| 25 | * sheetsRange?: string |
| 26 | * }} ImportOptions */ |
| 27 | |
| 28 | /** |
| 29 | * Run import for a source type. |
| 30 | * @param {string} sourceType - markdown, chatgpt-export, claude-export, mif, mem0-export, audio, video, etc. |
| 31 | * @param {string} input - Path to file, folder, or ZIP |
| 32 | * @param {ImportOptions} options |
| 33 | * @returns {Promise<{ imported: { path: string, source_id?: string }[], count: number }>} |
| 34 | */ |
| 35 | export async function runImport(sourceType, input, options = {}) { |
| 36 | if (!isValidImportSourceType(sourceType)) { |
| 37 | throw new Error( |
| 38 | `Unknown source type: ${sourceType}. Valid: ${IMPORT_SOURCE_TYPES.join(', ')}.` |
| 39 | ); |
| 40 | } |
| 41 | /** Hosted bridge passes vaultPath (temp dir); skip loadConfig so Netlify is not tied to repo config/local.yaml. */ |
| 42 | let vaultPath = options.vaultPath; |
| 43 | if (!vaultPath) { |
| 44 | const config = loadConfig(projectRoot); |
| 45 | vaultPath = config.vault_path; |
| 46 | } |
| 47 | const project = options.project ? normalizeSlug(options.project) : null; |
| 48 | const outputBase = resolveOutputDir(vaultPath, options.outputDir, project); |
| 49 | const tags = options.tags || []; |
| 50 | const dryRun = options.dryRun === true; |
| 51 | |
| 52 | const ctx = { |
| 53 | vaultPath, |
| 54 | outputBase, |
| 55 | project, |
| 56 | tags: Array.isArray(tags) ? tags : String(tags).split(',').map((t) => t.trim()).filter(Boolean), |
| 57 | dryRun, |
| 58 | onProgress: options.onProgress, |
| 59 | onMemoryEvent: options.onMemoryEvent, |
| 60 | urlMode: options.urlMode, |
| 61 | ...(options.sheetsRange != null && String(options.sheetsRange).trim() !== '' |
| 62 | ? { sheetsRange: String(options.sheetsRange).trim() } |
| 63 | : {}), |
| 64 | }; |
| 65 | const importers = { |
| 66 | markdown: () => import('./importers/markdown.mjs').then((m) => m.importMarkdown(input, ctx)), |
| 67 | pdf: () => import('./importers/pdf.mjs').then((m) => m.importPdf(input, ctx)), |
| 68 | docx: () => import('./importers/docx.mjs').then((m) => m.importDocx(input, ctx)), |
| 69 | url: () => import('./importers/url.mjs').then((m) => m.importUrl(input, ctx)), |
| 70 | 'chatgpt-export': () => import('./importers/chatgpt.mjs').then((m) => m.importChatGPT(input, ctx)), |
| 71 | 'claude-export': () => import('./importers/claude.mjs').then((m) => m.importClaude(input, ctx)), |
| 72 | mif: () => import('./importers/mif.mjs').then((m) => m.importMIF(input, ctx)), |
| 73 | 'mem0-export': () => import('./importers/mem0.mjs').then((m) => m.importMem0(input, ctx)), |
| 74 | 'supabase-memory': () => import('./importers/supabase-memory.mjs').then((m) => m.importSupabaseMemory(input, ctx)), |
| 75 | audio: () => import('./importers/audio.mjs').then((m) => m.importAudio(input, ctx)), |
| 76 | video: () => import('./importers/audio.mjs').then((m) => m.importVideo(input, ctx)), |
| 77 | notion: () => import('./importers/notion.mjs').then((m) => m.importNotion(input, ctx)), |
| 78 | 'jira-export': () => import('./importers/jira.mjs').then((m) => m.importJira(input, ctx)), |
| 79 | notebooklm: () => import('./importers/notebooklm.mjs').then((m) => m.importNotebookLM(input, ctx)), |
| 80 | gdrive: () => import('./importers/gdrive.mjs').then((m) => m.importGDrive(input, ctx)), |
| 81 | 'generic-csv': () => import('./importers/generic-csv.mjs').then((m) => m.importGenericCsv(input, ctx)), |
| 82 | 'excel-xlsx': () => import('./importers/excel-xlsx.mjs').then((m) => m.importExcelXlsx(input, ctx)), |
| 83 | vcf: () => import('./importers/vcf.mjs').then((m) => m.importVcf(input, ctx)), |
| 84 | 'google-sheets': () => import('./importers/google-sheets.mjs').then((m) => m.importGoogleSheets(input, ctx)), |
| 85 | 'linear-export': () => import('./importers/linear.mjs').then((m) => m.importLinear(input, ctx)), |
| 86 | 'wallet-csv': () => import('./importers/wallet-csv.mjs').then((m) => m.importWalletCSV(input, ctx)), |
| 87 | 'json-rows': () => import('./importers/json-rows.mjs').then((m) => m.importJsonRows(input, ctx)), |
| 88 | }; |
| 89 | |
| 90 | const fn = importers[sourceType]; |
| 91 | if (!fn) { |
| 92 | throw new Error(`No importer registered for source type: ${sourceType}`); |
| 93 | } |
| 94 | |
| 95 | return fn(); |
| 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Resolve output directory: options.outputDir (vault-relative), or inbox/projects/<project>/inbox |
| 100 | * @param {string} vaultPath |
| 101 | * @param {string|undefined} outputDir - vault-relative |
| 102 | * @param {string|null} project |
| 103 | * @returns {string} vault-relative path |
| 104 | */ |
| 105 | function resolveOutputDir(vaultPath, outputDir, project) { |
| 106 | if (outputDir) { |
| 107 | const normalized = outputDir.replace(/\\/g, '/').replace(/\/$/, ''); |
| 108 | return normalized || 'inbox'; |
| 109 | } |
| 110 | return project ? `projects/${project}/inbox` : 'inbox'; |
| 111 | } |
File History
2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠
1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6
docs: accept Calendar Events v0 spec with Phase 0 security …
Human
1 day ago