mesurer-solid 0.2.1-beta.0 → 0.2.1-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ The installer writes a self-contained skill and injection artifact:
17
17
  .agents/skills/mesurer-ui/
18
18
  ├── SKILL.md
19
19
  └── assets/
20
+ ├── mediabunny-vendor.js
20
21
  └── inject-script.js
21
22
  ```
22
23
 
@@ -24,7 +25,7 @@ The installer writes a self-contained skill and injection artifact:
24
25
 
25
26
  The base inspector includes Select, X-ray, Rulers, Typography, Guides, Distance, and Settings. Color Picker uses application-local host capture when available and otherwise uses a working browser `EyeDropper`.
26
27
 
27
- First-party plugins add Context, Edit, Screenshot, and optional Codex delivery. Edit movement preserves the existing Arrange agent method names for compatibility. The complete public map, including the low-level inspection methods and plugin host, is in [Capabilities](../../docs/CAPABILITIES.md).
28
+ First-party plugins add Context, Edit, Screenshot, Recording, and optional Codex delivery. Recording is a human video-capture workflow with a typed `recording:v1` service; it is not the normal coding-agent evidence channel. Edit movement preserves the existing Arrange agent method names for compatibility. The complete public map, including the low-level inspection methods and plugin host, is in [Capabilities](../../docs/CAPABILITIES.md).
28
29
 
29
30
  For normal coding-agent work, use `window.__MESURER__`. Use `window.__MESURER_INSTANCE__` only when the task requires mounted-instance or plugin-host operations.
30
31
 
@@ -43,7 +44,7 @@ if (hasMesurer) {
43
44
  }
44
45
  ```
45
46
 
46
- If it exists, use that instance. A person may already have selected targets, guides, measurements, annotations, Edit movement intent, text/style intent, or screenshot review state. That state is part of the request.
47
+ If it exists, use that instance. A person may already have selected targets, guides, measurements, annotations, Edit movement intent, text/style intent, screenshot review state, or a Recording preview. That state is part of the request.
47
48
 
48
49
  The injector reuses a connected instance by default. Deliberate replacement requires:
49
50
 
@@ -55,11 +56,11 @@ Do not replace a live instance while consuming human review state.
55
56
 
56
57
  ## Inject only when absent
57
58
 
58
- Use the browser, Electron, WebView, Playwright, CDP, or other evaluation channel the browser controller already provides. With the installed skill, evaluate `.agents/skills/mesurer-ui/assets/inject-script.js`. With the npm package installed, read `mesurer-solid/inject-script`.
59
+ Use the browser, Electron, WebView, Playwright, CDP, or other evaluation channel the browser controller already provides. With the installed skill, evaluate `.agents/skills/mesurer-ui/assets/mediabunny-vendor.js` first and then `.agents/skills/mesurer-ui/assets/inject-script.js`. With the npm package installed, use the sibling `mesurer-solid/mediabunny-vendor` classic asset before `mesurer-solid/inject-script`. Keep the two files separate so MediaBunny remains on its MPL-2.0 distribution boundary.
59
60
 
60
61
  Do not mutate application source or create another browser connection merely to get Mesurer into a page the browser controller can already evaluate.
61
62
 
62
- The optional human Screenshot plugin remains disabled during normal agent injection unless configured before first injection:
63
+ Human Screenshot and Recording UI are separate from the normal agent evidence path. Do not reinject a live instance merely to change either plugin's state. For compatibility, Screenshot can still be enabled before first injection:
63
64
 
