feat(page): print the eval-js value bare and use exception_detail for failures - #72
Merged
Merged
Conversation
… failures eval-js printed "Successfully executed action: evaluate_js" followed by "Result: <value>", so the evaluated value could not be piped without post-processing, and a legitimately empty value vanished entirely (the Result line was skipped when markdown was empty). The value now prints alone on stdout with the status line on stderr; -o json is unchanged. Failures across every page command now prefer the structured exception_detail (nottelabs/notte#907) over the legacy `exception` string. That string is rendered in whatever ErrorConfig mode the server ran in, which for the API is "user" - so a failed action reported "Sorry, this action cannot be executed at the moment." instead of the JavaScript error. The shared helper reports the concrete error type and the developer message, falling back to the legacy string for API builds that predate the field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| internal/cmd/output_helpers.go | Adds shared structured failure formatting, but forwards DevMessage without the sanitization used by the established API error path. |
| internal/cmd/page.go | Routes page failures through the new helper and separates eval-js result and status streams. |
| internal/cmd/execution_failure_test.go | Covers structured-detail preference and fallback ordering, though it does not exercise output sanitization. |
Prompt To Fix All With AI
### Issue 1
internal/cmd/output_helpers.go:240-254
**Developer errors bypass sanitization**
If `DevMessage` contains control characters or excessive text, `executionFailureError` forwards it as an ordinary error without the sanitization applied by the API error path, causing failed page actions to emit raw terminal sequences or unbounded output on stderr.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "feat(page): print the eval-js value bare..." | Re-trigger Greptile
Exercises the two shapes the docs promise - title=$(notte page eval-js "document.title") capturing the value alone, and piping JSON.stringify(...) output into a JSON parser - plus a JS null arriving as "null" rather than empty, -o json still emitting the envelope, and a failing script exiting non-zero with the actual JavaScript error instead of the generic user-facing sentence. The shared harness prepends `-o json`, so these use a text-mode runner: the point is what a shell sees without --output json. Note the filename: page_eval_js_test.go would end in _js, which Go reads as the js/wasm GOOS suffix and silently excludes from every other platform's build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 25, 2026
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.
Two changes to
notte page, both about surfacing what actually happened.1.
eval-jsoutputBefore, a successful eval printed two lines:
so the value could not be piped without post-processing — and when the evaluated value was legitimately empty the
Result:line was skipped entirely (it was gated onMarkdown != ""), leaving only a success banner.Now the value prints alone on stdout and the status line goes to stderr:
Interactive use is unchanged (stderr still shows in the terminal), and
-o jsonstill prints the full execution result. Help text documents the contract.2.
exception_detailacross every page commandThe API serializes a failure twice:
exceptionis a bare string rendered in whateverErrorConfigmode the server ran in — and the API runsset_error_mode("user"), so it is usually the generic "Sorry, this action cannot be executed at the moment." — whileexception_detail(nottelabs/notte#907, already in the generated client) carries the concrete error type, the per-audience messages and the retry/notify flags.A new shared
executionFailureErrorhelper prefers the structured field, so a failed action now reports e.g.instead of the generic sentence. It falls back to the legacy
exceptionstring, thenmessage, for API builds that predate the field. Wired into both failure sites:printExecuteResponse(used by click, fill, goto, scroll, press, wait, … — every page action) andeval-js.Tests
internal/cmd/execution_failure_test.go: prefers structured detail over the generic string, falls back touser_messagewhendev_messageis absent, legacy-string path, message-only path, and the nothing-to-go-on path. Fullgo test ./internal/...andgo vet ./...pass.🤖 Generated with Claude Code