mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
3e4828d68d
* feat: add scale-only screenshot sizing
* fix: refuse retired --max-size inputs on every released surface
Released sizing inputs must fail closed with migration guidance instead of
silently producing native-size artifacts:
- contracts: RETIRED_SCREENSHOT_MAX_SIZE declaration + SCREENSHOT_SCALE_LIMITS
as the single source for the scale bounds and migration messages
- .ad parser: released 'screenshot ... --max-size N' and 'record start ...
--max-size N' lines now refuse at parse time (frozen replay-compat witnesses)
- daemon: screenshot rejects old-client screenshotMaxSize like recording does;
the recording guard now shares the same contract data
- Node client: screenshot/record daemon writers refuse the removed { maxSize }
option before transport
- CLI: --max-size unknown-flag error carries the migration guidance
- config/env: stale screenshotMaxSize config keys and the retired
AGENT_DEVICE_SCREENSHOT_MAX_SIZE env var are refused for sizing commands
(other commands keep working)
Quality: numberField now reuses the canonical readOptionalNumber contract
helper (AppError bounds instead of plain Error); png-resize inlines one-use
wrappers and restores the worker-thread rationale; docs typo fixed.
* test: drop retired maxSize entries from the MCP undocumented-input allowlist
* fix: refuse retired maxSize at the MCP field-projection seam + release-provenance corpus witnesses
- readFieldInput silently dropped undeclared keys before the daemon writers
could refuse them, so an MCP call carrying { maxSize } reached transport and
returned native-size success. New retiredField() combinator declares the
removed key in the field map: the projection seam refuses it with the
canonical migration message and the JSON schema no longer advertises it.
Real-route MCP executor regressions cover screenshot and record.
- replay-compat corpus: derived v0.20.5 witnesses for the released screenshot
and record --max-size forms (SHA-256 pinned, new retired-capture-size
coverage surface) so check:replay-compat proves the shipped syntax refuses
with migration guidance instead of degrading silently.
---------
Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import path from 'node:path';
|
|
|
|
import { PUBLIC_COMMANDS } from '../../../src/command-catalog.ts';
|
|
import { assertPngFile } from '../provider-scenarios/assertions.ts';
|
|
import { type LiveContext, runStep, verifyCommand } from './live-harness.ts';
|
|
|
|
const C = PUBLIC_COMMANDS;
|
|
|
|
export async function assertCaptureAndClose(context: LiveContext): Promise<void> {
|
|
const screenshotPath = path.join(context.artifactDir, 'fixture-smoke.png');
|
|
const screenshot = await runStep(context, 'capture fixture screenshot', [
|
|
'screenshot',
|
|
screenshotPath,
|
|
'--scale',
|
|
'0.5',
|
|
]);
|
|
assert.ok(
|
|
JSON.stringify(screenshot.json?.data).includes(screenshotPath),
|
|
JSON.stringify(screenshot.json),
|
|
);
|
|
assertPngFile(screenshotPath);
|
|
verifyCommand(context, C.screenshot, 'captured Android fixture file has a valid PNG signature');
|
|
|
|
await runStep(context, 'close fixture session', ['close']);
|
|
const sessions = await runStep(context, 'verify fixture session released', ['session', 'list'], {
|
|
commonFlags: false,
|
|
});
|
|
const inventory = Array.isArray(sessions.json?.data?.sessions) ? sessions.json.data.sessions : [];
|
|
assert.equal(
|
|
inventory.some((session: { name?: unknown }) => session.name === context.session),
|
|
false,
|
|
JSON.stringify(sessions.json),
|
|
);
|
|
verifyCommand(context, C.close, 'session inventory proves Android fixture lease was removed');
|
|
}
|