@powerhousedao/knowledge-note 1.0.0 → 1.0.2
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/editors/health-report-editor/editor.d.ts.map +1 -1
- package/dist/editors/health-report-editor/editor.js +100 -17
- package/dist/editors/knowledge-note-editor/editor.d.ts.map +1 -1
- package/dist/editors/knowledge-note-editor/editor.js +12 -3
- package/dist/editors/knowledge-vault/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/knowledge-vault/components/GettingStarted.js +26 -7
- package/dist/editors/knowledge-vault/components/GraphView.d.ts +1 -1
- package/dist/editors/knowledge-vault/components/GraphView.d.ts.map +1 -1
- package/dist/editors/knowledge-vault/components/GraphView.js +1 -1
- package/dist/editors/knowledge-vault/components/HealthDashboard.d.ts.map +1 -1
- package/dist/editors/knowledge-vault/components/HealthDashboard.js +16 -4
- package/dist/editors/knowledge-vault/hooks/use-drive-init.d.ts.map +1 -1
- package/dist/editors/knowledge-vault/hooks/use-drive-init.js +78 -62
- package/dist/editors/moc-editor/editor.d.ts.map +1 -1
- package/dist/editors/moc-editor/editor.js +13 -4
- package/dist/editors/tension-editor/editor.d.ts.map +1 -1
- package/dist/editors/tension-editor/editor.js +60 -9
- package/dist/package.json +45 -1
- package/dist/processors/factory.d.ts.map +1 -1
- package/dist/processors/factory.js +4 -1
- package/dist/processors/graph-indexer/index.d.ts.map +1 -1
- package/dist/processors/graph-indexer/query.d.ts.map +1 -1
- package/dist/processors/graph-indexer/query.js +2 -1
- package/dist/processors/methodology-indexer/factory.d.ts +4 -0
- package/dist/processors/methodology-indexer/factory.d.ts.map +1 -0
- package/dist/processors/methodology-indexer/factory.js +23 -0
- package/dist/processors/methodology-indexer/index.d.ts +11 -0
- package/dist/processors/methodology-indexer/index.d.ts.map +1 -0
- package/dist/processors/methodology-indexer/index.js +116 -0
- package/dist/processors/methodology-indexer/migrations.d.ts +4 -0
- package/dist/processors/methodology-indexer/migrations.d.ts.map +1 -0
- package/dist/processors/methodology-indexer/migrations.js +39 -0
- package/dist/processors/methodology-indexer/query.d.ts +35 -0
- package/dist/processors/methodology-indexer/query.d.ts.map +1 -0
- package/dist/processors/methodology-indexer/query.js +114 -0
- package/dist/processors/methodology-indexer/schema.d.ts +22 -0
- package/dist/processors/methodology-indexer/schema.d.ts.map +1 -0
- package/dist/processors/methodology-indexer/schema.js +1 -0
- package/dist/style.css +15 -0
- package/dist/subgraphs/index.d.ts +1 -0
- package/dist/subgraphs/index.d.ts.map +1 -1
- package/dist/subgraphs/index.js +1 -0
- package/dist/subgraphs/knowledge-graph/subgraph.d.ts.map +1 -1
- package/dist/subgraphs/knowledge-graph/subgraph.js +45 -15
- package/dist/subgraphs/methodology/index.d.ts +2 -0
- package/dist/subgraphs/methodology/index.d.ts.map +1 -0
- package/dist/subgraphs/methodology/index.js +1 -0
- package/dist/subgraphs/methodology/subgraph.d.ts +47 -0
- package/dist/subgraphs/methodology/subgraph.d.ts.map +1 -0
- package/dist/subgraphs/methodology/subgraph.js +100 -0
- package/dist/tests/processor/graph-indexer.test.js +8 -2
- package/dist/tests/unit/knowledge-note-reducers.test.js +4 -1
- package/dist/tests/unit/lifecycle-state-machine.test.js +16 -4
- package/dist/tests/unit/moc-reducers.test.js +1 -1
- package/dist/tests/unit/pipeline-queue-reducers.test.js +10 -2
- package/package.json +45 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/health-report-editor/editor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/health-report-editor/editor.tsx"],"names":[],"mappings":"AAcA,MAAM,CAAC,OAAO,UAAU,MAAM,4CAuU7B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { DocumentToolbar } from "@powerhousedao/design-system/connect";
|
|
3
|
-
import { useSelectedHealthReportDocument
|
|
3
|
+
import { useSelectedHealthReportDocument } from "../../document-models/health-report/v1/hooks.js";
|
|
4
4
|
import { setSelectedNode, useDocumentsInSelectedDrive, } from "@powerhousedao/reactor-browser";
|
|
5
5
|
import { TOOLBAR_CLASS } from "../shared/theme-context.js";
|
|
6
6
|
const STATUS_BADGE = {
|
|
@@ -14,26 +14,103 @@ export default function Editor() {
|
|
|
14
14
|
const documents = useDocumentsInSelectedDrive();
|
|
15
15
|
const isEmpty = !state.generatedAt;
|
|
16
16
|
if (isEmpty) {
|
|
17
|
-
return (_jsx("div", { className: "min-h-screen", style: { backgroundColor: "var(--bai-bg)", color: "var(--bai-text)" }, children: _jsxs("div", { className: "mx-auto max-w-3xl", children: [_jsx(DocumentToolbar, { className: TOOLBAR_CLASS }), _jsx("div", { className: "flex h-64 items-center justify-center rounded-xl m-6", style: {
|
|
17
|
+
return (_jsx("div", { className: "min-h-screen", style: { backgroundColor: "var(--bai-bg)", color: "var(--bai-text)" }, children: _jsxs("div", { className: "mx-auto max-w-3xl", children: [_jsx(DocumentToolbar, { className: TOOLBAR_CLASS }), _jsx("div", { className: "flex h-64 items-center justify-center rounded-xl m-6", style: {
|
|
18
|
+
backgroundColor: "var(--bai-surface)",
|
|
19
|
+
border: "1px solid var(--bai-border)",
|
|
20
|
+
}, children: _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-sm", style: { color: "var(--bai-text-muted)" }, children: "No health report generated yet" }), _jsx("p", { className: "mt-1 text-xs", style: { color: "var(--bai-text-faint)" }, children: "Run /health in Claude Code to generate a vault health report" })] }) })] }) }));
|
|
18
21
|
}
|
|
19
22
|
const metrics = state.graphMetrics;
|
|
20
23
|
const checks = state.checks ?? [];
|
|
21
24
|
const recommendations = state.recommendations ?? [];
|
|
22
|
-
return (_jsx("div", { className: "min-h-screen", style: { backgroundColor: "var(--bai-bg)", color: "var(--bai-text)" }, children: _jsxs("div", { className: "mx-auto max-w-4xl", children: [_jsx(DocumentToolbar, { className: TOOLBAR_CLASS }), _jsxs("div", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-center gap-4 rounded-xl p-6", style: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
return (_jsx("div", { className: "min-h-screen", style: { backgroundColor: "var(--bai-bg)", color: "var(--bai-text)" }, children: _jsxs("div", { className: "mx-auto max-w-4xl", children: [_jsx(DocumentToolbar, { className: TOOLBAR_CLASS }), _jsxs("div", { className: "p-6 space-y-6", children: [_jsxs("div", { className: "flex items-center gap-4 rounded-xl p-6", style: {
|
|
26
|
+
backgroundColor: "var(--bai-surface)",
|
|
27
|
+
border: "1px solid var(--bai-border)",
|
|
28
|
+
}, children: [_jsx("span", { className: `rounded-full border px-4 py-1.5 text-sm font-bold ${STATUS_BADGE[state.overallStatus ?? "PASS"]}`, children: state.overallStatus }), _jsxs("div", { className: "flex-1", children: [_jsx("h1", { className: "text-xl font-bold", style: { color: "var(--bai-text)" }, children: "Vault Health" }), _jsxs("p", { className: "text-xs", style: { color: "var(--bai-text-muted)" }, children: ["Generated ", new Date(state.generatedAt).toLocaleString(), state.generatedBy && ` by ${state.generatedBy}`, state.mode && ` \u2022 ${state.mode} mode`] })] })] }), metrics && (_jsx("div", { className: "grid grid-cols-4 gap-3", children: [
|
|
29
|
+
{
|
|
30
|
+
label: "Notes",
|
|
31
|
+
value: metrics.noteCount,
|
|
32
|
+
color: "var(--bai-accent)",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: "MOCs",
|
|
36
|
+
value: metrics.mocCount,
|
|
37
|
+
color: undefined,
|
|
38
|
+
cls: "text-blue-400",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: "Edges",
|
|
42
|
+
value: metrics.connectionCount,
|
|
43
|
+
color: undefined,
|
|
44
|
+
cls: "text-emerald-400",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
label: "Density",
|
|
48
|
+
value: `${(metrics.density * 100).toFixed(1)}%`,
|
|
49
|
+
color: "var(--bai-text-secondary)",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: "Orphans",
|
|
53
|
+
value: metrics.orphanCount,
|
|
54
|
+
color: undefined,
|
|
55
|
+
cls: metrics.orphanCount > 0
|
|
56
|
+
? "text-amber-400"
|
|
57
|
+
: "text-emerald-400",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label: "Dangling",
|
|
61
|
+
value: metrics.danglingLinkCount,
|
|
62
|
+
color: undefined,
|
|
63
|
+
cls: metrics.danglingLinkCount > 0
|
|
64
|
+
? "text-red-400"
|
|
65
|
+
: "text-emerald-400",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: "Avg Links",
|
|
69
|
+
value: metrics.averageLinksPerNote.toFixed(1),
|
|
70
|
+
color: undefined,
|
|
71
|
+
cls: metrics.averageLinksPerNote < 2
|
|
72
|
+
? "text-amber-400"
|
|
73
|
+
: "text-emerald-400",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
label: "MOC Coverage",
|
|
77
|
+
value: `${(metrics.mocCoverage * 100).toFixed(0)}%`,
|
|
78
|
+
color: "var(--bai-text-tertiary)",
|
|
79
|
+
},
|
|
80
|
+
].map((m) => (_jsxs("div", { className: "rounded-xl p-4", style: {
|
|
81
|
+
backgroundColor: "var(--bai-surface)",
|
|
82
|
+
boxShadow: "0 0 0 1px var(--bai-ring)",
|
|
83
|
+
}, children: [_jsx("p", { className: `text-xl font-bold ${m.cls ?? ""}`, style: m.color ? { color: m.color } : undefined, children: m.value }), _jsx("p", { className: "text-[10px]", style: { color: "var(--bai-text-faint)" }, children: m.label })] }, m.label))) })), _jsxs("div", { className: "rounded-xl p-6", style: {
|
|
84
|
+
backgroundColor: "var(--bai-surface)",
|
|
85
|
+
border: "1px solid var(--bai-border)",
|
|
86
|
+
}, children: [_jsxs("h3", { className: "mb-3 text-xs font-semibold uppercase tracking-wider", style: { color: "var(--bai-text-muted)" }, children: ["Health Checks (", checks.length, ")"] }), checks.length === 0 ? (_jsx("p", { className: "text-sm py-4 text-center", style: { color: "var(--bai-text-faint)" }, children: "No checks recorded" })) : (_jsx("div", { className: "space-y-3", children: checks.map((check) => (_jsxs("div", { className: "rounded-lg px-4 py-3", style: {
|
|
87
|
+
backgroundColor: "var(--bai-bg)",
|
|
88
|
+
border: "1px solid var(--bai-border)",
|
|
89
|
+
}, children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("span", { className: `mt-0.5 shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-bold ${STATUS_BADGE[check.status]}`, children: check.status }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-xs font-medium", style: { color: "var(--bai-text-secondary)" }, children: check.category.replaceAll("_", " ") }), _jsx("p", { className: "mt-0.5 text-xs", style: { color: "var(--bai-text-muted)" }, children: check.message }), check.affectedItems.length > 0 &&
|
|
90
|
+
check.status !== "PASS" && (_jsxs("div", { className: "mt-1.5 flex flex-wrap gap-1", children: [check.affectedItems
|
|
91
|
+
.slice(0, 5)
|
|
92
|
+
.map((item, i) => {
|
|
93
|
+
const noteDoc = (documents ?? []).find((d) => (d.header.documentType ===
|
|
94
|
+
"bai/knowledge-note" ||
|
|
95
|
+
d.header.documentType ===
|
|
96
|
+
"bai/source") &&
|
|
33
97
|
(d.state.global.title === item ||
|
|
34
98
|
d.header.name === item));
|
|
35
|
-
return noteDoc ? (_jsx("button", { type: "button", onClick: () => setSelectedNode(noteDoc.header.id), className: "rounded px-1.5 py-0.5 text-[10px] cursor-pointer", style: {
|
|
36
|
-
|
|
99
|
+
return noteDoc ? (_jsx("button", { type: "button", onClick: () => setSelectedNode(noteDoc.header.id), className: "rounded px-1.5 py-0.5 text-[10px] cursor-pointer", style: {
|
|
100
|
+
backgroundColor: "var(--bai-hover)",
|
|
101
|
+
color: "var(--bai-accent)",
|
|
102
|
+
}, children: item.length > 50
|
|
103
|
+
? item.slice(0, 50) + "\u2026"
|
|
104
|
+
: item }, i)) : (_jsx("span", { className: "rounded px-1.5 py-0.5 text-[10px]", style: {
|
|
105
|
+
backgroundColor: "var(--bai-hover)",
|
|
106
|
+
color: "var(--bai-text-faint)",
|
|
107
|
+
}, children: item.length > 50
|
|
108
|
+
? item.slice(0, 50) + "\u2026"
|
|
109
|
+
: item }, i));
|
|
110
|
+
}), check.affectedItems.length > 5 && (_jsxs("span", { className: "text-[10px]", style: { color: "var(--bai-text-faint)" }, children: ["+", check.affectedItems.length - 5, " more"] }))] }))] })] }), check.status !== "PASS" && (_jsx(CheckGuidance, { category: check.category, affectedItems: check.affectedItems }))] }, check.id))) }))] }), recommendations.length > 0 && (_jsxs("div", { className: "rounded-xl p-6", style: {
|
|
111
|
+
backgroundColor: "var(--bai-surface)",
|
|
112
|
+
border: "1px solid var(--bai-border)",
|
|
113
|
+
}, children: [_jsxs("h3", { className: "mb-3 text-xs font-semibold uppercase tracking-wider", style: { color: "var(--bai-text-muted)" }, children: ["Recommendations (", recommendations.length, ")"] }), _jsx("ul", { className: "space-y-2", children: recommendations.map((rec, i) => (_jsxs("li", { className: "flex items-start gap-2 text-xs", style: { color: "var(--bai-text-secondary)" }, children: [_jsx("span", { className: "mt-0.5 h-1.5 w-1.5 shrink-0 rounded-full", style: { backgroundColor: "var(--bai-accent)" } }), rec] }, i))) })] }))] })] }) }));
|
|
37
114
|
}
|
|
38
115
|
const GUIDANCE = {
|
|
39
116
|
ORPHAN_DETECTION: {
|
|
@@ -77,9 +154,15 @@ const GUIDANCE = {
|
|
|
77
154
|
icon: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z",
|
|
78
155
|
},
|
|
79
156
|
};
|
|
80
|
-
function CheckGuidance({ category, affectedItems }) {
|
|
157
|
+
function CheckGuidance({ category, affectedItems, }) {
|
|
81
158
|
const guidance = GUIDANCE[category];
|
|
82
159
|
if (!guidance)
|
|
83
160
|
return null;
|
|
84
|
-
return (_jsx("div", { className: "mt-3 rounded-lg px-4 py-3", style: {
|
|
161
|
+
return (_jsx("div", { className: "mt-3 rounded-lg px-4 py-3", style: {
|
|
162
|
+
backgroundColor: "var(--bai-surface)",
|
|
163
|
+
border: "1px solid var(--bai-border)",
|
|
164
|
+
}, children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("svg", { className: "mt-0.5 h-4 w-4 shrink-0", style: { color: "var(--bai-accent)" }, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: guidance.icon }) }), _jsxs("div", { className: "flex-1 space-y-2", children: [_jsxs("div", { children: [_jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider", style: { color: "var(--bai-text-muted)" }, children: "How to fix" }), _jsx("p", { className: "mt-0.5 text-xs leading-relaxed", style: { color: "var(--bai-text-secondary)" }, children: guidance.manual })] }), _jsxs("div", { className: "flex items-center gap-2 rounded-md px-3 py-2", style: {
|
|
165
|
+
backgroundColor: "var(--bai-bg)",
|
|
166
|
+
border: "1px solid var(--bai-border)",
|
|
167
|
+
}, children: [_jsx("span", { className: "text-[10px] font-semibold", style: { color: "var(--bai-text-muted)" }, children: "AI Agent:" }), _jsx("code", { className: "text-[11px] font-mono", style: { color: "var(--bai-accent)" }, children: guidance.agent }), _jsx("span", { className: "text-[10px]", style: { color: "var(--bai-text-faint)" }, children: "in Claude Code" })] })] })] }) }));
|
|
85
168
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/knowledge-note-editor/editor.tsx"],"names":[],"mappings":"AAgCA,MAAM,CAAC,OAAO,UAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/knowledge-note-editor/editor.tsx"],"names":[],"mappings":"AAgCA,MAAM,CAAC,OAAO,UAAU,MAAM,4CA2X7B"}
|
|
@@ -64,10 +64,19 @@ export default function Editor() {
|
|
|
64
64
|
actor,
|
|
65
65
|
timestamp: ts,
|
|
66
66
|
comment,
|
|
67
|
-
})), onApprove: (id, actor, ts, comment) => dispatch(actions.approveNote({ id, actor, timestamp: ts, comment })), onReject: (id, actor, ts, comment) => dispatch(actions.rejectNote({ id, actor, timestamp: ts, comment })), onArchive: (id, actor, ts, comment) => dispatch(actions.archiveNote({ id, actor, timestamp: ts, comment })), onRestore: (id, actor, ts, comment) => dispatch(actions.restoreNote({ id, actor, timestamp: ts, comment })) }), _jsx("
|
|
68
|
-
if (e.key === "Enter")
|
|
67
|
+
})), onApprove: (id, actor, ts, comment) => dispatch(actions.approveNote({ id, actor, timestamp: ts, comment })), onReject: (id, actor, ts, comment) => dispatch(actions.rejectNote({ id, actor, timestamp: ts, comment })), onArchive: (id, actor, ts, comment) => dispatch(actions.archiveNote({ id, actor, timestamp: ts, comment })), onRestore: (id, actor, ts, comment) => dispatch(actions.restoreNote({ id, actor, timestamp: ts, comment })) }), _jsx("textarea", { defaultValue: state.title ?? "", placeholder: "Untitled Note", onBlur: (e) => handleSetTitle(e.target.value.trim()), onKeyDown: (e) => {
|
|
68
|
+
if (e.key === "Enter" && !e.shiftKey)
|
|
69
69
|
e.currentTarget.blur();
|
|
70
|
-
},
|
|
70
|
+
}, onInput: (e) => {
|
|
71
|
+
const el = e.currentTarget;
|
|
72
|
+
el.style.height = "auto";
|
|
73
|
+
el.style.height = `${el.scrollHeight}px`;
|
|
74
|
+
}, ref: (el) => {
|
|
75
|
+
if (el) {
|
|
76
|
+
el.style.height = "auto";
|
|
77
|
+
el.style.height = `${el.scrollHeight}px`;
|
|
78
|
+
}
|
|
79
|
+
}, rows: 1, className: "w-full resize-y border-0 bg-transparent text-2xl font-bold leading-snug outline-none", style: { color: "var(--bai-text)", overflow: "hidden" } })] }), _jsx("textarea", { defaultValue: state.description ?? "", placeholder: "Brief description (max 200 chars)...", maxLength: 200, rows: 2, onBlur: (e) => handleSetDescription(e.target.value.trim()), className: "w-full resize-none rounded-lg px-3 py-2 text-sm outline-none placeholder:opacity-50 focus:border-[#cba6f7]/50", style: {
|
|
71
80
|
backgroundColor: "var(--bai-bg)",
|
|
72
81
|
color: "var(--bai-text-secondary)",
|
|
73
82
|
border: "1px solid var(--bai-border)",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/DriveExplorer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA+BlD,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"DriveExplorer.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/DriveExplorer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA+BlD,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,2CA+UtD"}
|
|
@@ -14,16 +14,29 @@ function GettingStartedModal({ onClose }) {
|
|
|
14
14
|
{ id: "graph", label: "Graph & Links" },
|
|
15
15
|
{ id: "plugin", label: "AI Agent" },
|
|
16
16
|
];
|
|
17
|
-
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/60", onClick: onClose }), _jsxs("div", { className: "relative z-10 flex h-[80vh] w-[720px] max-w-[90vw] flex-col rounded-2xl shadow-2xl", style: {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/60", onClick: onClose }), _jsxs("div", { className: "relative z-10 flex h-[80vh] w-[720px] max-w-[90vw] flex-col rounded-2xl shadow-2xl", style: {
|
|
18
|
+
backgroundColor: "var(--bai-surface)",
|
|
19
|
+
border: "1px solid var(--bai-border)",
|
|
20
|
+
}, children: [_jsxs("div", { className: "flex items-center justify-between px-6 py-4", style: { borderBottom: "1px solid var(--bai-border)" }, children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-bold", style: { color: "var(--bai-text)" }, children: "Getting Started" }), _jsx("p", { className: "text-xs", style: { color: "var(--bai-text-muted)" }, children: "Learn how to use the Knowledge Vault" })] }), _jsx("button", { type: "button", onClick: onClose, className: "rounded-lg p-2 transition-colors", style: { color: "var(--bai-text-muted)" }, children: _jsx("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) })] }), _jsxs("div", { className: "flex flex-1 overflow-hidden", children: [_jsx("div", { className: "w-44 shrink-0 py-3", style: { borderRight: "1px solid var(--bai-border)" }, children: sections.map((s) => (_jsx("button", { type: "button", onClick: () => setActiveSection(s.id), className: "flex w-full px-4 py-2 text-left text-xs transition-colors", style: {
|
|
21
|
+
backgroundColor: activeSection === s.id
|
|
22
|
+
? "var(--bai-accent-soft)"
|
|
23
|
+
: "transparent",
|
|
24
|
+
color: activeSection === s.id
|
|
25
|
+
? "var(--bai-accent)"
|
|
26
|
+
: "var(--bai-text-tertiary)",
|
|
20
27
|
fontWeight: activeSection === s.id ? 500 : 400,
|
|
21
28
|
}, children: s.label }, s.id))) }), _jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-5", children: [activeSection === "overview" && _jsx(OverviewSection, {}), activeSection === "sources" && _jsx(SourcesSection, {}), activeSection === "notes" && _jsx(NotesSection, {}), activeSection === "pipeline" && _jsx(PipelineSection, {}), activeSection === "graph" && _jsx(GraphSection, {}), activeSection === "plugin" && _jsx(PluginSection, {})] })] })] })] }));
|
|
22
29
|
}
|
|
23
30
|
const H = ({ children }) => (_jsx("h3", { className: "mb-3 text-sm font-semibold", style: { color: "var(--bai-text)" }, children: children }));
|
|
24
31
|
const P = ({ children }) => (_jsx("p", { className: "mb-4 text-xs leading-relaxed", style: { color: "var(--bai-text-tertiary)" }, children: children }));
|
|
25
|
-
const Step = ({ n, title, children, }) => (_jsxs("div", { className: "mb-4 flex gap-3", children: [_jsx("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[10px] font-bold", style: {
|
|
26
|
-
|
|
32
|
+
const Step = ({ n, title, children, }) => (_jsxs("div", { className: "mb-4 flex gap-3", children: [_jsx("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[10px] font-bold", style: {
|
|
33
|
+
backgroundColor: "var(--bai-accent-soft)",
|
|
34
|
+
color: "var(--bai-accent)",
|
|
35
|
+
}, children: n }), _jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium", style: { color: "var(--bai-text)" }, children: title }), _jsx("p", { className: "mt-0.5 text-xs", style: { color: "var(--bai-text-muted)" }, children: children })] })] }));
|
|
36
|
+
const Tip = ({ children }) => (_jsx("div", { className: "mb-4 rounded-lg px-4 py-3", style: {
|
|
37
|
+
border: "1px solid var(--bai-accent-soft)",
|
|
38
|
+
backgroundColor: "var(--bai-accent-soft)",
|
|
39
|
+
}, children: _jsx("p", { className: "text-xs", style: { color: "var(--bai-accent)", opacity: 0.8 }, children: children }) }));
|
|
27
40
|
function OverviewSection() {
|
|
28
41
|
return (_jsxs("div", { children: [_jsx(H, { children: "What is the Knowledge Vault?" }), _jsx(P, { children: "A structured knowledge management system where raw content (articles, notes, transcripts) is processed into atomic claims, connected into a knowledge graph, and maintained over time." }), _jsx(H, { children: "The Navigation Tabs" }), _jsx("div", { className: "space-y-2 mb-4", children: [
|
|
29
42
|
{
|
|
@@ -62,7 +75,10 @@ function SourcesSection() {
|
|
|
62
75
|
"WEB_PAGE",
|
|
63
76
|
"BOOK_CHAPTER",
|
|
64
77
|
"MANUAL_ENTRY",
|
|
65
|
-
].map((t) => (_jsx("span", { className: "rounded px-2 py-1 text-[10px]", style: {
|
|
78
|
+
].map((t) => (_jsx("span", { className: "rounded px-2 py-1 text-[10px]", style: {
|
|
79
|
+
backgroundColor: "var(--bai-bg)",
|
|
80
|
+
color: "var(--bai-text-tertiary)",
|
|
81
|
+
}, children: t }, t))) }), _jsx(H, { children: "Source Lifecycle" }), _jsx(P, { children: "INBOX (new) \u2192 EXTRACTING (queued for AI) \u2192 EXTRACTED (claims created) \u2192 ARCHIVED (done)" }), _jsx(Tip, { children: "You can edit a source after creating it. Click \"Edit\" in the source viewer. Saving resets the status to INBOX so it can be re-processed with the updated content." }), _jsx(H, { children: "Deleting Sources" }), _jsx(P, { children: "In the Sources tab, hover over a source and click the trash icon. A confirmation dialog will appear before deletion." })] }));
|
|
66
82
|
}
|
|
67
83
|
function NotesSection() {
|
|
68
84
|
return (_jsxs("div", { children: [_jsx(H, { children: "Knowledge Notes" }), _jsx(P, { children: "Each note is an atomic claim \u2014 one idea, one point. Notes have declarative titles that read as complete sentences." }), _jsx(H, { children: "Note Structure" }), _jsx("div", { className: "space-y-1 mb-4", children: [
|
|
@@ -153,7 +169,10 @@ function GraphSection() {
|
|
|
153
169
|
].map((item) => (_jsxs("div", { className: "flex gap-2 rounded px-3 py-1.5", style: { backgroundColor: "var(--bai-bg)" }, children: [_jsx("span", { className: "shrink-0 text-[10px] font-medium w-20", style: { color: "var(--bai-text-secondary)" }, children: item.metric }), _jsx("span", { className: "text-[10px]", style: { color: "var(--bai-text-muted)" }, children: item.desc })] }, item.metric))) }), _jsx(Tip, { children: "The graph auto-syncs when notes change. If you add a link in the note editor, the graph view updates on the next tab switch." })] }));
|
|
154
170
|
}
|
|
155
171
|
function PluginSection() {
|
|
156
|
-
return (_jsxs("div", { children: [_jsx(H, { children: "AI Agent (Claude Plugin)" }), _jsx(P, { children: "The powerhouse-knowledge plugin connects Claude Code to your vault. The AI agent can extract claims, find connections, verify quality, and analyze the graph." }), _jsx(H, { children: "Setup \u2014 Local" }), _jsx(Step, { n: 1, title: "Start the reactor locally", children: "Run ph vetra --watch in your project directory. MCP is served at http://localhost:4001/mcp" }), _jsx(Step, { n: 2, title: "Open Claude Code with the plugin", children: "claude --plugin-dir ~/path/to/powerhouse-knowledge" }), _jsx(Step, { n: 3, title: "Run /setup", children: "This imports the Ars Contexta methodology (249 research claims) if not already present." }), _jsx(H, { children: "Setup \u2014 Remote Vault" }), _jsx(P, { children: "You can also connect to any remote Switchboard instance instead of running locally. Edit .mcp.json in the plugin directory to point to the remote reactor:" }), _jsxs("div", { className: "mb-4 rounded-lg px-4 py-3 font-mono text-[11px]", style: {
|
|
172
|
+
return (_jsxs("div", { children: [_jsx(H, { children: "AI Agent (Claude Plugin)" }), _jsx(P, { children: "The powerhouse-knowledge plugin connects Claude Code to your vault. The AI agent can extract claims, find connections, verify quality, and analyze the graph." }), _jsx(H, { children: "Setup \u2014 Local" }), _jsx(Step, { n: 1, title: "Start the reactor locally", children: "Run ph vetra --watch in your project directory. MCP is served at http://localhost:4001/mcp" }), _jsx(Step, { n: 2, title: "Open Claude Code with the plugin", children: "claude --plugin-dir ~/path/to/powerhouse-knowledge" }), _jsx(Step, { n: 3, title: "Run /setup", children: "This imports the Ars Contexta methodology (249 research claims) if not already present." }), _jsx(H, { children: "Setup \u2014 Remote Vault" }), _jsx(P, { children: "You can also connect to any remote Switchboard instance instead of running locally. Edit .mcp.json in the plugin directory to point to the remote reactor:" }), _jsxs("div", { className: "mb-4 rounded-lg px-4 py-3 font-mono text-[11px]", style: {
|
|
173
|
+
backgroundColor: "var(--bai-bg)",
|
|
174
|
+
color: "var(--bai-text-secondary)",
|
|
175
|
+
}, children: [_jsx("span", { style: { color: "var(--bai-text-muted)" }, children: `{` }), _jsx("br", {}), _jsx("span", { style: { color: "var(--bai-text-muted)" }, children: ` "mcpServers": { "reactor-mcp": {` }), _jsx("br", {}), _jsx("span", { style: { color: "var(--bai-text-muted)" }, children: ` "url": "` }), _jsx("span", { className: "text-emerald-400", children: "https://your-switchboard.example.com/mcp" }), _jsx("span", { style: { color: "var(--bai-text-muted)" }, children: `"` }), _jsx("br", {}), _jsx("span", { style: { color: "var(--bai-text-muted)" }, children: ` }}` }), _jsx("br", {}), _jsx("span", { style: { color: "var(--bai-text-muted)" }, children: `}` })] }), _jsx(Tip, { children: "No local reactor needed when connecting remotely. The plugin talks to the remote Switchboard via MCP over HTTPS. All skills work the same way \u2014 the only difference is the endpoint URL." }), _jsx(H, { children: "Key Commands" }), _jsx("div", { className: "space-y-1 mb-4", children: [
|
|
157
176
|
{ cmd: "/seed", desc: "Ingest source material for processing" },
|
|
158
177
|
{ cmd: "/extract", desc: "Extract atomic claims from a source" },
|
|
159
178
|
{ cmd: "/connect", desc: "Find and create links between notes" },
|
|
@@ -36,6 +36,6 @@ type GraphViewProps = {
|
|
|
36
36
|
mocs?: MocInfo[];
|
|
37
37
|
tensions?: TensionInfo[];
|
|
38
38
|
};
|
|
39
|
-
export declare function GraphView({ notes, graphState, mocs, tensions }: GraphViewProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare function GraphView({ notes, graphState, mocs, tensions, }: GraphViewProps): import("react/jsx-runtime").JSX.Element;
|
|
40
40
|
export {};
|
|
41
41
|
//# sourceMappingURL=GraphView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphView.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/GraphView.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAUzE,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,EAAE,CAAC;IACJ,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,EAAE,CAAC;IACJ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,IAAI,CAAC;AAET,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzD,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B,CAAC;
|
|
1
|
+
{"version":3,"file":"GraphView.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/GraphView.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAUzE,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,EAAE,CAAC;IACJ,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,EAAE,CAAC;IACJ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,IAAI,CAAC;AAET,KAAK,OAAO,GAAG;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzD,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B,CAAC;AA0XF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,UAAU,EACV,IAAI,EACJ,QAAQ,GACT,EAAE,cAAc,2CAupBhB"}
|
|
@@ -328,7 +328,7 @@ function getLayoutOptions() {
|
|
|
328
328
|
/* ------------------------------------------------------------------ */
|
|
329
329
|
/* Component */
|
|
330
330
|
/* ------------------------------------------------------------------ */
|
|
331
|
-
export function GraphView({ notes, graphState, mocs, tensions }) {
|
|
331
|
+
export function GraphView({ notes, graphState, mocs, tensions, }) {
|
|
332
332
|
const containerRef = useRef(null);
|
|
333
333
|
const cyRef = useRef(null);
|
|
334
334
|
const [selectedDetail, setSelectedDetail] = useState(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HealthDashboard.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/HealthDashboard.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,eAAe,
|
|
1
|
+
{"version":3,"file":"HealthDashboard.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/components/HealthDashboard.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,eAAe,4CA8kB9B"}
|
|
@@ -191,7 +191,14 @@ export function HealthDashboard() {
|
|
|
191
191
|
border: "1px solid var(--bai-border)",
|
|
192
192
|
}, children: [_jsx("span", { className: `rounded-full border px-4 py-1.5 text-sm font-bold ${STATUS_BADGE[agentReport?.overallStatus ?? health.overallStatus]}`, children: agentReport?.overallStatus ?? health.overallStatus }), _jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-lg font-bold", style: { color: "var(--bai-text)" }, children: "Vault Health" }), _jsx("p", { className: "text-xs", style: { color: "var(--bai-text-muted)" }, children: agentReport
|
|
193
193
|
? `Agent report from ${new Date(agentReport.generatedAt).toLocaleString()} by ${agentReport.generatedBy}`
|
|
194
|
-
: "Live metrics \u2014 run /health in Claude Code for a full agent report" })] }), _jsx("span", { className: "rounded-full border px-3 py-1 text-[10px] font-medium", style: {
|
|
194
|
+
: "Live metrics \u2014 run /health in Claude Code for a full agent report" })] }), _jsx("span", { className: "rounded-full border px-3 py-1 text-[10px] font-medium", style: {
|
|
195
|
+
borderColor: "var(--bai-border)",
|
|
196
|
+
color: "var(--bai-text-muted)",
|
|
197
|
+
}, children: agentReport ? "Agent" : "Live" })] }), agentReport?.recommendations &&
|
|
198
|
+
agentReport.recommendations.length > 0 && (_jsxs("div", { className: "rounded-xl p-4", style: {
|
|
199
|
+
backgroundColor: "var(--bai-accent-soft)",
|
|
200
|
+
border: "1px solid var(--bai-border)",
|
|
201
|
+
}, children: [_jsx("h3", { className: "mb-2 text-xs font-semibold", style: { color: "var(--bai-accent)" }, children: "Agent Recommendations" }), _jsx("ul", { className: "space-y-1", children: agentReport.recommendations.map((rec, i) => (_jsxs("li", { className: "flex items-start gap-2 text-xs", style: { color: "var(--bai-text-secondary)" }, children: [_jsx("span", { className: "mt-0.5 h-1.5 w-1.5 shrink-0 rounded-full", style: { backgroundColor: "var(--bai-accent)" } }), rec] }, i))) })] })), _jsx("div", { className: "grid grid-cols-4 gap-3", children: [
|
|
195
202
|
{
|
|
196
203
|
label: "Notes",
|
|
197
204
|
value: agentReport?.graphMetrics?.noteCount ?? health.noteCount,
|
|
@@ -225,13 +232,18 @@ export function HealthDashboard() {
|
|
|
225
232
|
{
|
|
226
233
|
label: "Orphans",
|
|
227
234
|
value: agentReport?.graphMetrics?.orphanCount ?? health.orphanCount,
|
|
228
|
-
colorClass: (agentReport?.graphMetrics?.orphanCount ?? health.orphanCount) >
|
|
235
|
+
colorClass: (agentReport?.graphMetrics?.orphanCount ?? health.orphanCount) >
|
|
236
|
+
0
|
|
237
|
+
? "text-amber-400"
|
|
238
|
+
: "text-emerald-400",
|
|
229
239
|
colorStyle: undefined,
|
|
230
240
|
},
|
|
231
241
|
{
|
|
232
242
|
label: "Avg Links",
|
|
233
|
-
value: (agentReport?.graphMetrics?.averageLinksPerNote ??
|
|
234
|
-
|
|
243
|
+
value: (agentReport?.graphMetrics?.averageLinksPerNote ??
|
|
244
|
+
health.avgLinksPerNote).toFixed(1),
|
|
245
|
+
colorClass: (agentReport?.graphMetrics?.averageLinksPerNote ??
|
|
246
|
+
health.avgLinksPerNote) < 2
|
|
235
247
|
? "text-amber-400"
|
|
236
248
|
: "text-emerald-400",
|
|
237
249
|
colorStyle: undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-drive-init.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/hooks/use-drive-init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-drive-init.d.ts","sourceRoot":"","sources":["../../../../editors/knowledge-vault/hooks/use-drive-init.ts"],"names":[],"mappings":"AA+DA,wBAAgB,YAAY,SAsB3B;AAsGD;;;GAGG;AACH,wBAAgB,YAAY,wBAI3B"}
|
|
@@ -1,19 +1,40 @@
|
|
|
1
|
-
import { useEffect
|
|
1
|
+
import { useEffect } from "react";
|
|
2
2
|
import { useSelectedDrive, useNodesInSelectedDrive, addDocument, addFolder, } from "@powerhousedao/reactor-browser";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Drive folder structure matching Ars Contexta layout:
|
|
5
|
+
*
|
|
6
|
+
* /knowledge/ <- notes, MOCs, knowledge graph
|
|
7
|
+
* /knowledge/notes/ <- knowledge notes
|
|
8
|
+
* /knowledge/inbox/ <- unprocessed captures
|
|
9
|
+
* /knowledge/insights/ <- synthesized insights
|
|
10
|
+
* /sources/ <- archived source material
|
|
11
|
+
* /ops/ <- operational coordination
|
|
12
|
+
* /ops/sessions/ <- session transcripts
|
|
13
|
+
* /ops/health/ <- health reports
|
|
14
|
+
* /ops/queue/ <- pipeline queue singleton
|
|
15
|
+
* /self/ <- system identity & config
|
|
16
|
+
* /self/methodology/ <- methodology notes
|
|
17
|
+
* /research/ <- bundled research claims
|
|
18
|
+
*
|
|
19
|
+
* Pattern: follows contributor-billing's proven approach —
|
|
20
|
+
* module-level tracking Set per drive prevents duplicates,
|
|
21
|
+
* sequential creation with delays for sync compatibility.
|
|
22
|
+
*/
|
|
23
|
+
// ─── Module-level state (survives re-renders, prevents duplicates) ───
|
|
24
|
+
const initStartedForDrives = new Set();
|
|
25
|
+
// Flat list of folders to create (order matters — parents first)
|
|
26
|
+
const FOLDERS = [
|
|
27
|
+
{ name: "knowledge" },
|
|
28
|
+
{ name: "notes", parentPath: "knowledge" },
|
|
29
|
+
{ name: "inbox", parentPath: "knowledge" },
|
|
30
|
+
{ name: "insights", parentPath: "knowledge" },
|
|
8
31
|
{ name: "sources" },
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
children: [{ name: "methodology" }],
|
|
16
|
-
},
|
|
32
|
+
{ name: "ops" },
|
|
33
|
+
{ name: "sessions", parentPath: "ops" },
|
|
34
|
+
{ name: "health", parentPath: "ops" },
|
|
35
|
+
{ name: "queue", parentPath: "ops" },
|
|
36
|
+
{ name: "self" },
|
|
37
|
+
{ name: "methodology", parentPath: "self" },
|
|
17
38
|
{ name: "research" },
|
|
18
39
|
];
|
|
19
40
|
const SINGLETONS = [
|
|
@@ -22,44 +43,61 @@ const SINGLETONS = [
|
|
|
22
43
|
type: "bai/pipeline-queue",
|
|
23
44
|
folderPath: "ops/queue",
|
|
24
45
|
},
|
|
25
|
-
{
|
|
26
|
-
name: "HealthReport",
|
|
27
|
-
type: "bai/health-report",
|
|
28
|
-
folderPath: "ops/health",
|
|
29
|
-
},
|
|
46
|
+
{ name: "HealthReport", type: "bai/health-report", folderPath: "ops/health" },
|
|
30
47
|
{ name: "KnowledgeGraph", type: "bai/knowledge-graph", folderPath: "self" },
|
|
31
48
|
{ name: "VaultConfig", type: "bai/vault-config", folderPath: "self" },
|
|
32
49
|
];
|
|
33
50
|
export function useDriveInit() {
|
|
34
|
-
// Use the drive ID (UUID), never the slug
|
|
35
51
|
const [selectedDrive] = useSelectedDrive();
|
|
36
52
|
const driveId = selectedDrive?.header.id;
|
|
37
53
|
const nodes = useNodesInSelectedDrive();
|
|
38
|
-
const initAttempted = useRef(false);
|
|
39
54
|
useEffect(() => {
|
|
40
|
-
if (!driveId ||
|
|
55
|
+
if (!driveId || nodes === undefined)
|
|
56
|
+
return;
|
|
57
|
+
if (initStartedForDrives.has(driveId))
|
|
41
58
|
return;
|
|
42
|
-
if (
|
|
43
|
-
return; // still loading
|
|
44
|
-
// Check if the root "knowledge" folder exists (our init marker)
|
|
59
|
+
// Check if already initialized (knowledge folder exists)
|
|
45
60
|
const hasKnowledgeFolder = (nodes ?? []).some((n) => n.kind === "folder" && n.name === "knowledge" && n.parentFolder == null);
|
|
46
|
-
if (hasKnowledgeFolder)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
if (hasKnowledgeFolder) {
|
|
62
|
+
initStartedForDrives.add(driveId);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
initStartedForDrives.add(driveId);
|
|
66
|
+
void initDrive(driveId, nodes ?? []);
|
|
50
67
|
}, [driveId, nodes]);
|
|
51
68
|
}
|
|
69
|
+
// ─── Single sequential init: folders then singletons ───
|
|
52
70
|
async function initDrive(driveId, existingNodes) {
|
|
53
71
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
const folderIds = new Map(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
// Phase 1: Create folders
|
|
73
|
+
console.log(`[VaultInit] Creating folders for drive ${driveId}...`);
|
|
74
|
+
const existingFolderMap = buildExistingFolderMap(existingNodes);
|
|
75
|
+
const folderIds = new Map(existingFolderMap);
|
|
76
|
+
for (const folder of FOLDERS) {
|
|
77
|
+
const path = folder.parentPath
|
|
78
|
+
? `${folder.parentPath}/${folder.name}`
|
|
79
|
+
: folder.name;
|
|
80
|
+
if (folderIds.has(path)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const parentId = folder.parentPath
|
|
84
|
+
? folderIds.get(folder.parentPath)
|
|
85
|
+
: undefined;
|
|
86
|
+
try {
|
|
87
|
+
const result = await addFolder(driveId, folder.name, parentId);
|
|
88
|
+
folderIds.set(path, result.id);
|
|
89
|
+
console.log(`[VaultInit] Created folder: /${path}/`);
|
|
90
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(`[VaultInit] Failed to create folder /${path}/:`, err);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
console.log("[VaultInit] Folders complete");
|
|
97
|
+
// Wait for reactor to process all folder operations
|
|
98
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
99
|
+
// Phase 2: Create singletons
|
|
100
|
+
console.log(`[VaultInit] Creating singletons...`);
|
|
63
101
|
const existingTypes = new Set(existingNodes
|
|
64
102
|
.filter((n) => n.kind === "file")
|
|
65
103
|
.map((n) => n.documentType));
|
|
@@ -70,11 +108,9 @@ async function initDrive(driveId, existingNodes) {
|
|
|
70
108
|
}
|
|
71
109
|
const parentFolderId = folderIds.get(singleton.folderPath);
|
|
72
110
|
try {
|
|
73
|
-
// addDocument uses the drive UUID internally
|
|
74
111
|
await addDocument(driveId, singleton.name, singleton.type, parentFolderId);
|
|
75
112
|
console.log(`[VaultInit] Created ${singleton.name} in /${singleton.folderPath}/`);
|
|
76
|
-
|
|
77
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
113
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
78
114
|
}
|
|
79
115
|
catch (err) {
|
|
80
116
|
console.error(`[VaultInit] Failed to create ${singleton.name}:`, err);
|
|
@@ -86,27 +122,7 @@ async function initDrive(driveId, existingNodes) {
|
|
|
86
122
|
console.error("[VaultInit] Drive initialization failed:", err);
|
|
87
123
|
}
|
|
88
124
|
}
|
|
89
|
-
|
|
90
|
-
for (const def of defs) {
|
|
91
|
-
const path = pathPrefix ? `${pathPrefix}/${def.name}` : def.name;
|
|
92
|
-
if (!folderIds.has(path)) {
|
|
93
|
-
try {
|
|
94
|
-
const result = await addFolder(driveId, def.name, parentFolderId);
|
|
95
|
-
folderIds.set(path, result.id);
|
|
96
|
-
console.log(`[VaultInit] Created folder: /${path}/`);
|
|
97
|
-
// Small delay to avoid revision conflicts
|
|
98
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
console.error(`[VaultInit] Failed to create folder /${path}/:`, err);
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (def.children) {
|
|
106
|
-
await createFolderTree(driveId, def.children, folderIds.get(path), path, folderIds);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
125
|
+
// ─── Helpers ───
|
|
110
126
|
function buildExistingFolderMap(nodes) {
|
|
111
127
|
const map = new Map();
|
|
112
128
|
const folders = nodes.filter((n) => n.kind === "folder");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/moc-editor/editor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/moc-editor/editor.tsx"],"names":[],"mappings":"AAuBA,MAAM,CAAC,OAAO,UAAU,MAAM,4CA6X7B"}
|