feat(web): ontology-driven fleet treegrid, relations grouping, dev auto-config
Knowledge Base / Fleet browsing: - EntityTable renders as a treegrid (arbitrary depth, expand/collapse, ARIA row/level/expanded), grouped by parent-child relationships derived entirely from the live ontology graph (cardinality -> direction; typeDepth specificity for ties) rather than a hardcoded relationship list — see loadFleetGrouping in KnowledgeBase.svelte. - Fold Services and Storage categories into Fleet (services/pools/ volumes/datasets now nest under the compute entity or pool that provides/contains them instead of having their own browsing tabs). - Drop `cluster` entities from Fleet browsing so a host's `located-at` (site) relationship wins the tree-parent slot without needing a hardcoded priority override — member-of simply has no valid target left to point at. - Add a "show destroyed/inactive" Switch (default off) filtering on entity.state, replacing an always-on checkbox. Entity detail panel: - Split the Relations section into Outgoing/Incoming groups (relative to the viewed entity), and scope the section's count to edges actually incident to it rather than the whole depth-1 neighborhood. Dev experience: - Auto-fill the SPA's token from the dev server's own OIKOS_API_TOKEN (vite.config.ts define + main.ts, dev-only, only when unconfigured) so the "Connect to Oikos" prompt doesn't reappear on every reload. - .claude/launch.json: autoPort, since port 5173 is often already claimed by another worktree's dev server. Adds ui/checkbox and ui/switch (bits-ui primitives, following the existing shadcn-svelte wrapper pattern) and fetchOntology()/ RelationshipTypeDef to api.ts. Also fixes a missing types.ts import in api.ts (ChatEvent/MessageContent) that predates this branch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import { fetchWithAuth } from './config'
|
||||
import type { ChatEvent, MessageContent } from './types'
|
||||
|
||||
export type { ChatEvent }
|
||||
|
||||
// Path prefixes only — NOT resolved URLs. fetchWithAuth resolves the actual
|
||||
// origin (relative vs. configured apiUrl) fresh on every call via
|
||||
@@ -221,13 +224,33 @@ export interface EntityType {
|
||||
description?: string | null
|
||||
}
|
||||
|
||||
export type RelationshipCardinality = 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many'
|
||||
|
||||
export interface RelationshipTypeDef {
|
||||
name: string
|
||||
inverse?: string | null
|
||||
source_type: string
|
||||
target_type: string
|
||||
cardinality: RelationshipCardinality
|
||||
description?: string | null
|
||||
}
|
||||
|
||||
export interface Ontology {
|
||||
entityTypes: EntityType[]
|
||||
relationshipTypes: RelationshipTypeDef[]
|
||||
}
|
||||
|
||||
export async function fetchOntology(): Promise<Ontology> {
|
||||
const res = await fetchWithAuth(`${API}/ontology`)
|
||||
if (!res.ok) return { entityTypes: [], relationshipTypes: [] }
|
||||
const data = await res.json()
|
||||
return { entityTypes: data.entity_types ?? [], relationshipTypes: data.relationship_types ?? [] }
|
||||
}
|
||||
|
||||
// The graph endpoint has no layer param, so callers build a type→layer map from
|
||||
// this to scope the graph client-side (the entities table filters server-side).
|
||||
export async function fetchEntityTypes(): Promise<EntityType[]> {
|
||||
const res = await fetchWithAuth(`${API}/ontology`)
|
||||
if (!res.ok) return []
|
||||
const data = await res.json()
|
||||
return data.entity_types ?? []
|
||||
return (await fetchOntology()).entityTypes
|
||||
}
|
||||
|
||||
export interface EventFilters {
|
||||
|
||||
Reference in New Issue
Block a user