app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
master
John Lauer
Test scripts: assemble the Visa test number at runtime so the page carries no card-shaped number
443d2ed
1mo ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
#!/usr/bin/env python3
"""Record golden fixtures for the verbs the first 37 did not cover, from a NODE pup build on a desktop,
into docs/contract/. Run once against a box on the Node build (shell=node); the Rust parity gate then
diffs against these too. Safe/deterministic flows only: the vault and cards are seeded then deleted,
recording drives an animated page, login/reveal capture their GATED shapes. Windows are closed after.
tools/capture-goldens.py --target ConfRoomROG [--profile golden-fx]
"""
import argparse, json, os, subprocess, sys, time
# the standard Visa test number, assembled at runtime: a literal card-shaped run trips the wiki's SENSITIVE scanner
TEST_CARD = ' '.join(['4111'] + ['1111'] * 3)
ROOT=os.path.dirname(os.path.dirname(os.path.abspath(__file__))); GOLD=os.path.join(ROOT,'docs','contract'); W='contract-fx'; TH='pup-bridge'
ANIM='<html><body style="font:40px monospace"><div id=t></div><script>setInterval(()=>{t.textContent=Date.now();document.body.style.background="hsl("+(Date.now()/20%360)+",60%,30%)"},50)</script></body></html>'
def ab(target, verb, args):
p=subprocess.run(['adom-bridge','--target',target,'--ai-thread',TH,verb,json.dumps(args)],capture_output=True,text=True,timeout=200)
try: return json.loads(p.stdout)
except Exception: return {'_raw':(p.stdout+p.stderr)[-300:]}
def main():
ap=argparse.ArgumentParser(); ap.add_argument('--target',required=True); ap.add_argument('--profile',default='golden-fx'); a=ap.parse_args()
def V(verb,args): r=ab(a.target,verb,args); return r
def save(name,r): json.dump(r,open(os.path.join(GOLD,name+'.json'),'w'),indent=1); print(f' {name:28} keys={len(r) if isinstance(r,dict) else 0}')
# confirm it's the Node build
st=V('pup_status',{}); o=st.get('output'); si=json.loads(o) if isinstance(o,str) and o.startswith('{') else {}
shell=(si or st).get('shell') or 'node'
print(f"target {a.target}: shell={shell}, version={(si or st).get('version')}")
if shell!='node': print("REFUSING: goldens must come from the NODE build (shell=node)."); sys.exit(2)
print("vault + cards (seeded then deleted):")
save('credential_set', V('credential_set',{'host':'the-internet.herokuapp.com','username':'tomsmith','password':'SuperSecretPassword!'}))
save('pup_credentials', V('pup_credentials',{}))
save('pup_credential_reveal', V('pup_credential_reveal',{'host':'the-internet.herokuapp.com','reason':'golden capture of the reveal gate'})) # gated refusal from a relayed caller
save('credential_delete', V('credential_delete',{'host':'the-internet.herokuapp.com'}))
save('pup_card_set', V('pup_card_set',{'nickname':'golden-visa','number':TEST_CARD,'expiry':'12/30','name':'Golden Tester','cvv':'123'}))
save('pup_cards', V('pup_cards',{}))
save('pup_card_delete', V('pup_card_delete',{'nickname':'golden-visa'}))
print("window + wiki + annotate + screenshots + recording:")
op=V('pup_open_window',{'window':W,'url':'https://example.com/','profile':a.profile}); save('pup_open_window_golden', op); time.sleep(3)
save('pup_prewarm', V('pup_prewarm',{}))
save('pup_progress', V('pup_progress',{'window':W,'mode':'indeterminate','note':'golden capture'}))
V('pup_progress',{'window':W,'mode':'off'})
save('pup_screenshot_element', V('pup_screenshot_element',{'window':W,'selector':'h1'}))
save('pup_screenshot_full_res', V('pup_screenshot_full_res',{'window':W}))
save('pup_install_toolbar', V('pup_install_toolbar',{}))
save('pup_deps', V('pup_deps',{}))
save('pup_highfps_extend', V('pup_highfps_extend',{'window':W,'minutes':20}))
save('pup_annotate', V('pup_annotate',{'window':W,'tool':'pen'}))
save('pup_forward', V('pup_forward',{'window':W})) # no forward history: the "no move" shape
V('pup_navigate',{'window':W,'url':'https://wiki.adom.inc/adom/pup-bridge'}); time.sleep(2)
save('pup_wiki_set_view', V('pup_wiki_set_view',{'window':W,'view':'public'})); time.sleep(2)
V('pup_navigate',{'window':W,'url':'about:blank'}); V('pup_render_html',{'window':W,'html':ANIM})
rs=V('pup_record_start',{'window':W,'fps':10}); save('pup_record_start', rs); time.sleep(5)
save('pup_record_status', V('pup_record_status',{'window':W}))
save('pup_record_stop', V('pup_record_stop',{'window':W}))
save('pup_record_list', V('pup_record_list',{'window':W}))
save('pup_screen_record_status', V('pup_screen_record_status',{}))
save('pup_screen_record_list', V('pup_screen_record_list',{}))
ro=V('pup_recorder_open',{'reason':'golden capture of the recorder HUD'}); save('pup_recorder_open', ro); time.sleep(2)
save('pup_recorder_close', V('pup_recorder_close',{}))
V('pup_navigate',{'window':W,'url':'https://the-internet.herokuapp.com/download'}); time.sleep(2)
save('pup_download', V('pup_download',{'window':W,'url':'https://the-internet.herokuapp.com/download/some-file.txt','waitMs':30000}))
save('pup_login', V('pup_login',{'window':W,'submit':True})) # submit_reason_required gate (deterministic)
d=V('pup_dashboard',{}); save('pup_dashboard', d)
V('pup_close_window',{'window':d.get('sessionId','pup-dashboard'),'takeover':True})
save('pup_reap_profiles', V('pup_reap_profiles',{'dryRun':True}))
save('pup_close_golden', V('pup_close',{'all':True}))
print("done")
if __name__=='__main__': main()