@@ -467,14 +467,7 @@ export let inspectPromptPromises = () => {
467467}
468468
469469let runAction = async ( data : AppMessage ) => {
470- // console.log(`[SDK] runAction called with:`, {
471- // channel: data?.channel,
472- // actionName: data?.state?.action?.name,
473- // actionFlag: data?.state?.action?.flag,
474- // actionValue: data?.state?.action?.value,
475- // shortcut: data?.state?.shortcut,
476- // mapKeys: Array.from(global.__kitActionsMap.keys())
477- // })
470+ global . log ( `[SDK] runAction called with: channel=${ data ?. channel } , shortcut=${ data ?. state ?. shortcut } , input=${ data ?. state ?. input } , focused.name=${ data ?. state ?. focused ?. name } , focused.value=${ data ?. state ?. focused ?. value } , mapKeys=${ Array . from ( global . __kitActionsMap . keys ( ) ) . join ( ',' ) } ` )
478471
479472 let action : Action | Shortcut
480473 // Try multiple ways to find the action
@@ -487,7 +480,7 @@ let runAction = async (data: AppMessage) => {
487480 for ( const key of possibleKeys ) {
488481 if ( global . __kitActionsMap . has ( key ) ) {
489482 action = global . __kitActionsMap . get ( key )
490- // console .log(`[SDK] Found action with key: ${key}`)
483+ global . log ( `[SDK] Found action with key: ${ key } ` )
491484 break
492485 }
493486 }
@@ -502,26 +495,28 @@ let runAction = async (data: AppMessage) => {
502495 value ?. key === data . state . shortcut
503496 ) {
504497 action = value
505- // console .log(`[SDK] Found action by shortcut: ${data.state.shortcut}`)
498+ global . log ( `[SDK] Found action by shortcut: ${ data . state . shortcut } , actionName= ${ ( action as any ) ?. name } ` )
506499 break
507500 }
508501 }
509502 }
510503
511504 if ( ! action ) {
512- // console .log(`[SDK] No action found for:`, data?.state)
505+ global . log ( `[SDK] No action found for shortcut: ${ data ?. state ?. shortcut } ` )
513506 }
514507
515508 if ( action ) {
516509 const hasOnAction =
517510 typeof ( action as Action ) ?. onAction === "function"
518511 const hasOnPress =
519512 typeof ( action as Shortcut ) ?. onPress === "function"
513+ global . log ( `[SDK] Action found: name=${ ( action as any ) ?. name } , hasOnAction=${ hasOnAction } , hasOnPress=${ hasOnPress } ` )
520514 if (
521515 action ?. value &&
522516 ! hasOnAction &&
523517 ! hasOnPress
524518 ) {
519+ global . log ( `[SDK] Submitting action value: ${ action . value } ` )
525520 submit ( action . value )
526521 return
527522 }
@@ -532,6 +527,7 @@ let runAction = async (data: AppMessage) => {
532527 ? ( action as Shortcut ) . onPress
533528 : null
534529 if ( actionFunction ) {
530+ global . log ( `[SDK] Calling action function for: ${ ( action as any ) ?. name } ` )
535531 return await actionFunction (
536532 data ?. state ?. input ,
537533 data ?. state
@@ -3564,3 +3560,227 @@ global.notify = async options => {
35643560 }
35653561 await sendWait ( Channel . NOTIFY , options )
35663562}
3563+
3564+ // Measure - Screen area measurement tool
3565+ global . measure = async ( options = { } ) => {
3566+ const defaultOptions = {
3567+ color : '#00ff00' ,
3568+ strokeWidth : 2 ,
3569+ fillOpacity : 0.1 ,
3570+ showDimensions : true ,
3571+ showCrosshair : true ,
3572+ fontSize : 14 ,
3573+ gridSnap : 1 ,
3574+ constrainToDisplay : false ,
3575+ allowKeyboardAdjust : true ,
3576+ hint : 'Click and drag to measure an area. Press Enter to confirm, Escape to cancel.' ,
3577+ clipboardFormat : 'dimensions'
3578+ }
3579+
3580+ const mergedOptions = { ...defaultOptions , ...options }
3581+
3582+ try {
3583+ // Use a long timeout (5 minutes) since measurement requires user interaction
3584+ // The default 1 second timeout was causing the measurement to fail
3585+ const FIVE_MINUTES = 5 * 60 * 1000
3586+ const result = await global . sendWait ( Channel . MEASURE , mergedOptions , FIVE_MINUTES )
3587+
3588+ if ( result && typeof result === 'object' && ! result . cancelled ) {
3589+ return {
3590+ ...result ,
3591+ right : result . x + result . width ,
3592+ bottom : result . y + result . height ,
3593+ centerX : result . x + Math . floor ( result . width / 2 ) ,
3594+ centerY : result . y + Math . floor ( result . height / 2 ) ,
3595+ area : result . width * result . height ,
3596+ cancelled : false
3597+ }
3598+ }
3599+
3600+ return null
3601+ } catch ( error ) {
3602+ console . error ( 'Measurement failed:' , error )
3603+ return null
3604+ }
3605+ }
3606+
3607+ // Screen Recording - Capture screen video
3608+ global . getScreenSources = async ( ) => {
3609+ try {
3610+ const sources = await global . sendWait ( Channel . GET_SCREEN_SOURCES , { } )
3611+ return sources || [ ]
3612+ } catch ( error ) {
3613+ console . error ( 'Failed to get screen sources:' , error )
3614+ return [ ]
3615+ }
3616+ }
3617+
3618+ global . screenRecord = async ( options = { } ) => {
3619+ const defaultOptions = {
3620+ format : 'webm' ,
3621+ quality : 0.9 ,
3622+ frameRate : 30 ,
3623+ includeAudio : false ,
3624+ selectArea : false ,
3625+ showControls : true ,
3626+ countdown : true ,
3627+ countdownSeconds : 3 ,
3628+ maxDuration : 0 ,
3629+ hint : 'Click and drag to select recording area. Press Escape to cancel.'
3630+ }
3631+
3632+ const mergedOptions = { ...defaultOptions , ...options }
3633+
3634+ try {
3635+ let sourceId = mergedOptions . sourceId
3636+
3637+ if ( ! sourceId ) {
3638+ const sources = await global . getScreenSources ( )
3639+
3640+ if ( sources . length === 0 ) {
3641+ console . error ( 'No screen sources available' )
3642+ return null
3643+ }
3644+
3645+ if ( sources . length === 1 ) {
3646+ sourceId = sources [ 0 ] . id
3647+ } else {
3648+ sourceId = await global . arg ( {
3649+ placeholder : 'Select screen to record' ,
3650+ hint : 'Choose which display to record'
3651+ } , sources . map ( s => ( {
3652+ name : s . name ,
3653+ value : s . id ,
3654+ img : s . thumbnail
3655+ } ) ) )
3656+
3657+ if ( ! sourceId ) {
3658+ return null
3659+ }
3660+ }
3661+ }
3662+
3663+ let area = mergedOptions . area
3664+
3665+ if ( mergedOptions . selectArea && ! area ) {
3666+ const measureResult = await global . measure ( {
3667+ hint : mergedOptions . hint ,
3668+ color : '#ff0000' ,
3669+ showDimensions : true
3670+ } )
3671+
3672+ if ( ! measureResult ) {
3673+ return null
3674+ }
3675+
3676+ area = {
3677+ x : measureResult . x ,
3678+ y : measureResult . y ,
3679+ width : measureResult . width ,
3680+ height : measureResult . height ,
3681+ displayId : measureResult . displayId ? parseInt ( measureResult . displayId ) : undefined
3682+ }
3683+ }
3684+
3685+ const startResult = await global . sendWait ( Channel . START_SCREEN_RECORDING , {
3686+ sourceId,
3687+ area,
3688+ options : {
3689+ format : mergedOptions . format ,
3690+ quality : mergedOptions . quality ,
3691+ frameRate : mergedOptions . frameRate ,
3692+ includeAudio : mergedOptions . includeAudio ,
3693+ filePath : mergedOptions . filePath ,
3694+ maxDuration : mergedOptions . maxDuration ,
3695+ showControls : mergedOptions . showControls ,
3696+ countdown : mergedOptions . countdown ,
3697+ countdownSeconds : mergedOptions . countdownSeconds
3698+ }
3699+ } )
3700+
3701+ if ( ! startResult || ! startResult . success ) {
3702+ console . error ( 'Failed to start recording:' , startResult ?. error )
3703+ return null
3704+ }
3705+
3706+ const result = await global . sendWait ( Channel . SCREEN_RECORDING_STATUS , {
3707+ waitForComplete : true
3708+ } )
3709+
3710+ if ( ! result || result . cancelled ) {
3711+ return null
3712+ }
3713+
3714+ return {
3715+ filePath : result . filePath ,
3716+ duration : result . duration || 0 ,
3717+ width : area ?. width || result . width || 0 ,
3718+ height : area ?. height || result . height || 0 ,
3719+ cancelled : false
3720+ }
3721+ } catch ( error ) {
3722+ console . error ( 'Screen recording failed:' , error )
3723+ return null
3724+ }
3725+ }
3726+
3727+ global . stopScreenRecording = async ( ) => {
3728+ try {
3729+ const result = await global . sendWait ( Channel . STOP_SCREEN_RECORDING , { } )
3730+
3731+ if ( ! result || ! result . success ) {
3732+ return null
3733+ }
3734+
3735+ return {
3736+ filePath : result . filePath ,
3737+ duration : result . duration || 0 ,
3738+ width : result . width || 0 ,
3739+ height : result . height || 0 ,
3740+ cancelled : false
3741+ }
3742+ } catch ( error ) {
3743+ console . error ( 'Failed to stop recording:' , error )
3744+ return null
3745+ }
3746+ }
3747+
3748+ global . pauseScreenRecording = async ( ) => {
3749+ try {
3750+ const result = await global . sendWait ( Channel . PAUSE_SCREEN_RECORDING , { } )
3751+ return result ?. success ?? false
3752+ } catch ( error ) {
3753+ console . error ( 'Failed to pause recording:' , error )
3754+ return false
3755+ }
3756+ }
3757+
3758+ global . resumeScreenRecording = async ( ) => {
3759+ try {
3760+ const result = await global . sendWait ( Channel . RESUME_SCREEN_RECORDING , { } )
3761+ return result ?. success ?? false
3762+ } catch ( error ) {
3763+ console . error ( 'Failed to resume recording:' , error )
3764+ return false
3765+ }
3766+ }
3767+
3768+ global . getScreenRecordingStatus = async ( ) => {
3769+ try {
3770+ const result = await global . sendWait ( Channel . SCREEN_RECORDING_STATUS , { } )
3771+ return {
3772+ isRecording : result ?. status === 'recording' ,
3773+ isPaused : result ?. status === 'paused' ,
3774+ duration : result ?. duration || 0 ,
3775+ status : result ?. status || 'idle'
3776+ }
3777+ } catch ( error ) {
3778+ console . error ( 'Failed to get recording status:' , error )
3779+ return {
3780+ isRecording : false ,
3781+ isPaused : false ,
3782+ duration : 0 ,
3783+ status : 'idle'
3784+ }
3785+ }
3786+ }
0 commit comments