64
65
  ```js
65
66
  window.__MESURER_CONFIG__ = { screenshot: true }
@@ -245,15 +246,15 @@ The optional human `screenshot()` plugin from `mesurer-solid/plugins` is a separ
245
246
 
246
247
  ## Optional human-to-Codex delivery
247
248
 
248
- The first-party `codex()` plugin is enabled by default and remains toggleable in Mesurer Settings. It is a human-triggered delivery path and does not add a generic send method to `window.__MESURER__`.
249
+ The first-party `codex()` plugin starts enabled when the native host capability exists. Browser-only hosts list it in Settings but start with it off. It is a human-triggered delivery path and does not add a generic send method to `window.__MESURER__`.
249
250
 
250
- Native hosts expose `window.__MESURER_HOST__.codexBridge(request)`. The matching `codexBridge()` implementation is published from `mesurer-solid/plugins/codex/bridge` and runs in the host process. Shared sessions use Codex's existing local app-server. When the host inherits both `CODEX_THREAD_ID` and `CODEX_APP_TOOLS_PIPE_PATH` from Codex Desktop, Mesurer exposes only that exact Desktop thread, queues once through Codex's native queue command, and wakes the same thread with `codex://threads/<id>`. The app-tools pipe is an ownership signal only and is never opened. There is no Mesurer Codex daemon, localhost listener, marketplace plugin, or lifecycle hook.
251
+ Native hosts expose `window.__MESURER_HOST__.codexBridge(request)`. Electron main can install `installMesurerCodexHost()`, and a bundled preload can expose `createMesurerCodexPreloadBridge()`. Turning Codex on waits for a native lease and transport readiness. Turning it off waits for lease release before Mesurer removes the plugin. Shared sessions use Codex's existing local app-server. When the host inherits both `CODEX_THREAD_ID` and `CODEX_APP_TOOLS_PIPE_PATH` from Codex Desktop, Mesurer exposes only that exact Desktop thread, queues once through Codex's native queue command, and wakes the same thread with `codex://threads/<id>`. The app-tools pipe is an ownership signal only and is never opened. There is no Mesurer Codex daemon, localhost listener, marketplace plugin, or Codex SessionStart/SessionEnd hook.
251
252
 
252
253
  Shared delivery exposes currently loaded Codex threads. Desktop fallback exposes only the exact inherited current thread and refuses any other destination. Page affinity and explicit destination overrides remain fail-closed.
253
254
 
254
255
  Shared delivery calls `thread/queue/add` directly. Desktop current-thread delivery uses the native queue command only for that exact inherited thread. Mesurer never calls `turn/steer`, never creates a thread, and never reconstructs a second user-message queue. The typed `codex:v1` service exposes `health()`, `listThreads()`, `useThread(thread)`, `delivery(deliveryId)`, and canonical `queue(request?)`. `send(request?)` remains a compatibility alias.
255
256
 
256
- Queue submission is single-flight. A matched completed turn may remove only the annotation ids sent with that delivery; interrupted, failed, ambiguous, or unreadable work keeps them. Turn completion is transport state, not proof that the requested UI result is correct.
257
+ Shared queue submission is single-flight while Mesurer tracks lifecycle. Desktop current-thread delivery keeps its durable queued receipt visible without blocking a later explicit queue action. A matched completed turn may remove only the annotation ids sent with that delivery; interrupted, failed, ambiguous, or unreadable work keeps them. Turn completion is transport state, not proof that the requested UI result is correct.
257
258
 
258
259
  See [Queue Context feedback to Codex](../../docs/CODEX.md) for host wiring, routing, recovery, privacy, and failure behavior.
259
260
 
package/README.md CHANGED
@@ -42,7 +42,7 @@ if (import.meta.env.DEV) {
42
42
  }
43
43
  ```
44
44
 
45
- For Vite, put this in the existing browser entry such as `src/main.tsx`, `src/main.ts`, or `src/index.tsx`. In Electron, use the renderer entry and keep privileged Electron work in preload/main. If preload exposes `window.__MESURER_HOST__.captureScreenshot`, Screenshot uses native capture and Color Picker samples the current application window through that same capability. Renderer configuration remains `screenshot()`; there is no Electron-specific Screenshot factory or Color Picker setup. In SSR applications, mount from a client-only module or lifecycle.
45
+ For Vite, put this in the existing browser entry such as `src/main.tsx`, `src/main.ts`, or `src/index.tsx`. In Electron, use the renderer entry and keep privileged Electron work in preload/main. If preload exposes `window.__MESURER_HOST__.captureScreenshot`, Screenshot uses native capture and Color Picker samples the current application window through that same capability. If preload exposes `window.__MESURER_HOST__.codexBridge`, Codex starts enabled and waits for a native activation lease before it becomes available. Browser-only hosts list Codex in Settings but start with it off. Renderer configuration remains runtime-neutral. In SSR applications, mount from a client-only module or lifecycle.
46
46
 
47
47
  `src/dev/mesurer.ts` is an optional organization pattern, not a required filename or directory. Do not mount Mesurer from `vite.config.ts`, server/API code, Node-only scripts, an Electron main process, or a module that also executes during SSR.
48
48
 
@@ -56,7 +56,7 @@ All public first-party plugin factories are exported from `mesurer-solid/plugins
56
56
 
