mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-30 21:36:47 +08:00
fix(operation-trace): correct capture scope, broaden coverage, polish panel
- Capture scope: treat the ``audit`` bucket (viewing the log / tracing settings) as a read-level observation instead of recording it from the mutation level. At "mutations only" the log no longer fills with GET page views; views are recorded only at the read level. - Coverage: classify plugin lifecycle (install / upgrade / config / page), skills, knowledge bases and MCP servers, with dedicated actions and resource types, so those operations are traced instead of falling into the generic resource bucket. Route rules now support multi-fragment AND matching and per-verb read/write actions. - Panel: move "Download logs" next to "Refresh" in the toolbar. - Verification: count hash mismatches and broken links separately instead of collapsing both into one "tampered" signal. - i18n: add the new action labels plus the split verification labels in all eight locales.
This commit is contained in:
@@ -323,6 +323,19 @@ export default function OperationTracePanel({
|
||||
)}
|
||||
{t('operationTrace.refresh')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => void downloadLogs()}
|
||||
disabled={exporting}
|
||||
>
|
||||
{exporting ? (
|
||||
<Loader2 className="size-3.5 animate-spin" />
|
||||
) : (
|
||||
<Download className="size-3.5" />
|
||||
)}
|
||||
{t('operationTrace.export')}
|
||||
</Button>
|
||||
</PanelToolbar>
|
||||
|
||||
<PanelBody className="space-y-6">
|
||||
@@ -429,13 +442,22 @@ export default function OperationTracePanel({
|
||||
{t('operationTrace.records')}
|
||||
</h3>
|
||||
<Badge variant="secondary">{total}</Badge>
|
||||
{(page?.tampered_count ?? 0) > 0 && (
|
||||
<Badge variant="destructive">
|
||||
{t('operationTrace.tamperedCount', {
|
||||
count: page?.tampered_count ?? 0,
|
||||
})}
|
||||
</Badge>
|
||||
)}
|
||||
{(page?.tampered_count ?? 0) > 0 &&
|
||||
(page?.integrity_failed_count ?? 0) > 0 && (
|
||||
<Badge variant="destructive">
|
||||
{t('operationTrace.integrityFailedCount', {
|
||||
count: page?.integrity_failed_count ?? 0,
|
||||
})}
|
||||
</Badge>
|
||||
)}
|
||||
{(page?.tampered_count ?? 0) > 0 &&
|
||||
(page?.chain_failed_count ?? 0) > 0 && (
|
||||
<Badge variant="destructive">
|
||||
{t('operationTrace.chainFailedCount', {
|
||||
count: page?.chain_failed_count ?? 0,
|
||||
})}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="ml-auto flex flex-wrap items-center gap-2">
|
||||
<Select
|
||||
@@ -490,19 +512,6 @@ export default function OperationTracePanel({
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => void downloadLogs()}
|
||||
disabled={exporting}
|
||||
>
|
||||
{exporting ? (
|
||||
<Loader2 className="size-3.5 animate-spin" />
|
||||
) : (
|
||||
<Download className="size-3.5" />
|
||||
)}
|
||||
{t('operationTrace.export')}
|
||||
</Button>
|
||||
<Select
|
||||
value={query.actor ?? ALL_VALUE}
|
||||
onValueChange={(value) =>
|
||||
|
||||
@@ -76,6 +76,10 @@ export interface OperationLogPage {
|
||||
offset: number;
|
||||
/** How many records on this page failed hash or chain verification. */
|
||||
tampered_count: number;
|
||||
/** Records whose stored hash no longer matches their content. */
|
||||
integrity_failed_count: number;
|
||||
/** Records whose predecessor link is broken. */
|
||||
chain_failed_count: number;
|
||||
}
|
||||
|
||||
export interface OperationLogFilters {
|
||||
|
||||
Reference in New Issue
Block a user