@@ -61,9 +61,12 @@ import projectsRoutes, { WORKSPACES_ROOT, validateWorkspacePath } from './routes
6161import cliAuthRoutes from './routes/cli-auth.js' ;
6262import userRoutes from './routes/user.js' ;
6363import codexRoutes from './routes/codex.js' ;
64- import { initializeDatabase } from './database/db.js' ;
64+ import bcrypt from 'bcrypt' ;
65+ import { initializeDatabase , userDb } from './database/db.js' ;
6566import { validateApiKey , authenticateToken , authenticateWebSocket } from './middleware/auth.js' ;
6667import { IS_PLATFORM } from './constants/config.js' ;
68+ import { getSystemGitConfig } from './utils/gitConfig.js' ;
69+ import yoloRoutes from './routes/yolo.js' ;
6770
6871// File system watchers for provider project/session folders
6972const PROVIDER_WATCH_PATHS = [
@@ -206,6 +209,60 @@ async function setupProjectsWatcher() {
206209 }
207210}
208211
212+ // YOLO file watcher - watches /home/coder/.yolo for bypass permissions gating
213+ const YOLO_FILE_PATH = '/home/coder/.yolo' ;
214+ const YOLO_PARENT_DIR = path . dirname ( YOLO_FILE_PATH ) ;
215+ const YOLO_FILE_NAME = path . basename ( YOLO_FILE_PATH ) ;
216+
217+ async function setupYoloWatcher ( ) {
218+ try {
219+ const chokidar = ( await import ( 'chokidar' ) ) . default ;
220+ const { checkYoloStatus } = await import ( './routes/yolo.js' ) ;
221+
222+ // Ensure parent directory exists before watching
223+ try {
224+ await fsPromises . mkdir ( YOLO_PARENT_DIR , { recursive : true } ) ;
225+ } catch {
226+ // Directory may already exist or be inaccessible
227+ }
228+
229+ const watcher = chokidar . watch ( YOLO_PARENT_DIR , {
230+ ignored : ( filePath ) => {
231+ // Only watch the .yolo file itself and the parent dir
232+ const base = path . basename ( filePath ) ;
233+ return filePath !== YOLO_PARENT_DIR && base !== YOLO_FILE_NAME ;
234+ } ,
235+ persistent : true ,
236+ ignoreInitial : true ,
237+ followSymlinks : false ,
238+ depth : 0 ,
239+ awaitWriteFinish : {
240+ stabilityThreshold : 100 ,
241+ pollInterval : 50
242+ }
243+ } ) ;
244+
245+ const broadcastYoloStatus = ( ) => {
246+ const allowed = checkYoloStatus ( ) ;
247+ const message = JSON . stringify ( { type : 'yolo_status' , allowed } ) ;
248+ connectedClients . forEach ( client => {
249+ if ( client . readyState === WebSocket . OPEN ) {
250+ client . send ( message ) ;
251+ }
252+ } ) ;
253+ } ;
254+
255+ watcher
256+ . on ( 'add' , broadcastYoloStatus )
257+ . on ( 'change' , broadcastYoloStatus )
258+ . on ( 'unlink' , broadcastYoloStatus )
259+ . on ( 'error' , ( error ) => {
260+ console . error ( '[ERROR] YOLO watcher error:' , error ) ;
261+ } ) ;
262+ } catch ( error ) {
263+ console . error ( '[WARN] Failed to setup YOLO file watcher:' , error ) ;
264+ }
265+ }
209266
210267const app = express ( ) ;
211268const server = http . createServer ( app ) ;
@@ -379,6 +436,9 @@ app.use('/api/user', authenticateToken, userRoutes);
379436// Codex API Routes (protected)
380437app . use ( '/api/codex' , authenticateToken , codexRoutes ) ;
381438
439+ // YOLO status API Routes (protected)
440+ app . use ( '/api/yolo' , authenticateToken , yoloRoutes ) ;
441+
382442// Agent API Routes (uses API key authentication)
383443app . use ( '/api/agent' , agentRoutes ) ;
384444
@@ -1918,6 +1978,31 @@ async function startServer() {
19181978 // Initialize authentication database
19191979 await initializeDatabase ( ) ;
19201980
1981+ // INSTANT_START: auto-provision user on startup
1982+ if ( process . env . INSTANT_START === 'true' ) {
1983+ try {
1984+ const hasUsers = userDb . hasUsers ( ) ;
1985+ if ( ! hasUsers ) {
1986+ const passwordHash = await bcrypt . hash ( 'password' , 12 ) ;
1987+ const user = userDb . createUser ( 'username' , passwordHash ) ;
1988+ console . log ( `${ c . ok ( '[OK]' ) } INSTANT_START: Created user "username" (id: ${ user . id } )` ) ;
1989+
1990+ const gitConfig = await getSystemGitConfig ( ) ;
1991+ if ( gitConfig . git_name || gitConfig . git_email ) {
1992+ userDb . updateGitConfig ( user . id , gitConfig . git_name , gitConfig . git_email ) ;
1993+ console . log ( `${ c . ok ( '[OK]' ) } INSTANT_START: Set git config: ${ gitConfig . git_name } <${ gitConfig . git_email } >` ) ;
1994+ }
1995+
1996+ userDb . completeOnboarding ( user . id ) ;
1997+ console . log ( `${ c . ok ( '[OK]' ) } INSTANT_START: Onboarding marked complete` ) ;
1998+ } else {
1999+ console . log ( `${ c . info ( '[INFO]' ) } INSTANT_START: User already exists, skipping auto-provisioning` ) ;
2000+ }
2001+ } catch ( error ) {
2002+ console . error ( `${ c . warn ( '[WARN]' ) } INSTANT_START: Failed to auto-provision user:` , error ) ;
2003+ }
2004+ }
2005+
19212006 // Check if running in production mode (dist folder exists)
19222007 const distIndexPath = path . join ( __dirname , '../dist/index.html' ) ;
19232008 const isProduction = fs . existsSync ( distIndexPath ) ;
@@ -1945,6 +2030,9 @@ async function startServer() {
19452030
19462031 // Start watching the projects folder for changes
19472032 await setupProjectsWatcher ( ) ;
2033+
2034+ // Start watching /home/coder/.yolo for YOLO mode gating
2035+ await setupYoloWatcher ( ) ;
19482036 } ) ;
19492037 } catch ( error ) {
19502038 console . error ( '[ERROR] Failed to start server:' , error ) ;
0 commit comments