char-slop/ai-dots
ai dotfiles
git clone https://git.t4t.associates/char-slop/ai-dots
dc2c12a
main
1import { StringEnum , Type , type Static } from "@earendil-works/pi-ai" ; 2 3const heldButtons = Type . Array ( StringEnum ([ "left" , "middle" , "right" ] as const ), { 4description :"Buttons held for this action" , 5}); 6 7export const parameters = Type . Object ( 8{ 9actions :Type . Array ( 10Type . Union ([ 11Type . Object ( 12{ 13action :StringEnum ([ "pointer" ] as const ), 14x :Type . Integer ({ 15minimum :0 , 16maximum :1919 , 17description :"Absolute screen x-coordinate: 0 is left, 1919 is right" , 18}), 19y :Type . Integer ({ 20minimum :0 , 21maximum :1079 , 22description :"Absolute screen y-coordinate: 0 is top, 1079 is bottom" , 23}), 24buttons :Type . Optional ( heldButtons ), 25}, 26{ additionalProperties :false }, 27), 28Type . Object ( 29{ 30action :StringEnum ([ "scroll" ] as const ), 31x :Type . Integer ({ 32minimum :0 , 33maximum :1919 , 34description :"Absolute screen x-coordinate: 0 is left, 1919 is right" , 35}), 36y :Type . Integer ({ 37minimum :0 , 38maximum :1079 , 39description :"Absolute screen y-coordinate: 0 is top, 1079 is bottom" , 40}), 41direction :StringEnum ([ "up" , "down" , "left" , "right" ] as const , { 42description :"Wheel direction" , 43}), 44buttons :Type . Optional ( heldButtons ), 45ticks :Type . Optional ( 46Type . Integer ({ 47minimum :1 , 48default :1 , 49description :"Wheel notches; omit for one" , 50}), 51), 52}, 53{ additionalProperties :false }, 54), 55Type . Object ( 56{ 57action :StringEnum ([ "type" ] as const ), 58text :Type . String ({ 59description : 60"Literal text to type; use a key action for named keys and shortcuts. On Wayland, characters missing from the remote keymap are dropped, not transliterated. Windows supports Unicode independently of the keyboard layout" , 61}), 62}, 63{ additionalProperties :false }, 64), 65Type . Object ( 66{ 67action :StringEnum ([ "key" ] as const ), 68key :Type . String ({ 69description : 70"One XKB-style key name, such as Return, Escape, Tab, BackSpace, Delete, Left, Page_Down, F5, or a. Put shortcut modifiers in modifiers; do not put them in key" , 71pattern :"^[A-Za-z0-9_]+$" , 72}), 73modifiers :Type . Optional ( 74Type . Array ( StringEnum ([ "shift" , "ctrl" , "alt" , "logo" ] as const ), { 75description :"Modifiers held while pressing the key" , 76uniqueItems :true , 77}), 78), 79}, 80{ additionalProperties :false }, 81), 82Type . Object ( 83{ 84action :StringEnum ([ "new_browser_tab" ] as const ), 85url :Type . String ({ 86description : 87"HTTP or HTTPS URL to open in a new Firefox tab every time on Wayland, or in the default browser on Windows (which controls tab reuse); prefer web_fetch for ordinary page reading" , 88pattern :"^https?://" , 89}), 90}, 91{ additionalProperties :false }, 92), 93Type . Object ( 94{ 95action :StringEnum ([ "recall" ] as const ), 96id :Type . String ({ 97description :"ID from an earlier screenshot result" , 98pattern :"^sc_[0-9a-f]{16}$" , 99}), 100}, 101{ additionalProperties :false }, 102), 103Type . Object ( 104{ action :StringEnum ([ "screenshot" ] as const ) }, 105{ additionalProperties :false }, 106), 107Type . Object ( 108{ 109action :StringEnum ([ "sleep" ] as const ), 110ms :Type . Integer ({ 111minimum :0 , 112maximum :30_000 , 113description :"Time to wait, in milliseconds" , 114}), 115}, 116{ additionalProperties :false }, 117), 118]), 119{ minItems :1 , maxItems :20 }, 120), 121}, 122{ additionalProperties :false }, 123); 124 125export type Action = Static < typeof parameters >[ "actions" ][ number ]; 126export type DesktopAction = Exclude < Action , { action :"recall" | "sleep" }>; 127 128export interface DesktopBackend { 129execute ( action :DesktopAction , signal ?:AbortSignal ) :Promise < Buffer | void >; 130close () :Promise < void >; 131} 132 133export function checkSignal ( signal ?:AbortSignal ) :void { 134if ( signal ?. aborted ) throw new Error ( "Operation aborted" ); 135} 136 137export function wait ( ms :number , signal ?:AbortSignal ) :Promise < void > { 138return new Promise (( resolve , reject ) => { 139if ( signal ?. aborted ) { 140reject ( new Error ( "Operation aborted" )); 141return ; 142} 143 144const timer = setTimeout (() => { 145signal ?. removeEventListener ( "abort" , abort ); 146resolve (); 147}, ms ); 148const abort = () => { 149clearTimeout ( timer ); 150reject ( new Error ( "Operation aborted" )); 151}; 152signal ?. addEventListener ( "abort" , abort , { once :true }); 153}); 154}