Files
accounted/components/agent-knowledge/AgentKnowledgePanel.tsx
T
Jakob Wennberg dcd33997b7 feat(agent): move 'Vad din agent vet' into settings (Assistenten -> Kunskap) (#1008)
Relocates the ledger-knowledge surface off the top nav and into the
assistant settings hub as a third tab (Minne / Kompetens / Kunskap), per
the code's own "minne + kunskap under Assistenten" intent and the #935
flag that this was an easy call to change.

Because both settings surfaces (the full-page rail and the intercepting
settings modal) mount each section as a propless component via
SETTINGS_SECTIONS, the knowledge data must be fetched client-side rather
than passed as a server prop:

- New GET /api/agent/knowledge aggregates buildLedgerContext +
  buildDeepEntities + buildAgentCompetence + company name (read-only,
  company-scoped via withRouteContext).
- AgentKnowledgeView + AgentCompetenceSections converted from async
  server components to client components (getTranslations ->
  useTranslations; no other server-only usage).
- New AgentKnowledgePanel client wrapper lazy-fetches the payload when
  the Kunskap tab opens (Radix unmounts inactive tabs), with Skeleton and
  error states matching the memory/skills panels.
- Removed the Brain/agent-knowledge entry (and its now-unused import)
  from the Analys nav group.
- /agent-knowledge kept as a redirect to /settings/assistant?view=knowledge
  so old links/bookmarks resolve.

Tests: new route test (auth 401, no-company 400, happy-path aggregation).
i18n: load_error_* keys added to both locales (parity kept).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 22:21:08 +02:00

81 lines
2.3 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
import { useTranslations } from 'next-intl'
import { Skeleton } from '@/components/ui/skeleton'
import { EmptyState } from '@/components/ui/empty-state'
import { Brain } from 'lucide-react'
import type { LedgerContext } from '@/lib/agent-context/ledger-context'
import type { DeepLedgerContext } from '@/lib/agent-context/ledger-deep'
import type { AgentCompetence } from '@/lib/agent-context/agent-competence'
import { AgentKnowledgeView } from './AgentKnowledgeView'
interface KnowledgePayload {
context: LedgerContext
deep: DeepLedgerContext
competence: AgentCompetence
companyName: string
}
/**
* Client wrapper for the "Vad din agent vet" view inside the assistant
* settings hub. Fetches the ledger context from /api/agent/knowledge on mount
* (lazy: this panel only renders when the Kunskap tab is opened, since Radix
* unmounts inactive tabs). Fetching client-side rather than via a server prop
* is deliberate: the settings sections mount as propless components in BOTH
* the full-page rail and the routed settings modal, so a server fetch wouldn't
* reach the modal.
*/
export function AgentKnowledgePanel() {
const t = useTranslations('agentKnowledge')
const [payload, setPayload] = useState<KnowledgePayload | null>(null)
const [error, setError] = useState(false)
useEffect(() => {
let cancelled = false
fetch('/api/agent/knowledge')
.then((res) => {
if (!res.ok) throw new Error(`knowledge fetch failed: ${res.status}`)
return res.json()
})
.then((json) => {
if (!cancelled) setPayload(json.data as KnowledgePayload)
})
.catch(() => {
if (!cancelled) setError(true)
})
return () => {
cancelled = true
}
}, [])
if (error) {
return (
<EmptyState
icon={Brain}
title={t('load_error_title')}
description={t('load_error_description')}
/>
)
}
if (!payload) {
return (
<div className="space-y-6">
<Skeleton className="h-64 w-full rounded-xl" />
<Skeleton className="h-9 w-64" />
<Skeleton className="h-48 w-full rounded-xl" />
</div>
)
}
return (
<AgentKnowledgeView
context={payload.context}
deep={payload.deep}
competence={payload.competence}
companyName={payload.companyName}
/>
)
}