mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 08:51:38 +00:00
* fix(agents): honor run abort signal in image and pdf tools
The image and pdf agent tools declared `execute: async (_toolCallId, args)`
and dropped the run abort signal that `wrapToolWithAbortSignal` supplies as
the third execute argument. The wrapper only races the execute promise, so an
aborted run kept sequentially downloading images/PDFs (up to the per-tool cap,
each up to the byte cap) and still issued a paid vision/PDF-model call for a
dead run.
Thread the signal into the existing `requestInit: { signal }` seam (which the
media fetch layer already merges into the download fetch) and add
`signal.throwIfAborted()` between sequential loop items and before the paid
model call. No new media-options signal field; non-abort behavior is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(agents): keep the pdf test suite under the lint ceiling; guard model dispatch
Follow-up on the abort-signal change, resolving the check-lint failure and a
review finding on the same seam.
max-lines
---------
Adding the two pdf abort tests pushed src/agents/tools/pdf-tool.test.ts to 1018
effective lines against a ceiling of 1000, failing check-lint. Resolved without
touching config/max-lines-baseline.txt — a suppression there would also have
tripped the max-lines ratchet.
- The new tests declared their own `describe` with `beforeEach`/`afterEach`
hooks identical to the existing `describe("createPdfTool")`. They exercise
that same tool, so they now live in it and the duplicated scaffolding is gone.
- `stubPdfToolInfra`, `createPdfModelRegistry` and `FAKE_PDF_MEDIA` moved to
pdf-tool.test-support.ts, which already exists for exactly this. They go
through `createPdfToolInfraStub(completeMock)` rather than being exported
directly, because the stub wires the suite's own `complete` mock into the
model registry and vi.mock handles are file-scoped. All 21 existing call
sites are unchanged.
Abort propagation into model dispatch
-------------------------------------
The previous revision stopped cancellation at download boundaries and before
the first model call, but `runImagePrompt`/`runPdfPrompt` never saw the signal.
A run cancelled while the first provider request was in flight could still
issue the remaining ones — the image path dispatches `describeImage` once per
image in a sequential loop, so a dead run kept paying for every later image.
Both now take an optional `signal` and check it immediately before each
provider dispatch (3 sites in image-tool, 4 in pdf-tool).
Forwarding the signal further, into the provider transports themselves, is a
different seam and is deliberately left out of this PR.
Also declares `requestInit` on `ImageToolLoadWebMediaOptions`. The local facade
omitted it while the underlying loader accepts it (web-media.ts declares it and
forwards it to readRemoteMediaBuffer), so the option worked at runtime and only
compiled because spread properties skip excess-property checking. A non-spread
call site would not have.
tsgo core + core-test, oxlint, oxfmt clean; pdf-tool and image-tool suites 266
tests pass.
* test(agents): prove in-flight media aborts
* test(agents): narrow PDF loader options
* test(agents): reject abort mocks with errors
* fix(agents): propagate media cancellation
* test(agents): type PDF abort fixture
* test(agents): type prepared runtime snapshot
* fix(agents): normalize abort rejection errors
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>