fix(web): 補 Work Items 租戶讀取上下文
This commit is contained in:
@@ -1105,6 +1105,11 @@ async function fetchJson<T>(url: string, timeoutMs = 8000): Promise<T | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function withProjectId(url: string, projectId: string) {
|
||||||
|
const separator = url.includes("?") ? "&" : "?";
|
||||||
|
return `${url}${separator}project_id=${encodeURIComponent(projectId)}`;
|
||||||
|
}
|
||||||
|
|
||||||
async function postJson<T>(
|
async function postJson<T>(
|
||||||
url: string,
|
url: string,
|
||||||
body: Record<string, unknown>,
|
body: Record<string, unknown>,
|
||||||
@@ -1146,8 +1151,14 @@ function recurrenceOpenItems(recurrence: RecurrenceResponse | null) {
|
|||||||
return (recurrence?.items ?? []).filter((item) => item.work_item?.status === "open");
|
return (recurrence?.items ?? []).filter((item) => item.work_item?.status === "open");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CANONICAL_INCIDENT_ID_RE = /^INC-\d{8}-[A-Z0-9]{4,}$/;
|
||||||
|
|
||||||
|
function isCanonicalIncidentId(candidate: string | null | undefined) {
|
||||||
|
return Boolean(candidate?.trim() && CANONICAL_INCIDENT_ID_RE.test(candidate.trim()));
|
||||||
|
}
|
||||||
|
|
||||||
function firstIncidentId(...candidates: Array<string | null | undefined>) {
|
function firstIncidentId(...candidates: Array<string | null | undefined>) {
|
||||||
return candidates.find((candidate) => Boolean(candidate?.trim()))?.trim() ?? null;
|
return candidates.find(isCanonicalIncidentId)?.trim() ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseRepairCandidateDraftWorkItemId(
|
function parseRepairCandidateDraftWorkItemId(
|
||||||
@@ -6105,22 +6116,46 @@ export default function AwoooPWorkItemsPage() {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const encodedProjectId = encodeURIComponent(projectId);
|
const encodedProjectId = encodeURIComponent(projectId);
|
||||||
const qualityUrl = `${API_BASE}/api/v1/platform/truth-chain/quality/summary?project_id=${encodedProjectId}&hours=24&limit=30`;
|
const qualityUrl = `${API_BASE}/api/v1/platform/truth-chain/quality/summary?project_id=${encodedProjectId}&hours=24&limit=30`;
|
||||||
const governanceEventsUrl = `${API_BASE}/api/v1/ai/governance/events?event_type=knowledge_degradation&event_type=governance_slo_data_gap&status=unresolved&size=10`;
|
const governanceEventsUrl = withProjectId(
|
||||||
const governanceQueueUrl = `${API_BASE}/api/v1/ai/governance/queue?dispatch_status=pending&size=10`;
|
`${API_BASE}/api/v1/ai/governance/events?event_type=knowledge_degradation&event_type=governance_slo_data_gap&status=unresolved&size=10`,
|
||||||
const governanceKnowledgeQueueUrl = `${API_BASE}/api/v1/ai/governance/queue?dispatch_status=all&event_type=knowledge_degradation&size=20`;
|
projectId
|
||||||
const knowledgeReviewDraftsUrl = `${API_BASE}/api/v1/knowledge?entry_type=auto_runbook&status=review&q=${encodeURIComponent("KM healthcheck")}&limit=100`;
|
);
|
||||||
const knowledgeReviewDedupeUrl = `${API_BASE}/api/v1/ai/governance/km-review-drafts/dedupe?limit=100`;
|
const governanceQueueUrl = withProjectId(
|
||||||
|
`${API_BASE}/api/v1/ai/governance/queue?dispatch_status=pending&size=10`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
const governanceKnowledgeQueueUrl = withProjectId(
|
||||||
|
`${API_BASE}/api/v1/ai/governance/queue?dispatch_status=all&event_type=knowledge_degradation&size=20`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
const knowledgeReviewDraftsUrl = withProjectId(
|
||||||
|
`${API_BASE}/api/v1/knowledge?entry_type=auto_runbook&status=review&q=${encodeURIComponent("KM healthcheck")}&limit=100`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
const knowledgeReviewDedupeUrl = withProjectId(
|
||||||
|
`${API_BASE}/api/v1/ai/governance/km-review-drafts/dedupe?limit=100`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
const knowledgeStaleCandidatesUrl = `${API_BASE}/api/v1/ai/governance/km-stale-candidates?project_id=${encodedProjectId}&limit=20`;
|
const knowledgeStaleCandidatesUrl = `${API_BASE}/api/v1/ai/governance/km-stale-candidates?project_id=${encodedProjectId}&limit=20`;
|
||||||
const knowledgeStaleOwnerReviewsUrl = `${API_BASE}/api/v1/ai/governance/km-stale-owner-reviews?project_id=${encodedProjectId}&dispatch_status=pending&limit=30`;
|
const knowledgeStaleOwnerReviewsUrl = `${API_BASE}/api/v1/ai/governance/km-stale-owner-reviews?project_id=${encodedProjectId}&dispatch_status=pending&limit=30`;
|
||||||
const knowledgeStaleOwnerReviewBurnDownUrl = `${API_BASE}/api/v1/ai/governance/km-stale-owner-review-burndown?project_id=${encodedProjectId}&limit=20`;
|
const knowledgeStaleOwnerReviewBurnDownUrl = `${API_BASE}/api/v1/ai/governance/km-stale-owner-review-burndown?project_id=${encodedProjectId}&limit=20`;
|
||||||
const knowledgeStaleOwnerReviewCompletionQueueUrl = `${API_BASE}/api/v1/ai/governance/km-stale-owner-review-completion-queue?project_id=${encodedProjectId}&status_bucket=all&limit=30`;
|
const knowledgeStaleOwnerReviewCompletionQueueUrl = `${API_BASE}/api/v1/ai/governance/km-stale-owner-review-completion-queue?project_id=${encodedProjectId}&status_bucket=all&limit=30`;
|
||||||
const channelEventsUrl = `${API_BASE}/api/v1/platform/events/recent?project_id=${encodedProjectId}&provider_prefix=alertmanager&limit=20`;
|
const channelEventsUrl = `${API_BASE}/api/v1/platform/events/recent?project_id=${encodedProjectId}&provider_prefix=alertmanager&limit=20`;
|
||||||
const recurrenceUrl = `${API_BASE}/api/v1/platform/events/dossier/recurrence?project_id=${encodedProjectId}&limit=100`;
|
const recurrenceUrl = `${API_BASE}/api/v1/platform/events/dossier/recurrence?project_id=${encodedProjectId}&limit=100`;
|
||||||
const sloUrl = `${API_BASE}/api/v1/ai/slo`;
|
const sloUrl = withProjectId(`${API_BASE}/api/v1/ai/slo`, projectId);
|
||||||
const remediationHistoryUrl = `${API_BASE}/api/v1/ai/slo/remediation/history?limit=80`;
|
const remediationHistoryUrl = withProjectId(
|
||||||
const driftFingerprintUrl = `${API_BASE}/api/v1/drift/fingerprints/state?namespace=awoooi-prod`;
|
`${API_BASE}/api/v1/ai/slo/remediation/history?limit=80`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
const driftFingerprintUrl = withProjectId(
|
||||||
|
`${API_BASE}/api/v1/drift/fingerprints/state?namespace=awoooi-prod`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
const callbackRepliesUrl = `${API_BASE}/api/v1/platform/runs/callback-replies?project_id=${encodedProjectId}&per_page=100`;
|
const callbackRepliesUrl = `${API_BASE}/api/v1/platform/runs/callback-replies?project_id=${encodedProjectId}&per_page=100`;
|
||||||
const aiRouteStatusUrl = `${API_BASE}/api/v1/platform/ai-route-status?workload_type=deep_rca`;
|
const aiRouteStatusUrl = withProjectId(
|
||||||
|
`${API_BASE}/api/v1/platform/ai-route-status?workload_type=deep_rca`,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
quality,
|
quality,
|
||||||
@@ -6177,7 +6212,10 @@ export default function AwoooPWorkItemsPage() {
|
|||||||
const timelineIncidentId = statusChain?.source_id ?? statusChainIncidentId;
|
const timelineIncidentId = statusChain?.source_id ?? statusChainIncidentId;
|
||||||
const incidentTimeline = timelineIncidentId
|
const incidentTimeline = timelineIncidentId
|
||||||
? await fetchJson<IncidentTimelineResponse>(
|
? await fetchJson<IncidentTimelineResponse>(
|
||||||
`${API_BASE}/api/v1/incidents/${encodeURIComponent(timelineIncidentId)}/timeline`,
|
withProjectId(
|
||||||
|
`${API_BASE}/api/v1/incidents/${encodeURIComponent(timelineIncidentId)}/timeline`,
|
||||||
|
projectId
|
||||||
|
),
|
||||||
12000
|
12000
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
Reference in New Issue
Block a user