Repository navigation
feat: throw SmartApplyError when smartapply refuses a model rewrite - #10
Merged
Merged
Conversation
Add SmartApplyError (extends Error, name 'SmartApplyError'), matching patchling-py. smartapply throws it, with the same message as before, when the model's rewrite changes lines the diff did not add or remove and the edit cannot be replayed from the +/- lines. Provider and network errors are not wrapped and still propagate as the original error object. Export it from src/index.js. Regenerate the .d.ts files with npm run types; this also brings src/filter.d.ts up to date for SNAKE_CASE_OPTIONS and the filterRelevant @throws note, which were not regenerated in #7. No landing/lib change: gptdiff.js and index.js are not vendored there.
Deploying patchling with
|
| Latest commit: |
0ceaeb6
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://5c57599f.patchling.pages.dev |
| Branch Preview URL: | https://feat-smartapply-error.patchling.pages.dev |
The 0.3.1 summary said there was no change to smartapply. Refusals now throw SmartApplyError: err.name, the constructor/class and the printed form (String(err), stack first line) change. The message text and the passthrough of provider/LLM errors do not.
mikkel
marked this pull request as ready for review
October 20, 2026 22:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes gap #3 from the JS↔Python parity audit. When Python's
smartapplyrefuses a model rewrite it raisesSmartApplyError. JS threw a plainError, so callers couldn't tell an intent refusal apart from a provider or network failure.This is a behavior change for refusals
When
smartapplyrefuses a model rewrite, the object it throws changes:ErrorSmartApplyError(err.constructor === SmartApplyError; stillinstanceof Error)err.name'Error''SmartApplyError'String(err), first line oferr.stack, uncaught output)Error: smartapply: refusing to write …SmartApplyError: smartapply: refusing to write …Code that checks
err.name === 'Error'orerr.constructor === Error, or that snapshots the printed error, will see the difference.What did not change:
smartapply: refusing to write "<path>": the model changed lines the diff did not add or remove.err.messagechecks and/did not add or remove/matchers keep working.SmartApplyError.CHANGELOG.md(0.3.1, unreleased) now records this under "Behavior changes", and its summary no longer says smartapply is unchanged.Changes
src/gptdiff.js: addsexport class SmartApplyError extends Error, which setsname = 'SmartApplyError'and has the constructor(message), like Python's. It's thrown at the refusal site, and thesmartapplyJSDoc gains a@throwsnote.src/index.js: exportsSmartApplyError.package.jsonexportsis unchanged..d.ts: regenerated withnpm run types(tsc 5.9.3 from the lockfile). This also bringsmain's out-of-datesrc/filter.d.tsup to date (SNAKE_CASE_OPTIONSand thefilterRelevant@throwsnote from filterRelevant: reject Python-style snake_case options #7). That part is generated type output only.CHANGELOG.md: the 0.3.1 entry described above.landing/libchange, so no site redeploy is needed.landing/libonly holds copies ofenv.js,filter.js,llm.jsandtext.js.Tests (
test/smartapply_error.test.js, 6 tests, all LLM calls mocked)src/gptdiff.js,instanceof Error,name, andString(err).instanceof SmartApplyErrorand the exact previous message, and the input isn't mutated.SmartApplyError.status: 402) from the injectedcallLlmForApplycomes through as the same object, not aSmartApplyError.TypeError('fetch failed')fromcallLlmpasses throughcallLlmForApplyunchanged.Local run
npm teston Node 20.19.2 at the head: 238 tests: 234 pass, 0 fail, 4 skipped. The skips are the live tests, which only run withLIVE_LLM/GPTDIFF_LIVE, so no LLM calls were made.