Repository navigation
fix(cli): abort non-interactive runs when a script opens a prompt - #2274
Conversation
Findings
|
| Layer / File(s) | Summary |
|---|---|
Define the headless prompt guard src/interactive/routePrompt.ts |
Adds abortIfHeadless, which throws ChoiceAbortError when execution is explicitly non-interactive and no prompt provider is attached. |
Guard prompt entry points src/api/requestInputs.ts, src/quickAddApi.ts, src/quickAddApi.audit-api-prompts.test.ts |
Calls the guard before routing prompts or requesting missing inputs. Tests cover prompt rejection and resolution with a caller-preset variable. |
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant QuickAddApi
participant abortIfHeadless
participant PromptProvider
participant ObsidianAPI
QuickAddApi->>abortIfHeadless: Check executor and prompt details
alt Explicitly non-interactive with no provider
abortIfHeadless-->>QuickAddApi: Throw ChoiceAbortError
else Guard permits routing
abortIfHeadless-->>QuickAddApi: Return
alt Prompt provider is attached
QuickAddApi->>PromptProvider: Dispatch prompt
else No prompt provider
QuickAddApi->>ObsidianAPI: Use prompt fallback
end
end
Merge Risk: 
Moderate · up to de679
-
Prompt wrappers now reject asynchronously. A script that calls one without awaiting it, such as infoDialog, may not stop a non-interactive run, and the CLI could report success even though the dialog was never shown. Confirm how the runner handles a discarded rejection before merging, or accept this edge case explicitly.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Title check
-
Explanation
The title names the main change: non-interactive runs now abort when a script opens a prompt. The raw summary shows abortIfHeadless added to quickAddApi prompt methods and requestInputs, which matches the title. The title is short, specific, and uses the conventional fix(cli) prefix.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 2 functions across 4 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
Generate docstrings
-
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
A rabbit checks the prompt before it hops,
If headless, ChoiceAbortError stops the stops.
With preset vars, the form can pass,
Or UI brings prompts to the grass.
Eight prompt paths now heed the guard,
The rabbit stamps its review card.
Why
A Macro run through the CLI without
uishould return"aborted":truewhen its user script asks for something only a person can answer. Before this change it hung forever, because the script prompt opened a modal on a desktop nobody was watching.What
Every script-facing prompt in
quickAddApi(suggester,inputPrompt,wideInputPrompt,yesNoPrompt,checkboxPrompt,infoDialog,datePrompt) andrequestInputsnow callsabortIfHeadlessfirst. In a non-interactive run with no remote provider, that throws aChoiceAbortErrornaming the prompt, for example:A script opened a suggester "Pick a source", but this run is non-interactive. Re-run with the ui flag.requestInputsonly aborts for inputs that are still missing, and its message names the ids to pass invars. Runs withui, GUI runs, andquickadd:interactivesessions are unchanged. The wrappers becameasync, so the abort is a rejection rather than a synchronous throw.Verification
In the isolated vault, a macro whose script opens each prompt kind, run through
quickadd:run:aborted:truein 1-7 ms, with no modal left open and no file written.requestInputswith the value preset invarsreturnsok:true.ui, the suggester opens. Accepting it completes the run and writes the file.The new unit tests fail on all eight prompt kinds with the fix reverted.
pnpm run lintandpnpm run testpass.Release impact
A script that relied on a CLI run (without
ui) showing a modal on the desktop now aborts. That was the hang this fixes.Note
Medium Risk
Changes non-interactive CLI behavior for every script prompt entry point; callers that depended on desktop modals will now abort instead of hang.
Overview
Non-interactive CLI macro runs no longer hang when user scripts call prompt APIs. Instead they fail fast with
ChoiceAbortError(aborted: true) and a message naming the prompt.A shared
abortIfHeadlesshelper inroutePrompt.tsruns wheninteractive === falseand there is no remotepromptProvider. It is wired into every script-facingquickAddApiprompt (suggester,inputPrompt,wideInputPrompt,yesNoPrompt,checkboxPrompt,infoDialog,datePrompt) and intorequestInputsonly when inputs are still missing—requestInputssuggests passing ids invarsor re-running withui. Preset variables still resolve without prompting. Interactive,ui, and remote sessions are unchanged.The API wrappers are now
asyncso abort surfaces as a rejected promise. New tests cover all eight prompt paths plusrequestInputswith preset vars.Reviewed by Cursor Bugbot for commit de679fd. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Abort non-interactive CLI runs when scripts open prompts
abortIfHeadlessin routePrompt.ts, which throwsChoiceAbortErrorwhen the executor is marked non-interactive and no prompt provider is set; otherwise it returns normallyinputPrompt,datePrompt,yesNoPrompt,suggester,checkboxPrompt, and others) in quickAddApi.ts to call this guard before routing to a provider or modalrequestInputsin requestInputs.ts aborts only when requested fields are missing; fully preset inputs resolve as beforeChoiceAbortErrorinstead of hanging on a prompt; runs with a provider or not explicitly marked non-interactive keep existing routingMacroscope summarized de679fd.
Summary by CodeRabbit