feat: Codex provider, note-aware context, built-in slash commands + UX improvements#17
Conversation
… dropdown native fetch blocked by Obsidian CSP for external domains; requestUrl bypasses it. Also adds Codex model dropdown with known models + custom fallback, updates normalizeModel for gpt-5.5/5.4-mini/5.3-codex-spark. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughReplace fetch with Obsidian.requestUrl for OAuth and Codex streaming, refine Codex model normalization and SSE parsing, add provider-gated Codex model UI and built-in slash commands, and append extracted document context to selection prompts. ChangesObsidian API Integration and Codex Client Updates
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/codex-auth.ts (2)
1-205:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrettier check is currently blocking this file.
CI reports formatting issues here; please run Prettier and commit the result to unblock merge.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/codex-auth.ts` around lines 1 - 205, The file src/codex-auth.ts fails CI Prettier formatting; run Prettier on that file and commit the formatted result. Specifically, reformat the whole file (including functions generatePKCE, randomState, decodeJWT, extractAccountId, exchangeCode, refreshCodexToken, getValidCodexToken, startCodexOAuthFlow) using your project's Prettier config (or npm/yarn prettier --write) so spacing, semicolons, and line breaks match CI expectations, then stage and push the updated file.
60-78:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHarden both OAuth token flows in
src/codex-auth.tsagainst transport failures and non-JSON responses.
requestUrl(..., throw: false)doesn’t cover transport/network errors; add a try/catch around therequestUrlcall in bothexchangeCode(lines ~60-78) andrefreshCodexToken(lines ~91-107).- Both flows read
res.jsonand assume a valid payload; handle empty/invalid JSON (e.g., guard/try-catch aroundres.jsonor parse viares.text) and validate the expected types before usingaccess_token,refresh_token, andexpires_in.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/codex-auth.ts` around lines 60 - 78, The OAuth flows in exchangeCode and refreshCodexToken must be hardened: wrap the requestUrl call in each function in a try/catch to handle transport/network errors and return null (or appropriate failure) on exception, and do not rely directly on res.json; instead read/parse the response safely (e.g., get res.text and JSON.parse in a try/catch or guard res.json access) and validate types for access_token, refresh_token, and expires_in before using them—if parsing fails or required fields are missing/incorrect types, return null and log/handle the error. Ensure you update both exchangeCode and refreshCodexToken to follow the same pattern and reference TOKEN_URL, CLIENT_ID, REDIRECT_URI, access_token, refresh_token, and expires_in when validating.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/codex-client.ts`:
- Around line 22-33: The normalizeModel function currently maps any string
containing "codex" to "gpt-5.1-codex", which silently rewrites arbitrary custom
Codex IDs (e.g., "gpt-5.6-codex"); update normalizeModel to stop using the broad
m.includes("codex") rule: remove or narrow the clause that returns
"gpt-5.1-codex" for any m.includes("codex") and instead only map explicit legacy
aliases (exact matches like "codex" or previously supported short IDs) or
specific known tokens (e.g., "codex-max", "codex-mini") already handled, letting
unknown codex-branded IDs fall through to the final return so custom model IDs
are preserved.
In `@src/settings.ts`:
- Around line 147-158: When the dropdown value is changed to "custom" the code
currently only calls this.display(), so this.plugin.settings.model remains the
previous value and the UI snaps back; update the onChange handler inside the
Setting(...).addDropdown callback (the handler that compares value !== "custom")
to also set this.plugin.settings.model = "custom" and await this.saveSettings()
before calling this.display(), ensuring the "custom" selection is persisted
(references: Setting, addDropdown, CODEX_MODELS, dropdownValue,
this.plugin.settings.model, saveSettings, display).
---
Outside diff comments:
In `@src/codex-auth.ts`:
- Around line 1-205: The file src/codex-auth.ts fails CI Prettier formatting;
run Prettier on that file and commit the formatted result. Specifically,
reformat the whole file (including functions generatePKCE, randomState,
decodeJWT, extractAccountId, exchangeCode, refreshCodexToken,
getValidCodexToken, startCodexOAuthFlow) using your project's Prettier config
(or npm/yarn prettier --write) so spacing, semicolons, and line breaks match CI
expectations, then stage and push the updated file.
- Around line 60-78: The OAuth flows in exchangeCode and refreshCodexToken must
be hardened: wrap the requestUrl call in each function in a try/catch to handle
transport/network errors and return null (or appropriate failure) on exception,
and do not rely directly on res.json; instead read/parse the response safely
(e.g., get res.text and JSON.parse in a try/catch or guard res.json access) and
validate types for access_token, refresh_token, and expires_in before using
them—if parsing fails or required fields are missing/incorrect types, return
null and log/handle the error. Ensure you update both exchangeCode and
refreshCodexToken to follow the same pattern and reference TOKEN_URL, CLIENT_ID,
REDIRECT_URI, access_token, refresh_token, and expires_in when validating.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2e8186c5-54c8-4668-82e2-2f062de90337
📒 Files selected for processing (3)
src/codex-auth.tssrc/codex-client.tssrc/settings.ts
response.output_text.delta has delta as plain string not object; fix parseSseText to handle it. Also fix custom model dropdown — selecting Custom now sets model to "" so isCustom triggers correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/settings.ts (1)
1-395:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRun Prettier on this file before merge.
CI is failing formatting for this file. Please run Prettier and commit the result (pipeline already flags this exact file).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/settings.ts` around lines 1 - 395, The file fails CI formatting; run the project's Prettier formatter on this file and commit the changes — e.g., run your repo's format script or `npx prettier --write src/settings.ts` — then re-run CI. Focus on formatting changes only (no logic edits) in symbols like DEFAULT_SETTINGS, InlineAISettingsTab, saveSettings and display so the file meets the project's Prettier rules before merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/settings.ts`:
- Around line 1-395: The file fails CI formatting; run the project's Prettier
formatter on this file and commit the changes — e.g., run your repo's format
script or `npx prettier --write src/settings.ts` — then re-run CI. Focus on
formatting changes only (no logic edits) in symbols like DEFAULT_SETTINGS,
InlineAISettingsTab, saveSettings and display so the file meets the project's
Prettier rules before merging.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b01a430e-05f0-4251-a241-b5b39b400e4b
📒 Files selected for processing (2)
src/codex-client.tssrc/settings.ts
…eset, token warning - pre-check port 1455 before OAuth flow to catch clashes early - 403: friendly message suggesting gpt-5.4-mini fallback - 429: "subscription limit reached" instead of raw error - add response.output_text.done SSE path for reasoning-only responses - reset model to gpt-5.4-mini when switching to Codex provider - 10s notice on session expiry prompting user to re-sign-in in settings - warn user tokens stored in plaintext data.json when signed in Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- model dropdown shows description for each option - custom model field shows validation warning when empty - guard against empty model before API call - truncate inputs >60k chars with notice - trim whitespace from output; clearer error for reasoning-only responses - auto-reset model to gpt-5.4-mini when switching to Codex provider Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/settings.ts (1)
225-239:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPreserve custom model value when toggling between dropdown options.
When the user switches from a predefined model to "Custom…", then to another predefined model, and back to "Custom…" again, their previously-entered custom model ID is lost (Line 234 always clears
modelto""). This forces the user to re-enter their custom model ID.💾 Suggested fix to preserve the last custom model
Maintain a separate field (e.g.,
lastCustomModel) or only clearmodelwhen switching from a predefined value to "custom" for the first time:.addDropdown((dd) => { CODEX_MODELS.forEach((m) => dd.addOption(m.value, m.label)); dd.setValue(dropdownValue).onChange(async (value) => { - this.plugin.settings.model = - value === "custom" ? "" : value; + if (value === "custom") { + // Only clear if currently on a predefined model + const wasPredefined = CODEX_MODELS.some( + m => m.value === this.plugin.settings.model && m.value !== "custom" + ); + if (wasPredefined) { + this.plugin.settings.model = ""; + } + // Otherwise keep the current custom value + } else { + this.plugin.settings.model = value; + } await this.saveSettings(); this.display(); });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/settings.ts` around lines 225 - 239, The dropdown currently clears this.plugin.settings.model to "" whenever the user selects "custom", which loses any previously-entered custom ID; modify the handler in the Setting.addDropdown callback (where CODEX_MODELS are added and dd.setValue(...).onChange(...)) to preserve the last custom value instead of unconditionally setting model = ""; implement either a new field this.plugin.settings.lastCustomModel that you update when the user edits a custom model and restore into this.plugin.settings.model when "custom" is reselected, or only clear model the very first time switching to "custom" (checking previous value) so subsequent toggles restore the stored custom value; ensure you still call await this.saveSettings() and this.display() after updating settings.
♻️ Duplicate comments (1)
src/codex-client.ts (1)
35-36:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPreserve custom Codex model IDs instead of coercing them to
gpt-5.1-codex.Line 35 still rewrites any model containing
"codex", so custom IDs (for example,gpt-5.6-codex) cannot pass through unchanged.💡 Proposed fix
- if (m.includes("gpt-5.1-codex") || m.includes("codex")) + if (m.includes("gpt-5.1-codex") || m === "codex") return "gpt-5.1-codex";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/codex-client.ts` around lines 35 - 36, The current mapping forcibly rewrites any model string containing "codex" to "gpt-5.1-codex", which discards custom Codex model IDs; update the logic in src/codex-client.ts where the variable `m` is checked so that if `m` contains "codex" you return `m` unchanged (or only coerce when `m` exactly equals a legacy alias), thereby preserving custom IDs like "gpt-5.6-codex" instead of always returning "gpt-5.1-codex".
🧹 Nitpick comments (1)
src/settings.ts (1)
76-100: ⚡ Quick winExtract model IDs to avoid duplication.
CODEX_MODEL_IDSdefined here duplicates the model IDs from theCODEX_MODELSarray at lines 167-212. If a model is added or removed from one list but not the other, they'll drift out of sync.♻️ Refactor to derive IDs from CODEX_MODELS
Move
CODEX_MODELSdefinition outside the display method (e.g., as a class constant or module-level constant), then derive the IDs:+const CODEX_MODELS: { + value: string; + label: string; + desc: string; +}[] = [ + { + value: "gpt-5.5", + label: "GPT-5.5", + desc: "Most capable — best for complex rewrites and reasoning", + }, + // ... rest of models +]; + +const CODEX_MODEL_IDS = CODEX_MODELS + .filter(m => m.value !== "custom") + .map(m => m.value); export class InlineAISettingsTab extends PluginSettingTab { // ... display(): void { // ... .onChange(async (value) => { - const CODEX_MODEL_IDS = [ - "gpt-5.5", - "gpt-5.4-mini", - "gpt-5.3-codex-spark", - "gpt-5.2-codex", - "gpt-5.1-codex", - "gpt-5.1-codex-max", - "codex-mini-latest", - ]; this.plugin.settings.provider = value as🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/settings.ts` around lines 76 - 100, The CODEX_MODEL_IDS array is duplicated and can drift from CODEX_MODELS; refactor by moving CODEX_MODELS to module-level or a class constant (e.g., export/const CODEX_MODELS) and replace the local CODEX_MODEL_IDS usage with a derived ID list (e.g., CODEX_MODELS.map(m => m.id)) where the switch-to-codex logic lives (the block referencing this.plugin.settings.provider and checking value === "codex" and CODEX_MODEL_IDS.includes(this.plugin.settings.model)), so the model-reset logic uses the single source of truth for model IDs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/api.ts`:
- Around line 331-342: Replace the fragile doc.indexOf-based search with the
actual editor selection range: use the provided selection range start/end (e.g.,
selectionRange.start and selectionRange.end or the editor's
selectionStart/selectionEnd variables) to compute selectionStart and
selectionEnd, then derive before = doc.slice(0, selectionStart) and after =
doc.slice(selectionEnd); keep the existing fallback to docBeforeCursor or
cursor-based slicing only if the explicit selection range is missing or invalid.
Ensure you update references that currently use selectionStart, selectionText
and cursor so they rely on the canonical selection indices.
---
Outside diff comments:
In `@src/settings.ts`:
- Around line 225-239: The dropdown currently clears this.plugin.settings.model
to "" whenever the user selects "custom", which loses any previously-entered
custom ID; modify the handler in the Setting.addDropdown callback (where
CODEX_MODELS are added and dd.setValue(...).onChange(...)) to preserve the last
custom value instead of unconditionally setting model = ""; implement either a
new field this.plugin.settings.lastCustomModel that you update when the user
edits a custom model and restore into this.plugin.settings.model when "custom"
is reselected, or only clear model the very first time switching to "custom"
(checking previous value) so subsequent toggles restore the stored custom value;
ensure you still call await this.saveSettings() and this.display() after
updating settings.
---
Duplicate comments:
In `@src/codex-client.ts`:
- Around line 35-36: The current mapping forcibly rewrites any model string
containing "codex" to "gpt-5.1-codex", which discards custom Codex model IDs;
update the logic in src/codex-client.ts where the variable `m` is checked so
that if `m` contains "codex" you return `m` unchanged (or only coerce when `m`
exactly equals a legacy alias), thereby preserving custom IDs like
"gpt-5.6-codex" instead of always returning "gpt-5.1-codex".
---
Nitpick comments:
In `@src/settings.ts`:
- Around line 76-100: The CODEX_MODEL_IDS array is duplicated and can drift from
CODEX_MODELS; refactor by moving CODEX_MODELS to module-level or a class
constant (e.g., export/const CODEX_MODELS) and replace the local CODEX_MODEL_IDS
usage with a derived ID list (e.g., CODEX_MODELS.map(m => m.id)) where the
switch-to-codex logic lives (the block referencing this.plugin.settings.provider
and checking value === "codex" and
CODEX_MODEL_IDS.includes(this.plugin.settings.model)), so the model-reset logic
uses the single source of truth for model IDs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0cb5ce40-1321-495f-927e-f103af4a9e6c
📒 Files selected for processing (7)
src/api.tssrc/codex-auth.tssrc/codex-client.tssrc/main.tssrc/modules/commands/parser.tssrc/modules/commands/source.tssrc/settings.ts
| const selectionStart = doc.indexOf( | ||
| selectionText, | ||
| Math.max(0, cursor - selectionText.length - 200), | ||
| ); | ||
| const before = | ||
| selectionStart > 0 | ||
| ? doc.slice(0, selectionStart) | ||
| : docBeforeCursor; | ||
| const after = | ||
| selectionStart >= 0 | ||
| ? doc.slice(selectionStart + selectionText.length) | ||
| : doc.slice(cursor); |
There was a problem hiding this comment.
Use the actual editor selection range for context slicing.
Line 331 can resolve the wrong occurrence when selected text repeats, which may attach unrelated context to the model prompt.
💡 Proposed fix
- const selectionStart = doc.indexOf(
- selectionText,
- Math.max(0, cursor - selectionText.length - 200),
- );
- const before =
- selectionStart > 0
- ? doc.slice(0, selectionStart)
- : docBeforeCursor;
- const after =
- selectionStart >= 0
- ? doc.slice(selectionStart + selectionText.length)
- : doc.slice(cursor);
+ const sel = cm.state.selection.main;
+ const selectionStart = sel.from;
+ const selectionEnd = sel.to;
+ const before = doc.slice(0, selectionStart);
+ const after = doc.slice(selectionEnd);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/api.ts` around lines 331 - 342, Replace the fragile doc.indexOf-based
search with the actual editor selection range: use the provided selection range
start/end (e.g., selectionRange.start and selectionRange.end or the editor's
selectionStart/selectionEnd variables) to compute selectionStart and
selectionEnd, then derive before = doc.slice(0, selectionStart) and after =
doc.slice(selectionEnd); keep the existing fallback to docBeforeCursor or
cursor-based slicing only if the explicit selection range is missing or invalid.
Ensure you update references that currently use selectionStart, selectionText
and cursor so they rely on the canonical selection indices.
|
Just added a new release with your changes! 1.2.7 It features your provider but I made some improvements; Let me know what you think! |
Summary
/fix/shorter/longer/formal/casual/bullets/summarize/continue— ship with the plugin, no setup needed; appear in autocomplete and settings/fix /formalchains both transforms in one promptCtrl+Shift+Spacefor "Show cursor tooltip"localStorageso history survives Obsidian restartsTest plan
Ctrl+Shift+Space→ type/fix→ confirm grammar corrected/fix /formal→ both transforms appliedtags:frontmatter → AI response reflects tags🤖 Generated with Claude Code