diff --git a/SHA256SUMS b/SHA256SUMS index 7706121..11ba42f 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -21,8 +21,8 @@ ecd8294e24a1cd55cc1aa0b3c5d6cde68c956524cfb1d7707766b4f6287b5e3e activity/index 6c8b74d4d57bff38a393ab038418c8f410627dc66721bc416905289110f151ac activity/legal/privacy.html 297c926eb462285e52e196af2d23f2ac70cb280324bfd30aeff74836e02f159c activity/legal/terms.html ac5a46a57d2c4ba90ed861c840b7240c9367359bbb21c8167890a7a61211f783 activity/src/connection.ts -df6b8511d942c38a498fc3a74b404d92556736be37e519021bb613871c1c2984 activity/src/main.ts -8010da4164c86394863cb645eaf4567f066822114c40edf1d2762c1a5da3806a activity/src/onboarding.ts +2e6808727e3230b32d41b1c37a3c50c1029d8a48edda6d43eddd20ad4cebeed1 activity/src/main.ts +4ebc81c7b8afd960ee6249ee60086606082e88240c1d7fbc05c30e125b75d307 activity/src/onboarding.ts 66988416b7ab216ad9d3947ed528bfe9f2e45f74943971d506a686ff0b044508 activity/style.css 3fb468ea85cd082f252d85b34bb3da8b62a10ae4aa984b48ef93f0ecacc7017f data/scams/README.md 2b1733d3ba70cd80dc5e91720f0deacf0fced2145e9af5d0e5f4029c50001694 data/scams/SHA256SUMS @@ -360,7 +360,7 @@ c29b2921019f406d52ea97f99b24f5fb1b3d7d188bd5be54bf40a2b3ca60de58 scripts/kaggle d3454c1ef2f5bd1b871358485104dfb5b849c53f13d8b9b892cc0e2cdfbe2570 scripts/migration-receipt.mjs fbe41f990d155b158571ba0b8db5c5138f5cbbeb20ce6b84059aecb7d9f9b00a scripts/migration-receipt.test.mjs b2d7f56ef5420637227298102779b2b2e07d3c56b7dbbdc32ff1bb1c99107acb scripts/onboarding-browser-server.mjs -34c33ad5a8f9ecf69cb74c5b2971faaa18c50764146f658216a7eef5d10a8a6d scripts/onboarding-browser.py +5699a82961b50dfbb0eabc02833b378a7447160c753af8e306aa749bca212d1d scripts/onboarding-browser.py 2c2432b67c1739d50bd339ba9d6504ace9a9f2bf20afa8deef67daef7110ed50 scripts/onboarding-live.mjs a9ba710e3953aebf3557647bda6447a807dca2e023f3dd588955ae6faf65edea scripts/pack-browser-workflow.js 071b1afae64f798864ce9cefcb95d4642a2b17e97d3f06efb1df235653a9c32a scripts/pack-browser.py diff --git a/activity/src/main.ts b/activity/src/main.ts index 6240c22..6757580 100644 --- a/activity/src/main.ts +++ b/activity/src/main.ts @@ -175,6 +175,7 @@ let session = '', guild = '', authority: Authority | null = null, sdk: SDK | nul let status: HTMLDivElement; let browserDashboardUrl='/setup'; let agentSetup: ReturnType | undefined; +function dashboardFor(guildId: string) { const url=new URL(browserDashboardUrl,location.href); if(guildId)url.searchParams.set('guild',guildId); return url.href; } function clearAgentSetup() { agentSetup?.stop(); agentSetup = undefined; } function initializeAgentSetup() { clearAgentSetup(); @@ -186,7 +187,7 @@ function initializeAgentSetup() { if(args[0]==='onboarding/apply'&&result.receipt) settings={value:result.after,revision:result.receipt.settingsRevision}; if(args[0]==='pause'){settings=await api('settings');void render().catch(fail);} return result; - },()=>{page='Agent setup';void render().catch(fail);},browserDashboardUrl); + },()=>{page='Agent setup';void render().catch(fail);},dashboardFor(expectedGuild),sdk?url=>sdk!.commands.openExternalLink({url}):undefined); } window.addEventListener('pagehide',clearAgentSetup); const can = (cap: Capability) => authority?.capabilities.includes(cap) ?? false; diff --git a/activity/src/onboarding.ts b/activity/src/onboarding.ts index 2ccd003..ff78457 100644 --- a/activity/src/onboarding.ts +++ b/activity/src/onboarding.ts @@ -42,7 +42,8 @@ export async function registerTools(context: ModelContext | undefined, api: Api, return true; } function el(tag: string, text = '', cls = '') { const e=document.createElement(tag); e.textContent=text; e.className=cls; return e; } -export function setupPanel(api: Api, onPlan?: ()=>void, dashboardUrl = '/setup') { +// Inside Discord, openExternal opens the dashboard through the SDK; a plain link does nothing in the Activity iframe. +export function setupPanel(api: Api, onPlan?: ()=>void, dashboardUrl = '/setup', openExternal?: (url: string)=>unknown) { let target: HTMLElement | undefined, plan: any, supported = false, active = true; const controller = new AbortController(); const stop = () => { active=false; controller.abort(); clearTimeout(expiry); clearInterval(poll); supported=false; if(target)target.prepend(el('p','Session ended or authority changed. Reconnect to continue.','notice error')); }; @@ -54,8 +55,9 @@ export function setupPanel(api: Api, onPlan?: ()=>void, dashboardUrl = '/setup') const pretty=(v: unknown)=>JSON.stringify(v,null,2); function draw() { if(!target)return;target.replaceChildren(); - target.append(el('p',supported?'Browser tools registered. Discovery by your agent still depends on browser support and iframe policy.':'WebMCP unavailable or blocked. Use the manual planner below; in Discord, try the standalone dashboard with its own login.','notice')); - const external=el('a','Open browser dashboard','button quiet') as HTMLAnchorElement;external.href=dashboardUrl;external.target='_blank';external.rel='noopener noreferrer';target.append(external); + target.append(el('p',supported?'Browser tools registered. Discovery by your agent still depends on browser support and iframe policy.':openExternal?'Set up TypeCheck with the planner below. To let an AI browser agent help instead, open the browser dashboard and sign in there; Discord does not let agents use tools inside Activities.':'Set up TypeCheck with the planner below. AI browser agent tools (WebMCP) are not available in this browser.','notice')); + if(openExternal)target.append(actions('Open browser dashboard',async()=>{await openExternal(dashboardUrl);})); + else{const external=el('a','Open browser dashboard','button quiet') as HTMLAnchorElement;external.href=dashboardUrl;external.target='_blank';external.rel='noopener noreferrer';target.append(external);} target.append(el('p',ONBOARDING_NOTICE,'muted')); const form=el('div','','panel form-stack'), chosen: HTMLInputElement[]=[]; for(const preset of ONBOARDING_PRESETS){const label=el('label','','check'), box=document.createElement('input');box.type='checkbox';box.value=preset.id;chosen.push(box);const copy=el('span',preset.name);copy.append(el('small',preset.purpose+' Components: '+preset.components.join(', ')));label.append(box,copy);form.append(label);} diff --git a/scripts/onboarding-browser.py b/scripts/onboarding-browser.py index ef349a7..36c99b1 100644 --- a/scripts/onboarding-browser.py +++ b/scripts/onboarding-browser.py @@ -27,7 +27,7 @@ async def main(): # Permanent visible labeling: screenshots never imply real Discord/provider acceptance. await page.evaluate("""() => {const b=document.createElement('p');b.textContent='OFFLINE SYNTHETIC DEMO — fake Discord/Jev; not live acceptance';b.style='background:#ffedb3;color:#191919;padding:14px;font-weight:bold';document.body.prepend(b)}""") native=await page.evaluate("({documentAPI:typeof document.modelContext?.registerTool,navigatorAPI:typeof navigator.modelContext?.registerTool})") - await page.get_by_text('WebMCP unavailable or blocked.',exact=False).wait_for() + await page.get_by_text('AI browser agent tools (WebMCP) are not available',exact=False).wait_for() await page.screenshot(path=str(root/'evidence'/f'issue44-fallback-{label}.png'),full_page=True) await page.get_by_label('Scam and phishing review',exact=False).check() await page.get_by_label('Add monitored channel IDs',exact=False).fill('100000000000000021')