@rubytech/create-maxy-code 0.1.138 → 0.1.142
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/package.json +1 -1
- package/payload/platform/config/brand.json +1 -1
- package/payload/platform/lib/obsidian-parser/dist/index.d.ts +98 -0
- package/payload/platform/lib/obsidian-parser/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/obsidian-parser/dist/index.js +480 -0
- package/payload/platform/lib/obsidian-parser/dist/index.js.map +1 -0
- package/payload/platform/lib/obsidian-parser/src/index.ts +572 -0
- package/payload/platform/lib/obsidian-parser/tsconfig.json +8 -0
- package/payload/platform/neo4j/schema.cypher +48 -67
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +15 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +14 -8
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +10 -7
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js.map +1 -1
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/docs/references/neo4j.md +3 -3
- package/payload/platform/plugins/docs/references/plugins-guide.md +3 -0
- package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/email/PLUGIN.md +3 -7
- package/payload/platform/plugins/email/mcp/dist/index.js +7 -46
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +4 -15
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +51 -43
- package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js +223 -229
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +7 -4
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts +14 -4
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js +69 -84
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +49 -64
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +1 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +3 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +89 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +101 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +7 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +122 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +580 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.d.ts +127 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.js +477 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.js.map +1 -0
- package/payload/platform/plugins/memory/references/schema-base.md +4 -4
- package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -1
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +1 -0
- package/payload/platform/plugins/notion-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/notion-import/PLUGIN.md +27 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +114 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/attachments.md +55 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/databases.md +83 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/page-tree.md +61 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/workspace-export.md +41 -0
- package/payload/platform/plugins/obsidian-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/obsidian-import/PLUGIN.md +39 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/SKILL.md +92 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/attachments.md +80 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/daily-notes.md +31 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/vault-structure.md +46 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/wikilinks.md +70 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +18 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +93 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts +80 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +395 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts +16 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js +111 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts +20 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js +63 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js.map +1 -0
- package/payload/platform/plugins/x-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/x-import/PLUGIN.md +33 -0
- package/payload/platform/plugins/x-import/references/archive-shape.md +124 -0
- package/payload/platform/plugins/x-import/references/transcript-shape.md +121 -0
- package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +123 -0
- package/payload/platform/templates/specialists/agents/database-operator.md +18 -2
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
/**
|
|
3
|
+
* obsidian-vault-import — server-side parser + write orchestrator for
|
|
4
|
+
* Obsidian vault ingestion. Two-phase by operator decision (CEO review):
|
|
5
|
+
*
|
|
6
|
+
* 1. mode='dry-run' — walks the extractedDir, parses, builds the
|
|
7
|
+
* resolution plan, returns counts + ambiguities the operator must
|
|
8
|
+
* disambiguate before the write commits. No writes happen.
|
|
9
|
+
*
|
|
10
|
+
* 2. mode='commit' — re-walks (parsing is deterministic + cheap on a
|
|
11
|
+
* local fs), applies operator-supplied resolutions, runs the
|
|
12
|
+
* content-hash idempotency check against the existing graph,
|
|
13
|
+
* copies attachments to {accountDir}/archive/obsidian/<importId>/,
|
|
14
|
+
* and invokes memoryArchiveWrite with archiveType='obsidian-vault'.
|
|
15
|
+
*
|
|
16
|
+
* The agent never parses markdown. It supplies extractedDir + ownerNodeId
|
|
17
|
+
* + operator-driven filter selection, runs the dry-run, surfaces
|
|
18
|
+
* ambiguities to the operator interactively, then re-invokes commit with
|
|
19
|
+
* the resolutions block. All schema decisions (label reuse, edge naming,
|
|
20
|
+
* MERGE keys) are pinned in memory-archive-write's obsidian-vault handler.
|
|
21
|
+
*/
|
|
22
|
+
export type ObsidianImportMode = "dry-run" | "commit";
|
|
23
|
+
export interface VaultImportFilters {
|
|
24
|
+
/** Only ingest pages whose obsidianPath starts with one of these prefixes. */
|
|
25
|
+
folderPrefixes?: string[];
|
|
26
|
+
/** Only ingest pages whose tags intersect this set (normalised, no `#`). */
|
|
27
|
+
tags?: string[];
|
|
28
|
+
/** Only ingest pages with mtime >= this ISO date or epoch-ms. */
|
|
29
|
+
modifiedSince?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Operator's disambiguation answers, keyed by the ambiguity id the dry-run
|
|
33
|
+
* returned. Each entry tells the commit phase which candidate to write the
|
|
34
|
+
* wikilink edge to.
|
|
35
|
+
*/
|
|
36
|
+
export type AmbiguityResolution = {
|
|
37
|
+
kind: "page";
|
|
38
|
+
obsidianPath: string;
|
|
39
|
+
} | {
|
|
40
|
+
kind: "entity";
|
|
41
|
+
nodeId: string;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "stub";
|
|
44
|
+
};
|
|
45
|
+
export interface VaultImportParams {
|
|
46
|
+
accountId: string;
|
|
47
|
+
ownerNodeId: string;
|
|
48
|
+
/** Absolute path to the extracted vault directory. Caller validates it
|
|
49
|
+
* lives under the account's archive area before invoking. */
|
|
50
|
+
extractedDir: string;
|
|
51
|
+
/** Stable id for the import run. Generated by dry-run, passed back in
|
|
52
|
+
* the commit call so observability lines tie together. */
|
|
53
|
+
importId?: string;
|
|
54
|
+
mode: ObsidianImportMode;
|
|
55
|
+
filters?: VaultImportFilters;
|
|
56
|
+
/** Operator answers to dry-run ambiguities. Required when mode='commit'
|
|
57
|
+
* AND the dry-run reported ambiguities; ignored otherwise. */
|
|
58
|
+
resolutions?: Record<string, AmbiguityResolution>;
|
|
59
|
+
/** Threshold above which the dry-run flags large vaults for the skill's
|
|
60
|
+
* selective-ingest filter conversation. Default 100 — mirrors the
|
|
61
|
+
* linkedin-connections threshold. */
|
|
62
|
+
selectiveIngestThreshold?: number;
|
|
63
|
+
sessionId?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface VaultImportAmbiguity {
|
|
66
|
+
/** Stable id the operator quotes back in the resolutions map. */
|
|
67
|
+
id: string;
|
|
68
|
+
/** The page that contains the wikilink. */
|
|
69
|
+
fromPath: string;
|
|
70
|
+
/** Raw wikilink text (without `[[…]]`, before alias `|`). */
|
|
71
|
+
target: string;
|
|
72
|
+
/** Candidate intra-vault pages by obsidianPath. */
|
|
73
|
+
pageCandidates: string[];
|
|
74
|
+
/** Candidate existing entities — `{nodeId, label, name, distance}`. */
|
|
75
|
+
entityCandidates: Array<{
|
|
76
|
+
nodeId: string;
|
|
77
|
+
label: string;
|
|
78
|
+
name: string;
|
|
79
|
+
distance: number;
|
|
80
|
+
}>;
|
|
81
|
+
}
|
|
82
|
+
export interface VaultImportPlan {
|
|
83
|
+
importId: string;
|
|
84
|
+
mode: ObsidianImportMode;
|
|
85
|
+
/** Total pages discovered before filtering. */
|
|
86
|
+
pagesDiscovered: number;
|
|
87
|
+
/** Pages surviving filters. */
|
|
88
|
+
pagesEligible: number;
|
|
89
|
+
/** Pages whose contentHash already matches the existing graph (skipped on commit). */
|
|
90
|
+
pagesUnchanged: number;
|
|
91
|
+
/** Wikilinks classified by resolution: intra-vault, fuzzy-entity, stub. */
|
|
92
|
+
wikilinks: {
|
|
93
|
+
page: number;
|
|
94
|
+
entity: number;
|
|
95
|
+
stub: number;
|
|
96
|
+
ambiguous: number;
|
|
97
|
+
};
|
|
98
|
+
/** Tags discovered across eligible pages. */
|
|
99
|
+
tagCount: number;
|
|
100
|
+
/** Distinct attachments referenced. */
|
|
101
|
+
attachmentCount: number;
|
|
102
|
+
/** Operator must resolve these before commit will run. */
|
|
103
|
+
ambiguities: VaultImportAmbiguity[];
|
|
104
|
+
/** Set when pagesEligible > selectiveIngestThreshold and dry-run was the call. */
|
|
105
|
+
selectiveIngestSuggested: boolean;
|
|
106
|
+
}
|
|
107
|
+
export interface VaultImportCommitResult extends VaultImportPlan {
|
|
108
|
+
written: {
|
|
109
|
+
createdPages: number;
|
|
110
|
+
mergedPages: number;
|
|
111
|
+
createdTags: number;
|
|
112
|
+
createdTagEdges: number;
|
|
113
|
+
createdAttachments: number;
|
|
114
|
+
createdAttachmentEdges: number;
|
|
115
|
+
createdWikilinkEdges: number;
|
|
116
|
+
};
|
|
117
|
+
attachmentsCopied: number;
|
|
118
|
+
errors: Array<{
|
|
119
|
+
rowIndex: number;
|
|
120
|
+
reason: string;
|
|
121
|
+
}>;
|
|
122
|
+
/** Server log line tag — the same string written to server.log. */
|
|
123
|
+
observabilityTag: string;
|
|
124
|
+
}
|
|
125
|
+
export declare function obsidianVaultImport(params: VaultImportParams): Promise<VaultImportPlan | VaultImportCommitResult>;
|
|
126
|
+
export type _BufferType = Buffer;
|
|
127
|
+
//# sourceMappingURL=obsidian-vault-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-vault-import.d.ts","sourceRoot":"","sources":["../../src/tools/obsidian-vault-import.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { walkVault, buildVaultIndex, resolveWikilinkInVault, normalizeTag, makeImportId, } from "../../../../../lib/obsidian-parser/dist/index.js";
|
|
4
|
+
import { levenshtein } from "../../../../../lib/graph-mcp/dist/schema-cypher-parser.js";
|
|
5
|
+
import { getSession } from "../lib/neo4j.js";
|
|
6
|
+
import { memoryArchiveWrite, } from "./memory-archive-write.js";
|
|
7
|
+
const FUZZY_MATCH_THRESHOLD = 2;
|
|
8
|
+
const SUPPORTED_ATTACHMENT_MIME = {
|
|
9
|
+
".png": "image/png",
|
|
10
|
+
".jpg": "image/jpeg",
|
|
11
|
+
".jpeg": "image/jpeg",
|
|
12
|
+
".gif": "image/gif",
|
|
13
|
+
".webp": "image/webp",
|
|
14
|
+
".svg": "image/svg+xml",
|
|
15
|
+
".pdf": "application/pdf",
|
|
16
|
+
".mp3": "audio/mpeg",
|
|
17
|
+
".mp4": "video/mp4",
|
|
18
|
+
".mov": "video/quicktime",
|
|
19
|
+
".wav": "audio/wav",
|
|
20
|
+
".m4a": "audio/mp4",
|
|
21
|
+
".webm": "video/webm",
|
|
22
|
+
};
|
|
23
|
+
export async function obsidianVaultImport(params) {
|
|
24
|
+
const importId = params.importId ?? makeImportId();
|
|
25
|
+
const threshold = params.selectiveIngestThreshold ?? 100;
|
|
26
|
+
const startedMs = Date.now();
|
|
27
|
+
await assertExtractedDir(params.extractedDir);
|
|
28
|
+
const walkOpts = {
|
|
29
|
+
folderPrefixes: params.filters?.folderPrefixes,
|
|
30
|
+
tagFilter: params.filters?.tags?.map(normalizeTag),
|
|
31
|
+
modifiedSinceMs: toEpochMs(params.filters?.modifiedSince),
|
|
32
|
+
};
|
|
33
|
+
const allPages = await walkVault(params.extractedDir, {});
|
|
34
|
+
const pagesDiscovered = allPages.length;
|
|
35
|
+
// Re-walk with filters for the "eligible" set so the plan honours the
|
|
36
|
+
// operator's selective-ingest choices.
|
|
37
|
+
const eligiblePages = walkOpts.folderPrefixes || walkOpts.tagFilter || walkOpts.modifiedSinceMs
|
|
38
|
+
? await walkVault(params.extractedDir, walkOpts)
|
|
39
|
+
: allPages;
|
|
40
|
+
const vaultIndex = buildVaultIndex(eligiblePages);
|
|
41
|
+
const knownPaths = new Set(eligiblePages.map((p) => p.obsidianPath));
|
|
42
|
+
const session = getSession();
|
|
43
|
+
let resolved;
|
|
44
|
+
try {
|
|
45
|
+
resolved = await resolveAllWikilinks(eligiblePages, vaultIndex, knownPaths, params.accountId, session);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
await session.close();
|
|
49
|
+
}
|
|
50
|
+
const tagCount = countDistinct(eligiblePages.flatMap((p) => p.tags.map(normalizeTag)));
|
|
51
|
+
const attachmentCount = countDistinct(eligiblePages.flatMap((p) => p.attachments.map((a) => a.resolvedPath)));
|
|
52
|
+
// Idempotency: query existing contentHashes for these paths and mark
|
|
53
|
+
// unchanged. Only the dry-run plan reports the count; the commit phase
|
|
54
|
+
// uses the same map to filter rows before write.
|
|
55
|
+
const idemSession = getSession();
|
|
56
|
+
let unchangedSet;
|
|
57
|
+
try {
|
|
58
|
+
unchangedSet = await findUnchangedPages(idemSession, params.accountId, eligiblePages);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await idemSession.close();
|
|
62
|
+
}
|
|
63
|
+
const ambiguities = resolved.ambiguities;
|
|
64
|
+
const plan = {
|
|
65
|
+
importId,
|
|
66
|
+
mode: params.mode,
|
|
67
|
+
pagesDiscovered,
|
|
68
|
+
pagesEligible: eligiblePages.length,
|
|
69
|
+
pagesUnchanged: unchangedSet.size,
|
|
70
|
+
wikilinks: {
|
|
71
|
+
page: resolved.counts.page,
|
|
72
|
+
entity: resolved.counts.entity,
|
|
73
|
+
stub: resolved.counts.stub,
|
|
74
|
+
ambiguous: ambiguities.length,
|
|
75
|
+
},
|
|
76
|
+
tagCount,
|
|
77
|
+
attachmentCount,
|
|
78
|
+
ambiguities,
|
|
79
|
+
selectiveIngestSuggested: eligiblePages.length > threshold &&
|
|
80
|
+
!walkOpts.folderPrefixes &&
|
|
81
|
+
!walkOpts.tagFilter &&
|
|
82
|
+
!walkOpts.modifiedSinceMs,
|
|
83
|
+
};
|
|
84
|
+
process.stderr.write(`[obsidian-import] event=dry-run-complete importId=${importId}` +
|
|
85
|
+
` pages=${eligiblePages.length} unchanged=${unchangedSet.size}` +
|
|
86
|
+
` wikilinks-page=${resolved.counts.page} wikilinks-entity=${resolved.counts.entity}` +
|
|
87
|
+
` wikilinks-stub=${resolved.counts.stub} wikilinks-ambiguous=${ambiguities.length}` +
|
|
88
|
+
` tags=${tagCount} attachments=${attachmentCount}` +
|
|
89
|
+
` ms=${Date.now() - startedMs}\n`);
|
|
90
|
+
if (params.mode === "dry-run")
|
|
91
|
+
return plan;
|
|
92
|
+
// Commit phase — refuse if unresolved ambiguities remain.
|
|
93
|
+
const resolutions = params.resolutions ?? {};
|
|
94
|
+
const missing = ambiguities.filter((a) => !(a.id in resolutions));
|
|
95
|
+
if (missing.length > 0) {
|
|
96
|
+
throw new Error(`obsidian-vault-import commit refused: ${missing.length} unresolved ambiguities. Re-run dry-run, surface to operator, supply resolutions.`);
|
|
97
|
+
}
|
|
98
|
+
const accountDir = resolveAccountDir(params.accountId);
|
|
99
|
+
const importArchiveDir = path.join(accountDir, "archive", "obsidian", importId);
|
|
100
|
+
await fs.mkdir(importArchiveDir, { recursive: true });
|
|
101
|
+
let attachmentsCopied = 0;
|
|
102
|
+
const rows = [];
|
|
103
|
+
for (const page of eligiblePages) {
|
|
104
|
+
if (unchangedSet.has(page.obsidianPath))
|
|
105
|
+
continue;
|
|
106
|
+
const pageWikilinks = resolveWithOverrides(page, resolved.byPage.get(page.obsidianPath) ?? [], resolutions);
|
|
107
|
+
const pageAttachments = await stageAttachments(page, params.extractedDir, importArchiveDir, (n) => {
|
|
108
|
+
attachmentsCopied += n;
|
|
109
|
+
});
|
|
110
|
+
rows.push({
|
|
111
|
+
obsidianPath: page.obsidianPath,
|
|
112
|
+
title: page.title,
|
|
113
|
+
aliases: page.aliases,
|
|
114
|
+
tags: page.tags.map(normalizeTag),
|
|
115
|
+
body: page.body,
|
|
116
|
+
contentHash: page.contentHash,
|
|
117
|
+
noteDate: page.noteDate,
|
|
118
|
+
mtimeMs: page.mtimeMs,
|
|
119
|
+
wikilinks: pageWikilinks,
|
|
120
|
+
attachments: pageAttachments,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
let written = {
|
|
124
|
+
createdPages: 0,
|
|
125
|
+
mergedPages: 0,
|
|
126
|
+
createdTags: 0,
|
|
127
|
+
createdTagEdges: 0,
|
|
128
|
+
createdAttachments: 0,
|
|
129
|
+
createdAttachmentEdges: 0,
|
|
130
|
+
createdWikilinkEdges: 0,
|
|
131
|
+
};
|
|
132
|
+
const errors = [];
|
|
133
|
+
if (rows.length > 0) {
|
|
134
|
+
const result = await memoryArchiveWrite({
|
|
135
|
+
archiveType: "obsidian-vault",
|
|
136
|
+
ownerNodeId: params.ownerNodeId,
|
|
137
|
+
accountId: params.accountId,
|
|
138
|
+
rows,
|
|
139
|
+
sessionId: params.sessionId,
|
|
140
|
+
});
|
|
141
|
+
written = {
|
|
142
|
+
createdPages: result.counters.createdPages ?? 0,
|
|
143
|
+
mergedPages: result.counters.mergedPages ?? 0,
|
|
144
|
+
createdTags: result.counters.createdTags ?? 0,
|
|
145
|
+
createdTagEdges: result.counters.createdTagEdges ?? 0,
|
|
146
|
+
createdAttachments: result.counters.createdAttachments ?? 0,
|
|
147
|
+
createdAttachmentEdges: result.counters.createdAttachmentEdges ?? 0,
|
|
148
|
+
createdWikilinkEdges: result.counters.createdWikilinkEdges ?? 0,
|
|
149
|
+
};
|
|
150
|
+
errors.push(...result.errors);
|
|
151
|
+
}
|
|
152
|
+
const elapsedMs = Date.now() - startedMs;
|
|
153
|
+
const observabilityTag = `[obsidian-import] event=commit-complete importId=${importId}` +
|
|
154
|
+
` pages=${eligiblePages.length} written=${rows.length} skipped=${unchangedSet.size}` +
|
|
155
|
+
` wikilinks=${written.createdWikilinkEdges} tags=${written.createdTags}` +
|
|
156
|
+
` attachments=${attachmentsCopied} errors=${errors.length} ms=${elapsedMs}`;
|
|
157
|
+
process.stderr.write(observabilityTag + "\n");
|
|
158
|
+
return {
|
|
159
|
+
...plan,
|
|
160
|
+
written,
|
|
161
|
+
attachmentsCopied,
|
|
162
|
+
errors,
|
|
163
|
+
observabilityTag,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Helpers
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
async function assertExtractedDir(extractedDir) {
|
|
170
|
+
if (!extractedDir || !path.isAbsolute(extractedDir)) {
|
|
171
|
+
throw new Error(`obsidian-vault-import: extractedDir must be an absolute path; got "${extractedDir}".`);
|
|
172
|
+
}
|
|
173
|
+
const stat = await fs.stat(extractedDir).catch(() => null);
|
|
174
|
+
if (!stat || !stat.isDirectory()) {
|
|
175
|
+
throw new Error(`obsidian-vault-import: extractedDir does not exist or is not a directory: ${extractedDir}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function toEpochMs(modifiedSince) {
|
|
179
|
+
if (!modifiedSince)
|
|
180
|
+
return undefined;
|
|
181
|
+
if (/^\d+$/.test(modifiedSince))
|
|
182
|
+
return Number.parseInt(modifiedSince, 10);
|
|
183
|
+
const t = Date.parse(modifiedSince);
|
|
184
|
+
return Number.isFinite(t) ? t : undefined;
|
|
185
|
+
}
|
|
186
|
+
function countDistinct(values) {
|
|
187
|
+
return new Set(values.filter(Boolean)).size;
|
|
188
|
+
}
|
|
189
|
+
function resolveAccountDir(accountId) {
|
|
190
|
+
// Same convention as memory plugin's attachment-store: lives under the
|
|
191
|
+
// configured DATA_ROOT/accounts/<accountId>/. If neither env is set we
|
|
192
|
+
// throw — fail loud rather than write attachments to an unexpected path.
|
|
193
|
+
const root = process.env.MAXY_DATA_ROOT ??
|
|
194
|
+
process.env.DATA_ROOT ??
|
|
195
|
+
process.env.PLATFORM_DATA_ROOT;
|
|
196
|
+
if (!root) {
|
|
197
|
+
throw new Error("obsidian-vault-import: data root env (MAXY_DATA_ROOT / DATA_ROOT / PLATFORM_DATA_ROOT) is not set; cannot resolve attachment archive directory.");
|
|
198
|
+
}
|
|
199
|
+
return path.join(root, "accounts", accountId);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Build the resolution plan for every wikilink in every eligible page.
|
|
203
|
+
*
|
|
204
|
+
* Resolution order:
|
|
205
|
+
* 1. Intra-vault page (title or alias) — if unique, page target.
|
|
206
|
+
* 2. Existing entity fuzzy match against :Person/:Organization/:Concept
|
|
207
|
+
* with name distance ≤ FUZZY_MATCH_THRESHOLD — if unique, entity target.
|
|
208
|
+
* 3. Otherwise, stub target (the handler creates a :Concept stub at write).
|
|
209
|
+
*
|
|
210
|
+
* Ambiguity: both an intra-vault page AND an existing entity match; or
|
|
211
|
+
* multiple intra-vault candidates; or ≥2 entity candidates within
|
|
212
|
+
* threshold. Stub-only matches are NOT ambiguities — we simply create the
|
|
213
|
+
* stub.
|
|
214
|
+
*/
|
|
215
|
+
async function resolveAllWikilinks(pages, index, knownPaths, accountId, session) {
|
|
216
|
+
const distinctTargets = new Set();
|
|
217
|
+
for (const p of pages) {
|
|
218
|
+
for (const wl of p.wikilinks)
|
|
219
|
+
distinctTargets.add(wl.target);
|
|
220
|
+
}
|
|
221
|
+
const entityIndex = await loadEntityIndex(session, accountId, distinctTargets);
|
|
222
|
+
const byPage = new Map();
|
|
223
|
+
const ambiguities = [];
|
|
224
|
+
const counts = { page: 0, entity: 0, stub: 0 };
|
|
225
|
+
let ambiguityCounter = 0;
|
|
226
|
+
for (const page of pages) {
|
|
227
|
+
const resolved = [];
|
|
228
|
+
for (const wl of page.wikilinks) {
|
|
229
|
+
const pageHits = resolveWikilinkInVault(wl.target, index, knownPaths);
|
|
230
|
+
const entityHits = lookupEntities(wl.target, entityIndex);
|
|
231
|
+
const decision = decideResolution(wl, pageHits, entityHits);
|
|
232
|
+
if (decision.kind === "ambiguous") {
|
|
233
|
+
ambiguityCounter++;
|
|
234
|
+
const id = `amb-${ambiguityCounter}`;
|
|
235
|
+
ambiguities.push({
|
|
236
|
+
id,
|
|
237
|
+
fromPath: page.obsidianPath,
|
|
238
|
+
target: wl.target,
|
|
239
|
+
pageCandidates: decision.pageCandidates,
|
|
240
|
+
entityCandidates: decision.entityCandidates,
|
|
241
|
+
});
|
|
242
|
+
// Provisional resolution for the dry-run summary: stub, until
|
|
243
|
+
// the operator decides. The commit phase overrides via resolutions.
|
|
244
|
+
resolved.push(toResolvedWikilink(wl, { kind: "stub", name: wl.target }, id));
|
|
245
|
+
counts.stub++;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
resolved.push(toResolvedWikilink(wl, decision.target));
|
|
249
|
+
counts[decision.target.kind]++;
|
|
250
|
+
}
|
|
251
|
+
byPage.set(page.obsidianPath, resolved);
|
|
252
|
+
}
|
|
253
|
+
return { byPage, ambiguities, counts };
|
|
254
|
+
}
|
|
255
|
+
async function loadEntityIndex(session, accountId, distinctTargets) {
|
|
256
|
+
if (distinctTargets.size === 0) {
|
|
257
|
+
return { byName: new Map(), allNames: [] };
|
|
258
|
+
}
|
|
259
|
+
const result = await session.run(`MATCH (n)
|
|
260
|
+
WHERE n.accountId = $accountId
|
|
261
|
+
AND (n:Person OR n:Organization OR n:Concept)
|
|
262
|
+
AND NOT n:Trashed
|
|
263
|
+
AND n.name IS NOT NULL
|
|
264
|
+
RETURN elementId(n) AS nodeId, labels(n) AS labels, n.name AS name
|
|
265
|
+
LIMIT 50000`, { accountId });
|
|
266
|
+
const allNames = [];
|
|
267
|
+
const byName = new Map();
|
|
268
|
+
for (const rec of result.records) {
|
|
269
|
+
const labels = rec.get("labels");
|
|
270
|
+
const primary = labels.find((l) => l === "Person" || l === "Organization" || l === "Concept") ?? labels[0];
|
|
271
|
+
const entry = {
|
|
272
|
+
nodeId: rec.get("nodeId"),
|
|
273
|
+
label: primary,
|
|
274
|
+
name: rec.get("name"),
|
|
275
|
+
};
|
|
276
|
+
allNames.push(entry);
|
|
277
|
+
const key = entry.name.toLowerCase();
|
|
278
|
+
const arr = byName.get(key);
|
|
279
|
+
if (arr)
|
|
280
|
+
arr.push(entry);
|
|
281
|
+
else
|
|
282
|
+
byName.set(key, [entry]);
|
|
283
|
+
}
|
|
284
|
+
return { byName, allNames };
|
|
285
|
+
}
|
|
286
|
+
function lookupEntities(target, index) {
|
|
287
|
+
const t = target.toLowerCase().trim();
|
|
288
|
+
if (!t)
|
|
289
|
+
return [];
|
|
290
|
+
const exact = index.byName.get(t);
|
|
291
|
+
if (exact && exact.length > 0) {
|
|
292
|
+
return exact.map((e) => ({ ...e, distance: 0 }));
|
|
293
|
+
}
|
|
294
|
+
const out = [];
|
|
295
|
+
for (const entry of index.allNames) {
|
|
296
|
+
const d = levenshtein(t, entry.name.toLowerCase());
|
|
297
|
+
if (d <= FUZZY_MATCH_THRESHOLD) {
|
|
298
|
+
out.push({ ...entry, distance: d });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
out.sort((a, b) => a.distance - b.distance);
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
function decideResolution(wl, pageHits, entityHits) {
|
|
305
|
+
// Exact entity (distance 0) is treated as a strong hit alongside any page hit.
|
|
306
|
+
const exactEntities = entityHits.filter((e) => e.distance === 0);
|
|
307
|
+
if (pageHits.length === 1 && exactEntities.length === 0 && entityHits.length === 0) {
|
|
308
|
+
return { kind: "resolved", target: { kind: "page", obsidianPath: pageHits[0] } };
|
|
309
|
+
}
|
|
310
|
+
if (pageHits.length === 0 && exactEntities.length === 1) {
|
|
311
|
+
return {
|
|
312
|
+
kind: "resolved",
|
|
313
|
+
target: { kind: "entity", nodeId: exactEntities[0].nodeId, nodeLabel: exactEntities[0].label },
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
// Two or more competing categories or candidates → ambiguous.
|
|
317
|
+
if (pageHits.length >= 1 && exactEntities.length >= 1) {
|
|
318
|
+
return { kind: "ambiguous", pageCandidates: pageHits, entityCandidates: entityHits };
|
|
319
|
+
}
|
|
320
|
+
if (pageHits.length >= 2) {
|
|
321
|
+
return { kind: "ambiguous", pageCandidates: pageHits, entityCandidates: [] };
|
|
322
|
+
}
|
|
323
|
+
if (exactEntities.length >= 2) {
|
|
324
|
+
return { kind: "ambiguous", pageCandidates: [], entityCandidates: exactEntities };
|
|
325
|
+
}
|
|
326
|
+
// Only fuzzy entity matches (distance > 0). Single fuzzy hit → resolve.
|
|
327
|
+
// Multiple fuzzy hits → ambiguous.
|
|
328
|
+
if (pageHits.length === 0 && entityHits.length === 1) {
|
|
329
|
+
return {
|
|
330
|
+
kind: "resolved",
|
|
331
|
+
target: { kind: "entity", nodeId: entityHits[0].nodeId, nodeLabel: entityHits[0].label },
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
if (pageHits.length === 0 && entityHits.length >= 2) {
|
|
335
|
+
return { kind: "ambiguous", pageCandidates: [], entityCandidates: entityHits };
|
|
336
|
+
}
|
|
337
|
+
// No hits anywhere → stub.
|
|
338
|
+
return { kind: "resolved", target: { kind: "stub", name: wl.target } };
|
|
339
|
+
}
|
|
340
|
+
function toResolvedWikilink(wl, target, ambiguityId) {
|
|
341
|
+
return {
|
|
342
|
+
linkText: wl.target,
|
|
343
|
+
alias: wl.alias,
|
|
344
|
+
anchor: wl.anchor,
|
|
345
|
+
target,
|
|
346
|
+
...(ambiguityId ? { _ambiguityId: ambiguityId } : {}),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function resolveWithOverrides(page, resolvedForPage, resolutions) {
|
|
350
|
+
return resolvedForPage.map((wl) => {
|
|
351
|
+
const tagged = wl;
|
|
352
|
+
if (!tagged._ambiguityId)
|
|
353
|
+
return wl;
|
|
354
|
+
const decision = resolutions[tagged._ambiguityId];
|
|
355
|
+
if (!decision)
|
|
356
|
+
return wl;
|
|
357
|
+
if (decision.kind === "page") {
|
|
358
|
+
return { ...wl, target: { kind: "page", obsidianPath: decision.obsidianPath } };
|
|
359
|
+
}
|
|
360
|
+
if (decision.kind === "entity") {
|
|
361
|
+
// nodeLabel is not strictly required by the Cypher (elementId scopes
|
|
362
|
+
// by accountId guard); pass empty string when not known.
|
|
363
|
+
return { ...wl, target: { kind: "entity", nodeId: decision.nodeId, nodeLabel: "" } };
|
|
364
|
+
}
|
|
365
|
+
return { ...wl, target: { kind: "stub", name: wl.linkText } };
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
async function findUnchangedPages(session, accountId, pages) {
|
|
369
|
+
if (pages.length === 0)
|
|
370
|
+
return new Set();
|
|
371
|
+
const payload = pages.map((p) => ({
|
|
372
|
+
obsidianPath: p.obsidianPath,
|
|
373
|
+
contentHash: p.contentHash,
|
|
374
|
+
}));
|
|
375
|
+
const result = await session.run(`UNWIND $payload AS row
|
|
376
|
+
MATCH (k:KnowledgeDocument {accountId: $accountId, obsidianPath: row.obsidianPath})
|
|
377
|
+
WHERE k.contentHash = row.contentHash AND NOT k:Trashed
|
|
378
|
+
RETURN k.obsidianPath AS p`, { accountId, payload });
|
|
379
|
+
const out = new Set();
|
|
380
|
+
for (const rec of result.records)
|
|
381
|
+
out.add(rec.get("p"));
|
|
382
|
+
return out;
|
|
383
|
+
}
|
|
384
|
+
async function stageAttachments(page, vaultRoot, importArchiveDir, onCopied) {
|
|
385
|
+
const staged = [];
|
|
386
|
+
const seen = new Set();
|
|
387
|
+
for (const att of page.attachments) {
|
|
388
|
+
if (seen.has(att.resolvedPath))
|
|
389
|
+
continue;
|
|
390
|
+
seen.add(att.resolvedPath);
|
|
391
|
+
const src = await findAttachmentSource(vaultRoot, page.obsidianPath, att);
|
|
392
|
+
if (!src) {
|
|
393
|
+
process.stderr.write(`[obsidian-import] event=attachment-missing page=${page.obsidianPath} path=${att.resolvedPath}\n`);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
const safeName = sanitizeArchiveName(src.relPath);
|
|
397
|
+
const dest = path.join(importArchiveDir, safeName);
|
|
398
|
+
const destDir = path.dirname(dest);
|
|
399
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
400
|
+
try {
|
|
401
|
+
await fs.copyFile(src.absPath, dest);
|
|
402
|
+
onCopied(1);
|
|
403
|
+
}
|
|
404
|
+
catch (err) {
|
|
405
|
+
process.stderr.write(`[obsidian-import] event=attachment-copy-failed page=${page.obsidianPath} path=${att.resolvedPath} reason=${err instanceof Error ? err.message : String(err)}\n`);
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
const ext = path.extname(src.relPath).toLowerCase();
|
|
409
|
+
staged.push({
|
|
410
|
+
rawPath: att.rawPath,
|
|
411
|
+
archivePath: dest,
|
|
412
|
+
encodingFormat: SUPPORTED_ATTACHMENT_MIME[ext] ?? "application/octet-stream",
|
|
413
|
+
alt: att.alt,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
return staged;
|
|
417
|
+
}
|
|
418
|
+
async function findAttachmentSource(vaultRoot, pagePath, att) {
|
|
419
|
+
// 1. Vault-root-relative as written.
|
|
420
|
+
const candidates = [att.resolvedPath];
|
|
421
|
+
// 2. Page-relative.
|
|
422
|
+
candidates.push(path.posix.join(path.posix.dirname(pagePath), att.resolvedPath));
|
|
423
|
+
for (const rel of candidates) {
|
|
424
|
+
const abs = path.join(vaultRoot, rel.split("/").join(path.sep));
|
|
425
|
+
try {
|
|
426
|
+
const stat = await fs.stat(abs);
|
|
427
|
+
if (stat.isFile())
|
|
428
|
+
return { absPath: abs, relPath: rel };
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
// try next candidate
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// 3. Bare filename — search the vault for a single match (typical when
|
|
435
|
+
// operator stores attachments in a default folder Obsidian inserts by name).
|
|
436
|
+
const basename = path.posix.basename(att.resolvedPath);
|
|
437
|
+
if (!basename.includes("/")) {
|
|
438
|
+
const hit = await searchByBasename(vaultRoot, basename);
|
|
439
|
+
if (hit)
|
|
440
|
+
return hit;
|
|
441
|
+
}
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
async function searchByBasename(root, basename) {
|
|
445
|
+
const queue = [root];
|
|
446
|
+
while (queue.length > 0) {
|
|
447
|
+
const dir = queue.shift();
|
|
448
|
+
let entries;
|
|
449
|
+
try {
|
|
450
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
for (const entry of entries) {
|
|
456
|
+
if (entry.name.startsWith("."))
|
|
457
|
+
continue;
|
|
458
|
+
const abs = path.join(dir, entry.name);
|
|
459
|
+
if (entry.isDirectory()) {
|
|
460
|
+
queue.push(abs);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (entry.isFile() && entry.name === basename) {
|
|
464
|
+
const rel = path.relative(root, abs).split(path.sep).join("/");
|
|
465
|
+
return { absPath: abs, relPath: rel };
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
function sanitizeArchiveName(rel) {
|
|
472
|
+
return rel
|
|
473
|
+
.split("/")
|
|
474
|
+
.filter((seg) => seg && seg !== "." && seg !== "..")
|
|
475
|
+
.join("/");
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=obsidian-vault-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-vault-import.js","sourceRoot":"","sources":["../../src/tools/obsidian-vault-import.ts"],"names":[],"mappings":"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"}
|