Skip to content

Commit d368224

Browse files
committed
feat: v1.2.2 Ontology Store — typed entity graph with properties and relationships
1 parent 1777134 commit d368224

10 files changed

Lines changed: 1423 additions & 3 deletions

File tree

src/App.css

Lines changed: 631 additions & 0 deletions
Large diffs are not rendered by default.

src/App.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { UpdateBanner } from './components/UpdateBanner'
4848
import { BatchGenerationPanel } from './components/BatchGenerationPanel'
4949
import { SkillComposer } from './components/SkillComposer'
5050
import { SkillRegistry } from './components/SkillRegistry'
51+
import { OntologyPanel } from './components/OntologyPanel'
5152
import { SkillBuilder } from './components/SkillBuilder'
5253
import type { ModelInfo, CitationEntry, Skill } from './types'
5354
import type { SearXNGResult } from './lib/searxngApi'
@@ -65,7 +66,7 @@ import type { Locale } from './lib/i18n'
6566
import './App.css'
6667
import { useLocale } from './hooks/useLocale'
6768

68-
type View = 'chat' | 'models' | 'changelog' | 'cache' | 'arena' | 'benchmark' | 'custom-models' | 'persona-marketplace' | 'knowledge' | 'plugins' | 'mcp-servers' | 'webdav' | 'memory' | 'agent' | 'usage-analytics' | 'comparison' | 'skill-registry' | 'skill-builder'
69+
type View = 'chat' | 'models' | 'changelog' | 'cache' | 'arena' | 'benchmark' | 'custom-models' | 'persona-marketplace' | 'knowledge' | 'plugins' | 'mcp-servers' | 'webdav' | 'memory' | 'agent' | 'usage-analytics' | 'comparison' | 'skill-registry' | 'skill-builder' | 'ontology'
6970

7071
const BASE = '/monday'
7172

@@ -88,6 +89,7 @@ const VIEW_PATH: Record<View, string> = {
8889
comparison: BASE + '/comparison',
8990
'skill-registry': BASE + '/skill-registry',
9091
'skill-builder': BASE + '/skill-builder',
92+
ontology: BASE + '/ontology',
9193
}
9294

9395
function viewFromPath(pathname: string): View {
@@ -176,6 +178,7 @@ export default function App() {
176178

177179
// v1.2: load persistent memories and skills when memory view is open
178180
const [installedSkills, setInstalledSkills] = useState<Skill[]>([])
181+
const [ontologyEntities, setOntologyEntities] = useState<import('./types').OntologyEntity[]>([])
179182
useEffect(() => {
180183
if (view === 'memory') {
181184
Promise.all([
@@ -188,6 +191,12 @@ export default function App() {
188191
}
189192
}, [view])
190193

194+
useEffect(() => {
195+
if (view === 'ontology') {
196+
import('./lib/storage').then((m) => m.loadOntologyEntities()).then((ents) => setOntologyEntities(ents))
197+
}
198+
}, [view])
199+
191200
// Apply base filter to vector store when active base changes
192201
useEffect(() => {
193202
vectorStore.setBaseFilter(activeBaseDocIds ?? null)
@@ -533,6 +542,10 @@ export default function App() {
533542
setView('comparison')
534543
closeSidebarOnMobile()
535544
}}
545+
onOpenOntology={() => {
546+
setView('ontology')
547+
closeSidebarOnMobile()
548+
}}
536549
onOpenShortcuts={() => {
537550
setShowShortcuts(true)
538551
closeSidebarOnMobile()
@@ -842,6 +855,40 @@ export default function App() {
842855
onClose={() => setView('chat')}
843856
/>
844857
</div>
858+
) : view === 'ontology' ? (
859+
<div className="main-content main-content--ontology">
860+
<OntologyPanel
861+
entities={ontologyEntities}
862+
onAdd={async (type, name, props) => {
863+
const m = await import('./lib/storage')
864+
const ent = await m.createOntologyEntity(type, name, props)
865+
setOntologyEntities((prev) => [ent, ...prev])
866+
}}
867+
onEdit={async (id, name, props) => {
868+
await import('./lib/storage').then((m) => m.updateOntologyEntity(id, name, props))
869+
setOntologyEntities((prev) => prev.map((e) => e.id === id ? { ...e, name, properties: props, updatedAt: Date.now() } : e))
870+
}}
871+
onDelete={async (id) => {
872+
await import('./lib/storage').then((m) => m.deleteOntologyEntity(id))
873+
setOntologyEntities((prev) => prev.filter((e) => e.id !== id))
874+
}}
875+
onAddRelationship={async (fromId, toId, label) => {
876+
await import('./lib/storage').then((m) => m.addEntityRelationship(fromId, toId, label))
877+
setOntologyEntities((prev) => prev.map((e) => e.id === fromId ? { ...e, relationships: [...e.relationships, toId], updatedAt: Date.now() } : e))
878+
}}
879+
onRemoveRelationship={async (fromId, toId) => {
880+
await import('./lib/storage').then((m) => m.removeEntityRelationship(fromId, toId))
881+
setOntologyEntities((prev) => prev.map((e) => e.id === fromId ? { ...e, relationships: e.relationships.filter((r) => r !== toId), updatedAt: Date.now() } : e))
882+
}}
883+
onInjectAsContext={() => {
884+
import('./lib/storage').then((m) => {
885+
const ctx = ontologyEntities.map((e) => `[${e.type}] ${e.name}${Object.keys(e.properties).length > 0 ? ' {' + Object.entries(e.properties).map(([k, v]) => ` ${k}: ${v}`).join(', ') + ' }' : ''}`).join('; ')
886+
navigator.clipboard.writeText(ctx)
887+
})
888+
}}
889+
onClose={() => setView('chat')}
890+
/>
891+
</div>
845892
) : view === 'usage-analytics' ? (
846893
<div className="main-content main-content--usage-analytics">
847894
<UsageAnalytics />

0 commit comments

Comments
 (0)