getNextPermissionMode.ts
utils/permissions/getNextPermissionMode.ts
102
Lines
3301
Bytes
2
Exports
5
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with shell-safety, permissions, modes. It contains 102 lines, 5 detected imports, and 2 detected exports.
Important relationships
- utils/permissions/PermissionMode.ts
- utils/permissions/PermissionPromptToolResultSchema.ts
- utils/permissions/PermissionResult.ts
- utils/permissions/PermissionRule.ts
- utils/permissions/PermissionUpdate.ts
- utils/permissions/PermissionUpdateSchema.ts
- utils/permissions/autoModeState.ts
- utils/permissions/bashClassifier.ts
Detected exports
getNextPermissionModecyclePermissionMode
Keywords
toolpermissioncontextmodeautocancycletoautocasecontextpermissionmodeisautomodegateenabledisautomodeavailablenextmode
Detected imports
bun:bundle../../Tool.js../debug.js./PermissionMode.js./permissionSetup.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
import { feature } from 'bun:bundle'
import type { ToolPermissionContext } from '../../Tool.js'
import { logForDebugging } from '../debug.js'
import type { PermissionMode } from './PermissionMode.js'
import {
getAutoModeUnavailableReason,
isAutoModeGateEnabled,
transitionPermissionMode,
} from './permissionSetup.js'
// Checks both the cached isAutoModeAvailable (set at startup by
// verifyAutoModeGateAccess) and the live isAutoModeGateEnabled() — these can
// diverge if the circuit breaker or settings change mid-session. The
// live check prevents transitionPermissionMode from throwing
// (permissionSetup.ts:~559), which would silently crash the shift+tab handler
// and leave the user stuck at the current mode.
function canCycleToAuto(ctx: ToolPermissionContext): boolean {
if (feature('TRANSCRIPT_CLASSIFIER')) {
const gateEnabled = isAutoModeGateEnabled()
const can = !!ctx.isAutoModeAvailable && gateEnabled
if (!can) {
logForDebugging(
`[auto-mode] canCycleToAuto=false: ctx.isAutoModeAvailable=${ctx.isAutoModeAvailable} isAutoModeGateEnabled=${gateEnabled} reason=${getAutoModeUnavailableReason()}`,
)
}
return can
}
return false
}
/**
* Determines the next permission mode when cycling through modes with Shift+Tab.
*/
export function getNextPermissionMode(
toolPermissionContext: ToolPermissionContext,
_teamContext?: { leadAgentId: string },
): PermissionMode {
switch (toolPermissionContext.mode) {
case 'default':
// Ants skip acceptEdits and plan — auto mode replaces them
if (process.env.USER_TYPE === 'ant') {
if (toolPermissionContext.isBypassPermissionsModeAvailable) {
return 'bypassPermissions'
}
if (canCycleToAuto(toolPermissionContext)) {
return 'auto'
}
return 'default'
}
return 'acceptEdits'
case 'acceptEdits':
return 'plan'
case 'plan':
if (toolPermissionContext.isBypassPermissionsModeAvailable) {
return 'bypassPermissions'
}
if (canCycleToAuto(toolPermissionContext)) {
return 'auto'
}
return 'default'
case 'bypassPermissions':
if (canCycleToAuto(toolPermissionContext)) {
return 'auto'
}
return 'default'
case 'dontAsk':
// Not exposed in UI cycle yet, but return default if somehow reached
return 'default'
default:
// Covers auto (when TRANSCRIPT_CLASSIFIER is enabled) and any future modes — always fall back to default
return 'default'
}
}
/**
* Computes the next permission mode and prepares the context for it.
* Handles any context cleanup needed for the target mode (e.g., stripping
* dangerous permissions when entering auto mode).
*
* @returns The next mode and the context to use (with dangerous permissions stripped if needed)
*/
export function cyclePermissionMode(
toolPermissionContext: ToolPermissionContext,
teamContext?: { leadAgentId: string },
): { nextMode: PermissionMode; context: ToolPermissionContext } {
const nextMode = getNextPermissionMode(toolPermissionContext, teamContext)
return {
nextMode,
context: transitionPermissionMode(
toolPermissionContext.mode,
nextMode,
toolPermissionContext,
),
}
}