1. Description
When installing or linking Workspace Skills (e.g., running /skills link --scope workspace) in interactive mode, the "Yes/No" consent dialog remains visible on the screen even after the user selects "Yes" and the operation completes successfully. This blocks the input area, forcing the user to run /clear or restart the CLI to resume work.
2. Steps to Reproduce
- Start Gemini CLI in interactive mode.
- Execute:
/skills link <path_to_skill> --scope workspace.
- When the
ConsentPrompt appears, use arrow keys to select "Yes" and press Enter (\r).
- Observe: The terminal history shows "Successfully linked...", but the selection dialog persists on top of the input area.
3. Expected Behavior
After pressing Enter to confirm, the ConsentPrompt should be immediately unmounted from the DialogManager, and the UI should return to the normal input state.
4. Actual Behavior
The dialog persists. React DevTools (or state inspection) shows that commandConfirmationRequest in UIState still holds the previous request object instead of being reset to null.
5. Technical Root Cause Analysis
A. Missing State Cleanup Logic
In packages/cli/src/config/extensions/consent.ts, the onConfirm callback in promptForConsentInteractive only resolves the promise but fails to clear the UI state.
Affected Code:
// packages/cli/src/config/extensions/consent.ts
async function promptForConsentInteractive(
prompt: string,
addExtensionUpdateConfirmationRequest: (value: ConfirmationRequest) => void,
): Promise<boolean> {
return new Promise<boolean>((resolve) => {
addExtensionUpdateConfirmationRequest({
prompt,
onConfirm: (resolvedConfirmed) => {
// BUG: Missing addExtensionUpdateConfirmationRequest(null) to clear UI
resolve(resolvedConfirmed);
},
});
});
}
B. Rendering Blocked by Heavy Async Operations (Race Condition)
In packages/cli/src/ui/commands/skillsCommand.ts, linkSkill performs heavy I/O operations (like reloadSkills). Since several synchronous tasks are executed immediately after the await, the Ink rendering engine doesn't get a "frame" to process the "hide dialog" state update before the main thread becomes busy, leading to a visual freeze.
6. Suggested Fixes
- Update
promptForConsentInteractive: Ensure addExtensionUpdateConfirmationRequest(null) is called inside onConfirm. Wrap the resolve in setImmediate if necessary to ensure the UI update takes precedence.
- Refine Type Definitions: Update
packages/cli/src/ui/commands/types.ts to explicitly allow setConfirmationRequest to accept null.
- Command-Level Cleanup: Manually call
context.ui.setConfirmationRequest(null) at the end of the linkSkill action in skillsCommand.ts as a safety measure.
7. Environment Information
- Version: Gemini CLI v0.34.0-nightly (or latest)
- Platform: Linux/macOS
- Renderer: Ink (React for CLI)
1. Description
When installing or linking Workspace Skills (e.g., running
/skills link --scope workspace) in interactive mode, the "Yes/No" consent dialog remains visible on the screen even after the user selects "Yes" and the operation completes successfully. This blocks the input area, forcing the user to run/clearor restart the CLI to resume work.2. Steps to Reproduce
/skills link <path_to_skill> --scope workspace.ConsentPromptappears, use arrow keys to select "Yes" and pressEnter(\r).3. Expected Behavior
After pressing
Enterto confirm, theConsentPromptshould be immediately unmounted from theDialogManager, and the UI should return to the normal input state.4. Actual Behavior
The dialog persists. React DevTools (or state inspection) shows that
commandConfirmationRequestinUIStatestill holds the previous request object instead of being reset tonull.5. Technical Root Cause Analysis
A. Missing State Cleanup Logic
In
packages/cli/src/config/extensions/consent.ts, theonConfirmcallback inpromptForConsentInteractiveonly resolves the promise but fails to clear the UI state.Affected Code:
B. Rendering Blocked by Heavy Async Operations (Race Condition)
In
packages/cli/src/ui/commands/skillsCommand.ts,linkSkillperforms heavy I/O operations (likereloadSkills). Since several synchronous tasks are executed immediately after theawait, the Ink rendering engine doesn't get a "frame" to process the "hide dialog" state update before the main thread becomes busy, leading to a visual freeze.6. Suggested Fixes
promptForConsentInteractive: EnsureaddExtensionUpdateConfirmationRequest(null)is called insideonConfirm. Wrap theresolveinsetImmediateif necessary to ensure the UI update takes precedence.packages/cli/src/ui/commands/types.tsto explicitly allowsetConfirmationRequestto acceptnull.context.ui.setConfirmationRequest(null)at the end of thelinkSkillaction inskillsCommand.tsas a safety measure.7. Environment Information