57
57
  ```ts
58
58
  import { mountMesurer } from "mesurer-solid"
59
- import { context, edit, layoutGuides, screenshot } from "mesurer-solid/plugins"
59
+ import { context, edit, layoutGuides, recording, screenshot } from "mesurer-solid/plugins"
60
60
 
61
61
  const mesurer = mountMesurer({
62
62
  agent: true,
@@ -65,11 +65,12 @@ const mesurer = mountMesurer({
65
65
  edit(),
66
66
  layoutGuides(),
67
67
  screenshot(),
68
+ recording(),
68
69
  ],
69
70
  })
70
71
  ```
71
72
 
72
- The base inspector includes Select, X-ray, Rulers, Typography, Guides, Distance, Settings, plugin hosting, direct text editing, and the low-level inspection API. The toolbar groups those controls into Select and Edit. Typography stays read-only in Select; Edit owns movement and direct text/style changes. Color Picker uses application-local capture when `window.__MESURER_HOST__.captureScreenshot` is available; other supported browser hosts use an operational `EyeDropper`. A successful sample is copied to the clipboard using `colorPickerClickFormat`.
73
+ The base inspector includes Select, X-ray, Rulers, Typography, Guides, Distance, Settings, plugin hosting, direct text editing, and the low-level inspection API. First-party Recording uses MediaBunny for encoded video, trim, resize, and WebM/MP4 export; its capture adapters only acquire pixels. Electron apps should import `mesurer-solid/electron` once from the main-process entrypoint before creating BrowserWindows; Mesurer then owns its narrow Recording preload/IPC automatically, so the app does not add Recording code to its own preload. The toolbar groups those controls into Select and Edit. Typography stays read-only in Select; Edit owns movement and direct text/style changes. Color Picker uses application-local capture when `window.__MESURER_HOST__.captureScreenshot` is available; other supported browser hosts use an operational `EyeDropper`. A successful sample is copied to the clipboard using `colorPickerClickFormat`.
73
74
 
74
75
  `mesurer-solid/plugins` also exports the built-in factories for lower-level composition. Normal mounts already include the built-ins. Use `excludeBuiltins` with names such as `"xray"`, `"typography"`, and `"colorPicker"` when a mount should omit one.
75
76
 
@@ -83,9 +84,14 @@ Advanced integrations may supply their own `pluginHost`. That host remains calle
83
84
  | `mesurer-solid/plugins` | All first-party plugin factories and plugin-specific contracts |
84
85
  | `mesurer-solid/core` | Lower-level framework-neutral public contracts |
85
86
  | `mesurer-solid/inject` | Programmatic browser injection |
86
- | `mesurer-solid/inject-script` | Built classic injection artifact |
87
+ | `mesurer-solid/inject-script` | Built classic Mesurer injection artifact; load `mesurer-solid/mediabunny-vendor` first for raw classic evaluation |
88
+ | `mesurer-solid/mediabunny-vendor` | Separate MPL-2.0 MediaBunny classic runtime for raw injection and the extension; the normal ESM entrypoints use an internal relative `dist/mediabunny-runtime.js` so MediaBunny is not installed into consumer dependency graphs |
87
89
  | `mesurer-skill` | Install the portable coding-agent skill |
