1/** 2 * dashboard-report-api.js â Dashboard å ±åé è³æå±¤ï¼Stage 1: è³ææµï¼ 3 * 4 * è `dashboard-client.js` çæ¢å® bundle contractï¼browser client å¥ç´æ¸¬è©¦ 5 * éå®ç mode/sites/data/connectors/tasks/billing/decision åºåï¼åé¢ï¼ 6 * æ¬æªæ¡åªæåãå ±ååå¡ãæéçè£å è³æï¼çµä¸è§¸ç¢° bundle æ¢æç端é»é åºã 7 * æå ¥é»ï¼`dashboard.html` å¨ dashboard-client.js ä¹å¾è¼å ¥æ¬æªï¼ 8 * åå§åç± `dashboard-report-stage1.js` ç root.AgentIdReportStage1.init() é© åã 9 * 10 * è¨è¨å¥ç´ï¼è docs/dashboard-frontend-architecture-2026-08-15.md ä¸è´ï¼ï¼ 11 * 1. ææ fetch 帶åºå® timeoutï¼6sï¼ï¼å¤±æä¸å¾å¸¸æ åçº { error: string }ï¼ 12 * çµä¸æåºãçµä¸è®åå¡ç´ç¼ºå¤±è®ææ´é é¯èª¤ï¼pending_not_zero æ¿çï¼ã 13 * 2. JSON è§£æå¤±æä¹å¸¸æ åçº invalid_jsonï¼ä¸ä¸åº SyntaxErrorã 14 * 3. åå³å¼çµæ§åªåæå°å卿§é©èï¼ä¸åå ¨ schema æ ¡é©ï¼æ¢æç«¯é»æ¬ä½ä»¥ 15 * server.py _build_customer_evidence_dashboard 實測å¼çºæºï¼ã 16 */ 17(() => { 18 "use strict"; 19 20 const REPORT_API_TIMEOUT_MS = 6000; 21 22 const parseJsonSafe = (text) => { 23 try { return JSON.parse(text); } 24 catch (_) { return null; } 25 }; 26 27 /** 28 * å®å ¨ JSON fetchï¼{ ok:true, data } | { ok:false, error, url? } 29 * 失æåå åä¸é¡ï¼http_<status> / invalid_json / network_unreachableã 30 */ 31 const fetchJson = async (url, options = {}) => { 32 const ctrl = new AbortController(); 33 const timer = window.setTimeout(() => ctrl.abort(), REPORT_API_TIMEOUT_MS); 34 try { 35 const res = await window.fetch(url, Object.assign({}, options, { signal: ctrl.signal })); 36 if (!res.ok) return { ok: false, error: `http_${res.status}`, url }; 37 const text = await res.text(); 38 const data = parseJsonSafe(text); 39 return data == null ? { ok: false, error: "invalid_json", url } : { ok: true, data }; 40 } catch (_) { 41 return { ok: false, error: "network_unreachable", url }; 42 } finally { 43 window.clearTimeout(timer); 44 } 45 }; 46 47 /** 48 * ä¸»å ±å payload å ç± page coordinator ç¼å¸ãå ¬é demo èç»å ¥å¾ bundle 49 * 齿²¿ç¨åè³æï¼ä¸å¦ç¼è«æ±ï¼å°æªå®æææ¬ææ¸ é¤çæ æä¿æ unavailableã 50 */ 51 // The page coordinator is the only payload producer. Stages never initiate 52 // a demo request or infer authority from a URL/body/visible DOM label. 53 let context = null; 54 const publish = (mode, host, data) => { 55 const normalize = window.AgentIdDashboardClient.normalizeHost; 56 if (!["customer", "demo"].includes(mode) || !normalize(host) 57 || normalize(data?.customer?.host) !== normalize(host)) { 58 throw new Error("dashboard_report_subject_mismatch"); 59 } 60 context = {mode, host: normalize(host), data}; 61 window.dispatchEvent(new Event("dashboard-report-change")); 62 }; 63 const clear = () => { 64 context = null; 65 window.dispatchEvent(new Event("dashboard-report-change")); 66 }; 67 const current = () => context; 68 const fetchReportPayload = async () => context 69 ? {ok: true, data: context.data} 70 : {ok: false, error: "dashboard_report_not_authorized"}; 71 72 /** 73 * Common Crawl èªæå卿¥è©¢ï¼é url= 忏ï¼å¤±æå¸¸æ åã 74 */ 75 const fetchCommonCrawl = async (url) => 76 fetchJson(`/api/agent/common_crawl_presence?url=${window.encodeURIComponent(url)}`); 77 78 window.AgentIdReportApi = Object.freeze({ 79 fetchJson, 80 fetchReportPayload, 81 fetchCommonCrawl, 82 publish, clear, current, 83 }); 84})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.