/ utils / permissions / PermissionMode.ts
PermissionMode.ts
  1  import { feature } from 'bun:bundle'
  2  import z from 'zod/v4'
  3  import { PAUSE_ICON } from '../../constants/figures.js'
  4  // Types extracted to src/types/permissions.ts to break import cycles
  5  import {
  6    EXTERNAL_PERMISSION_MODES,
  7    type ExternalPermissionMode,
  8    PERMISSION_MODES,
  9    type PermissionMode,
 10  } from '../../types/permissions.js'
 11  import { lazySchema } from '../lazySchema.js'
 12  
 13  // Re-export for backwards compatibility
 14  export {
 15    EXTERNAL_PERMISSION_MODES,
 16    PERMISSION_MODES,
 17    type ExternalPermissionMode,
 18    type PermissionMode,
 19  }
 20  
 21  export const permissionModeSchema = lazySchema(() => z.enum(PERMISSION_MODES))
 22  export const externalPermissionModeSchema = lazySchema(() =>
 23    z.enum(EXTERNAL_PERMISSION_MODES),
 24  )
 25  
 26  type ModeColorKey =
 27    | 'text'
 28    | 'planMode'
 29    | 'permission'
 30    | 'autoAccept'
 31    | 'error'
 32    | 'warning'
 33  
 34  type PermissionModeConfig = {
 35    title: string
 36    shortTitle: string
 37    symbol: string
 38    color: ModeColorKey
 39    external: ExternalPermissionMode
 40  }
 41  
 42  const PERMISSION_MODE_CONFIG: Partial<
 43    Record<PermissionMode, PermissionModeConfig>
 44  > = {
 45    default: {
 46      title: 'Default',
 47      shortTitle: 'Default',
 48      symbol: '',
 49      color: 'text',
 50      external: 'default',
 51    },
 52    plan: {
 53      title: 'Plan Mode',
 54      shortTitle: 'Plan',
 55      symbol: PAUSE_ICON,
 56      color: 'planMode',
 57      external: 'plan',
 58    },
 59    acceptEdits: {
 60      title: 'Accept edits',
 61      shortTitle: 'Accept',
 62      symbol: '⏵⏵',
 63      color: 'autoAccept',
 64      external: 'acceptEdits',
 65    },
 66    bypassPermissions: {
 67      title: 'Bypass Permissions',
 68      shortTitle: 'Bypass',
 69      symbol: '⏵⏵',
 70      color: 'error',
 71      external: 'bypassPermissions',
 72    },
 73    dontAsk: {
 74      title: "Don't Ask",
 75      shortTitle: 'DontAsk',
 76      symbol: '⏵⏵',
 77      color: 'error',
 78      external: 'dontAsk',
 79    },
 80    ...(feature('TRANSCRIPT_CLASSIFIER')
 81      ? {
 82          auto: {
 83            title: 'Auto mode',
 84            shortTitle: 'Auto',
 85            symbol: '⏵⏵',
 86            color: 'warning' as ModeColorKey,
 87            external: 'default' as ExternalPermissionMode,
 88          },
 89        }
 90      : {}),
 91  }
 92  
 93  /**
 94   * Type guard to check if a PermissionMode is an ExternalPermissionMode.
 95   * auto is ant-only and excluded from external modes.
 96   */
 97  export function isExternalPermissionMode(
 98    mode: PermissionMode,
 99  ): mode is ExternalPermissionMode {
100    // External users can't have auto, so always true for them
101    if (process.env.USER_TYPE !== 'ant') {
102      return true
103    }
104    return mode !== 'auto' && mode !== 'bubble'
105  }
106  
107  function getModeConfig(mode: PermissionMode): PermissionModeConfig {
108    return PERMISSION_MODE_CONFIG[mode] ?? PERMISSION_MODE_CONFIG.default!
109  }
110  
111  export function toExternalPermissionMode(
112    mode: PermissionMode,
113  ): ExternalPermissionMode {
114    return getModeConfig(mode).external
115  }
116  
117  export function permissionModeFromString(str: string): PermissionMode {
118    return (PERMISSION_MODES as readonly string[]).includes(str)
119      ? (str as PermissionMode)
120      : 'default'
121  }
122  
123  export function permissionModeTitle(mode: PermissionMode): string {
124    return getModeConfig(mode).title
125  }
126  
127  export function isDefaultMode(mode: PermissionMode | undefined): boolean {
128    return mode === 'default' || mode === undefined
129  }
130  
131  export function permissionModeShortTitle(mode: PermissionMode): string {
132    return getModeConfig(mode).shortTitle
133  }
134  
135  export function permissionModeSymbol(mode: PermissionMode): string {
136    return getModeConfig(mode).symbol
137  }
138  
139  export function getModeColor(mode: PermissionMode): ModeColorKey {
140    return getModeConfig(mode).color
141  }