@extension.dev/mcp 6.6.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@
6
6
  // ╚═╝ ╚═╝ ╚═════╝╚═╝
7
7
  // Apache License 2.0 (c) 2026 Cezar Augusto and the extension.dev collaborators
8
8
 
9
- (()=>{"use strict";JSON.stringify({alarms:["alarms"],bookmarks:["bookmarks"],contextMenus:["contextMenus"],cookies:["cookies"],downloads:["downloads"],history:["history"],notifications:["notifications"],offscreen:["offscreen"],contentSettings:["contentSettings"],debugger:["debugger"],declarativeNetRequest:["declarativeNetRequest","declarativeNetRequestWithHostAccess"],fontSettings:["fontSettings"],identity:["identity"],idle:["idle"],instanceID:["gcm"],management:["management"],mdns:["mdns"],power:["power"],printerProvider:["printerProvider"],printing:["printing"],privacy:["privacy"],proxy:["proxy"],sidePanel:["sidePanel"],tabCapture:["tabCapture"],tabGroups:["tabGroups"],topSites:["topSites"],tts:["tts"],userScripts:["userScripts"],webNavigation:["webNavigation"],webRequest:["webRequest"]}),JSON.stringify(["getSelf","getPermissionWarningsByManifest","uninstallSelf","installReplacementWebApp"]),JSON.stringify({"system.cpu":["system.cpu"],"system.memory":["system.memory"],"system.storage":["system.storage"],"system.display":["system.display"]}),JSON.stringify(["extension","i18n","runtime","scripting","storage"]);let e={storage:["storage"],notifications:["notifications"],contextMenus:["contextMenus"],downloads:["downloads"],cookies:["cookies"],bookmarks:["bookmarks"],history:["history"],alarms:["alarms"],offscreen:["offscreen"],scripting:["scripting","activeTab"]};function t(t,r){let n=t.split(".")[0]??"",o=e[n];return!o||null===r||o.some(e=>r.has(e))?null:`chrome.${n} needs the "${o.join('" or "')}" permission, which this session did not declare. Declare it in the manifest (and re-register the session) to use this API.`}function r(e,t,r){let n=t.active??t.id===e.activeTabId;return{id:t.id,index:t.index??r,windowId:e.id,url:t.url,title:t.title,active:n,highlighted:n,selected:n,pinned:t.pinned??!1,discarded:t.discarded??!1,groupId:t.tabGroupId??-1,status:t.status??(t.discarded?"unloaded":"complete"),incognito:t.incognito??!1}}let n=new Set(["storage.setAccessLevel","storage.get","storage.set","storage.remove","storage.clear","tabs.create","tabs.update","tabs.remove","tabs.move","tabs.discard","tabs.goBack","tabs.goForward","tabs.group","tabs.ungroup","tabGroups.query","tabGroups.get","tabGroups.update","tabGroups.move","tabs.get"]);async function o(e){let{data:t,windows:n,getStorage:o,setStorage:s,removeStorageKeys:a,clearStorage:i,onStorageChanged:l,onCreateTab:c,onUpdateTab:d,onRemoveTab:u,onMoveTab:g,onDiscardTab:m,onGroupTabs:p,onUngroupTabs:f,onQueryTabGroups:h,onGetTabGroup:w,onUpdateTabGroup:b,onMoveTabGroup:y,onTabGoBack:x,onTabGoForward:v,onSetStorageAccessLevel:k,respond:I}=e;switch(t.api){case"storage.setAccessLevel":{let[e,r]=t.args,n=e?.accessLevel;if("TRUSTED_CONTEXTS"!==n&&"TRUSTED_AND_UNTRUSTED_CONTEXTS"!==n)return void I({error:"Invalid access level."});await k?.(t.extensionId,r??"session",n),I({result:void 0});return}case"storage.get":{let[e,r]=t.args,n=o(t.extensionId,r??"local");if(!e)return void I({result:n});if(Array.isArray(e)){let t={};e.forEach(e=>{e in n&&(t[e]=n[e])}),I({result:t});return}if("string"==typeof e)return void I({result:e in n?{[e]:n[e]}:{}});if("object"==typeof e){let t={};Object.keys(e).forEach(r=>{t[r]=r in n?n[r]:e[r]}),I({result:t});return}I({result:n});return}case"storage.set":{let[e,r]=t.args,n=r??"local";if(e&&"object"==typeof e){let r=o(t.extensionId,n),a={};for(let t of Object.keys(e)){let n=r[t],o=e[t];if(JSON.stringify(n)===JSON.stringify(o))continue;let s={newValue:o};t in r&&(s.oldValue=n),a[t]=s}await s(t.extensionId,e,n),l&&Object.keys(a).length>0&&l(t.extensionId,a,n)}I({result:!0});return}case"storage.remove":{let[e,r]=t.args,n=r??"local",s=(Array.isArray(e)?e:[e]).filter(Boolean).map(String),i=o(t.extensionId,n),c={};for(let e of s)e in i&&(c[e]={oldValue:i[e]});await a(t.extensionId,s,n),l&&Object.keys(c).length>0&&l(t.extensionId,c,n),I({result:!0});return}case"storage.clear":{let[e]=t.args,r=e??"local",n=o(t.extensionId,r),s={};for(let e of Object.keys(n))s[e]={oldValue:n[e]};await i(t.extensionId,r),l&&Object.keys(s).length>0&&l(t.extensionId,s,r),I({result:!0});return}case"tabs.create":{let[e]=t.args;I({result:await c(e?.url??"chrome://newtab",e)??!0});return}case"tabs.update":{let[e,r]=t.args;null!==e&&"object"==typeof e&&(r=e,e=void 0),I({result:await d(e,r??{})??!0});return}case"tabs.remove":{let[e]=t.args;await u(e),I({result:void 0});return}case"tabs.move":{let[e,r]=t.args;I({result:await g?.(t.extensionId,e,r??{})});return}case"tabs.discard":{let[e]=t.args;I({result:await m?.(t.extensionId,e)});return}case"tabs.goBack":{let[e]=t.args;await x?.(t.extensionId,e),I({result:void 0});return}case"tabs.goForward":{let[e]=t.args;await v?.(t.extensionId,e),I({result:void 0});return}case"tabs.group":{let[e]=t.args;I({result:await p?.(t.extensionId,e??{})});return}case"tabs.ungroup":{let[e]=t.args;await f?.(t.extensionId,e),I({result:void 0});return}case"tabGroups.query":{let[e]=t.args;I({result:await h?.(t.extensionId,e)??[]});return}case"tabGroups.get":{let[e]=t.args;I({result:await w?.(t.extensionId,e)});return}case"tabGroups.update":{let[e,r]=t.args;I({result:await b?.(t.extensionId,e,r??{})});return}case"tabGroups.move":{let[e,r]=t.args;I({result:await y?.(t.extensionId,e,r??{})});return}case"tabs.get":{let[e]=t.args;for(let t of n)for(let n=0;n<t.tabs.length;n+=1){let o=t.tabs[n];if(o&&o.id===e)return void I({result:r(t,o,n)})}I({error:`No tab with id: ${String(e)}.`})}}}function s(e,t,r,n){let o;return"function"!=typeof e&&(r({error:(o=n?` on the ${n} lane`:"",`No backend implements ${t}${o}, so the call did not run. This is a preview limitation, not an error in your extension: the API is on the bridge's wire protocol but nothing is wired behind it here.`),refused:!0}),!0)}let a=new Set(["tabs.query","sidePanel.open","action.openPopup","runtime.openOptionsPage","devtools.panels.create","action.setPopup","action.getBadgeText","action.getBadgeBackgroundColor","action.getTitle","action.setBadgeText","action.setBadgeBackgroundColor","action.setTitle","action.setIcon"]);async function i(e){let{data:t,windows:n,onOpenSidePanel:o,onOpenActionPopup:a,onOpenOptionsPage:i,onDevtoolsPanelCreate:l,onSetActionPopup:c,onGetActionState:d,onSetBadgeText:u,onSetBadgeBackground:g,onSetActionTitle:m,onSetActionIcon:p,respond:f}=e;switch(t.api){case"tabs.query":{let[e]=t.args,o=n.find(e=>e.focused)??n[0],s=n;e?.windowId!==void 0?s=-2===e.windowId?o?[o]:[]:n.filter(t=>t.id===e.windowId):e?.currentWindow===!0||e?.lastFocusedWindow===!0?s=o?[o]:[]:e?.currentWindow===!1&&(s=n.filter(e=>e!==o));let a=e?.url?Array.isArray(e.url)?e.url:[e.url]:null;f({result:s.flatMap(t=>t.tabs.map((e,n)=>r(t,e,n)).filter(t=>e?.active===void 0||t.active===e.active).filter(t=>e?.pinned===void 0||t.pinned===e.pinned).filter(t=>e?.status===void 0||t.status===e.status).filter(t=>e?.discarded===void 0||t.discarded===e.discarded).filter(t=>e?.groupId===void 0||(t.groupId??-1)===e.groupId).filter(e=>!a||a.some(t=>(function(e,t){if(!e)return!1;if("<all_urls>"===t)return!0;let r=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return RegExp(`^${r.replace(/\*/g,".*")}$`).test(e)})(e.url,t))))});return}case"sidePanel.open":await o(t.extensionId),f({result:void 0});return;case"action.openPopup":if(s(a,t.api,f))return;a?.(t.extensionId),f({result:void 0});return;case"runtime.openOptionsPage":if(s(i,t.api,f))return;i?.(t.extensionId),f({result:void 0});return;case"devtools.panels.create":{if(s(l,t.api,f))return;let[e]=t.args;l?.(t.extensionId,e?.page??""),f({result:!0});return}case"action.setPopup":{if(s(c,t.api,f))return;let[e]=t.args;c?.(t.extensionId,e?.popup??""),f({result:void 0});return}case"action.getBadgeText":{let[e]=t.args,r=await d?.(t.extensionId,e?.tabId);f({result:r?.badgeText??""});return}case"action.getBadgeBackgroundColor":{let[e]=t.args,r=await d?.(t.extensionId,e?.tabId);f({result:r?.badgeColor??null});return}case"action.getTitle":{let[e]=t.args,r=await d?.(t.extensionId,e?.tabId);f({result:r?.title??""});return}case"action.setBadgeText":{let[e]=t.args;await u(t.extensionId,e?.text,e?.tabId),f({result:!0});return}case"action.setBadgeBackgroundColor":{let[e]=t.args;await g(t.extensionId,e?.color,e?.tabId),f({result:!0});return}case"action.setTitle":{let[e]=t.args;await m(t.extensionId,e?.title,e?.tabId),f({result:!0});return}case"action.setIcon":{let[e]=t.args,r="string"==typeof e?.path?e.path:"object"==typeof e?.path?Object.values(e.path)[0]:void 0;await p(t.extensionId,r),f({result:!0})}}}let l=new Set(["contextMenus.create","contextMenus.update","contextMenus.remove","contextMenus.removeAll","notifications.create","notifications.clear","notifications.update","notifications.getAll","downloads.search","downloads.cancel","downloads.pause","downloads.resume","downloads.erase","downloads.download"]);async function c(e){let{data:t,onCreateContextMenu:r,onUpdateContextMenu:n,onRemoveContextMenu:o,onClearContextMenus:a,onCreateNotification:i,onClearNotification:l,onUpdateNotification:c,onGetNotifications:d,onDownload:u,onSearchDownloads:g,onCancelDownload:m,onPauseDownload:p,onResumeDownload:f,onEraseDownloads:h,respond:w}=e;switch(t.api){case"contextMenus.create":{let[e]=t.args;w({result:await r(t.extensionId,e??{})});return}case"contextMenus.update":{let[e,r]=t.args;w({result:await n(t.extensionId,String(e??""),r??{})});return}case"contextMenus.remove":{let[e]=t.args;w({result:await o(t.extensionId,String(e??""))});return}case"contextMenus.removeAll":return void w({result:await a(t.extensionId)});case"notifications.create":{let[e,r]=t.args,n="string"==typeof e?e:void 0,o="string"==typeof e?r:e;w({result:await i(t.extensionId,n,o??{})});return}case"notifications.clear":{let[e]=t.args;w({result:await l(t.extensionId,String(e??""))});return}case"notifications.update":{let[e,r]=t.args;w({result:await c?.(t.extensionId,String(e??""),r??{})??!1});return}case"notifications.getAll":return void w({result:await d(t.extensionId)});case"downloads.search":{let[e]=t.args;w({result:await g?.(t.extensionId,e)??[]});return}case"downloads.cancel":{if(s(m,t.api,w))return;let[e]=t.args;await m?.(t.extensionId,e),w({result:void 0});return}case"downloads.pause":{if(s(p,t.api,w))return;let[e]=t.args;await p?.(t.extensionId,e),w({result:void 0});return}case"downloads.resume":{if(s(f,t.api,w))return;let[e]=t.args;await f?.(t.extensionId,e),w({result:void 0});return}case"downloads.erase":{if(s(h,t.api,w))return;let[e]=t.args;w({result:await h?.(t.extensionId,e)??[]});return}case"downloads.download":{let[e]=t.args;w({result:await u(t.extensionId,e??{})})}}}let d=new Set(["bookmarks.getTree","bookmarks.get","bookmarks.getChildren","bookmarks.search","bookmarks.create","bookmarks.update","bookmarks.remove","bookmarks.removeTree","bookmarks.move","history.search","history.getVisits","history.addUrl","history.deleteUrl","history.deleteRange","history.deleteAll","windows.get","windows.getAll","windows.getCurrent","windows.create","windows.update","windows.remove"]);async function u(e){let{data:t,windows:r,onGetWindow:n,onGetAllWindows:o,onCreateWindow:s,onUpdateWindow:a,onRemoveWindow:i,onGetBookmarkTree:l,onGetBookmarks:c,onGetBookmarkChildren:d,onSearchBookmarks:u,onCreateBookmark:g,onUpdateBookmark:m,onRemoveBookmark:p,onMoveBookmark:f,onSearchHistory:h,onGetHistoryVisits:w,onAddHistoryUrl:b,onDeleteHistoryUrl:y,onDeleteHistoryRange:x,onDeleteAllHistory:v,respond:k}=e;switch(t.api){case"bookmarks.getTree":return void k({result:await l(t.extensionId)});case"bookmarks.get":{let[e]=t.args,r=Array.isArray(e)?e:[e];k({result:await c(t.extensionId,r.filter(e=>null!=e).map(String))});return}case"bookmarks.getChildren":{let[e]=t.args;k({result:await d(t.extensionId,null==e?void 0:String(e))});return}case"bookmarks.search":{let[e]=t.args;k({result:await u(t.extensionId,e)});return}case"bookmarks.create":{let[e]=t.args;k({result:await g(t.extensionId,e??{})});return}case"bookmarks.update":{let[e,r]=t.args;k({result:await m(t.extensionId,String(e??""),r??{})});return}case"bookmarks.remove":{let[e]=t.args;k({result:await p(t.extensionId,String(e??""),!1)});return}case"bookmarks.removeTree":{let[e]=t.args;k({result:await p(t.extensionId,String(e??""),!0)});return}case"bookmarks.move":{let[e,r]=t.args;k({result:await f?.(t.extensionId,String(e??""),r??{})});return}case"history.search":{let[e]=t.args;k({result:await h(t.extensionId,e??{})});return}case"history.getVisits":{let[e]=t.args;k({result:await w(t.extensionId,e??{})});return}case"history.addUrl":{let[e]=t.args;await b(t.extensionId,e??{}),k({result:!0});return}case"history.deleteUrl":{let[e]=t.args;await y(t.extensionId,e??{}),k({result:!0});return}case"history.deleteRange":{let[e]=t.args;await x(t.extensionId,e??{}),k({result:!0});return}case"history.deleteAll":await v(t.extensionId),k({result:!0});return;case"windows.get":{let[e,r]=t.args;k({result:await n(t.extensionId,null==e?void 0:String(e),r)});return}case"windows.getAll":{let[e]=t.args;k({result:await o(t.extensionId,e)});return}case"windows.getCurrent":{let e=r.find(e=>e.focused)??r[0];k({result:e?{id:e.id,focused:!0,tabs:e.tabs}:null});return}case"windows.create":{let[e]=t.args;k({result:await s(t.extensionId,e?.url)});return}case"windows.update":{let[e,r]=t.args;k({result:await a(t.extensionId,null==e?void 0:String(e),r??{})});return}case"windows.remove":{let[e]=t.args;k({result:await i(t.extensionId,null==e?void 0:String(e))})}}}let g=new Set(["runtime.sendMessage","tabs.sendMessage","runtime.getContexts","permissions.contains","permissions.request","permissions.remove","permissions.getAll","offscreen.createDocument","offscreen.closeDocument","offscreen.hasDocument","cookies.get","cookies.getAll","cookies.set","cookies.remove","scripting.executeScript","scripting.insertCSS"]);async function m(e){let{data:t,onRuntimeMessage:r,onTabMessage:n,onGetRuntimeContexts:o,onContainsPermissions:s,onRequestPermissions:a,onRemovePermissions:i,onGetAllPermissions:l,onCreateOffscreenDocument:c,onCloseOffscreenDocument:d,onHasOffscreenDocument:u,onGetCookie:g,onGetAllCookies:m,onSetCookie:p,onRemoveCookie:f,onExecuteScript:h,onInsertCss:w,respond:b,source:y}=e;switch(t.api){case"runtime.sendMessage":{let[e]=t.args;b({result:await r(t.extensionId,e,y)});return}case"tabs.sendMessage":{let[e,r]=t.args;if(!n)return void b({error:"Could not establish connection. Receiving end does not exist."});b({result:await n(t.extensionId,e,r)});return}case"runtime.getContexts":return void b({result:await o(t.extensionId)});case"permissions.contains":{let[e]=t.args;b({result:await s(t.extensionId,e??{})});return}case"permissions.request":{let[e]=t.args;b({result:await a(t.extensionId,e??{})});return}case"permissions.remove":{let[e]=t.args;b({result:await i(t.extensionId,e??{})});return}case"permissions.getAll":return void b({result:await l(t.extensionId)});case"offscreen.createDocument":{let[e]=t.args,r=await c(t.extensionId,e??{});b({result:"boolean"!=typeof r||r});return}case"offscreen.closeDocument":{let e=await d(t.extensionId);b({result:"boolean"!=typeof e||e});return}case"offscreen.hasDocument":return void b({result:await u(t.extensionId)});case"cookies.get":{let[e]=t.args;b({result:await g(t.extensionId,e??{})});return}case"cookies.getAll":{let[e]=t.args;b({result:await m(t.extensionId,e??{})});return}case"cookies.set":{let[e]=t.args;b({result:await p(t.extensionId,e??{})});return}case"cookies.remove":{let[e]=t.args;b({result:await f(t.extensionId,e??{})});return}case"scripting.executeScript":{let[e]=t.args;b({result:await h(t.extensionId,e??{})});return}case"scripting.insertCSS":{let[e]=t.args;await w(t.extensionId,e??{}),b({result:!0})}}}let p=["local","sync","session","managed"];function f(e,t){let r=Math.min(e.length,t.length),n=0;for(;n<r&&e[n]===t[n];)n+=1;return n}function h(e){let t=function(e){let t=[...n,...a,...l,...d,...g].sort();if(t.includes(e))return null;let r=e.split(".");if(3===r.length&&"storage"===r[0]&&p.includes(r[1]??"")){let e=`storage.${r[2]}`;if(t.includes(e))return e}let o=r[r.length-1]??"",s=t.filter(e=>e.endsWith(`.${o}`));if(s.length)return s.sort((t,r)=>f(r,e)-f(t,e))[0];let i=t.filter(e=>e.startsWith(`${r[0]}.`));return i.length?i[0]??null:null}(e),r=`Unsupported API: ${e}.`;if(!t)return`${r} No wire name resembles it, so this API is not on the bridge at all. It may still work natively inside your extension's own contexts: the bridge is what an observer page can DRIVE, not the whole runtime.`;let o=t.startsWith("storage.")&&e.startsWith("storage.")?` The bridge takes the storage area as an ARGUMENT, not as part of the name: ${t}(keys, "local").`:"";return`${r} The closest wire name the bridge routes is ${t}.${o}`}let w=e=>"string"==typeof e&&e.length>0;function b(e,t){return`Error in invocation of ${e}: ${t}`}function y(e,t){return b(e,`missing required property '${t}'`)}function x(e,t,r,n){return b(e,`'${t}' expects a ${r}, got ${typeof n}`)}async function v(e){let{data:r,respond:s,getDeclaredPermissions:p,getSessionStorageAccessLevel:f}=e;try{var b;if(b=r.api,!(n.has(b)||a.has(b)||l.has(b)||d.has(b)||g.has(b)))return void s({error:h(r.api),refused:!0});let v=function(e,t){let r=t[0];switch(e){case"downloads.download":if(!r||!("url"in r))return y(e,"url");if(!w(r.url))return x(e,"url","non-empty string",r.url);if(void 0!==r.filename&&"string"!=typeof r.filename)return x(e,"filename","string",r.filename);return null;case"offscreen.createDocument":if(!r||!w(r.url))return y(e,"url");if(!Array.isArray(r.reasons)||0===r.reasons.length)return y(e,"reasons");if(!w(r.justification))return y(e,"justification");return null;case"contextMenus.create":if(!r)return y(e,"title");if(void 0!==r.id&&"string"!=typeof r.id)return x(e,"id","string",r.id);if("separator"!==r.type&&!w(r.title))return y(e,"title");return null;case"notifications.create":{let r="string"==typeof t[0]?t[1]:t[0];if(!r)return y(e,"options");for(let t of["type","iconUrl","title","message"])if(!w(r[t]))return y(e,t);return null}case"action.setTitle":if(r&&void 0!==r.title&&"string"!=typeof r.title)return x(e,"title","string",r.title);return null;case"action.setBadgeText":if(r&&void 0!==r.text&&"string"!=typeof r.text)return x(e,"text","string",r.text);return null;case"action.setBadgeBackgroundColor":if(!r||void 0===r.color)return y(e,"color");if("string"!=typeof r.color&&!Array.isArray(r.color))return x(e,"color","string or array",r.color);return null;case"tabs.create":if(r?.url!==void 0&&"string"!=typeof r.url)return x(e,"url","string",r.url);return null;default:return null}}(r.api,r.args);if(v)return void s({error:v});if(p){let e=t(r.api,p(r.extensionId));if(e)return void s({error:e,refused:!0})}if(r.untrustedContext&&r.api.startsWith("storage.")){let e="storage.clear"===r.api?r.args[0]:r.args[1],t=f?.(r.extensionId)??"TRUSTED_CONTEXTS";if("session"===e&&"TRUSTED_AND_UNTRUSTED_CONTEXTS"!==t)return void s({error:"Access to storage is not allowed from this context.",refused:!0})}if(n.has(r.api))return void await o(e);if(a.has(r.api))return void await i(e);if(l.has(r.api))return void await c(e);if(d.has(r.api))return void await u(e);if(g.has(r.api))return void await m(e);s({error:h(r.api),refused:!0})}catch(e){s({error:e instanceof Error?e.message:"Unknown error"})}}function k(e,t){throw Error(`${e} did not run on the real lane: ${t}`)}let I=e=>{let t=Number(e);return Number.isFinite(t)?t:void 0},S=e=>{let t=Number(e);return Number.isFinite(t)?t:void 0},C=new Set(["system.cpu.getInfo","system.memory.getInfo","system.storage.getInfo","system.storage.ejectDevice","system.display.getInfo","system.display.getDisplayLayout","system.display.setDisplayProperties","system.display.setDisplayLayout"]),T=["topSites","fontSettings","printing","power","tts","userScripts","debugger","system.network","enterprise.deviceAttributes","instanceID","identity","webNavigation","proxy.settings","contentSettings","tabCapture"].sort((e,t)=>t.length-e.length);function A(e){if(C.has(e))return"refused";for(let t of T)if(e===t||e.startsWith(`${t}.`))return"mocked";return"emulated"}let E=new Set(["storage","action","offscreen","runtime","tabs.sendMessage","scripting","downloads","notifications","contextMenus"]);function $(e){return!!e&&(e.startsWith("Unsupported API: ")||e.startsWith("No backend implements ")||/needs the ".+" permission, which this (session did not declare|extension's manifest does not declare)/.test(e))}function D(e){return e.refused||$(e.error)?"refused":"real"===e.lane?"real":A(e.api)}let M=new Set(["local","sync","session","managed"]);function N(e,t){let r=e.split(".");if("storage"!==r[0])return e;if(3===r.length&&M.has(r[1]??""))return`storage.${r[2]}@${r[1]}`;if(2===r.length){let e="clear"===r[1]?t?.[0]:t?.[1];return`storage.${r[1]}@${"string"==typeof e?e:"local"}`}return e}let B=new TextEncoder;function R(e,t){return{path:e,bytes:B.encode(t),text:t}}let P={manifest_version:3,name:"Hello Emulator",version:"0.1.0",description:"Trace fixture exercising emulated, mocked, and refused chrome.* tiers.",permissions:["storage","tabs","notifications","system.cpu","bookmarks","history","cookies","alarms","topSites","fontSettings","power","tts","identity","webNavigation"],action:{default_title:"Hello Emulator",default_popup:"popup.html"},background:{service_worker:"background.js"}},O=`<!doctype html>
9
+ (()=>{"use strict";let e={alarms:["alarms"],bookmarks:["bookmarks"],contextMenus:["contextMenus"],cookies:["cookies"],downloads:["downloads"],history:["history"],notifications:["notifications"],offscreen:["offscreen"],contentSettings:["contentSettings"],debugger:["debugger"],declarativeNetRequest:["declarativeNetRequest","declarativeNetRequestWithHostAccess"],fontSettings:["fontSettings"],identity:["identity"],idle:["idle"],instanceID:["gcm"],management:["management"],mdns:["mdns"],power:["power"],printerProvider:["printerProvider"],printing:["printing"],privacy:["privacy"],proxy:["proxy"],sidePanel:["sidePanel"],tabCapture:["tabCapture"],tabGroups:["tabGroups"],topSites:["topSites"],tts:["tts"],userScripts:["userScripts"],webNavigation:["webNavigation"],webRequest:["webRequest"]};function t(e){let t=e.discarded??!1;return{id:e.id,index:e.index,windowId:e.windowId,url:e.url,title:e.title,active:e.active,highlighted:e.active,selected:e.active,pinned:e.pinned??!1,discarded:t,autoDiscardable:!0,frozen:!1,groupId:e.groupId??-1,splitViewId:-1,status:e.status??(t?"unloaded":"complete"),incognito:e.incognito??!1,audible:!1,mutedInfo:{muted:!1},width:e.width??1280,height:e.height??800,...void 0===e.lastAccessed?{}:{lastAccessed:e.lastAccessed}}}function r(e,r,n){return t({id:r.id,index:r.index??n,windowId:e.id,url:r.url,title:r.title,active:r.active??r.id===e.activeTabId,pinned:r.pinned,discarded:r.discarded,groupId:r.tabGroupId,status:r.status,incognito:r.incognito})}JSON.stringify(e),JSON.stringify(["getSelf","getPermissionWarningsByManifest","uninstallSelf","installReplacementWebApp"]),JSON.stringify({"system.cpu":["system.cpu"],"system.memory":["system.memory"],"system.storage":["system.storage"],"system.display":["system.display"]});let n=new Set(["0","1","2","3"]),o="Invalid downloadId",s="Can't modify the root bookmark folders.";function a(e){return`No tab with id: ${String(e)}.`}function i(e){return`No window with id: ${String(e)}.`}function l(e){return null!=e}function c(e,t){for(let r of Array.isArray(t)?t:[t])if(l(r)&&!function(e,t){for(let r of e)for(let e=0;e<r.tabs.length;e+=1){let n=r.tabs[e];if(n&&n.id===t)return{window:r,index:e}}}(e,r))return r}function d(e,t){let r=String(t);return e.some(e=>void 0!==e.id&&String(e.id)===r)}function u(e){return n.has(String(e??""))}let g=new Set(["storage.setAccessLevel","storage.get","storage.set","storage.remove","storage.clear","tabs.create","tabs.update","tabs.remove","tabs.move","tabs.discard","tabs.goBack","tabs.goForward","tabs.group","tabs.ungroup","tabGroups.query","tabGroups.get","tabGroups.update","tabGroups.move","tabs.get"]);async function f(e){let{data:t,windows:n,getStorage:o,setStorage:s,removeStorageKeys:i,clearStorage:d,onStorageChanged:u,onCreateTab:g,onUpdateTab:f,onRemoveTab:m,onMoveTab:p,onDiscardTab:h,onGroupTabs:w,onUngroupTabs:b,onQueryTabGroups:y,onGetTabGroup:v,onUpdateTabGroup:x,onMoveTabGroup:I,onTabGoBack:k,onTabGoForward:S,onSetStorageAccessLevel:A,respond:C}=e;switch(t.api){case"storage.setAccessLevel":{let[e,r]=t.args,n=e?.accessLevel;if("TRUSTED_CONTEXTS"!==n&&"TRUSTED_AND_UNTRUSTED_CONTEXTS"!==n)return void C({error:"Invalid access level."});await A?.(t.extensionId,r??"session",n),C({result:void 0});return}case"storage.get":{let[e,r]=t.args,n=o(t.extensionId,r??"local");if(!e)return void C({result:n});if(Array.isArray(e)){let t={};e.forEach(e=>{e in n&&(t[e]=n[e])}),C({result:t});return}if("string"==typeof e)return void C({result:e in n?{[e]:n[e]}:{}});if("object"==typeof e){let t={};Object.keys(e).forEach(r=>{t[r]=r in n?n[r]:e[r]}),C({result:t});return}C({result:n});return}case"storage.set":{let[e,r]=t.args,n=r??"local";if(e&&"object"==typeof e){let r=o(t.extensionId,n),a={};for(let t of Object.keys(e)){let n=r[t],o=e[t];if(JSON.stringify(n)===JSON.stringify(o))continue;let s={newValue:o};t in r&&(s.oldValue=n),a[t]=s}await s(t.extensionId,e,n),u&&Object.keys(a).length>0&&u(t.extensionId,a,n)}C({result:!0});return}case"storage.remove":{let[e,r]=t.args,n=r??"local",s=(Array.isArray(e)?e:[e]).filter(Boolean).map(String),a=o(t.extensionId,n),l={};for(let e of s)e in a&&(l[e]={oldValue:a[e]});await i(t.extensionId,s,n),u&&Object.keys(l).length>0&&u(t.extensionId,l,n),C({result:!0});return}case"storage.clear":{let[e]=t.args,r=e??"local",n=o(t.extensionId,r),s={};for(let e of Object.keys(n))s[e]={oldValue:n[e]};await d(t.extensionId,r),u&&Object.keys(s).length>0&&u(t.extensionId,s,r),C({result:!0});return}case"tabs.create":{let[e]=t.args;C({result:await g(e?.url??"chrome://newtab",e)??!0});return}case"tabs.update":{let[e,r]=t.args;if(null!==e&&"object"==typeof e&&(r=e,e=void 0),l(e)&&void 0!==c(n,e))return void C({error:a(e),refused:!0});C({result:await f(e,r??{})??!0});return}case"tabs.remove":{let[e]=t.args,r=c(n,e);if(void 0!==r)return void C({error:a(r),refused:!0});await m(e),C({result:void 0});return}case"tabs.move":{let[e,r]=t.args;C({result:await p?.(t.extensionId,e,r??{})});return}case"tabs.discard":{let[e]=t.args,r=c(n,e);if(void 0!==r)return void C({error:a(r),refused:!0});C({result:await h?.(t.extensionId,e)});return}case"tabs.goBack":{let[e]=t.args;await k?.(t.extensionId,e),C({result:void 0});return}case"tabs.goForward":{let[e]=t.args;await S?.(t.extensionId,e),C({result:void 0});return}case"tabs.group":{let[e]=t.args,r=c(n,e?.tabIds);if(void 0!==r)return void C({error:a(r),refused:!0});C({result:await w?.(t.extensionId,e??{})});return}case"tabs.ungroup":{let[e]=t.args,r=c(n,e);if(void 0!==r)return void C({error:a(r),refused:!0});await b?.(t.extensionId,e),C({result:void 0});return}case"tabGroups.query":{let[e]=t.args;C({result:await y?.(t.extensionId,e)??[]});return}case"tabGroups.get":{let[e]=t.args;C({result:await v?.(t.extensionId,e)});return}case"tabGroups.update":{let[e,r]=t.args;C({result:await x?.(t.extensionId,e,r??{})});return}case"tabGroups.move":{let[e,r]=t.args;C({result:await I?.(t.extensionId,e,r??{})});return}case"tabs.get":{let[e]=t.args;for(let t of n)for(let n=0;n<t.tabs.length;n+=1){let o=t.tabs[n];if(o&&o.id===e)return void C({result:r(t,o,n)})}C({error:`No tab with id: ${String(e)}.`})}}}let m=[0,0,0,0],p=e=>Math.max(0,Math.min(255,Math.round(e))),h={transparent:[0,0,0,0],black:[0,0,0,255],white:[255,255,255,255],red:[255,0,0,255],green:[0,128,0,255],blue:[0,0,255,255],yellow:[255,255,0,255],orange:[255,165,0,255],grey:[128,128,128,255],gray:[128,128,128,255]};function w(e,t,r,n){let o;return"function"!=typeof e&&(r({error:(o=n?` on the ${n} lane`:"",`No backend implements ${t}${o}, so the call did not run. This is a preview limitation, not an error in your extension: the API is on the bridge's wire protocol but nothing is wired behind it here.`),refused:!0}),!0)}let b=new Set(["tabs.query","sidePanel.open","action.openPopup","runtime.openOptionsPage","devtools.panels.create","action.setPopup","action.getBadgeText","action.getBadgeBackgroundColor","action.getTitle","action.setBadgeText","action.setBadgeBackgroundColor","action.setTitle","action.setIcon"]);async function y(e){let{data:t,windows:n,onOpenSidePanel:o,onOpenActionPopup:s,onOpenOptionsPage:a,onDevtoolsPanelCreate:i,onSetActionPopup:l,onGetActionState:c,onSetBadgeText:d,onSetBadgeBackground:u,onSetActionTitle:g,onSetActionIcon:f,respond:b}=e;switch(t.api){case"tabs.query":{let[e]=t.args,o=n.find(e=>e.focused)??n[0],s=n;e?.windowId!==void 0?s=-2===e.windowId?o?[o]:[]:n.filter(t=>t.id===e.windowId):e?.currentWindow===!0||e?.lastFocusedWindow===!0?s=o?[o]:[]:e?.currentWindow===!1&&(s=n.filter(e=>e!==o));let a=e?.url?Array.isArray(e.url)?e.url:[e.url]:null;b({result:s.flatMap(t=>t.tabs.map((e,n)=>r(t,e,n)).filter(t=>e?.active===void 0||t.active===e.active).filter(t=>e?.pinned===void 0||t.pinned===e.pinned).filter(t=>e?.status===void 0||t.status===e.status).filter(t=>e?.discarded===void 0||t.discarded===e.discarded).filter(t=>e?.groupId===void 0||(t.groupId??-1)===e.groupId).filter(e=>!a||a.some(t=>(function(e,t){if(!e)return!1;if("<all_urls>"===t)return!0;let r=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return RegExp(`^${r.replace(/\*/g,".*")}$`).test(e)})(e.url,t))))});return}case"sidePanel.open":await o(t.extensionId),b({result:void 0});return;case"action.openPopup":if(w(s,t.api,b))return;s?.(t.extensionId),b({result:void 0});return;case"runtime.openOptionsPage":if(w(a,t.api,b))return;a?.(t.extensionId),b({result:void 0});return;case"devtools.panels.create":{if(w(i,t.api,b))return;let[e]=t.args;i?.(t.extensionId,e?.page??""),b({result:!0});return}case"action.setPopup":{if(w(l,t.api,b))return;let[e]=t.args;l?.(t.extensionId,e?.popup??""),b({result:void 0});return}case"action.getBadgeText":{let[e]=t.args,r=await c?.(t.extensionId,e?.tabId);b({result:r?.badgeText??""});return}case"action.getBadgeBackgroundColor":{let[e]=t.args,r=await c?.(t.extensionId,e?.tabId);b({result:r?.badgeColor===void 0||null===r.badgeColor?m:function(e){if(Array.isArray(e)){let[t,r,n,o]=e;return[p(Number(t)||0),p(Number(r)||0),p(Number(n)||0),p(void 0===o?255:Number(o)||0)]}if("string"!=typeof e)return m;let t=e.trim().toLowerCase();if(!t)return m;let r=h[t];if(r)return[...r];let n=/^rgba?\(([^)]+)\)$/.exec(t);if(n?.[1]){let e=n[1].split(",").map(e=>Number(e.trim()));if(e.length>=3&&e.slice(0,3).every(e=>!Number.isNaN(e))){let t=e[3];return[p(e[0]),p(e[1]),p(e[2]),void 0===t||Number.isNaN(t)?255:p(255*t)]}return m}let o=/^#([0-9a-f]{3,8})$/.exec(t);if(o?.[1]){let e=o[1],t=e=>1===e.length?parseInt(e+e,16):parseInt(e,16);if(3===e.length||4===e.length)return[t(e[0]),t(e[1]),t(e[2]),4===e.length?t(e[3]):255];if(6===e.length||8===e.length)return[parseInt(e.slice(0,2),16),parseInt(e.slice(2,4),16),parseInt(e.slice(4,6),16),8===e.length?parseInt(e.slice(6,8),16):255]}return m}(r.badgeColor)});return}case"action.getTitle":{let[e]=t.args,r=await c?.(t.extensionId,e?.tabId);b({result:r?.title??""});return}case"action.setBadgeText":{let[e]=t.args;await d(t.extensionId,e?.text,e?.tabId),b({result:!0});return}case"action.setBadgeBackgroundColor":{let[e]=t.args;await u(t.extensionId,e?.color,e?.tabId),b({result:!0});return}case"action.setTitle":{let[e]=t.args;await g(t.extensionId,e?.title,e?.tabId),b({result:!0});return}case"action.setIcon":{let[e]=t.args,r="string"==typeof e?.path?e.path:"object"==typeof e?.path?Object.values(e.path)[0]:void 0;await f(t.extensionId,r),b({result:!0})}}}let v=new Set(["contextMenus.create","contextMenus.update","contextMenus.remove","contextMenus.removeAll","notifications.create","notifications.clear","notifications.update","notifications.getAll","downloads.search","downloads.cancel","downloads.pause","downloads.resume","downloads.erase","downloads.download"]);async function x(e){let{data:t,onCreateContextMenu:r,onUpdateContextMenu:n,onRemoveContextMenu:s,onClearContextMenus:a,onCreateNotification:i,onClearNotification:l,onUpdateNotification:c,onGetNotifications:d,onDownload:u,onSearchDownloads:g,onCancelDownload:f,onPauseDownload:m,onResumeDownload:p,onEraseDownloads:h,respond:b}=e;switch(t.api){case"contextMenus.create":{let[e]=t.args;b({result:await r(t.extensionId,e??{})});return}case"contextMenus.update":{let[e,r]=t.args;b({result:await n(t.extensionId,String(e??""),r??{})});return}case"contextMenus.remove":{let[e]=t.args;b({result:await s(t.extensionId,String(e??""))});return}case"contextMenus.removeAll":return void b({result:await a(t.extensionId)});case"notifications.create":{let[e,r]=t.args,n="string"==typeof e?e:void 0,o="string"==typeof e?r:e;b({result:await i(t.extensionId,n,o??{})});return}case"notifications.clear":{let[e]=t.args;b({result:await l(t.extensionId,String(e??""))});return}case"notifications.update":{let[e,r]=t.args;b({result:await c?.(t.extensionId,String(e??""),r??{})??!1});return}case"notifications.getAll":return void b({result:await d(t.extensionId)});case"downloads.search":{let[e]=t.args;b({result:await g?.(t.extensionId,e)??[]});return}case"downloads.cancel":{if(w(f,t.api,b))return;let[e]=t.args;if(await f?.(t.extensionId,e)===!1)return void b({error:o,refused:!0});b({result:void 0});return}case"downloads.pause":{if(w(m,t.api,b))return;let[e]=t.args;if(await m?.(t.extensionId,e)===!1)return void b({error:o,refused:!0});b({result:void 0});return}case"downloads.resume":{if(w(p,t.api,b))return;let[e]=t.args;if(await p?.(t.extensionId,e)===!1)return void b({error:o,refused:!0});b({result:void 0});return}case"downloads.erase":{if(w(h,t.api,b))return;let[e]=t.args;b({result:await h?.(t.extensionId,e)??[]});return}case"downloads.download":{let[e]=t.args;b({result:await u(t.extensionId,e??{})})}}}let I={"bookmarks-bar":"bookmarks-bar","other-bookmarks":"other","mobile-bookmarks":"mobile"};function k(e,t={}){let r=void 0===e.url,n=e.parentId??t.parentId,o=I[e.id];return{id:e.id,title:e.title??"",syncing:!1,...void 0===e.url?{}:{url:e.url},...void 0===e.index?{}:{index:e.index},...void 0===n?{}:{parentId:n},...void 0===e.dateAdded?{}:{dateAdded:e.dateAdded},...r&&void 0!==e.dateGroupModified?{dateGroupModified:e.dateGroupModified}:{},...o?{folderType:o}:{},...e.children?{children:e.children.map(t=>k(t,{parentId:e.id}))}:{}}}function S(e){return(e??[]).map(e=>k(e))}function A(e,r={}){let n={id:e.id,focused:e.focused??!1,incognito:e.incognito??!1,alwaysOnTop:e.alwaysOnTop??!1,state:e.state??"normal",type:e.type??"normal",top:e.top??0,left:e.left??0,width:e.width??1280,height:e.height??800};return r.populate?{...n,tabs:(e.tabs??[]).map((r,n)=>t({id:r.id,index:r.index??n,windowId:e.id,url:r.url,title:r.title,active:r.active??r.id===e.activeTabId,pinned:r.pinned,discarded:r.discarded,groupId:r.tabGroupId,status:r.status,incognito:r.incognito}))}:n}let C=new Set(["bookmarks.getTree","bookmarks.get","bookmarks.getChildren","bookmarks.search","bookmarks.create","bookmarks.update","bookmarks.remove","bookmarks.removeTree","bookmarks.move","history.search","history.getVisits","history.addUrl","history.deleteUrl","history.deleteRange","history.deleteAll","windows.get","windows.getAll","windows.getCurrent","windows.create","windows.update","windows.remove"]);async function T(e){let{data:t,windows:r,onGetWindow:n,onGetAllWindows:o,onCreateWindow:a,onUpdateWindow:c,onRemoveWindow:g,onGetBookmarkTree:f,onGetBookmarks:m,onGetBookmarkChildren:p,onSearchBookmarks:h,onCreateBookmark:w,onUpdateBookmark:b,onRemoveBookmark:y,onMoveBookmark:v,onSearchHistory:x,onGetHistoryVisits:I,onAddHistoryUrl:C,onDeleteHistoryUrl:T,onDeleteHistoryRange:$,onDeleteAllHistory:E,respond:N}=e;switch(t.api){case"bookmarks.getTree":let D,M;return void N({result:(M=(D=await f(t.extensionId)??[]).map(e=>e.dateAdded).filter(e=>void 0!==e).sort((e,t)=>e-t)[0],[k({id:"0",title:"",children:D,...void 0===M?{}:{dateAdded:M}})])});case"bookmarks.get":{let[e]=t.args,r=Array.isArray(e)?e:[e];N({result:S(await m(t.extensionId,r.filter(e=>null!=e).map(String)))});return}case"bookmarks.getChildren":{let[e]=t.args;N({result:S(await p(t.extensionId,null==e?void 0:String(e)))});return}case"bookmarks.search":{let[e]=t.args;N({result:S(await h(t.extensionId,e))});return}case"bookmarks.create":{let[e]=t.args,r=await w(t.extensionId,e??{});N({result:r?k(r):null});return}case"bookmarks.update":{let[e,r]=t.args;if(u(e))return void N({error:s,refused:!0});let n=await b(t.extensionId,String(e??""),r??{});N({result:n?k(n):null});return}case"bookmarks.remove":{let[e]=t.args;if(u(e))return void N({error:s,refused:!0});N({result:await y(t.extensionId,String(e??""),!1)});return}case"bookmarks.removeTree":{let[e]=t.args;if(u(e))return void N({error:s,refused:!0});N({result:await y(t.extensionId,String(e??""),!0)});return}case"bookmarks.move":{let[e,r]=t.args;if(u(e))return void N({error:s,refused:!0});N({result:await v?.(t.extensionId,String(e??""),r??{})});return}case"history.search":{let[e]=t.args;N({result:await x(t.extensionId,e??{})});return}case"history.getVisits":{let[e]=t.args;N({result:await I(t.extensionId,e??{})});return}case"history.addUrl":{let[e]=t.args;await C(t.extensionId,e??{}),N({result:!0});return}case"history.deleteUrl":{let[e]=t.args;await T(t.extensionId,e??{}),N({result:!0});return}case"history.deleteRange":{let[e]=t.args;await $(t.extensionId,e??{}),N({result:!0});return}case"history.deleteAll":await E(t.extensionId),N({result:!0});return;case"windows.get":{let[e,o]=t.args;if(l(e)&&!d(r,e))return void N({error:i(e),refused:!0});let s=await n(t.extensionId,null==e?void 0:String(e),o);N({result:s?A(s,{populate:o?.populate}):null});return}case"windows.getAll":{let[e]=t.args;N({result:function(e,t={}){return e.map(e=>A(e,t))}(await o(t.extensionId,e),{populate:e?.populate})});return}case"windows.getCurrent":{let[e]=t.args,n=r.find(e=>e.focused)??r[0];N({result:n?A(n,{populate:e?.populate}):null});return}case"windows.create":{let[e]=t.args,r=await a(t.extensionId,e?.url);N({result:r?A(r,{populate:!0}):null});return}case"windows.update":{let[e,n]=t.args;if(l(e)&&!d(r,e))return void N({error:i(e),refused:!0});let o=await c(t.extensionId,null==e?void 0:String(e),n??{});N({result:o?A(o):null});return}case"windows.remove":{let[e]=t.args;if(l(e)&&!d(r,e))return void N({error:i(e),refused:!0});N({result:await g(t.extensionId,null==e?void 0:String(e))})}}}let $=new Set(["runtime.sendMessage","tabs.sendMessage","runtime.getContexts","permissions.contains","permissions.request","permissions.remove","permissions.getAll","offscreen.createDocument","offscreen.closeDocument","offscreen.hasDocument","cookies.get","cookies.getAll","cookies.set","cookies.remove","scripting.executeScript","scripting.insertCSS"]);async function E(e){let{data:t,onRuntimeMessage:r,onTabMessage:n,onGetRuntimeContexts:o,onContainsPermissions:s,onRequestPermissions:a,onRemovePermissions:i,onGetAllPermissions:l,onCreateOffscreenDocument:c,onCloseOffscreenDocument:d,onHasOffscreenDocument:u,onGetCookie:g,onGetAllCookies:f,onSetCookie:m,onRemoveCookie:p,onExecuteScript:h,onInsertCss:w,respond:b,source:y}=e;switch(t.api){case"runtime.sendMessage":{let[e]=t.args;b({result:await r(t.extensionId,e,y)});return}case"tabs.sendMessage":{let[e,r]=t.args;if(!n)return void b({error:"Could not establish connection. Receiving end does not exist."});b({result:await n(t.extensionId,e,r)});return}case"runtime.getContexts":return void b({result:await o(t.extensionId)});case"permissions.contains":{let[e]=t.args;b({result:await s(t.extensionId,e??{})});return}case"permissions.request":{let[e]=t.args;b({result:await a(t.extensionId,e??{})});return}case"permissions.remove":{let[e]=t.args;b({result:await i(t.extensionId,e??{})});return}case"permissions.getAll":return void b({result:await l(t.extensionId)});case"offscreen.createDocument":{let[e]=t.args,r=await c(t.extensionId,e??{});b({result:"boolean"!=typeof r||r});return}case"offscreen.closeDocument":{let e=await d(t.extensionId);b({result:"boolean"!=typeof e||e});return}case"offscreen.hasDocument":return void b({result:await u(t.extensionId)});case"cookies.get":{let[e]=t.args;b({result:await g(t.extensionId,e??{})});return}case"cookies.getAll":{let[e]=t.args;b({result:await f(t.extensionId,e??{})});return}case"cookies.set":{let[e]=t.args;b({result:await m(t.extensionId,e??{})});return}case"cookies.remove":{let[e]=t.args;b({result:await p(t.extensionId,e??{})});return}case"scripting.executeScript":{let[e]=t.args;b({result:await h(t.extensionId,e??{})});return}case"scripting.insertCSS":{let[e]=t.args;await w(t.extensionId,e??{}),b({result:!0})}}}let N=["local","sync","session","managed"];function D(){return[...g,...b,...v,...C,...$].sort()}function M(e,t){let r=Math.min(e.length,t.length),n=0;for(;n<r&&e[n]===t[n];)n+=1;return n}function U(e){let t=function(e){let t=D();if(t.includes(e))return null;let r=e.split(".");if(3===r.length&&"storage"===r[0]&&N.includes(r[1]??"")){let e=`storage.${r[2]}`;if(t.includes(e))return e}let n=r[r.length-1]??"",o=t.filter(e=>e.endsWith(`.${n}`));if(o.length)return o.sort((t,r)=>M(r,e)-M(t,e))[0];let s=t.filter(e=>e.startsWith(`${r[0]}.`));return s.length?s[0]??null:null}(e),r=`Unsupported API: ${e}.`;if(!t)return`${r} No wire name resembles it, so this API is not on the bridge at all. It may still work natively inside your extension's own contexts: the bridge is what an observer page can DRIVE, not the whole runtime.`;let n=t.startsWith("storage.")&&e.startsWith("storage.")?` The bridge takes the storage area as an ARGUMENT, not as part of the name: ${t}(keys, "local").`:"";return`${r} The closest wire name the bridge routes is ${t}.${n}`}let R={dom:"*",extension:["getURL","inIncognitoContext","lastError","onRequest","sendRequest"],i18n:"*",runtime:["connect","getManifest","getURL","getVersion","id","onConnect","onMessage","sendMessage"],scripting:["globalParams"],storage:"*"};function B(e){let[t="",r=""]=e.split("."),n=R[t];return"*"===n||!!Array.isArray(n)&&n.includes(r)}let P=D().filter(e=>!B(e));function O(e){var t;let r;return e.untrustedContext?B(e.api)?null:(r=(t=e.api).split(".")[0]??t,`chrome.${r} is not available to content scripts. Chrome gives a content script only chrome.storage, chrome.i18n, chrome.dom, chrome.extension and the messaging half of chrome.runtime, so ${t} cannot be reached from a page context. Call it from the background service worker or an extension page and reach the content script with runtime.sendMessage.`):null}let j=["extension","i18n","runtime","scripting","storage"],q=P.filter(e=>j.includes(e.split(".")[0]??""));JSON.stringify(j),JSON.stringify(q);let G=["url","pendingUrl","title","favIconUrl"],L=new Set(["tabs.get","tabs.query","tabs.create","tabs.update","tabs.move","tabs.discard"]),_=new Set(["windows.get","windows.getAll","windows.getCurrent","windows.create","windows.update"]),W=["url","title"];function V(e){return"<all_urls>"===e||e.includes("://")}function H(e,t){if(!e||"object"!=typeof e||function(e,t){if(e.has("tabs"))return!0;if(!t)return!1;for(let r of e){if(!V(r))continue;let e=function(e){let t;if("<all_urls>"===e)return/^(?:https?|file|ftp):\/\//;let r=/^(\*|https?|file|ftp):\/\/([^/]*)(\/.*)?$/.exec(e);if(!r)return null;let[,n="",o="",s="/*"]=r,a="*"===n?"https?":n.replace(/[.+?^${}()|[\]\\]/g,"\\$&");t="*"===o?"[^/]+":o.startsWith("*.")?`(?:[^/]+\\.)?${o.slice(2).replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*")}`:o.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*");let i=s.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return RegExp(`^${a}://${t}${i}$`)}(r);if(e?.test(t))return!0}return!1}(t,"string"==typeof e.url?e.url:"string"==typeof e.pendingUrl?e.pendingUrl:void 0))return e;let r={...e};for(let e of G)delete r[e];return r}function F(e,t){return e&&"object"==typeof e&&Array.isArray(e.tabs)?{...e,tabs:e.tabs.map(e=>H(e,t))}:e}let J={...e,storage:["storage"],scripting:["scripting","activeTab"]};function z(e,t){let r=e.split(".")[0]??"",n=J[r];return!n||null===t||n.some(e=>t.has(e))?null:`chrome.${r} needs the "${n.join('" or "')}" permission, which this session did not declare. Declare it in the manifest (and re-register the session) to use this API.`}let X=e=>"string"==typeof e&&e.length>0;function K(e,t){return`Error in invocation of ${e}: ${t}`}function Q(e,t){return K(e,`missing required property '${t}'`)}function Y(e,t,r,n){return K(e,`'${t}' expects a ${r}, got ${typeof n}`)}async function Z(e){let{data:t,getDeclaredPermissions:r,getSessionStorageAccessLevel:n}=e,o=r?r(t.extensionId):void 0,s=r=>{var n,s;return e.respond("result"in r?{...r,result:(n=t.api,s=r.result,!o||o.has("tabs")?s:L.has(n)?Array.isArray(s)?s.map(e=>H(e,o)):H(s,o):_.has(n)?Array.isArray(s)?s.map(e=>F(e,o)):F(s,o):s)}:r)},a={...e,respond:s};try{var i;if(i=t.api,!(g.has(i)||b.has(i)||v.has(i)||C.has(i)||$.has(i)))return void s({error:U(t.api),refused:!0});let e=O(t);if(e)return void s({error:e,refused:!0});let r=function(e,t){let r=t[0];switch(e){case"downloads.download":if(!r||!("url"in r))return Q(e,"url");if(!X(r.url))return Y(e,"url","non-empty string",r.url);if(void 0!==r.filename&&"string"!=typeof r.filename)return Y(e,"filename","string",r.filename);return null;case"offscreen.createDocument":if(!r||!X(r.url))return Q(e,"url");if(!Array.isArray(r.reasons)||0===r.reasons.length)return Q(e,"reasons");if(!X(r.justification))return Q(e,"justification");return null;case"contextMenus.create":if(!r)return Q(e,"title");if(void 0!==r.id&&"string"!=typeof r.id)return Y(e,"id","string",r.id);if("separator"!==r.type&&!X(r.title))return Q(e,"title");return null;case"notifications.create":{let r="string"==typeof t[0]?t[1]:t[0];if(!r)return Q(e,"options");for(let t of["type","iconUrl","title","message"])if(!X(r[t]))return Q(e,t);return null}case"action.setTitle":if(r&&void 0!==r.title&&"string"!=typeof r.title)return Y(e,"title","string",r.title);return null;case"action.setBadgeText":if(r&&void 0!==r.text&&"string"!=typeof r.text)return Y(e,"text","string",r.text);return null;case"action.setBadgeBackgroundColor":if(!r||void 0===r.color)return Q(e,"color");if("string"!=typeof r.color&&!Array.isArray(r.color))return Y(e,"color","string or array",r.color);return null;case"tabs.create":if(r?.url!==void 0&&"string"!=typeof r.url)return Y(e,"url","string",r.url);return null;default:return null}}(t.api,t.args);if(r)return void s({error:r});let l=function(e,t,r){var n,o;let s=O(e);if(s)return s;if(void 0!==t){let r=z(e.api,t)??function(e,t,r){if("tabs.query"!==e||!r||r.has("tabs")||function(e){for(let t of e)if(V(t))return!0;return!1}(r))return null;let[n]=t;if(!n||"object"!=typeof n)return null;let o=W.filter(e=>void 0!==n[e]);return o.length?`chrome.tabs.query cannot filter by "${o.join('" or "')}" without the "tabs" permission or a matching host permission, which this session did not declare. Declare it in the manifest (and re-register the session) to filter on it.`:null}(e.api,e.args,t);if(r)return r}return e.untrustedContext&&e.api.startsWith("storage.")?"session"!==(n=e.api,o=e.args,"storage.clear"===n?o[0]:o[1])||"TRUSTED_AND_UNTRUSTED_CONTEXTS"===(r?.(e.extensionId)??"TRUSTED_CONTEXTS")?null:"Access to storage is not allowed from this context.":null}(t,o,n);if(l)return void s({error:l,refused:!0});if(g.has(t.api))return void await f(a);if(b.has(t.api))return void await y(a);if(v.has(t.api))return void await x(a);if(C.has(t.api))return void await T(a);if($.has(t.api))return void await E(a);s({error:U(t.api),refused:!0})}catch(e){s({error:e instanceof Error?e.message:"Unknown error"})}}function ee(e,t){if(t){if(/^(https?|blob|data|chrome-extension):/i.test(t))return t;if(e)for(let r of[t,t.replace(/^\.?\//,""),`/${t.replace(/^\.?\//,"")}`,`./${t.replace(/^\.?\//,"")}`]){let t=e[r];if(t)return t}}}async function et(e){let t=await fetch(e);if(!t.ok)throw Error(`could not read the guest asset (HTTP ${t.status})`);let r=await t.blob(),n=new Uint8Array(await r.arrayBuffer()),o="";for(let e of n)o+=String.fromCharCode(e);let s=r.type||"application/octet-stream";return`data:${s};base64,${btoa(o)}`}async function er(e){let t=await fetch(e);if(!t.ok)throw Error(`could not read the guest icon (HTTP ${t.status})`);let r=await createImageBitmap(await t.blob());try{let e=new OffscreenCanvas(r.width,r.height).getContext("2d");if(!e)throw Error("no 2d context is available to decode the guest icon");return e.drawImage(r,0,0),e.getImageData(0,0,r.width,r.height)}finally{r.close()}}async function en(e,t){let r={...e};for(let e of["iconUrl","imageUrl","appIconMaskUrl"]){let n=ee(t,r[e]);n&&(r[e]=await et(n))}return Array.isArray(r.buttons)&&(r.buttons=await Promise.all(r.buttons.map(async e=>{let r=ee(t,e.iconUrl);return r?{...e,iconUrl:await et(r)}:e}))),r}function eo(e,t){throw Error(`${e} did not run on the real lane: ${t}`)}let es=e=>{let t=Number(e);return Number.isFinite(t)?t:void 0},ea=e=>{let t=Number(e);return Number.isFinite(t)?t:void 0},ei=new Set(["system.cpu.getInfo","system.memory.getInfo","system.storage.getInfo","system.storage.ejectDevice","system.display.getInfo","system.display.getDisplayLayout","system.display.setDisplayProperties","system.display.setDisplayLayout"]),el=["topSites","fontSettings","printing","power","tts","userScripts","debugger","system.network","enterprise.deviceAttributes","instanceID","identity","webNavigation","proxy.settings","contentSettings","tabCapture"].sort((e,t)=>t.length-e.length);function ec(e){if(ei.has(e))return"refused";for(let t of el)if(e===t||e.startsWith(`${t}.`))return"mocked";return"emulated"}let ed=/^__(ext|extjs|extension)[a-z0-9-]*__$/i,eu=new Set(["runtime.connect","runtime.onConnect","runtime.sendMessage","runtime.onMessage","tabs.connect","tabs.sendMessage"]);function eg(e){return"string"==typeof e&&ed.test(e)}let ef=new Set(["storage","action","offscreen","runtime","tabs.sendMessage","scripting","downloads","notifications","contextMenus"]);function em(e){return!!e&&(e.startsWith("Unsupported API: ")||e.startsWith("No backend implements ")||/needs the ".+" permission, which this (session did not declare|extension's manifest does not declare)/.test(e))}function ep(e){return e.refused||em(e.error)?"refused":"real"===e.lane?"real":ec(e.api)}let eh=new Set(["local","sync","session","managed"]);function ew(e,t){let r=e.split(".");if("storage"!==r[0])return e;if(3===r.length&&eh.has(r[1]??""))return`storage.${r[2]}@${r[1]}`;if(2===r.length){let e="clear"===r[1]?t?.[0]:t?.[1];return`storage.${r[1]}@${"string"==typeof e?e:"local"}`}return e}let eb=new TextEncoder;function ey(e,t){return{path:e,bytes:eb.encode(t),text:t}}let ev={manifest_version:3,name:"Hello Emulator",version:"0.1.0",description:"Trace fixture exercising emulated, mocked, and refused chrome.* tiers.",permissions:["storage","tabs","notifications","system.cpu","bookmarks","history","cookies","alarms","topSites","fontSettings","power","tts","identity","webNavigation"],action:{default_title:"Hello Emulator",default_popup:"popup.html"},background:{service_worker:"background.js"}},ex=`<!doctype html>
10
10
  <html>
11
11
  <head>
12
12
  <meta charset="utf-8" />
@@ -58,7 +58,7 @@
58
58
  <script src="popup.js"></script>
59
59
  </body>
60
60
  </html>
61
- `,q=`const out = document.getElementById("out");
61
+ `,eI=`const out = document.getElementById("out");
62
62
  const show = (label, value) => {
63
63
  out.textContent = label + "\\n" + JSON.stringify(value, null, 2);
64
64
  };
@@ -164,7 +164,7 @@ document.getElementById("battery").addEventListener("click", async () => {
164
164
  failed: failed.length ? failed : "none",
165
165
  });
166
166
  });
167
- `,U=`chrome.runtime.onInstalled.addListener(() => {
167
+ `,ek=`chrome.runtime.onInstalled.addListener(() => {
168
168
  console.log("[hello-emulator] installed");
169
169
  });
170
170
 
@@ -174,4 +174,4 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
174
174
  }
175
175
  return true;
176
176
  });
177
- `;R("manifest.json",JSON.stringify(P,null,2)),R("popup.html",O),R("popup.js",q),R("background.js",U),P.name;let{PING:j,PONG:G,BRIDGE:L,SESSION:W,INJECT:V,EVENT_PORT:_,EVENT:H,TRACE:F}={PING:"extensiondev:ping",PONG:"extensiondev:pong",BRIDGE:"extensiondev:bridge",SESSION:"extensiondev:session",INJECT:"extensiondev:inject",EVENT_PORT:"extensiondev:events",EVENT:"extensiondev:event",TRACE:"extensiondev:trace"},J=function(e={}){let t=e.engine??"chromium-emulated",r=e.limit??500,n=e.now??(()=>new Date),o=n().toISOString(),s=[],a=new Set,i=0,l=e=>{for(let t of(s.push(e),s.length>r&&s.splice(0,s.length-r),a))t(e);return e};return{recordCall:(e,r,o,s)=>l({seq:i+=1,api:e,args:o??[],extensionId:r,at:n().toISOString(),tier:A(e),engine:t,policy:s}),recordOutcome(e){let r=N(e.api,e.args),o=s.find(t=>t.extensionId===e.extensionId&&N(t.api,t.args)===r&&void 0===t.status&&void 0===t.requestId),c={requestId:e.requestId,lane:e.lane,status:void 0===e.error?"ok":"error",error:e.error,result:e.result,durationMs:e.durationMs,carrierScoped:!e.refused&&!$(e.error)&&function(e,t){if("real"!==t)return!1;if(E.has(e))return!0;let r=e.split(".")[0]??"";return E.has(r)}(e.api,e.lane)||void 0};if(o){Object.assign(o,c),o.tier=D(e);for(let e of a)e(o);return o}return l({seq:i+=1,api:e.api,args:e.args,extensionId:e.extensionId,at:n().toISOString(),tier:D(e),engine:t,...c})},events:()=>[...s],snapshot(){let e={real:0,emulated:0,mocked:0,refused:0},r=0;for(let t of s)e[t.tier??A(t.api)]+=1,"error"===t.status&&(r+=1);return{engine:t,startedAt:o,events:[...s],counts:{total:s.length,byTier:e,errors:r}}},subscribe:e=>(a.add(e),()=>a.delete(e)),clear(){s.length=0}}}({engine:"chromium-real"}),z=new Set;J.subscribe(e=>{for(let t of z)try{t.postMessage({type:F,event:e})}catch{}});let X=function(){let e={local:{},sync:{},session:{},managed:{}},t=e=>chrome.storage[e??"local"]??chrome.storage.local,r=t=>e[t??"local"]??e.local;for(let e of["local","sync","session","managed"])t(e).get(null).then(t=>{Object.assign(r(e),t)}).catch(()=>void 0);chrome.storage.onChanged.addListener((t,n)=>{if(!(n in e))return;let o=r(n);for(let[e,r]of Object.entries(t))void 0===r.newValue?delete o[e]:o[e]=r.newValue});let n=new Map;return{getStorage:(e,t)=>({...r(t)}),setStorage:(e,n,o)=>(Object.assign(r(o),n),t(o).set(n)),removeStorageKeys:(e,n,o)=>{let s=r(o);for(let e of n)delete s[e];return t(o).remove(n)},clearStorage:(e,n)=>{let o=r(n);for(let e of Object.keys(o))delete o[e];return t(n).clear()},onSetStorageAccessLevel:async(e,t,r)=>{if("session"!==t)return;n.set(e,r);let o=chrome.storage.session;await o.setAccessLevel?.({accessLevel:r})},getSessionStorageAccessLevel:e=>n.get(e),onCreateTab:(e,t)=>chrome.tabs.create({url:e,...t?.active!==void 0?{active:t.active}:{},...t?.pinned!==void 0?{pinned:t.pinned}:{},...t?.index!==void 0?{index:t.index}:{},...t?.windowId!==void 0?{windowId:t.windowId}:{},...t?.openerTabId!==void 0?{openerTabId:t.openerTabId}:{}}),onUpdateTab:(e,t)=>{let r=I(e);return null!=r?chrome.tabs.update(r,t):chrome.tabs.update(t)},onRemoveTab:e=>{let t=I(e);return null==t&&k("tabs.remove",`"${String(e)}" is not a real tab id`),chrome.tabs.remove(t)},onGetWindow:(e,t,r)=>{let n=S(t);return null==n?chrome.windows.getCurrent(r??{}):chrome.windows.get(n,r??{})},onGetAllWindows:(e,t)=>chrome.windows.getAll(t??{}),onCreateWindow:(e,t)=>chrome.windows.create({url:t}),onUpdateWindow:(e,t,r)=>{let n=S(t);return null==n?null:chrome.windows.update(n,r)},onRemoveWindow:async(e,t)=>{let r=S(t);return null!=r&&(await chrome.windows.remove(r),!0)},onOpenSidePanel:async()=>{let e=await chrome.windows.getCurrent();null==e.id&&k("sidePanel.open","there is no focused window to open it in"),await chrome.sidePanel.open({windowId:e.id})},onSetBadgeText:(e,t,r)=>{let n=I(r);return chrome.action.setBadgeText(null!=n?{text:t??"",tabId:n}:{text:t??""})},onSetBadgeBackground:(e,t,r)=>{t||k("action.setBadgeBackgroundColor","no color was given");let n=I(r);return chrome.action.setBadgeBackgroundColor(null!=n?{color:t,tabId:n}:{color:t})},onSetActionTitle:(e,t,r)=>{let n=I(r);return chrome.action.setTitle(null!=n?{title:t??"",tabId:n}:{title:t??""})},onGetActionState:async(e,t)=>{let r=I(t),n=null!=r?{tabId:r}:{},[o,s,a]=await Promise.all([chrome.action.getBadgeText(n),chrome.action.getBadgeBackgroundColor(n),chrome.action.getTitle(n)]);return{badgeText:o,badgeColor:Array.isArray(s)?`rgba(${s[0]}, ${s[1]}, ${s[2]}, ${(s[3]??255)/255})`:s??void 0,title:a}},onSetActionIcon:(e,t)=>(t||k("action.setIcon","no icon path was given"),chrome.action.setIcon({path:t})),onCreateContextMenu:(e,t)=>chrome.contextMenus.create(t),onUpdateContextMenu:async(e,t,r)=>(await chrome.contextMenus.update(t,r),!0),onRemoveContextMenu:async(e,t)=>(await chrome.contextMenus.remove(t),!0),onClearContextMenus:async()=>(await chrome.contextMenus.removeAll(),!0),onCreateNotification:(e,t,r)=>chrome.notifications.create(t??"",r),onClearNotification:(e,t)=>chrome.notifications.clear(t),onGetNotifications:()=>chrome.notifications.getAll(),onDownload:(e,t)=>chrome.downloads.download(t),onSearchDownloads:(e,t)=>chrome.downloads.search(t??{}),onCancelDownload:async(e,t)=>{await chrome.downloads.cancel(t).catch(()=>void 0)},onPauseDownload:(e,t)=>chrome.downloads.pause(t),onResumeDownload:(e,t)=>chrome.downloads.resume(t),onEraseDownloads:(e,t)=>chrome.downloads.erase(t??{}),onGetBookmarkTree:()=>chrome.bookmarks.getTree(),onGetBookmarks:(e,t)=>chrome.bookmarks.get(t),onGetBookmarkChildren:(e,t)=>t?chrome.bookmarks.getChildren(t):chrome.bookmarks.getTree(),onSearchBookmarks:(e,t)=>chrome.bookmarks.search(t??""),onCreateBookmark:(e,t)=>chrome.bookmarks.create(t),onUpdateBookmark:(e,t,r)=>chrome.bookmarks.update(t,r),onRemoveBookmark:async(e,t,r)=>(r?await chrome.bookmarks.removeTree(t):await chrome.bookmarks.remove(t),!0),onSearchHistory:(e,t)=>chrome.history.search({text:t?.text??"",...t}),onGetHistoryVisits:(e,t)=>chrome.history.getVisits({url:t?.url??""}),onAddHistoryUrl:async(e,t)=>{t?.url&&await chrome.history.addUrl({url:t.url})},onDeleteHistoryUrl:async(e,t)=>{t?.url&&await chrome.history.deleteUrl({url:t.url})},onDeleteHistoryRange:async(e,t)=>{await chrome.history.deleteRange({startTime:t?.startTime??0,endTime:t?.endTime??Date.now()})},onDeleteAllHistory:async()=>{await chrome.history.deleteAll()},onRuntimeMessage:(e,t)=>chrome.runtime.sendMessage(t),onGetRuntimeContexts:()=>chrome.runtime.getContexts({}),onContainsPermissions:(e,t)=>chrome.permissions.contains(t),onRequestPermissions:(e,t)=>chrome.permissions.request(t),onRemovePermissions:(e,t)=>chrome.permissions.remove(t),onGetAllPermissions:async()=>{let e=await chrome.permissions.getAll();return{permissions:e.permissions??[],origins:e.origins??[]}},onCreateOffscreenDocument:async(e,t)=>(await chrome.offscreen.createDocument(t),!0),onCloseOffscreenDocument:async()=>(await chrome.offscreen.closeDocument(),await chrome.offscreen.hasDocument().catch(()=>!1)&&k("offscreen.closeDocument","the offscreen document was still open after closeDocument resolved"),!0),onHasOffscreenDocument:()=>chrome.offscreen.hasDocument(),onGetCookie:(e,t)=>chrome.cookies.get(t),onGetAllCookies:(e,t)=>chrome.cookies.getAll(t),onSetCookie:(e,t)=>chrome.cookies.set(t),onRemoveCookie:(e,t)=>chrome.cookies.remove(t),onExecuteScript:(e,t)=>{let r=I(t.target?.tabId);return null==r&&k("scripting.executeScript",`target.tabId "${String(t.target?.tabId)}" is not a real tab id`),t.files?.length||k("scripting.executeScript","only the `files` form is supported here; a func/code body cannot be serialized across the bridge into a real page. Ship the code as a file in your extension and pass files: [...]"),chrome.scripting.executeScript({target:{tabId:r},files:t.files})},onInsertCss:async(e,t)=>{let r=I(t.target?.tabId);(null==r&&k("scripting.insertCSS",`target.tabId "${String(t.target?.tabId)}" is not a real tab id`),t.css)?await chrome.scripting.insertCSS({target:{tabId:r},css:t.css}):t.files?.length?await chrome.scripting.insertCSS({target:{tabId:r},files:t.files}):k("scripting.insertCSS","neither css nor files was given")}}}(),K=new Map;async function Q(){try{return(await chrome.windows.getAll({populate:!0})).map(e=>{let t=e.tabs??[],r=t.find(e=>e.active);return{id:e.id??void 0,focused:e.focused,activeTabId:r?.id??"",tabs:t.map(e=>({id:e.id??"",url:e.url??e.pendingUrl??"",title:e.title??"",active:e.active,index:e.index,status:e.status,pinned:e.pinned,discarded:e.discarded,incognito:e.incognito,tabGroupId:e.groupId}))}})}catch{return[]}}async function Y(e){let r,n=Date.now(),o=t=>(J.recordOutcome({requestId:e.requestId,extensionId:e.extensionId,api:e.api,args:e.args,lane:"real",result:t.result,error:t.error,durationMs:Date.now()-n,source:"frame",...t.refused?{refused:!0}:{}}),t),s=(r=t(e.api,K.get(e.extensionId)??new Set))?{error:r,refused:!0}:null;if(s)return o(s);let a="tabs.query"===e.api||"tabs.get"===e.api||"windows.getCurrent"===e.api?await Q():[];return new Promise(t=>{let r=!1,n=e=>{r||(r=!0,t(o(e)))};v({data:e,windows:a,...X,respond:n,source:"frame"}).catch(e=>n({error:e instanceof Error?e.message:"Bridge error"}))})}async function Z(e){let t,r,{extensionId:n,url:o,code:s,css:a,matches:i=[]}=e,l=K.get(n);if(!(l&&(l.has("scripting")||l.has("activeTab"))))return{ok:!1,error:'This extension does not declare the "scripting" (or "activeTab") permission.'};if(!i.length||!i.some(e=>{let t=function(e){let t;if("<all_urls>"===e)return/^https?:\/\/.*/;let r=/^(\*|https?|file|ftp):\/\/([^/]*)(\/.*)$/.exec(e);if(!r)return null;let[,n="",o="",s=""]=r,a="*"===n?"https?":n.replace(/[.+?^${}()|[\]\\]/g,"\\$&");t="*"===o?"[^/]+":o.startsWith("*.")?`(?:[^/]+\\.)?${o.slice(2).replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*")}`:o.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*");let i=s.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return RegExp(`^${a}://${t}${i}$`)}(e);return!!t&&t.test(o)}))return{ok:!1,error:`This extension's content scripts / host permissions do not match ${o}.`};try{t=await chrome.tabs.create({url:o,active:!0})}catch(e){return{ok:!1,error:`Could not open the tab: ${String(e)}`}}let c=t.id;if(null==c)return{ok:!1,error:"No tab id."};if(await new Promise(e=>{let t=setTimeout(()=>e(),8e3),r=(n,o)=>{n===c&&"complete"===o.status&&(clearTimeout(t),chrome.tabs.onUpdated.removeListener(r),e())};chrome.tabs.onUpdated.addListener(r)}),a)try{await chrome.scripting.insertCSS({target:{tabId:c},css:a})}catch(e){r=String(e)}if(!s)return{ok:!0,injected:!1,...r?{cssError:r}:{}};try{let[e]=await chrome.scripting.executeScript({target:{tabId:c},world:"MAIN",func:e=>{try{return(0,eval)(e),{ran:!0}}catch(e){return{ran:!1,error:String(e)}}},args:[s]}),t=e?.result;if(t&&!1===t.ran)return{ok:!0,injected:!1,blocked:!0,reason:t.error,...r?{cssError:r}:{}};return{ok:!0,injected:!0,...r?{cssError:r}:{}}}catch(e){return{ok:!1,error:`Injection failed: ${String(e)}`}}}chrome.runtime.onInstalled.addListener(()=>{}),chrome.runtime.onConnectExternal.addListener(e=>{if(e.name!==_)return;for(let t of(z.add(e),J.events()))try{e.postMessage({type:F,event:t,backlog:!0})}catch{break}let t=[],r=(r,n)=>{let o=chrome[r],s=o?.[n];if(!s||"function"!=typeof s.addListener)return;let a=(...t)=>((t,r,n)=>{try{e.postMessage({type:H,namespace:t,event:r,args:n})}catch{}})(r,n,t);s.addListener(a),t.push(()=>s.removeListener(a))};r("storage","onChanged"),r("alarms","onAlarm"),r("tabs","onCreated"),r("tabs","onUpdated"),r("tabs","onRemoved"),r("tabs","onActivated"),r("windows","onCreated"),r("windows","onRemoved"),r("windows","onFocusChanged"),r("bookmarks","onCreated"),r("bookmarks","onChanged"),r("bookmarks","onMoved"),r("bookmarks","onRemoved"),r("history","onVisited"),r("history","onVisitRemoved"),r("downloads","onCreated"),r("downloads","onChanged"),r("downloads","onErased"),r("cookies","onChanged"),r("notifications","onClicked"),r("notifications","onClosed"),r("notifications","onButtonClicked"),r("contextMenus","onClicked"),e.onDisconnect.addListener(()=>{for(let r of(z.delete(e),t))r()})}),chrome.runtime.onMessageExternal.addListener((e,t,r)=>e?.type===j?(r({type:G,version:chrome.runtime.getManifest().version,ready:!0}),!1):e?.type===W&&"string"==typeof e.extensionId?(K.set(e.extensionId,new Set(Array.isArray(e.permissions)?e.permissions:[])),r({ok:!0}),!1):e?.type===L&&e.request?(Y(e.request).then(r),!0):e?.type===V&&"string"==typeof e.url&&(Z(e).then(r),!0))})();
177
+ `;ey("manifest.json",JSON.stringify(ev,null,2)),ey("popup.html",ex),ey("popup.js",eI),ey("background.js",ek),ev.name;let{PING:eS,PONG:eA,BRIDGE:eC,SESSION:eT,INJECT:e$,EVENT_PORT:eE,EVENT:eN,TRACE:eD}={PING:"extensiondev:ping",PONG:"extensiondev:pong",BRIDGE:"extensiondev:bridge",SESSION:"extensiondev:session",INJECT:"extensiondev:inject",EVENT_PORT:"extensiondev:events",EVENT:"extensiondev:event",TRACE:"extensiondev:trace"},eM=function(e={}){let t=e.engine??"chromium-emulated",r=e.limit??500,n=e.now??(()=>new Date),o=n().toISOString(),s=[],a=new Set,i=0,l=e=>{for(s.push(e);s.length>r;){let e=s.findIndex(e=>"framework"===e.attribution);s.splice(-1===e?0:e,1)}for(let t of a)t(e);return e};return{recordCall(e,r,o,s){let a=o??[];return l({seq:i+=1,api:e,args:a,extensionId:r,at:n().toISOString(),tier:ec(e),engine:t,policy:s,...!function(e,t=[]){if(!eu.has(e))return!1;for(let e of t)if(eg(e)||e&&"object"==typeof e&&(eg(e.name)||eg(e.type)||eg(e.channel)))return!0;return!1}(e,a)?{}:{attribution:"framework"}})},recordOutcome(e){let r=ew(e.api,e.args),o=s.find(t=>t.extensionId===e.extensionId&&ew(t.api,t.args)===r&&void 0===t.status&&void 0===t.requestId),c={requestId:e.requestId,lane:e.lane,status:void 0===e.error?"ok":"error",error:e.error,result:e.result,durationMs:e.durationMs,laneDowngraded:e.laneDowngraded||void 0,downgradeReason:e.downgradeReason,carrierScoped:!e.refused&&!em(e.error)&&function(e,t){if("real"!==t)return!1;if(ef.has(e))return!0;let r=e.split(".")[0]??"";return ef.has(r)}(e.api,e.lane)||void 0};if(o){Object.assign(o,c),o.tier=ep(e);for(let e of a)e(o);return o}return l({seq:i+=1,api:e.api,args:e.args,extensionId:e.extensionId,at:n().toISOString(),tier:ep(e),engine:t,...c})},events:()=>[...s],snapshot(){let e={real:0,emulated:0,mocked:0,refused:0},r=0;for(let t of s)e[t.tier??ec(t.api)]+=1,"error"===t.status&&(r+=1);return{engine:t,startedAt:o,events:[...s],counts:{total:s.length,byTier:e,errors:r}}},subscribe:e=>(a.add(e),()=>a.delete(e)),clear(){s.length=0}}}({engine:"chromium-real"}),eU=new Set;eM.subscribe(e=>{for(let t of eU)try{t.postMessage({type:eD,event:e})}catch{}});let eR=new Map,eB=function(e={}){let t={local:{},sync:{},session:{},managed:{}},r=e=>chrome.storage[e??"local"]??chrome.storage.local,n=e=>t[e??"local"]??t.local;for(let e of["local","sync","session","managed"])r(e).get(null).then(t=>{Object.assign(n(e),t)}).catch(()=>void 0);chrome.storage.onChanged.addListener((e,r)=>{if(!(r in t))return;let o=n(r);for(let[t,r]of Object.entries(e))void 0===r.newValue?delete o[t]:o[t]=r.newValue});let o=new Map;return{getStorage:(e,t)=>({...n(t)}),setStorage:(e,t,o)=>(Object.assign(n(o),t),r(o).set(t)),removeStorageKeys:(e,t,o)=>{let s=n(o);for(let e of t)delete s[e];return r(o).remove(t)},clearStorage:(e,t)=>{let o=n(t);for(let e of Object.keys(o))delete o[e];return r(t).clear()},onSetStorageAccessLevel:async(e,t,r)=>{if("session"!==t)return;o.set(e,r);let n=chrome.storage.session;await n.setAccessLevel?.({accessLevel:r})},getSessionStorageAccessLevel:e=>o.get(e),...function(e={}){return{onCreateTab:(e,t)=>chrome.tabs.create({url:e,...t?.active!==void 0?{active:t.active}:{},...t?.pinned!==void 0?{pinned:t.pinned}:{},...t?.index!==void 0?{index:t.index}:{},...t?.windowId!==void 0?{windowId:t.windowId}:{},...t?.openerTabId!==void 0?{openerTabId:t.openerTabId}:{}}),onUpdateTab:(e,t)=>{let r=es(e);return null!=r?chrome.tabs.update(r,t):chrome.tabs.update(t)},onRemoveTab:e=>{let t=es(e);return null==t&&eo("tabs.remove",`"${String(e)}" is not a real tab id`),chrome.tabs.remove(t)},onDiscardTab:(e,t)=>{let r=es(t);return null!=r?chrome.tabs.discard(r):chrome.tabs.discard()},onGroupTabs:async(e,t)=>{let r=Array.isArray(t.tabIds)?t.tabIds:void 0!==t.tabIds?[t.tabIds]:[];return r.length||eo("tabs.group","no tabIds were given to group"),chrome.tabs.group({tabIds:r,...void 0===t.groupId?{}:{groupId:t.groupId}})},onUngroupTabs:(e,t)=>chrome.tabs.ungroup(Array.isArray(t)?t:[t]),onGetWindow:(e,t,r)=>{let n=ea(t);return null==n?chrome.windows.getCurrent(r??{}):chrome.windows.get(n,r??{})},onGetAllWindows:(e,t)=>chrome.windows.getAll(t??{}),onCreateWindow:(e,t)=>chrome.windows.create({url:t}),onUpdateWindow:(e,t,r)=>{let n=ea(t);return null==n?null:chrome.windows.update(n,r)},onRemoveWindow:async(e,t)=>{let r=ea(t);return null!=r&&(await chrome.windows.remove(r),!0)},onOpenSidePanel:async()=>{let e=await chrome.windows.getCurrent();null==e.id&&eo("sidePanel.open","there is no focused window to open it in"),await chrome.sidePanel.open({windowId:e.id})},onSetBadgeText:(e,t,r)=>{let n=es(r);return chrome.action.setBadgeText(null!=n?{text:t??"",tabId:n}:{text:t??""})},onSetBadgeBackground:(e,t,r)=>{t||eo("action.setBadgeBackgroundColor","no color was given");let n=es(r);return chrome.action.setBadgeBackgroundColor(null!=n?{color:t,tabId:n}:{color:t})},onSetActionTitle:(e,t,r)=>{let n=es(r);return chrome.action.setTitle(null!=n?{title:t??"",tabId:n}:{title:t??""})},onGetActionState:async(e,t)=>{let r=es(t),n=null!=r?{tabId:r}:{},[o,s,a]=await Promise.all([chrome.action.getBadgeText(n),chrome.action.getBadgeBackgroundColor(n),chrome.action.getTitle(n)]);return{badgeText:o,badgeColor:Array.isArray(s)?`rgba(${s[0]}, ${s[1]}, ${s[2]}, ${(s[3]??255)/255})`:s??void 0,title:a}},onSetActionIcon:async(t,r)=>{r||eo("action.setIcon","no icon path was given");let n=ee(e.getGuestAssetUrls?.(t),r);return n||eo("action.setIcon",`"${r}" is not in this guest's asset map, so the carrier cannot reach it`),chrome.action.setIcon({imageData:await er(n)})},onCreateContextMenu:(e,t)=>chrome.contextMenus.create(t),onUpdateContextMenu:async(e,t,r)=>(await chrome.contextMenus.update(t,r),!0),onRemoveContextMenu:async(e,t)=>(await chrome.contextMenus.remove(t),!0),onClearContextMenus:async()=>(await chrome.contextMenus.removeAll(),!0),onCreateNotification:async(t,r,n)=>chrome.notifications.create(r??"",await en(n??{},e.getGuestAssetUrls?.(t))),onClearNotification:(e,t)=>chrome.notifications.clear(t),onGetNotifications:()=>chrome.notifications.getAll(),onDownload:(e,t)=>chrome.downloads.download(t),onSearchDownloads:(e,t)=>chrome.downloads.search(t??{}),onCancelDownload:async(e,t)=>{await chrome.downloads.cancel(t).catch(()=>void 0)},onPauseDownload:(e,t)=>chrome.downloads.pause(t),onResumeDownload:(e,t)=>chrome.downloads.resume(t),onEraseDownloads:(e,t)=>chrome.downloads.erase(t??{}),onGetBookmarkTree:()=>chrome.bookmarks.getTree(),onGetBookmarks:(e,t)=>chrome.bookmarks.get(t),onGetBookmarkChildren:(e,t)=>t?chrome.bookmarks.getChildren(t):chrome.bookmarks.getTree(),onSearchBookmarks:(e,t)=>chrome.bookmarks.search(t??""),onCreateBookmark:(e,t)=>chrome.bookmarks.create(t),onUpdateBookmark:(e,t,r)=>chrome.bookmarks.update(t,r),onRemoveBookmark:async(e,t,r)=>(r?await chrome.bookmarks.removeTree(t):await chrome.bookmarks.remove(t),!0),onMoveBookmark:(e,t,r)=>chrome.bookmarks.move(t,r),onSearchHistory:(e,t)=>chrome.history.search({text:t?.text??"",...t}),onGetHistoryVisits:(e,t)=>chrome.history.getVisits({url:t?.url??""}),onAddHistoryUrl:async(e,t)=>{t?.url&&await chrome.history.addUrl({url:t.url})},onDeleteHistoryUrl:async(e,t)=>{t?.url&&await chrome.history.deleteUrl({url:t.url})},onDeleteHistoryRange:async(e,t)=>{await chrome.history.deleteRange({startTime:t?.startTime??0,endTime:t?.endTime??Date.now()})},onDeleteAllHistory:async()=>{await chrome.history.deleteAll()},onRuntimeMessage:(e,t)=>chrome.runtime.sendMessage(t),onGetRuntimeContexts:()=>chrome.runtime.getContexts({}),onContainsPermissions:(e,t)=>chrome.permissions.contains(t),onRequestPermissions:(e,t)=>chrome.permissions.request(t),onRemovePermissions:(e,t)=>chrome.permissions.remove(t),onGetAllPermissions:async()=>{let e=await chrome.permissions.getAll();return{permissions:e.permissions??[],origins:e.origins??[]}},onCreateOffscreenDocument:async(e,t)=>{let r=t?.url;eo("offscreen.createDocument",`the shared Live Preview carrier cannot host "${r??"an offscreen document"}", because Chrome only loads offscreen documents from the extension that asks for one. Run \`extension dev\` to load this extension as itself, where offscreen documents work normally`)},onCloseOffscreenDocument:async()=>(await chrome.offscreen.closeDocument(),await chrome.offscreen.hasDocument().catch(()=>!1)&&eo("offscreen.closeDocument","the offscreen document was still open after closeDocument resolved"),!0),onHasOffscreenDocument:()=>chrome.offscreen.hasDocument(),onGetCookie:(e,t)=>chrome.cookies.get(t),onGetAllCookies:(e,t)=>chrome.cookies.getAll(t),onSetCookie:(e,t)=>chrome.cookies.set(t),onRemoveCookie:(e,t)=>chrome.cookies.remove(t),onExecuteScript:(e,t)=>{let r=es(t.target?.tabId);return null==r&&eo("scripting.executeScript",`target.tabId "${String(t.target?.tabId)}" is not a real tab id`),t.files?.length||eo("scripting.executeScript","only the `files` form is supported here; a func/code body cannot be serialized across the bridge into a real page. Ship the code as a file in your extension and pass files: [...]"),chrome.scripting.executeScript({target:{tabId:r},files:t.files})},onInsertCss:async(e,t)=>{let r=es(t.target?.tabId);(null==r&&eo("scripting.insertCSS",`target.tabId "${String(t.target?.tabId)}" is not a real tab id`),t.css)?await chrome.scripting.insertCSS({target:{tabId:r},css:t.css}):t.files?.length?await chrome.scripting.insertCSS({target:{tabId:r},files:t.files}):eo("scripting.insertCSS","neither css nor files was given")}}}(e)}}({getGuestAssetUrls:e=>eR.get(e)}),eP=globalThis.crypto?.randomUUID?.()??String(Date.now()),eO=new Set(["TRUSTED_CONTEXTS","TRUSTED_AND_UNTRUSTED_CONTEXTS"]),ej=new Map;async function eq(){try{return(await chrome.windows.getAll({populate:!0})).map(e=>{let t=e.tabs??[],r=t.find(e=>e.active);return{id:e.id??void 0,focused:e.focused,activeTabId:r?.id??"",tabs:t.map(e=>({id:e.id??"",url:e.url??e.pendingUrl??"",title:e.title??"",active:e.active,index:e.index,status:e.status,pinned:e.pinned,discarded:e.discarded,incognito:e.incognito,tabGroupId:e.groupId}))}})}catch{return[]}}async function eG(e){let t,r=Date.now(),n=t=>(eM.recordOutcome({requestId:e.requestId,extensionId:e.extensionId,api:e.api,args:e.args,lane:"real",result:t.result,error:t.error,durationMs:Date.now()-r,source:"frame",...t.refused?{refused:!0}:{}}),t),o=(t=z(e.api,ej.get(e.extensionId)??new Set))?{error:t,refused:!0}:null;if(o)return n(o);let s="tabs.query"===e.api||"tabs.get"===e.api||"windows.getCurrent"===e.api?await eq():[];return new Promise(t=>{let r=!1,o=e=>{r||(r=!0,t(n(e)))};Z({data:e,windows:s,...eB,getDeclaredPermissions:e=>ej.get(e)??new Set,respond:o,source:"frame"}).catch(e=>o({error:e instanceof Error?e.message:"Bridge error"}))})}async function eL(e){let t,r,{extensionId:n,url:o,code:s,css:a,matches:i=[]}=e,l=!0===e.active,c=ej.get(n);if(!(c&&(c.has("scripting")||c.has("activeTab"))))return{ok:!1,error:'This extension does not declare the "scripting" (or "activeTab") permission.'};if(!i.length||!i.some(e=>{let t=function(e){let t;if("<all_urls>"===e)return/^https?:\/\/.*/;let r=/^(\*|https?|file|ftp):\/\/([^/]*)(\/.*)$/.exec(e);if(!r)return null;let[,n="",o="",s=""]=r,a="*"===n?"https?":n.replace(/[.+?^${}()|[\]\\]/g,"\\$&");t="*"===o?"[^/]+":o.startsWith("*.")?`(?:[^/]+\\.)?${o.slice(2).replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*")}`:o.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*");let i=s.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return RegExp(`^${a}://${t}${i}$`)}(e);return!!t&&t.test(o)}))return{ok:!1,error:`This extension's content scripts / host permissions do not match ${o}.`};try{t=await chrome.tabs.create({url:o,active:l})}catch(e){return{ok:!1,error:`Could not open the tab: ${String(e)}`}}let d=t.id;if(null==d)return{ok:!1,error:"No tab id."};if(await new Promise(e=>{let t=setTimeout(()=>e(),8e3),r=(n,o)=>{n===d&&"complete"===o.status&&(clearTimeout(t),chrome.tabs.onUpdated.removeListener(r),e())};chrome.tabs.onUpdated.addListener(r)}),a)try{await chrome.scripting.insertCSS({target:{tabId:d},css:a})}catch(e){r=String(e)}let u={tabId:d,active:l};if(!s)return{ok:!0,injected:!1,...u,...r?{cssError:r}:{}};try{let[e]=await chrome.scripting.executeScript({target:{tabId:d},world:"MAIN",func:e=>{try{return(0,eval)(e),{ran:!0}}catch(e){return{ran:!1,error:String(e)}}},args:[s]}),t=e?.result;if(t&&!1===t.ran)return{ok:!0,injected:!1,blocked:!0,reason:t.error,...u,...r?{cssError:r}:{}};return{ok:!0,injected:!0,...u,...r?{cssError:r}:{}}}catch(e){return{ok:!1,error:`Injection failed: ${String(e)}`}}}chrome.runtime.onInstalled.addListener(()=>{}),chrome.runtime.onConnectExternal.addListener(e=>{if(e.name!==eE)return;for(let t of(eU.add(e),eM.events()))try{e.postMessage({type:eD,event:t,backlog:!0})}catch{break}let t=[],r=(r,n)=>{let o=chrome[r],s=o?.[n];if(!s||"function"!=typeof s.addListener)return;let a=(...t)=>((t,r,n)=>{try{e.postMessage({type:eN,namespace:t,event:r,args:n})}catch{}})(r,n,t);s.addListener(a),t.push(()=>s.removeListener(a))};r("storage","onChanged"),r("alarms","onAlarm"),r("tabs","onCreated"),r("tabs","onUpdated"),r("tabs","onRemoved"),r("tabs","onActivated"),r("windows","onCreated"),r("windows","onRemoved"),r("windows","onFocusChanged"),r("bookmarks","onCreated"),r("bookmarks","onChanged"),r("bookmarks","onMoved"),r("bookmarks","onRemoved"),r("history","onVisited"),r("history","onVisitRemoved"),r("downloads","onCreated"),r("downloads","onChanged"),r("downloads","onErased"),r("cookies","onChanged"),r("notifications","onClicked"),r("notifications","onClosed"),r("notifications","onButtonClicked"),r("contextMenus","onClicked"),e.onDisconnect.addListener(()=>{for(let r of(eU.delete(e),t))r()})}),chrome.runtime.onMessageExternal.addListener((e,t,r)=>{if(e?.type===eS)return r({type:eA,version:chrome.runtime.getManifest().version,ready:!0,workerEpoch:eP}),!1;if(e?.type===eT&&"string"==typeof e.extensionId){var n,o;return ej.set(e.extensionId,new Set(Array.isArray(e.permissions)?e.permissions:[])),e.assetUrls&&"object"==typeof e.assetUrls&&eR.set(e.extensionId,e.assetUrls),n=e.extensionId,"string"==typeof(o=e.sessionAccessLevel)&&eO.has(o)&&Promise.resolve(eB.onSetStorageAccessLevel?.(n,"session",o)).catch(()=>void 0),r({ok:!0,workerEpoch:eP}),!1}return e?.type===eC&&e.request?(eG(e.request).then(r),!0):e?.type===e$&&"string"==typeof e.url&&(eL(e).then(r),!0)})})();
@@ -29,7 +29,6 @@
29
29
  "externally_connectable": {
30
30
  "matches": [
31
31
  "https://intelligence.extension.dev/*",
32
- "https://inspect.extension.dev/*",
33
32
  "https://themes.extension.dev/*",
34
33
  "https://preview.extension.dev/*",
35
34
  "http://localhost/*",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@extension.dev/mcp",
3
3
  "type": "module",
4
- "version": "6.6.0",
4
+ "version": "7.0.0",
5
5
  "description": "MCP server that lets AI agents (Claude Code, Claude Desktop, Cursor, Copilot, Codex) build, run, inspect, and publish browser extensions. 36 tools for scaffolding, live DOM inspection, log streaming, and store-ready builds across Chrome, Edge, Firefox, Safari, and every Chromium- or Gecko-based browser (Brave, Opera, Vivaldi, Yandex, Waterfox, LibreWolf). Powered by extension.dev and Extension.js.",
6
6
  "mcpName": "io.github.extensiondev/mcp",
7
7
  "license": "Apache-2.0",
package/server.json CHANGED
@@ -7,13 +7,13 @@
7
7
  "source": "github"
8
8
  },
9
9
  "websiteUrl": "https://extension.dev",
10
- "version": "6.6.0",
10
+ "version": "7.0.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "registryBaseUrl": "https://registry.npmjs.org",
15
15
  "identifier": "@extension.dev/mcp",
16
- "version": "6.6.0",
16
+ "version": "7.0.0",
17
17
  "runtimeHint": "npx",
18
18
  "transport": {
19
19
  "type": "stdio"
@@ -1,31 +0,0 @@
1
- export interface DeviceCodeStart {
2
- deviceCode: string;
3
- userCode: string;
4
- verificationUri: string;
5
- interval: number;
6
- expiresIn: number;
7
- }
8
- export type PollResult = {
9
- ok: true;
10
- githubToken: string;
11
- } | {
12
- ok: false;
13
- reason: "pending" | "expired" | "denied";
14
- error?: string;
15
- };
16
- type FetchImpl = typeof fetch;
17
- type SleepImpl = (ms: number) => Promise<void>;
18
- export declare function startDeviceCode(args: {
19
- clientId: string;
20
- scope?: string;
21
- fetchImpl?: FetchImpl;
22
- }): Promise<DeviceCodeStart>;
23
- export declare function pollForToken(args: {
24
- clientId: string;
25
- deviceCode: string;
26
- interval: number;
27
- budgetMs: number;
28
- fetchImpl?: FetchImpl;
29
- sleepImpl?: SleepImpl;
30
- }): Promise<PollResult>;
31
- export {};