88
- | `mesurer-solid/plugins/codex/bridge` | Native-host Codex Bridge for the first-party Codex plugin |
90
+ | `mesurer-solid/electron` | Preferred Electron main-process bootstrap; automatically installs Mesurer's narrow Recording bridge/preload |
91
+ | `mesurer-solid/plugins/codex/bridge` | Native Codex transport and Electron main-process host adapter |
92
+ | `mesurer-solid/plugins/codex/preload` | Bundle-friendly Electron preload adapter for the Codex host capability |
93
+ | `mesurer-solid/plugins/recording/bridge` | Advanced/manual Electron Recording host adapter for custom sender policy |
94
+ | `mesurer-solid/plugins/recording/preload` | Advanced/manual Electron Recording preload adapter |
89
95
 
90
96
  Programmatic injection reuses an existing connected instance by default. Lifecycle-owning integrations can set `recoverDisconnected: true` in `MesurerInjectConfig` to remount Mesurer when page DOM replacement disconnects its host. The option defaults to `false`, so ordinary one-shot injection does not silently reappear after disposal.
91
97
 
@@ -98,13 +104,14 @@ Programmatic injection reuses an existing connected instance by default. Lifecyc
98
104
  - Inspect rendered typography in Select. Edit previews reversible direct copy and style changes.
99
105
  - Use Edit to move selected UI and change direct text, typography, and text color without changing source.
100
106
  - Capture page regions through the optional Screenshot plugin. It selects native host capture, the Chromium extension adapter, or browser display capture internally.
107
+ - Record selected regions through the optional Recording plugin. Browser and extension/native-host APIs only acquire the stream; MediaBunny owns encoding, inspection, trim, resize, and WebM/MP4 export.
101
108
  - Read selection, measurements, guides, annotations, layout, styles, and saved human intent through Context and agent APIs.
102
109
  - Keep saved annotations across same-tab reloads and conservatively rebind them to their original DOM targets; markers, cards, and ownership evidence stay attached through scrolling, repeated-note markers stay local, Add Note remains available while a note is open, and cards/composers occlude Select hover and selection chrome.
103
110
  - Extend the runtime with tools, settings, overlays, commands, hooks, state, and services.
104
111
  - Compact the toolbar to active controls without changing tool state or order.
105
112
  - Choose System, Light, or Dark appearance while keeping the same theme across isolated and document-backed Mesurer UI.
106
113
 
107
- Use `1` for Select and `2` for Edit. Select contains inspection tools. Edit owns movement and direct text/style changes. Context and Codex remain visible in both modes. The grouped toolbar changes modes in 150 ms. `Shift+A` still enters Edit for compatibility with existing Arrange workflows.
114
+ Use `1` for Select and `2` for Edit. Select contains inspection tools. Edit owns movement and direct text/style changes. Context and Codex remain visible in both modes. The grouped toolbar changes modes in 150 ms. `Shift+A` still enters Edit as a compatibility shortcut.
108
115
 
109
116
  Toolbar dragging starts after the pointer crosses the drag threshold. Dragging from Settings, Guide, or plugin triggers closes the open menu or panel. Pointer activity inside menus, dialogs, form controls, editable regions, and sliders does not drag the toolbar.
110
117
 
