fix(web): surface knowledge RAG asset gap
This commit is contained in:
@@ -1940,7 +1940,9 @@
|
||||
"ownerQueueSub": "ready {ready} / blocked {blocked}",
|
||||
"writeback": "已寫回",
|
||||
"writebackSafe": "只讀回讀;讀取不寫入",
|
||||
"writebackUnsafe": "偵測到讀取寫入風險"
|
||||
"writebackUnsafe": "偵測到讀取寫入風險",
|
||||
"ragIndex": "RAG 索引",
|
||||
"ragIndexSub": "sources {sources};0 代表語意檢索尚未沉澱"
|
||||
}
|
||||
},
|
||||
"overview": {
|
||||
@@ -1978,6 +1980,10 @@
|
||||
"verifier": {
|
||||
"title": "Verifier 回寫",
|
||||
"detail": "已批准或完成驗證 {ready} 筆;待 負責人審查 {pending} 筆。"
|
||||
},
|
||||
"rag": {
|
||||
"title": "RAG / 向量索引",
|
||||
"detail": "索引 chunks {ready};來源 {pending}。0 代表 KM 尚未進入語意檢索資產。"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1940,7 +1940,9 @@
|
||||
"ownerQueueSub": "ready {ready} / blocked {blocked}",
|
||||
"writeback": "已寫回",
|
||||
"writebackSafe": "只讀回讀;讀取不寫入",
|
||||
"writebackUnsafe": "偵測到讀取寫入風險"
|
||||
"writebackUnsafe": "偵測到讀取寫入風險",
|
||||
"ragIndex": "RAG 索引",
|
||||
"ragIndexSub": "sources {sources};0 代表語意檢索尚未沉澱"
|
||||
}
|
||||
},
|
||||
"overview": {
|
||||
@@ -1978,6 +1980,10 @@
|
||||
"verifier": {
|
||||
"title": "Verifier 回寫",
|
||||
"detail": "已批准或完成驗證 {ready} 筆;待 負責人審查 {pending} 筆。"
|
||||
},
|
||||
"rag": {
|
||||
"title": "RAG / 向量索引",
|
||||
"detail": "索引 chunks {ready};來源 {pending}。0 代表 KM 尚未進入語意檢索資產。"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -116,14 +116,20 @@ interface KnowledgeStaleOwnerReviewCompletionQueueResponse {
|
||||
batch_writes_allowed: boolean
|
||||
}
|
||||
|
||||
interface KnowledgeRagStatsResponse {
|
||||
total_chunks?: number
|
||||
sources?: number
|
||||
}
|
||||
|
||||
interface KnowledgeGovernanceTelemetry {
|
||||
staleCandidates: KnowledgeStaleCandidatesResponse | null
|
||||
ownerReviews: KnowledgeStaleOwnerReviewInboxResponse | null
|
||||
burnDown: KnowledgeStaleOwnerReviewBurnDownResponse | null
|
||||
completionQueue: KnowledgeStaleOwnerReviewCompletionQueueResponse | null
|
||||
ragStats: KnowledgeRagStatsResponse | null
|
||||
}
|
||||
|
||||
type AutomationAssetKey = 'km' | 'playbook' | 'script' | 'monitoring' | 'verifier'
|
||||
type AutomationAssetKey = 'km' | 'playbook' | 'script' | 'monitoring' | 'verifier' | 'rag'
|
||||
|
||||
// =============================================================================
|
||||
// Category Config
|
||||
@@ -301,6 +307,7 @@ export default function KnowledgeBasePage({
|
||||
ownerReviews: null,
|
||||
burnDown: null,
|
||||
completionQueue: null,
|
||||
ragStats: null,
|
||||
})
|
||||
const [governanceLoading, setGovernanceLoading] = useState(true)
|
||||
|
||||
@@ -360,7 +367,7 @@ export default function KnowledgeBasePage({
|
||||
setGovernanceLoading(true)
|
||||
try {
|
||||
const apiBase = process.env.NEXT_PUBLIC_API_URL ?? ''
|
||||
const [staleCandidates, ownerReviews, burnDown, completionQueue] = await Promise.all([
|
||||
const [staleCandidates, ownerReviews, burnDown, completionQueue, ragStats] = await Promise.all([
|
||||
fetch(`${apiBase}/api/v1/ai/governance/km-stale-candidates?project_id=awoooi&limit=5`)
|
||||
.then(res => res.ok ? res.json() : null)
|
||||
.catch(() => null),
|
||||
@@ -373,6 +380,9 @@ export default function KnowledgeBasePage({
|
||||
fetch(`${apiBase}/api/v1/ai/governance/km-stale-owner-review-completion-queue?project_id=awoooi&status_bucket=all&limit=5`)
|
||||
.then(res => res.ok ? res.json() : null)
|
||||
.catch(() => null),
|
||||
fetch(`${apiBase}/api/v1/knowledge/rag/stats`)
|
||||
.then(res => res.ok ? res.json() : null)
|
||||
.catch(() => null),
|
||||
])
|
||||
|
||||
setGovernanceTelemetry({
|
||||
@@ -380,6 +390,7 @@ export default function KnowledgeBasePage({
|
||||
ownerReviews,
|
||||
burnDown,
|
||||
completionQueue,
|
||||
ragStats,
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch knowledge governance telemetry', err)
|
||||
@@ -615,6 +626,8 @@ export default function KnowledgeBasePage({
|
||||
entry.status === 'approved'
|
||||
|| hasTag(entry, ['human_approved', 'postmortem']),
|
||||
)
|
||||
const ragChunks = governanceTelemetry.ragStats?.total_chunks ?? 0
|
||||
const ragSources = governanceTelemetry.ragStats?.sources ?? 0
|
||||
const ownerPending =
|
||||
governanceTelemetry.ownerReviews?.total
|
||||
?? governanceTelemetry.completionQueue?.pending_count
|
||||
@@ -666,6 +679,16 @@ export default function KnowledgeBasePage({
|
||||
pct: pct(verifierReady),
|
||||
tone: 'border-status-healthy/20 bg-status-healthy/10 text-status-healthy',
|
||||
},
|
||||
{
|
||||
key: 'rag' as AutomationAssetKey,
|
||||
icon: FileSearch,
|
||||
ready: ragChunks,
|
||||
pending: ragSources,
|
||||
pct: ragChunks > 0 ? 100 : 0,
|
||||
tone: ragChunks > 0
|
||||
? 'border-status-healthy/20 bg-status-healthy/10 text-status-healthy'
|
||||
: 'border-status-critical/25 bg-status-critical/10 text-status-critical',
|
||||
},
|
||||
] as const
|
||||
}, [displayedEntries, governanceTelemetry])
|
||||
|
||||
@@ -686,6 +709,8 @@ export default function KnowledgeBasePage({
|
||||
return t('assetLedger.asset.monitoring.detail', values)
|
||||
case 'verifier':
|
||||
return t('assetLedger.asset.verifier.detail', values)
|
||||
case 'rag':
|
||||
return t('assetLedger.asset.rag.detail', values)
|
||||
}
|
||||
},
|
||||
[formatCount, t],
|
||||
@@ -809,6 +834,8 @@ export default function KnowledgeBasePage({
|
||||
const thresholdText = governanceSummary.threshold === null ? '--' : `${governanceSummary.threshold}%`
|
||||
const staleTotalValue = governanceSummary.staleTotal === null ? '--' : formatCount(governanceSummary.staleTotal)
|
||||
const entriesToThreshold = governanceSummary.entriesToThreshold === null ? '--' : formatCount(governanceSummary.entriesToThreshold)
|
||||
const ragChunks = governanceTelemetry.ragStats?.total_chunks ?? 0
|
||||
const ragSources = governanceTelemetry.ragStats?.sources ?? 0
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -848,8 +875,17 @@ export default function KnowledgeBasePage({
|
||||
? 'border-status-critical/25 bg-status-critical/10 text-status-critical'
|
||||
: 'border-status-healthy/25 bg-status-healthy/10 text-status-healthy',
|
||||
},
|
||||
{
|
||||
key: 'ragIndex',
|
||||
icon: FileSearch,
|
||||
value: formatCount(ragChunks),
|
||||
sub: t('decision.card.ragIndexSub', { sources: formatCount(ragSources) }),
|
||||
tone: ragChunks > 0
|
||||
? 'border-status-healthy/25 bg-status-healthy/10 text-status-healthy'
|
||||
: 'border-status-critical/25 bg-status-critical/10 text-status-critical',
|
||||
},
|
||||
] as const
|
||||
}, [formatCount, governanceSummary, t])
|
||||
}, [formatCount, governanceSummary, governanceTelemetry.ragStats, t])
|
||||
|
||||
const content = (
|
||||
<div className="flex min-h-[calc(100vh-64px)] flex-col lg:h-[calc(100vh-64px)] lg:flex-row">
|
||||
@@ -1020,7 +1056,7 @@ export default function KnowledgeBasePage({
|
||||
<ArrowRight className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mt-3 grid grid-cols-2 gap-2 xl:grid-cols-4">
|
||||
<div className="mt-3 grid grid-cols-2 gap-2 xl:grid-cols-5">
|
||||
{governanceDecisionCards.map(card => {
|
||||
const Icon = card.icon
|
||||
return (
|
||||
@@ -1095,7 +1131,7 @@ export default function KnowledgeBasePage({
|
||||
{t('assetLedger.readOnly')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-5">
|
||||
<div className="grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-6">
|
||||
{automationAssetRows.map(row => {
|
||||
const Icon = row.icon
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user