@rubytech/create-maxy-code 0.1.132 → 0.1.140
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/__tests__/installer-specialist-registration.test.js +5 -40
- package/dist/index.js +24 -28
- package/dist/specialist-registration.js +0 -15
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -1
- package/payload/platform/lib/graph-search/dist/boosts.d.ts +39 -0
- package/payload/platform/lib/graph-search/dist/boosts.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/boosts.js +57 -0
- package/payload/platform/lib/graph-search/dist/boosts.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/dedup.d.ts +29 -0
- package/payload/platform/lib/graph-search/dist/dedup.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/dedup.js +97 -0
- package/payload/platform/lib/graph-search/dist/dedup.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/index.d.ts +70 -8
- package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-search/dist/index.js +323 -62
- package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-search/dist/query-expansion.d.ts +37 -0
- package/payload/platform/lib/graph-search/dist/query-expansion.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/query-expansion.js +101 -0
- package/payload/platform/lib/graph-search/dist/query-expansion.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/route.d.ts +29 -0
- package/payload/platform/lib/graph-search/dist/route.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/route.js +53 -0
- package/payload/platform/lib/graph-search/dist/route.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts +31 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.js +57 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.js.map +1 -0
- package/payload/platform/lib/graph-search/src/__tests__/boosts.test.ts +59 -0
- package/payload/platform/lib/graph-search/src/__tests__/dedup.test.ts +83 -0
- package/payload/platform/lib/graph-search/src/__tests__/query-expansion.test.ts +96 -0
- package/payload/platform/lib/graph-search/src/__tests__/route.test.ts +62 -0
- package/payload/platform/lib/graph-search/src/__tests__/rrf-fusion.test.ts +39 -0
- package/payload/platform/lib/graph-search/src/boosts.ts +61 -0
- package/payload/platform/lib/graph-search/src/dedup.ts +108 -0
- package/payload/platform/lib/graph-search/src/index.ts +407 -65
- package/payload/platform/lib/graph-search/src/query-expansion.ts +129 -0
- package/payload/platform/lib/graph-search/src/route.ts +70 -0
- package/payload/platform/lib/graph-search/src/rrf-fusion.ts +62 -0
- 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 +86 -1
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +10 -0
- package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +4 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js +6 -4
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/docs/references/internals.md +36 -10
- package/payload/platform/plugins/docs/references/neo4j.md +63 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +2 -0
- package/payload/platform/plugins/docs/references/session-retrospective.md +11 -4
- package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js +2 -2
- package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js.map +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +3 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +203 -7
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js +25 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js +70 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +50 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts +33 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js +99 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +21 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +24 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts +13 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js +151 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +55 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js +290 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts +19 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +102 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +18 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +64 -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 +258 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +14 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +29 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +22 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +31 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +182 -50
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +76 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-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/mcp/dist/tools/session-retrospective-skip-rate.d.ts +30 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js +129 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +72 -0
- package/payload/platform/plugins/memory/mcp/scripts/generate-edge-docs.ts +75 -0
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -0
- package/payload/platform/plugins/memory/references/schema-base.md +44 -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 +110 -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 +81 -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/scripts/seed-neo4j.sh +49 -0
- package/payload/platform/templates/agents/admin/IDENTITY.md +4 -3
- package/payload/platform/templates/specialists/agents/database-operator.md +21 -1
- package/payload/server/{adminuser-self-heal-QAWOZ3JV.js → adminuser-self-heal-YC47O34W.js} +2 -1
- package/payload/server/{chunk-JSBRDJBE.js → chunk-HYQNUVGO.js} +9 -1
- package/payload/server/{chunk-HCYM5FLU.js → chunk-T3DJD5QR.js} +3 -1
- package/payload/server/maxy-edge.js +3 -2
- package/payload/server/public/assets/{admin-FcRHAL-3.js → admin-BM9aXUUh.js} +1 -1
- package/payload/server/public/assets/{data-Ds37mflX.js → data-Ds2ECtfP.js} +1 -1
- package/payload/server/public/assets/{graph-CmWRhaiS.js → graph-BzxObKMM.js} +1 -1
- package/payload/server/public/assets/{graph-labels-Ch2r00Gt.js → graph-labels-Dwgep_nr.js} +1 -1
- package/payload/server/public/assets/{page-BcHhJXUt.js → page-BlkBsjP2.js} +1 -1
- package/payload/server/public/assets/page-h_SA5SVQ.js +51 -0
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/graph.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/server.js +803 -76
- package/payload/server/public/assets/page-BOtNny_4.js +0 -51
|
@@ -1,44 +1,72 @@
|
|
|
1
1
|
import { getSession } from "../lib/neo4j.js";
|
|
2
2
|
import { embed } from "../lib/embeddings.js";
|
|
3
3
|
import { buildTextRepresentation } from "./memory-write.js";
|
|
4
|
-
import { checkGraphWriteGate } from "../lib/graph-write-gate.js";
|
|
4
|
+
import { checkGraphWriteGate, checkPropertyWriteGate, COMPILED_TRUTH_MAX_CHARS, } from "../lib/graph-write-gate.js";
|
|
5
5
|
import { checkLabelOriginGate } from "../lib/label-origin-gate.js";
|
|
6
6
|
import { withWriteEvent, pickName } from "../lib/log-ingest.js";
|
|
7
|
+
import { rewriteCompiledTruth, } from "../lib/compiled-truth-rewriter.js";
|
|
8
|
+
/** Stripped silently — operator can't update these via the agent. */
|
|
9
|
+
const RESTRICTED_KEYS = new Set(["embedding", "accountId", "createdAt", "createdOn"]);
|
|
10
|
+
/** Loud-fail keys — write attempts throw rather than silently strip (Task 306). */
|
|
11
|
+
const SYSTEM_MANAGED_KEYS = new Set([
|
|
12
|
+
"compiledTruth",
|
|
13
|
+
"compiledTruthUpdatedAt",
|
|
14
|
+
"compiledTruthSource",
|
|
15
|
+
]);
|
|
16
|
+
const OPERATOR_COOLDOWN_MS = 7 * 24 * 60 * 60 * 1000;
|
|
17
|
+
const REWRITER_EVENT_LIMIT = 10;
|
|
18
|
+
const TIMELINE_SUBJECT_LABELS = new Set(["Person", "Organization", "Concept"]);
|
|
7
19
|
export async function memoryUpdate(params) {
|
|
8
20
|
const nameHint = pickName(params.properties);
|
|
9
21
|
return withWriteEvent({ tool: "memory-update", accountId: params.accountId, name: nameHint }, () => memoryUpdateImpl(params), (r) => ({ elementId: r.nodeId, labels: r.labels, name: nameHint }));
|
|
10
22
|
}
|
|
11
23
|
async function memoryUpdateImpl(params) {
|
|
12
|
-
const { nodeId, properties, accountId, createdBy } = params;
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
const { nodeId, properties, accountId, createdBy, rewriteCompiledTruth: doRewrite, forceRewrite } = params;
|
|
25
|
+
// Loud-fail on system-managed keys (Task 306). Silent strip is a known
|
|
26
|
+
// failure class — the caller thinks the update landed, agents lose track
|
|
27
|
+
// of writer identity, compiledTruth integrity breaks.
|
|
28
|
+
for (const key of Object.keys(properties)) {
|
|
29
|
+
if (SYSTEM_MANAGED_KEYS.has(key)) {
|
|
30
|
+
throw new Error(`Update blocked (system-managed-key): '${key}' cannot be set directly. ` +
|
|
31
|
+
`Use memory-update with rewriteCompiledTruth:true to recompute compiledTruth.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (Object.keys(properties).length === 0 && !doRewrite) {
|
|
35
|
+
throw new Error("No properties to update — provide at least one property or rewriteCompiledTruth:true.");
|
|
36
|
+
}
|
|
37
|
+
// Property-level cap. compiledTruth direct-write is blocked above; this
|
|
38
|
+
// covers the case where a future property carries the same cap doctrine.
|
|
39
|
+
const propGate = checkPropertyWriteGate({ properties });
|
|
40
|
+
if (!propGate.ok) {
|
|
41
|
+
throw new Error(`Update blocked (${propGate.reason}): ${propGate.message}`);
|
|
15
42
|
}
|
|
16
|
-
// Filter
|
|
17
|
-
const restricted = new Set(["embedding", "accountId", "createdAt", "createdOn"]);
|
|
43
|
+
// Filter restricted keys (silently — operator can't update these).
|
|
18
44
|
const safeProps = {};
|
|
19
45
|
for (const [key, value] of Object.entries(properties)) {
|
|
20
|
-
if (!
|
|
46
|
+
if (!RESTRICTED_KEYS.has(key))
|
|
21
47
|
safeProps[key] = value;
|
|
22
|
-
}
|
|
23
48
|
}
|
|
24
|
-
if (Object.keys(safeProps).length === 0) {
|
|
49
|
+
if (Object.keys(safeProps).length === 0 && !doRewrite) {
|
|
25
50
|
throw new Error("All provided properties are restricted and cannot be updated.");
|
|
26
51
|
}
|
|
27
52
|
const session = getSession();
|
|
28
53
|
try {
|
|
29
|
-
// fetch the target node's labels
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
// safe and simpler than encoding the exemption inside the update cypher.
|
|
54
|
+
// fetch the target node's labels + compiled-truth state up front. Labels
|
|
55
|
+
// don't mutate on existing nodes; the compiled-truth state is read so the
|
|
56
|
+
// rewriter (if invoked) can enforce the operator cooldown.
|
|
33
57
|
const labelResult = await session.run(`MATCH (n) WHERE elementId(n) = $nodeId AND n.accountId = $accountId
|
|
34
|
-
RETURN labels(n) AS nodeLabels
|
|
58
|
+
RETURN labels(n) AS nodeLabels,
|
|
59
|
+
n.compiledTruth AS compiledTruth,
|
|
60
|
+
n.compiledTruthSource AS compiledTruthSource,
|
|
61
|
+
n.compiledTruthUpdatedAt AS compiledTruthUpdatedAt,
|
|
62
|
+
n.name AS name`, { nodeId, accountId });
|
|
35
63
|
if (labelResult.records.length === 0) {
|
|
36
64
|
throw new Error(`Node not found or not owned by this account (ID: ${nodeId}).`);
|
|
37
65
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
//
|
|
66
|
+
const labelRecord = labelResult.records[0];
|
|
67
|
+
const targetLabels = labelRecord.get("nodeLabels");
|
|
68
|
+
// Task 350 + Task 306: refuse agent-origin property mutations against the
|
|
69
|
+
// per-account root :LocalBusiness.
|
|
42
70
|
const origin = checkLabelOriginGate({ labels: targetLabels, createdBy, accountId, tool: "memory-update" });
|
|
43
71
|
if (!origin.ok) {
|
|
44
72
|
throw new Error(`Update blocked (${origin.reason}): ${origin.message}`);
|
|
@@ -47,44 +75,148 @@ async function memoryUpdateImpl(params) {
|
|
|
47
75
|
if (!gate.ok) {
|
|
48
76
|
throw new Error(`Update blocked (${gate.reason}): ${gate.message}`);
|
|
49
77
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
let rewriterOutcome;
|
|
79
|
+
// ----- Property update branch -----
|
|
80
|
+
let updatedNodeId = nodeId;
|
|
81
|
+
let nodeLabels = targetLabels;
|
|
82
|
+
let allProps = {};
|
|
83
|
+
if (Object.keys(safeProps).length > 0) {
|
|
84
|
+
const updateQuery = `
|
|
85
|
+
MATCH (n)
|
|
86
|
+
WHERE elementId(n) = $nodeId AND n.accountId = $accountId
|
|
87
|
+
SET n += $props, n.updatedAt = $updatedAt
|
|
88
|
+
RETURN elementId(n) AS nodeId, labels(n) AS nodeLabels, properties(n) AS allProps
|
|
89
|
+
`;
|
|
90
|
+
const result = await session.run(updateQuery, {
|
|
91
|
+
nodeId,
|
|
92
|
+
accountId,
|
|
93
|
+
updatedAt: new Date().toISOString(),
|
|
94
|
+
props: safeProps,
|
|
95
|
+
});
|
|
96
|
+
if (result.records.length === 0) {
|
|
97
|
+
throw new Error(`Node not found or not owned by this account (ID: ${nodeId}).`);
|
|
98
|
+
}
|
|
99
|
+
const record = result.records[0];
|
|
100
|
+
updatedNodeId = record.get("nodeId");
|
|
101
|
+
nodeLabels = record.get("nodeLabels");
|
|
102
|
+
allProps = record.get("allProps");
|
|
103
|
+
// Re-embed from updated properties
|
|
104
|
+
const propsForEmbed = { ...allProps };
|
|
105
|
+
delete propsForEmbed.embedding;
|
|
106
|
+
delete propsForEmbed.accountId;
|
|
107
|
+
try {
|
|
108
|
+
const textForEmbedding = buildTextRepresentation(nodeLabels, propsForEmbed);
|
|
109
|
+
const embedding = await embed(textForEmbedding);
|
|
110
|
+
await session.run(`MATCH (n) WHERE elementId(n) = $nodeId SET n.embedding = $embedding`, { nodeId: updatedNodeId, embedding });
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Properties were updated successfully — embedding re-computation failed.
|
|
114
|
+
// Stale embedding is acceptable; the node remains searchable with the old vector.
|
|
115
|
+
}
|
|
65
116
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// Re-embed from updated properties
|
|
71
|
-
const propsForEmbed = { ...allProps };
|
|
72
|
-
delete propsForEmbed.embedding;
|
|
73
|
-
delete propsForEmbed.accountId;
|
|
74
|
-
try {
|
|
75
|
-
const textForEmbedding = buildTextRepresentation(nodeLabels, propsForEmbed);
|
|
76
|
-
const embedding = await embed(textForEmbedding);
|
|
77
|
-
await session.run(`MATCH (n) WHERE elementId(n) = $nodeId SET n.embedding = $embedding`, { nodeId: updatedNodeId, embedding });
|
|
117
|
+
else {
|
|
118
|
+
// No property update; still need allProps for the rewriter context.
|
|
119
|
+
const probe = await session.run(`MATCH (n) WHERE elementId(n) = $nodeId RETURN properties(n) AS allProps`, { nodeId });
|
|
120
|
+
allProps = probe.records[0].get("allProps");
|
|
78
121
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
122
|
+
// ----- Rewriter branch (Task 306) -----
|
|
123
|
+
if (doRewrite) {
|
|
124
|
+
const isSubject = targetLabels.some((l) => TIMELINE_SUBJECT_LABELS.has(l));
|
|
125
|
+
if (!isSubject) {
|
|
126
|
+
throw new Error(`rewriteCompiledTruth is only valid on :Person / :Organization / :Concept. ` +
|
|
127
|
+
`Got labels: [${targetLabels.join(", ")}]`);
|
|
128
|
+
}
|
|
129
|
+
// Operator cooldown: if compiledTruthSource = 'operator' and the last
|
|
130
|
+
// update is within 7 days, refuse unless forceRewrite is set. The
|
|
131
|
+
// cooldown protects an operator-authored summary from being overwritten
|
|
132
|
+
// by the next backfill / dream-cycle pass.
|
|
133
|
+
const currentSource = labelRecord.get("compiledTruthSource");
|
|
134
|
+
const currentUpdated = labelRecord.get("compiledTruthUpdatedAt");
|
|
135
|
+
if (currentSource === "operator" &&
|
|
136
|
+
currentUpdated &&
|
|
137
|
+
!forceRewrite) {
|
|
138
|
+
const updatedMs = new Date(String(currentUpdated)).getTime();
|
|
139
|
+
const elapsed = Date.now() - updatedMs;
|
|
140
|
+
if (!Number.isNaN(updatedMs) && elapsed < OPERATOR_COOLDOWN_MS) {
|
|
141
|
+
const daysRemaining = Math.ceil((OPERATOR_COOLDOWN_MS - elapsed) / (24 * 60 * 60 * 1000));
|
|
142
|
+
console.log(`[compiled-truth-rewriter] refused nodeId=${nodeId.slice(0, 12)} ` +
|
|
143
|
+
`reason=operator-edit-cooldown daysRemaining=${daysRemaining}`);
|
|
144
|
+
return {
|
|
145
|
+
nodeId: updatedNodeId,
|
|
146
|
+
labels: nodeLabels,
|
|
147
|
+
updated: Object.keys(safeProps).length > 0,
|
|
148
|
+
rewriter: {
|
|
149
|
+
kind: "refused",
|
|
150
|
+
reason: "operator-edit-cooldown",
|
|
151
|
+
daysRemaining,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Fetch the most recent N :TimelineEvent rows.
|
|
157
|
+
const eventsResult = await session.run(`MATCH (e) WHERE elementId(e) = $nodeId
|
|
158
|
+
MATCH (e)-[:HAS_TIMELINE_EVENT]->(t:TimelineEvent)
|
|
159
|
+
RETURN toString(t.occurredAt) AS occurredAt, t.kind AS kind, t.summary AS summary
|
|
160
|
+
ORDER BY t.occurredAt DESC
|
|
161
|
+
LIMIT $limit`, { nodeId, limit: REWRITER_EVENT_LIMIT });
|
|
162
|
+
const events = eventsResult.records.map((r) => ({
|
|
163
|
+
occurredAt: r.get("occurredAt"),
|
|
164
|
+
kind: r.get("kind"),
|
|
165
|
+
summary: r.get("summary"),
|
|
166
|
+
}));
|
|
167
|
+
const subjectLabel = targetLabels.find((l) => TIMELINE_SUBJECT_LABELS.has(l));
|
|
168
|
+
const subjectName = typeof allProps.name === "string"
|
|
169
|
+
? allProps.name
|
|
170
|
+
: typeof allProps.title === "string"
|
|
171
|
+
? allProps.title
|
|
172
|
+
: "(unnamed)";
|
|
173
|
+
const currentTruth = labelRecord.get("compiledTruth") ?? "";
|
|
174
|
+
const rewrite = await rewriteCompiledTruth({
|
|
175
|
+
subjectLabel,
|
|
176
|
+
subjectName,
|
|
177
|
+
currentTruth,
|
|
178
|
+
events,
|
|
179
|
+
});
|
|
180
|
+
if (rewrite.kind === "ok") {
|
|
181
|
+
// Validate the rewriter output against the cap before writing.
|
|
182
|
+
const writeCheck = checkPropertyWriteGate({
|
|
183
|
+
properties: { compiledTruth: rewrite.compiledTruth },
|
|
184
|
+
});
|
|
185
|
+
if (!writeCheck.ok) {
|
|
186
|
+
// Should not happen — the rewriter enforces this internally — but
|
|
187
|
+
// defend the gate anyway.
|
|
188
|
+
throw new Error(`Rewriter output failed graph-write-gate: ${writeCheck.message}`);
|
|
189
|
+
}
|
|
190
|
+
await session.run(`MATCH (n) WHERE elementId(n) = $nodeId AND n.accountId = $accountId
|
|
191
|
+
SET n.compiledTruth = $truth,
|
|
192
|
+
n.compiledTruthUpdatedAt = datetime(),
|
|
193
|
+
n.compiledTruthSource = 'rewriter'`, { nodeId, accountId, truth: rewrite.compiledTruth });
|
|
194
|
+
rewriterOutcome = {
|
|
195
|
+
kind: "ok",
|
|
196
|
+
charsBefore: currentTruth.length,
|
|
197
|
+
charsAfter: rewrite.compiledTruth.length,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
else if (rewrite.kind === "refused") {
|
|
201
|
+
rewriterOutcome = { kind: "refused", reason: "no-events" };
|
|
202
|
+
}
|
|
203
|
+
else if (rewrite.kind === "too-long") {
|
|
204
|
+
rewriterOutcome = { kind: "too-long", attemptedLen: rewrite.attemptedLen };
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
rewriterOutcome = { kind: "llm-failure", cause: rewrite.fallback.cause };
|
|
208
|
+
}
|
|
83
209
|
}
|
|
84
|
-
return {
|
|
210
|
+
return {
|
|
211
|
+
nodeId: updatedNodeId,
|
|
212
|
+
labels: nodeLabels,
|
|
213
|
+
updated: Object.keys(safeProps).length > 0,
|
|
214
|
+
rewriter: rewriterOutcome,
|
|
215
|
+
};
|
|
85
216
|
}
|
|
86
217
|
finally {
|
|
87
218
|
await session.close();
|
|
88
219
|
}
|
|
89
220
|
}
|
|
221
|
+
export { COMPILED_TRUTH_MAX_CHARS };
|
|
90
222
|
//# sourceMappingURL=memory-update.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-update.js","sourceRoot":"","sources":["../../src/tools/memory-update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"memory-update.js","sourceRoot":"","sources":["../../src/tools/memory-update.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-write.d.ts","sourceRoot":"","sources":["../../src/tools/memory-write.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"memory-write.d.ts","sourceRoot":"","sources":["../../src/tools/memory-write.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAO9E,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACf,MAAM,8CAA8C,CAAC;AAEtD,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6HAA6H;IAC7H,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,+EAA+E;IAC/E,SAAS,EAAE,SAAS,CAAC;IACrB;;;;;;OAMG;IACH,SAAS,EAAE,YAAY,CAAC;IACxB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAOD,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAS3E;AAsRD,wFAAwF;AACxF,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GACd;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKhD;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EAAE,EAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,MAAM,CAUR"}
|
|
@@ -2,10 +2,16 @@ import { getSession } from "../lib/neo4j.js";
|
|
|
2
2
|
import { embed } from "../lib/embeddings.js";
|
|
3
3
|
import { validateWrite } from "../lib/schema-validator.js";
|
|
4
4
|
import { resolveActiveVertical } from "../lib/resolve-active-vertical.js";
|
|
5
|
-
import { checkGraphWriteGate } from "../lib/graph-write-gate.js";
|
|
5
|
+
import { checkGraphWriteGate, checkPropertyWriteGate } from "../lib/graph-write-gate.js";
|
|
6
|
+
import { extractDatedStatements } from "../lib/timeline-extractor.js";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
6
8
|
import { checkLabelOriginGate } from "../lib/label-origin-gate.js";
|
|
7
9
|
import { withWriteEvent, pickName } from "../lib/log-ingest.js";
|
|
8
10
|
import { writeNodeWithEdges, injectConversationProvenance, } from "../../../../../lib/graph-write/dist/index.js";
|
|
11
|
+
/** Subject labels that carry the compiled-truth + timeline doctrine (Task 306). */
|
|
12
|
+
const TIMELINE_SUBJECT_LABELS = ["Person", "Organization", "Concept"];
|
|
13
|
+
/** Default `compiledTruthUpdatedAt` on first write — epoch makes stale-detection trivial. */
|
|
14
|
+
const COMPILED_TRUTH_EPOCH = "1970-01-01T00:00:00Z";
|
|
9
15
|
export async function memoryWrite(params) {
|
|
10
16
|
const { labels, properties, accountId, scope, relationships, createdBy, validator, producedByTaskId } = params;
|
|
11
17
|
const nameHint = pickName(properties);
|
|
@@ -57,6 +63,13 @@ async function memoryWriteImpl(params) {
|
|
|
57
63
|
throw new Error(`Write blocked (${gate.reason}): ${gate.message}`);
|
|
58
64
|
}
|
|
59
65
|
}
|
|
66
|
+
// Property-level gate (Task 306). Refuse a write whose
|
|
67
|
+
// `compiledTruth` exceeds COMPILED_TRUTH_MAX_CHARS — this protects against
|
|
68
|
+
// operators / agents pasting in long bodies as compiled truth.
|
|
69
|
+
const propGate = checkPropertyWriteGate({ properties });
|
|
70
|
+
if (!propGate.ok) {
|
|
71
|
+
throw new Error(`Write blocked (${propGate.reason}): ${propGate.message}`);
|
|
72
|
+
}
|
|
60
73
|
const textForEmbedding = buildTextRepresentation(labels, properties);
|
|
61
74
|
const embedding = await embed(textForEmbedding);
|
|
62
75
|
const nodeProps = {
|
|
@@ -69,6 +82,21 @@ async function memoryWriteImpl(params) {
|
|
|
69
82
|
if (!properties.createdOn && !properties.createdAt) {
|
|
70
83
|
nodeProps.createdAt = new Date().toISOString();
|
|
71
84
|
}
|
|
85
|
+
// Task 306: stamp compiled-truth defaults on the three subject labels
|
|
86
|
+
// that carry the compiled-truth + timeline doctrine. New nodes start with
|
|
87
|
+
// an empty compiledTruth and an epoch updatedAt so stale-detection
|
|
88
|
+
// queries treat them as eligible for the next rewriter pass.
|
|
89
|
+
// `compiledTruthSource = "rewriter"` is the default writer; the operator
|
|
90
|
+
// override is set only when the graph UI edits the property directly.
|
|
91
|
+
const isCompiledTruthSubject = TIMELINE_SUBJECT_LABELS.some((l) => labels.includes(l));
|
|
92
|
+
if (isCompiledTruthSubject) {
|
|
93
|
+
if (nodeProps.compiledTruth === undefined)
|
|
94
|
+
nodeProps.compiledTruth = "";
|
|
95
|
+
if (nodeProps.compiledTruthUpdatedAt === undefined)
|
|
96
|
+
nodeProps.compiledTruthUpdatedAt = COMPILED_TRUTH_EPOCH;
|
|
97
|
+
if (nodeProps.compiledTruthSource === undefined)
|
|
98
|
+
nodeProps.compiledTruthSource = "rewriter";
|
|
99
|
+
}
|
|
72
100
|
// compose the inbound `:PRODUCED` edge from the active
|
|
73
101
|
// Task before delegating to the gate. We resolve the Task here (not
|
|
74
102
|
// in the gate) so we can verify accountId parity and emit a clear
|
|
@@ -117,6 +145,53 @@ async function memoryWriteImpl(params) {
|
|
|
117
145
|
relationships: resolvedRelationships,
|
|
118
146
|
createdBy,
|
|
119
147
|
});
|
|
148
|
+
// Task 306: extract dated statements from the body of compiled-truth
|
|
149
|
+
// subjects and path-anchor-MERGE :TimelineEvent rows. Strictly deterministic
|
|
150
|
+
// here; the 305 typed-edge hook upgrades `kind` from "mentioned" to a
|
|
151
|
+
// more specific value asynchronously. Failures here MUST NOT roll back
|
|
152
|
+
// the entity write — the node persisting with an empty timeline is the
|
|
153
|
+
// right degradation mode; a rewriter call on demand still works.
|
|
154
|
+
if (isCompiledTruthSubject && typeof properties.body === "string" && accountId) {
|
|
155
|
+
try {
|
|
156
|
+
const statements = extractDatedStatements(properties.body);
|
|
157
|
+
if (statements.length > 0) {
|
|
158
|
+
for (const s of statements) {
|
|
159
|
+
await session.run(`MATCH (e) WHERE elementId(e) = $entityId AND e.accountId = $accountId
|
|
160
|
+
MERGE (e)-[:HAS_TIMELINE_EVENT]->(t:TimelineEvent {timelineEventId: $id})
|
|
161
|
+
ON CREATE SET t.accountId = $accountId,
|
|
162
|
+
t.occurredAt = datetime($occurredAt),
|
|
163
|
+
t.kind = $kind,
|
|
164
|
+
t.summary = $summary,
|
|
165
|
+
t.source = $source,
|
|
166
|
+
t.matched = $matched,
|
|
167
|
+
t.createdAt = datetime(),
|
|
168
|
+
t.scope = $scope
|
|
169
|
+
RETURN elementId(t) AS timelineEventNodeId`, {
|
|
170
|
+
entityId: result.nodeId,
|
|
171
|
+
accountId,
|
|
172
|
+
id: randomUUID(),
|
|
173
|
+
occurredAt: s.occurredAt,
|
|
174
|
+
kind: "mentioned",
|
|
175
|
+
summary: s.summary,
|
|
176
|
+
source: typeof properties.sourceMessageId === "string"
|
|
177
|
+
? properties.sourceMessageId
|
|
178
|
+
: "memory-write",
|
|
179
|
+
matched: s.matched,
|
|
180
|
+
scope,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
console.log(`[timeline-extract] nodeId=${result.nodeId.slice(0, 12)} ` +
|
|
185
|
+
`subject="${properties.name ?? "?"}" dates=${statements.length} kinds=[mentioned×${statements.length}]`);
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
189
|
+
const bodyLen = properties.body.length;
|
|
190
|
+
console.error(`[timeline-extract] error nodeId=${result.nodeId.slice(0, 12)} ` +
|
|
191
|
+
`body-len=${bodyLen} error="${msg}"`);
|
|
192
|
+
// intentional swallow — entity write succeeded; timeline is opportunistic.
|
|
193
|
+
}
|
|
194
|
+
}
|
|
120
195
|
return { nodeId: result.nodeId, labels: result.labels, created: true };
|
|
121
196
|
}
|
|
122
197
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-write.js","sourceRoot":"","sources":["../../src/tools/memory-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAqB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"memory-write.js","sourceRoot":"","sources":["../../src/tools/memory-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -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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"}
|