@@ -176,11 +183,11 @@ See [Agent integration](https://github.com/jhomra21/mesurer-solid/blob/main/pack
176
183
 
177
184
  ### Queue to Codex
178
185
 
179
- Codex is enabled by default and remains toggleable under **Settings -> Plugins**.
186
+ Codex starts enabled when the native host capability exists and remains toggleable under **Settings -> Plugins**. Browser-only hosts list it but start with it off.
180
187
 
181
- Native applications expose `window.__MESURER_HOST__.codexBridge` from preload/main and back it with `codexBridge()` from `mesurer-solid/plugins/codex/bridge`. The bridge runs in the native host process. Shared sessions use Codex's local app-server directly. If the host inherited an exact Codex Desktop thread, the bridge queues once to that thread through Codex's native queue command and wakes it with `codex://threads/<id>`. The Desktop app-tools pipe is never opened. There is no Mesurer localhost server, helper Electron process, marketplace plugin, SessionStart hook, or repeated trust step.
188
+ Native applications install `installMesurerCodexHost()` in Electron main and expose `createMesurerCodexPreloadBridge()` from a bundled preload. The bridge runs in the native host process. Each enabled renderer owns a native lease. Settings waits for activation readiness before committing ON and waits for lease release before committing OFF. Shared sessions use Codex's local app-server directly. An inherited Codex Desktop thread uses one native queue operation and one `codex://threads/<id>` wake. Mesurer never opens the private Desktop app-tools pipe or starts a second Mesurer process.
182
189
 
183
- **Queue to Codex** remains one runtime-neutral API. Shared delivery tracks Queued, Working, Finished, or Interrupted through the shared app-server. Desktop current-thread delivery reports the durable queued submission and wake result without fabricating private Desktop lifecycle state. It does not create threads or invoke Steer.
190
+ **Queue to Codex** remains one runtime-neutral API. Shared delivery tracks Queued, Working, Finished, or Interrupted through the shared app-server. Desktop current-thread delivery keeps the durable queued submission and wake result visible without fabricating private Desktop lifecycle state. It does not create threads or invoke Steer.
184
191
 
185
192
  Saved annotations included in a delivery are removed only after the exact matched turn completes. Interrupted, failed, ambiguous, or unreadable deliveries keep them. Set `codex({ clearCompletedAnnotations: false })` to retain completed notes.
186
193
 
@@ -27,3 +27,12 @@ Mesurer is licensed under the MIT License:
27
27
  > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
28
  > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
29
  > SOFTWARE.
30
+
31
+
32
+ ## MediaBunny
33
+
34
+ Recording uses [MediaBunny](https://github.com/Vanilagy/mediabunny) version 1.59.0 for browser video encoding, media inspection, trimming, resizing, conversion, and WebM/MP4 export.
35
+
36
+ MediaBunny is licensed under the Mozilla Public License 2.0 (MPL-2.0). Mesurer keeps normal npm imports on the MediaBunny package boundary. The classic browser/extension injector ships MediaBunny as a separate `mediabunny-vendor.js` file and includes the dependency's full license text as `mediabunny-LICENSE.txt`.
37
+
38
+ Source for the pinned version is available from the upstream repository at tag/version 1.59.0.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type MesurerAgentHarness, type MesurerTextEditIntent } from "./agent";
2
- import { type ArrangeCapturePlan, type ArrangeIntent, type ArrangePresentation, type ArrangeReview } from "./arrange";
2
+ import { type EditCapturePlan, type EditIntent, type EditPresentation, type EditReview } from "./arrange";
3
3
  import type { MesurerAnnotation, MesurerCapturePlanV1, MesurerContextRequest, MesurerContextV1, MesurerReviewV1 } from "./context";
4
4
  import type { MesurerPlugin, MesurerPluginDescription, MesurerPluginHost } from "./core";
5
5
  import { type MesurerHostLayerMode } from "./host-layer";
@@ -202,14 +202,16 @@ export type MesurerContextHarness = {
202
202
  prepareCapture(): Promise<void>;
203
203
  finishCapture(): Promise<void>;
204
204
  };
205
- export type MesurerArrangeHarness = {
206
- arrangements(): Promise<ArrangeIntent[]>;
207
- arrange(id: string): Promise<ArrangeIntent>;
208
- showArrange(id: string, state: ArrangePresentation): Promise<void>;
209
- arrangeCapturePlan(id: string, state: ArrangePresentation): Promise<ArrangeCapturePlan>;
210
- reviewArrange(id: string, tolerance?: number): Promise<ArrangeReview>;
205
+ export type MesurerEditHarness = {
206
+ arrangements(): Promise<EditIntent[]>;
207
+ arrange(id: string): Promise<EditIntent>;
208
+ showArrange(id: string, state: EditPresentation): Promise<void>;
209
+ arrangeCapturePlan(id: string, state: EditPresentation): Promise<EditCapturePlan>;
210
+ reviewArrange(id: string, tolerance?: number): Promise<EditReview>;
211
211
  };
212
- export type MesurerBrowserAgent = MesurerAgentHarness & MesurerContextHarness & MesurerArrangeHarness;
212
+ /** @deprecated Use `MesurerEditHarness`. The method names remain for compatibility. */
213
+ export type MesurerArrangeHarness = MesurerEditHarness;
214
+ export type MesurerBrowserAgent = MesurerAgentHarness & MesurerContextHarness & MesurerEditHarness;
213
215
  export type MountedMesurer = {
214
216
  readonly element: HTMLDivElement;
215
217
  readonly root: HTMLDivElement | ShadowRoot;
@@ -229,11 +231,11 @@ export type MountedMesurer = {
229
231
  capturePlan(request?: MesurerContextRequest): Promise<MesurerCapturePlanV1>;
230
232
  prepareCapture(): Promise<void>;
231
233
  finishCapture(): Promise<void>;
232
- arrangements(): Promise<ArrangeIntent[]>;
233
- arrange(id: string): Promise<ArrangeIntent>;
234
- showArrange(id: string, state: ArrangePresentation): Promise<void>;
235
- arrangeCapturePlan(id: string, state: ArrangePresentation): Promise<ArrangeCapturePlan>;
236
- reviewArrange(id: string, tolerance?: number): Promise<ArrangeReview>;
234
+ arrangements(): Promise<EditIntent[]>;
235
+ arrange(id: string): Promise<EditIntent>;
236
+ showArrange(id: string, state: EditPresentation): Promise<void>;
237
+ arrangeCapturePlan(id: string, state: EditPresentation): Promise<EditCapturePlan>;
238
+ reviewArrange(id: string, tolerance?: number): Promise<EditReview>;
237
239
  textEdits(): Promise<MesurerTextEditIntent[]>;
238
240
  textEdit(id: string): Promise<MesurerTextEditIntent>;
239
241
  bringToFront(): void;
@@ -250,7 +252,7 @@ export declare const mountMeasurer: typeof mountMesurer;
250
252
  export { createMesurerAgentHarness, MESURER_TEXT_EDIT_SERVICE_ID } from "./agent";
251
253
  export { MESURER_VERSION } from "./version";
252
254
  export type { AgentDistance, AgentEdges, AgentElementInspection, AgentFeedbackSnapshot, AgentRect, AgentViewportSnapshot, CreateMesurerAgentHarnessOptions, MesurerAgentHarness, MesurerTextEditIntent, MesurerTextEditService, MesurerTextStyleChange, MesurerTextStyleProperty, } from "./agent";
253
- export type { ArrangeCapturePlan, ArrangeIntent, ArrangeOffset, ArrangePresentation, ArrangeRect, ArrangeReview, ArrangeReviewTarget, ArrangeTarget, MesurerArrangeService, } from "./arrange";
255
+ export type { ArrangeCapturePlan, ArrangeIntent, ArrangeOffset, ArrangePresentation, ArrangeRect, ArrangeReview, ArrangeReviewTarget, ArrangeTarget, MesurerArrangeService, EditCapturePlan, EditIntent, EditOffset, EditPresentation, EditRect, EditReview, EditReviewTarget, EditTarget, MesurerEditService, } from "./arrange";
254
256
  export { captureMesurerContext, copyTextToClipboard, createMesurerCapturePlan, formatMesurerContext, reviewMesurerAnnotation, } from "./context";
255
257
  export type { MesurerAnnotation, MesurerAnnotationBaseline, MesurerAnnotationTarget, MesurerCapturePlanV1, MesurerContextDistance, MesurerContextEdges, MesurerContextGuide, MesurerContextLayoutGuide, MesurerContextMeasurement, MesurerContextRect, MesurerContextRequest, MesurerContextTarget, MesurerContextV1, MesurerElementFingerprint, MesurerElementInspection, MesurerReviewChange, MesurerReviewMetricChange, MesurerReviewPresenceChange, MesurerReviewV1, } from "./context";
256
258
  export { createMesurerPluginHost, createMesurerRuntime, defineMesurerPlugin } from "./core";