Files
filip131311 d0b3356ebf feat(tool-server): paste tool (device clipboard + paste shortcut) (#879)
## Summary
Registers a real `paste` tool. The `tools/paste/index.ts` from #506 was
never registered and sent a `{cmd:"paste"}` WebSocket command
simulator-server doesn't implement — dead on every platform.

- **iOS simulator**: simulator-server `POST /api/clipboard/text` fills a
private pasteboard and pushes it into the sim synchronously (host
clipboard untouched); the tool then sends the ⌘V chord over the existing
`key` command (the same `simulatorSendKeyEvent` path the keyboard tool
uses).
- **Android emulator**: same route over the emulator gRPC bridge, then
`KEYCODE_PASTE` via `adb shell input`.
- **ios-remote**: the MoQ transport's existing paste primitive, awaited.
- Clean 400 for tvOS / Android TV (runtime probe), physical devices,
Chromium (a renderer paste would clobber the *host* clipboard), Vega.
- `{{secret:<NAME>}}` placeholders as in `keyboard`; allowed inside
`run-sequence`; device-interact SKILL updated.
- Description/skill tell the agent `paste` is **not** a `keyboard`
substitute — only where a real user would paste (OTP/2FA code, long
link/token, testing paste handling).

## Blocked on
a simulator-server built with the `clipboard` feature:
software-mansion/radon#185 adds it to the `argent` alias (no sim-server
API change). Until a release + bin bump, the tool reports
`PASTE_CLIPBOARD_UNSUPPORTED` (with an update hint) against the shipped
binary.

## Test plan
- 13 new unit tests (`test/paste.test.ts`) + secret-placeholder tests;
full tool-server suite, lint, knip green (the 4 telemetry/bind test
files that fail locally fail identically on `main`).
- Live against a locally built simulator-server: iOS 26.5 Settings
search (12 back-to-back pastes in order), Messages composer
(multi-line/tab/emoji/diacritics preserved), `{{secret:EMAIL}}` never
echoed or logged; Pixel_9 Settings search (ASCII + `Zażółć🔑`), Expensify
RN login field; `run-sequence` paste steps; live 400s for tvOS sim /
phone serial / chromium id.
2026-08-21 16:51:51 +02:00
..
2026-08-21 16:03:35 +02:00

Argent documentation

The Argent documentation site, published at docs.swmansion.com/argent.

Built with Docusaurus and the shared Software Mansion docs theme, @swmansion/t-rex-ui.

The site has no landing page of its own. That is argent.swmansion.com; the root route here redirects to the getting started page.

Development

This site lives at packages/docs but is a standalone npm project with its own lockfile, excluded from the root packages/* workspace glob so its dependencies stay out of the toolkit's lockfile. ESLint still runs from the repo root (npm run lint) with the shared eslint.config.mjs; install this package's dependencies first so the type-aware rules can load tsconfig.json.

cd packages/docs
npm install
npm start        # dev server on http://localhost:3000/argent/
npm run build    # production build into packages/docs/build
npm run serve    # serve the production build

Layout

Path Contents
docs/ Documentation pages (MDX), grouped into sidebar categories
src/pages/ The root route, which redirects into the docs
src/css/ Argent color palette, typography and theme overrides
src/components/ Components used from MDX, registered in src/theme/MDXComponents.tsx
static/img/ Logos, favicon and other static assets
static/video/ Encoded screen recordings, see Videos

Colors in src/css/colors.css are derived from the Argent brand palette used on argent.swmansion.com.

Videos

Screen recordings go through scripts/encode-video.sh, which produces a web-sized MP4 and a poster frame in static/video/:

npm run encode:video -- ~/Desktop/tap-flow.mov

Record in the simulator or with QuickTime, then encode. Never commit a GIF: the same ten second capture is around thirty times larger as a GIF than as H.264.

Embed the result with the <Video> component, which is global in MDX and needs no import:

<Video src="/video/tap-flow.mp4" portrait caption="Tapping through the sign-in flow" />
Prop Meaning
src Site-relative path to the MP4
portrait Caps the height at 480px, for simulator and emulator captures
poster Poster frame; defaults to the sibling .jpg the encode script writes
caption Optional caption rendered below the clip
width / height Intrinsic pixel size, reserves space so the page does not reflow

Clips are muted and loop on their own. Nothing downloads until the player nears the viewport, playback pauses while it is off screen, and readers who ask for reduced motion get a paused player with controls instead of a loop.

Once static/video/ grows past a few tens of megabytes, move the files behind a CDN and pass absolute URLs to src rather than growing the git history.