Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 51 additions & 39 deletions src/ui/hooks/useUnifiedCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,44 +120,58 @@ export function useUnifiedCompletion({

setIsLoadingCommands(true)
try {
const { readdirSync, statSync } = await import('fs')
// Use minimal fallback commands immediately to avoid blocking
setSystemCommands(getMinimalFallbackCommands())

// Then load full command list asynchronously without blocking
const { readdir, stat } = await import('fs/promises')
const pathDirs = (process.env.PATH || '').split(':').filter(Boolean)
const commandSet = new Set<string>()

const essentialCommands = getEssentialCommands()

essentialCommands.forEach(cmd => commandSet.add(cmd))

// Process directories with small delays to avoid blocking
for (const dir of pathDirs) {
try {
if (readdirSync && statSync) {
const entries = readdirSync(dir)
for (const entry of entries) {
try {
const fullPath = `${dir}/${entry}`
const stats = statSync(fullPath)
if (stats.isFile() && (stats.mode & 0o111) !== 0) {
commandSet.add(entry)
const entries = await readdir(dir).catch(() => [])
// Process entries in batches with yields
for (let i = 0; i < entries.length; i += 10) {
const batch = entries.slice(i, i + 10)
await Promise.all(
batch.map(async entry => {
try {
const fullPath = `${dir}/${entry}`
const stats = await stat(fullPath).catch(() => null)
if (stats?.isFile() && (stats.mode & 0o111) !== 0) {
commandSet.add(entry)
}
} catch {
// Ignore errors for individual files
}
} catch {
}
}),
)
// Yield to event loop every batch
if (i + 10 < entries.length) {
await new Promise(resolve => setImmediate(resolve))
}
}
} catch {
// Ignore errors for directories
}
}

const commands = Array.from(commandSet).sort()
setSystemCommands(commands)
} catch (error) {
logError(error)
debugLogger.warn('UNIFIED_COMPLETION_SYSTEM_COMMANDS_LOAD_FAILED', {
error: error instanceof Error ? error.message : String(error),
})
setSystemCommands(getMinimalFallbackCommands())
} finally {
setIsLoadingCommands(false)
}
} catch (error) {
logError(error)
debugLogger.warn('UNIFIED_COMPLETION_SYSTEM_COMMANDS_LOAD_FAILED', {
error: error instanceof Error ? error.message : String(error),
})
// Keep minimal fallback commands already set
} finally {
setIsLoadingCommands(false)
}
}, [systemCommands.length, isLoadingCommands])

useEffect(() => {
Expand Down Expand Up @@ -188,14 +202,14 @@ export function useUnifiedCompletion({
})

setModelSuggestions(suggestions)
} catch (error) {
logError(error)
debugLogger.warn('UNIFIED_COMPLETION_MODELS_LOAD_FAILED', {
error: error instanceof Error ? error.message : String(error),
})
setModelSuggestions([])
}
}, [])
} catch (error) {
logError(error)
debugLogger.warn('UNIFIED_COMPLETION_MODELS_LOAD_FAILED', {
error: error instanceof Error ? error.message : String(error),
})
setModelSuggestions([])
}
}, [])

useEffect(() => {
getActiveAgents()
Expand Down Expand Up @@ -268,14 +282,14 @@ export function useUnifiedCompletion({
})
setAgentSuggestions(suggestions)
})
.catch(error => {
logError(error)
debugLogger.warn('UNIFIED_COMPLETION_AGENTS_LOAD_FAILED', {
error: error instanceof Error ? error.message : String(error),
})
setAgentSuggestions([])
})
}, [])
.catch(error => {
logError(error)
debugLogger.warn('UNIFIED_COMPLETION_AGENTS_LOAD_FAILED', {
error: error instanceof Error ? error.message : String(error),
})
setAgentSuggestions([])
})
}, [])

const generateSuggestions = useCallback(
(context: CompletionContext): UnifiedSuggestion[] =>
Expand Down Expand Up @@ -352,8 +366,6 @@ export function useUnifiedCompletion({
input.slice(actualEndPos)
onInputChange(newInput)
setCursorOffset(context.startPos + completion.length)


},
[input, onInputChange, setCursorOffset, onSubmit, commands],
)
Expand Down