@triscope/core 0.4.0

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.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/compose.d.ts +11 -0
  4. package/dist/compose.d.ts.map +1 -0
  5. package/dist/compose.js +152 -0
  6. package/dist/compose.js.map +1 -0
  7. package/dist/editor.d.ts +14 -0
  8. package/dist/editor.d.ts.map +1 -0
  9. package/dist/editor.js +131 -0
  10. package/dist/editor.js.map +1 -0
  11. package/dist/harness.d.ts +199 -0
  12. package/dist/harness.d.ts.map +1 -0
  13. package/dist/harness.js +1027 -0
  14. package/dist/harness.js.map +1 -0
  15. package/dist/index.d.ts +32 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +20 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/inspect.d.ts +94 -0
  20. package/dist/inspect.d.ts.map +1 -0
  21. package/dist/inspect.js +434 -0
  22. package/dist/inspect.js.map +1 -0
  23. package/dist/knob-utils.d.ts +22 -0
  24. package/dist/knob-utils.d.ts.map +1 -0
  25. package/dist/knob-utils.js +51 -0
  26. package/dist/knob-utils.js.map +1 -0
  27. package/dist/lab/css.d.ts +11 -0
  28. package/dist/lab/css.d.ts.map +1 -0
  29. package/dist/lab/css.js +57 -0
  30. package/dist/lab/css.js.map +1 -0
  31. package/dist/lab/dom.d.ts +13 -0
  32. package/dist/lab/dom.d.ts.map +1 -0
  33. package/dist/lab/dom.js +76 -0
  34. package/dist/lab/dom.js.map +1 -0
  35. package/dist/motion-probe.d.ts +47 -0
  36. package/dist/motion-probe.d.ts.map +1 -0
  37. package/dist/motion-probe.js +122 -0
  38. package/dist/motion-probe.js.map +1 -0
  39. package/dist/probe-utils.d.ts +14 -0
  40. package/dist/probe-utils.d.ts.map +1 -0
  41. package/dist/probe-utils.js +18 -0
  42. package/dist/probe-utils.js.map +1 -0
  43. package/dist/scene-cameras.d.ts +6 -0
  44. package/dist/scene-cameras.d.ts.map +1 -0
  45. package/dist/scene-cameras.js +20 -0
  46. package/dist/scene-cameras.js.map +1 -0
  47. package/dist/scene-delta.d.ts +21 -0
  48. package/dist/scene-delta.d.ts.map +1 -0
  49. package/dist/scene-delta.js +57 -0
  50. package/dist/scene-delta.js.map +1 -0
  51. package/dist/scene-introspect.d.ts +78 -0
  52. package/dist/scene-introspect.d.ts.map +1 -0
  53. package/dist/scene-introspect.js +164 -0
  54. package/dist/scene-introspect.js.map +1 -0
  55. package/dist/scene-registry.d.ts +36 -0
  56. package/dist/scene-registry.d.ts.map +1 -0
  57. package/dist/scene-registry.js +64 -0
  58. package/dist/scene-registry.js.map +1 -0
  59. package/dist/scene-view.d.ts +52 -0
  60. package/dist/scene-view.d.ts.map +1 -0
  61. package/dist/scene-view.js +171 -0
  62. package/dist/scene-view.js.map +1 -0
  63. package/dist/source-tag.d.ts +34 -0
  64. package/dist/source-tag.d.ts.map +1 -0
  65. package/dist/source-tag.js +120 -0
  66. package/dist/source-tag.js.map +1 -0
  67. package/dist/telemetry.d.ts +53 -0
  68. package/dist/telemetry.d.ts.map +1 -0
  69. package/dist/telemetry.js +302 -0
  70. package/dist/telemetry.js.map +1 -0
  71. package/dist/types.d.ts +142 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +9 -0
  74. package/dist/types.js.map +1 -0
  75. package/dist/uniform-access.d.ts +32 -0
  76. package/dist/uniform-access.d.ts.map +1 -0
  77. package/dist/uniform-access.js +144 -0
  78. package/dist/uniform-access.js.map +1 -0
  79. package/dist/validate.d.ts +2 -0
  80. package/dist/validate.d.ts.map +1 -0
  81. package/dist/validate.js +81 -0
  82. package/dist/validate.js.map +1 -0
  83. package/dist/vite.d.ts +3 -0
  84. package/dist/vite.d.ts.map +1 -0
  85. package/dist/vite.js +4 -0
  86. package/dist/vite.js.map +1 -0
  87. package/dist/warnings.d.ts +24 -0
  88. package/dist/warnings.d.ts.map +1 -0
  89. package/dist/warnings.js +26 -0
  90. package/dist/warnings.js.map +1 -0
  91. package/package.json +60 -0
  92. package/src/compose.ts +164 -0
  93. package/src/editor.ts +138 -0
  94. package/src/harness.ts +1263 -0
  95. package/src/index.ts +58 -0
  96. package/src/inspect.ts +498 -0
  97. package/src/knob-utils.ts +60 -0
  98. package/src/lab/css.ts +56 -0
  99. package/src/lab/dom.ts +88 -0
  100. package/src/motion-probe.ts +135 -0
  101. package/src/probe-utils.ts +17 -0
  102. package/src/scene-cameras.ts +33 -0
  103. package/src/scene-delta.ts +69 -0
  104. package/src/scene-introspect.ts +230 -0
  105. package/src/scene-registry.ts +103 -0
  106. package/src/scene-view.ts +204 -0
  107. package/src/source-tag.ts +139 -0
  108. package/src/telemetry.ts +337 -0
  109. package/src/three-webgpu-shim.d.ts +130 -0
  110. package/src/types.ts +121 -0
  111. package/src/uniform-access.ts +152 -0
  112. package/src/validate.ts +82 -0
  113. package/src/vite.ts +5 -0
  114. package/src/warnings.ts +41 -0
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Inspect mode: solo-view + OrbitControls + raycaster picking + hover
3
+ * highlight + click-to-select. Writes selection into
4
+ * window.__TRISCOPE__.lastSelection so MCP read_telemetry .selection
5
+ * surfaces the source frame for the picked mesh.
6
+ *
7
+ * Activation: URL `?inspect=<element>&camera=<name>` (camera optional, falls
8
+ * back to the first declared camera). When inactive the harness behaves
9
+ * exactly as before — the grid view.
10
+ *
11
+ * Highlight is a single shared wireframe Mesh that borrows the hovered
12
+ * object's geometry (no per-frame allocation). Click-selection persists
13
+ * the same overlay with a different color until the next click.
14
+ */
15
+ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
16
+ import * as THREE from 'three/webgpu';
17
+ export function buildParentChain(obj) {
18
+ const chain = [];
19
+ let cur = obj;
20
+ while (cur) {
21
+ chain.unshift(describeObj(cur));
22
+ cur = cur.parent ?? null;
23
+ }
24
+ return chain;
25
+ }
26
+ /**
27
+ * Compact human-readable description of an Object3D used in parentChain
28
+ * and clipboard formats. Prefers the author's `.name` (most specific);
29
+ * falls back to a self-describing shorthand like `Mesh<PlaneGeometry
30
+ * #e6dcc0>` so the user can still grep — even when no names are set on
31
+ * the scene tree.
32
+ */
33
+ export function describeObj(obj) {
34
+ if (obj.name)
35
+ return obj.name;
36
+ const ctor = obj.constructor?.name ?? '?';
37
+ const mesh = obj;
38
+ const geom = mesh.geometry?.type;
39
+ let color;
40
+ try {
41
+ const mat = mesh.material;
42
+ if (mat?.color?.getHexString)
43
+ color = '#' + mat.color.getHexString();
44
+ }
45
+ catch {
46
+ /* color extraction is best-effort */
47
+ }
48
+ if (geom || color) {
49
+ const parts = [geom, color].filter(Boolean).join(' ');
50
+ return `${ctor}<${parts}>`;
51
+ }
52
+ return ctor;
53
+ }
54
+ /**
55
+ * Walk the scene tree and return the first Mesh whose source tag matches
56
+ * the given frame (same file + line). Used by inspect-mode persistence to
57
+ * restore the selection across full-reload — the Mesh object identity
58
+ * changes after reload but the source location is stable.
59
+ */
60
+ export function findMeshBySource(scene, source) {
61
+ if (!source?.file)
62
+ return null;
63
+ let match = null;
64
+ scene.traverse?.((obj) => {
65
+ if (match)
66
+ return;
67
+ const tag = obj.userData?.__tris;
68
+ if (!tag?.source)
69
+ return;
70
+ if (tag.source.file === source.file && tag.source.line === source.line) {
71
+ match = obj;
72
+ }
73
+ });
74
+ return match;
75
+ }
76
+ /** Parse the URL for inspect activation. Returns null when off. */
77
+ export function readInspectFromUrl(elementName) {
78
+ if (typeof window === 'undefined')
79
+ return null;
80
+ const params = new URLSearchParams(window.location.search);
81
+ const inspectParam = params.get('inspect');
82
+ if (inspectParam == null)
83
+ return null;
84
+ // `?inspect`, `?inspect=1`, `?inspect=<el>` all activate.
85
+ // `?inspect=<el>` activates only when the el matches our element.
86
+ if (inspectParam === '' || inspectParam === '1' || inspectParam === elementName) {
87
+ return { camera: params.get('camera') ?? undefined };
88
+ }
89
+ return null;
90
+ }
91
+ export function createInspectMode(init) {
92
+ const cameraName = init.cameraName ?? Object.keys(init.cameras)[0];
93
+ const camera = init.cameras[cameraName];
94
+ if (!camera) {
95
+ return {
96
+ active: false,
97
+ cameraName: null,
98
+ camera: null,
99
+ render: () => { },
100
+ state: () => ({ hover: null, selection: null, selections: [] }),
101
+ dispose: () => { },
102
+ };
103
+ }
104
+ // OrbitControls — right-button rotates per user request, left-button is
105
+ // reserved for picking (we wire click → raycast below). Scroll zooms.
106
+ const controls = new OrbitControls(camera, init.canvas);
107
+ controls.enablePan = true;
108
+ controls.enableDamping = true;
109
+ controls.dampingFactor = 0.08;
110
+ controls.mouseButtons = {
111
+ LEFT: null, // we handle left clicks for picking
112
+ MIDDLE: THREE.MOUSE.PAN,
113
+ RIGHT: THREE.MOUSE.ROTATE,
114
+ };
115
+ // OrbitControls' target defaults to (0,0,0); use the camera's declared target.
116
+ const t = camera.userData?.target;
117
+ if (Array.isArray(t) && t.length === 3)
118
+ controls.target.set(t[0], t[1], t[2]);
119
+ controls.update();
120
+ // Highlight overlay: one wireframe mesh whose geometry is swapped to
121
+ // match the hovered/selected mesh. Bright green for hover, bright cyan
122
+ // for the persistent click-selection. `raycast` is a no-op so the
123
+ // overlay never grabs subsequent picks.
124
+ const hoverMat = new THREE.MeshBasicNodeMaterial({
125
+ color: 0x66ff66,
126
+ wireframe: true,
127
+ transparent: true,
128
+ opacity: 0.9,
129
+ depthTest: false,
130
+ });
131
+ const selectMat = new THREE.MeshBasicNodeMaterial({
132
+ color: 0x00ffff,
133
+ wireframe: true,
134
+ transparent: true,
135
+ opacity: 0.95,
136
+ depthTest: false,
137
+ });
138
+ const overlay = new THREE.Mesh(new THREE.BufferGeometry(), hoverMat);
139
+ overlay.renderOrder = 999;
140
+ overlay.frustumCulled = false;
141
+ overlay.visible = false;
142
+ overlay.raycast = () => { }; // ignore in picking
143
+ init.scene.add(overlay);
144
+ const selectOverlay = new THREE.Mesh(new THREE.BufferGeometry(), selectMat);
145
+ selectOverlay.renderOrder = 1000;
146
+ selectOverlay.frustumCulled = false;
147
+ selectOverlay.visible = false;
148
+ selectOverlay.raycast = () => { };
149
+ init.scene.add(selectOverlay);
150
+ const raycaster = new THREE.Raycaster();
151
+ const ndc = new THREE.Vector2();
152
+ let hoverHit = null;
153
+ let selectionHit = null;
154
+ let hoveredObject = null;
155
+ let selectedObject = null;
156
+ // Pending restore-poller handle (a chain of setTimeouts) + a disposed guard so
157
+ // dispose() can cancel it — otherwise it keeps writing selection state (and an
158
+ // overlay borrowing now-freed geometry) for up to ~3s after teardown.
159
+ let restoreTimer = null;
160
+ let disposed = false;
161
+ // Multi-select state. selectionsByUuid maps uuid → selection. extraOverlays
162
+ // maps uuid → its wireframe overlay Mesh (the primary cyan overlay is
163
+ // reserved for the most-recently-clicked item, kept in sync with
164
+ // selectedObject). Built up via Shift+click; plain click resets.
165
+ const selectionsByUuid = new Map();
166
+ const extraOverlaysByUuid = new Map();
167
+ const extraOverlayMat = new THREE.MeshBasicNodeMaterial({
168
+ color: 0x00ccff,
169
+ wireframe: true,
170
+ transparent: true,
171
+ opacity: 0.75,
172
+ depthTest: false,
173
+ });
174
+ function eventToNdc(ev) {
175
+ const rect = init.canvas.getBoundingClientRect();
176
+ ndc.x = ((ev.clientX - rect.left) / rect.width) * 2 - 1;
177
+ ndc.y = -((ev.clientY - rect.top) / rect.height) * 2 + 1;
178
+ }
179
+ function pick() {
180
+ raycaster.setFromCamera(ndc, camera);
181
+ const hits = raycaster.intersectObjects(init.scene.children, true);
182
+ // Filter out overlays + lights + non-mesh helpers.
183
+ for (const h of hits) {
184
+ if (h.object === overlay || h.object === selectOverlay)
185
+ continue;
186
+ if (!h.object.isMesh)
187
+ continue;
188
+ return { obj: h.object, distance: h.distance, point: h.point };
189
+ }
190
+ return null;
191
+ }
192
+ function selectionFrom(hit) {
193
+ const tag = hit.obj.userData?.__tris ?? null;
194
+ return {
195
+ camera: cameraName,
196
+ point: [hit.point.x, hit.point.y, hit.point.z],
197
+ distance: +hit.distance.toFixed(3),
198
+ source: tag?.source ?? null,
199
+ stack: tag?.stack ?? [],
200
+ type: tag?.type ?? hit.obj.constructor.name,
201
+ geometry: tag?.geometry,
202
+ material: tag?.material,
203
+ name: tag?.name ?? hit.obj.name ?? undefined,
204
+ parentChain: buildParentChain(hit.obj),
205
+ uuid: hit.obj.uuid,
206
+ };
207
+ }
208
+ function syncOverlayTo(target, which) {
209
+ which.geometry = target.geometry;
210
+ target.updateMatrixWorld(true);
211
+ which.matrix.copy(target.matrixWorld);
212
+ which.matrixAutoUpdate = false;
213
+ which.visible = true;
214
+ }
215
+ // mousemove → hover (RAF-throttled so we don't raycast 1000x/s).
216
+ let pendingHover = false;
217
+ function onMouseMove(ev) {
218
+ eventToNdc(ev);
219
+ if (pendingHover)
220
+ return;
221
+ pendingHover = true;
222
+ requestAnimationFrame(() => {
223
+ pendingHover = false;
224
+ const hit = pick();
225
+ if (!hit) {
226
+ if (hoveredObject) {
227
+ hoveredObject = null;
228
+ hoverHit = null;
229
+ overlay.visible = false;
230
+ }
231
+ return;
232
+ }
233
+ if (hit.obj === hoveredObject)
234
+ return;
235
+ hoveredObject = hit.obj;
236
+ hoverHit = selectionFrom(hit);
237
+ syncOverlayTo(hit.obj, overlay);
238
+ });
239
+ }
240
+ function clearMultiOverlays() {
241
+ for (const ov of extraOverlaysByUuid.values())
242
+ init.scene.remove(ov);
243
+ extraOverlaysByUuid.clear();
244
+ selectionsByUuid.clear();
245
+ }
246
+ function ensureMultiOverlay(uuid, target) {
247
+ if (extraOverlaysByUuid.has(uuid)) {
248
+ // Already overlaid; just re-sync transform in case the mesh moved.
249
+ syncOverlayTo(target, extraOverlaysByUuid.get(uuid));
250
+ return;
251
+ }
252
+ const ov = new THREE.Mesh(new THREE.BufferGeometry(), extraOverlayMat);
253
+ ov.renderOrder = 1000;
254
+ ov.frustumCulled = false;
255
+ ov.raycast = () => { };
256
+ init.scene.add(ov);
257
+ extraOverlaysByUuid.set(uuid, ov);
258
+ syncOverlayTo(target, ov);
259
+ }
260
+ /**
261
+ * Best-effort clipboard write — silently ignores rejections on browsers
262
+ * that gate navigator.clipboard behind a user-activation check (it's
263
+ * fine here because we're called from a click event handler).
264
+ *
265
+ * Format is rich enough to grep with when source.line drifts (which it
266
+ * does, because Error.stack in browsers reports positions in the
267
+ * vite-served file, not source-mapped originals). Example output:
268
+ * PirateShipMesh.ts:1599 — Mesh<PlaneGeometry #e6dcc0> @ (4.2,8.1,0.3) chain=Scene>pirate.ship>mainmast>Mesh<PlaneGeometry #e6dcc0>
269
+ * The user can paste this into chat or `rg` and find the real call
270
+ * site even if the line number is off by 100 lines.
271
+ */
272
+ function copySelection(sel) {
273
+ const src = sel.source;
274
+ const fileLine = src ? `${src.file.split('/').slice(-1)[0]}:${src.line}` : `(uuid=${sel.uuid})`;
275
+ const desc = sel.name ?? `${sel.type}<${[sel.geometry, sel.material?.color].filter(Boolean).join(' ')}>`;
276
+ const pos = `(${sel.point.map((n) => n.toFixed(2)).join(',')})`;
277
+ const chain = sel.parentChain?.length ? ` chain=${sel.parentChain.join('>')}` : '';
278
+ const text = `${fileLine} — ${desc} @ ${pos}${chain}`;
279
+ try {
280
+ navigator.clipboard?.writeText(text);
281
+ }
282
+ catch { }
283
+ }
284
+ function onMouseDown(ev) {
285
+ if (ev.button !== 0)
286
+ return; // left only
287
+ eventToNdc(ev);
288
+ const hit = pick();
289
+ if (!hit) {
290
+ // Plain background click clears everything; Shift+background keeps
291
+ // the current multi-set so the user can de-target a stray click.
292
+ if (!ev.shiftKey) {
293
+ selectionHit = null;
294
+ selectedObject = null;
295
+ selectOverlay.visible = false;
296
+ clearMultiOverlays();
297
+ init.onSelectionChange(null, []);
298
+ try {
299
+ window.localStorage.removeItem(STORAGE_KEY);
300
+ }
301
+ catch { }
302
+ }
303
+ return;
304
+ }
305
+ const sel = selectionFrom(hit);
306
+ if (!ev.shiftKey) {
307
+ // Plain click: replace set with this one item.
308
+ clearMultiOverlays();
309
+ }
310
+ else if (selectedObject && selectionHit) {
311
+ // Shift+click on a NEW mesh: the previous "primary" is about to lose
312
+ // the primary overlay (which will swap to the new mesh). Give the
313
+ // old primary its own multi-overlay so it stays visible. Without
314
+ // this the user sees only the latest pick, not the accumulated set.
315
+ ensureMultiOverlay(selectionHit.uuid, selectedObject);
316
+ }
317
+ selectedObject = hit.obj;
318
+ selectionHit = sel;
319
+ syncOverlayTo(hit.obj, selectOverlay);
320
+ selectionsByUuid.set(sel.uuid, sel);
321
+ init.onSelectionChange(sel, [...selectionsByUuid.values()]);
322
+ copySelection(sel);
323
+ try {
324
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(sel));
325
+ }
326
+ catch { }
327
+ }
328
+ init.canvas.addEventListener('mousemove', onMouseMove);
329
+ init.canvas.addEventListener('mousedown', onMouseDown);
330
+ // Restore last selection across full-reload (vite force-reload on
331
+ // shader edits). Match by source frame (file:line) — the actual Mesh
332
+ // object is new after reload but the source location is stable.
333
+ //
334
+ // Element mounting may happen across many frames (TSL pipeline init,
335
+ // async texture loads, RAF-driven sub-mesh adds). Poll up to ~3 s
336
+ // looking for the stored source in the scene tree, so we don't give
337
+ // up before the element has finished assembling itself.
338
+ const STORAGE_KEY = `triscope:selection:${init.elementName}`;
339
+ try {
340
+ const raw = window.localStorage.getItem(STORAGE_KEY);
341
+ if (raw) {
342
+ const stored = JSON.parse(raw);
343
+ let attempts = 0;
344
+ const maxAttempts = 30; // 30 × 100ms ≈ 3s
345
+ const tryRestore = () => {
346
+ if (disposed)
347
+ return;
348
+ attempts += 1;
349
+ try {
350
+ const target = findMeshBySource(init.scene, stored.source);
351
+ if (target) {
352
+ selectedObject = target;
353
+ selectionHit = selectionFrom({
354
+ obj: target,
355
+ distance: stored.distance,
356
+ point: new THREE.Vector3(...stored.point),
357
+ });
358
+ syncOverlayTo(target, selectOverlay);
359
+ selectionsByUuid.set(selectionHit.uuid, selectionHit);
360
+ init.onSelectionChange(selectionHit, [...selectionsByUuid.values()]);
361
+ return;
362
+ }
363
+ }
364
+ catch {
365
+ /* corrupt stored selection — drop it */
366
+ try {
367
+ window.localStorage.removeItem(STORAGE_KEY);
368
+ }
369
+ catch { }
370
+ return;
371
+ }
372
+ if (attempts < maxAttempts)
373
+ restoreTimer = setTimeout(tryRestore, 100);
374
+ };
375
+ restoreTimer = setTimeout(tryRestore, 100);
376
+ }
377
+ }
378
+ catch {
379
+ /* localStorage unavailable — silent */
380
+ }
381
+ function render() {
382
+ controls.update();
383
+ // Keep overlays glued to their target's current world matrix in case
384
+ // the underlying mesh moved (animation, knob change).
385
+ if (selectedObject && selectionHit) {
386
+ selectedObject.updateMatrixWorld(true);
387
+ selectOverlay.matrix.copy(selectedObject.matrixWorld);
388
+ }
389
+ if (hoveredObject) {
390
+ hoveredObject.updateMatrixWorld(true);
391
+ overlay.matrix.copy(hoveredObject.matrixWorld);
392
+ }
393
+ init.renderer.setScissorTest(false);
394
+ const w = init.renderer.domElement.width / init.renderer.getPixelRatio();
395
+ const h = init.renderer.domElement.height / init.renderer.getPixelRatio();
396
+ init.renderer.setViewport(0, 0, w, h);
397
+ camera.aspect = w / Math.max(h, 1);
398
+ camera.updateProjectionMatrix();
399
+ init.renderer.clear();
400
+ init.renderer.render(init.scene, camera);
401
+ }
402
+ function dispose() {
403
+ disposed = true;
404
+ if (restoreTimer) {
405
+ clearTimeout(restoreTimer);
406
+ restoreTimer = null;
407
+ }
408
+ init.canvas.removeEventListener('mousemove', onMouseMove);
409
+ init.canvas.removeEventListener('mousedown', onMouseDown);
410
+ // Remove every overlay from the shared scene + drop the borrowed geometry
411
+ // references so a disposed element's freed BufferGeometry can be GC'd.
412
+ init.scene.remove(overlay);
413
+ init.scene.remove(selectOverlay);
414
+ overlay.geometry = new THREE.BufferGeometry();
415
+ selectOverlay.geometry = new THREE.BufferGeometry();
416
+ clearMultiOverlays();
417
+ hoveredObject = null;
418
+ selectedObject = null;
419
+ controls.dispose();
420
+ }
421
+ return {
422
+ active: true,
423
+ cameraName,
424
+ camera,
425
+ render,
426
+ state: () => ({
427
+ hover: hoverHit,
428
+ selection: selectionHit,
429
+ selections: [...selectionsByUuid.values()],
430
+ }),
431
+ dispose,
432
+ };
433
+ }
434
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../src/inspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Knob } from './types.js';
2
+ /** Result of clamping a candidate knob value against its spec. */
3
+ export interface ClampResult {
4
+ /** True when the final value differs from what the caller asked for. */
5
+ clamped: boolean;
6
+ /** The value actually safe to apply. */
7
+ final: number | string | boolean;
8
+ }
9
+ /**
10
+ * Coerce + clamp a candidate knob value to what its spec actually allows, so a
11
+ * stray `set_knob('windPressure', 9999)` can't silently corrupt the scene.
12
+ * Returns both the safe `final` value and whether it had to be changed, so the
13
+ * caller (harness / MCP) can tell the agent its input was out of range.
14
+ *
15
+ * number → coerce to finite, snap to `step` (if any), clamp to [min, max]
16
+ * int → coerce, round, clamp to [min, max]
17
+ * color → keep valid #rgb / #rrggbb, else fall back to the spec default
18
+ * boolean → coerce truthiness
19
+ * trigger → pass the pulse through untouched (no persisted value)
20
+ */
21
+ export declare function clampKnob(spec: Knob, value: number | string | boolean): ClampResult;
22
+ //# sourceMappingURL=knob-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knob-utils.d.ts","sourceRoot":"","sources":["../src/knob-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CAClC;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CA+BnF"}
@@ -0,0 +1,51 @@
1
+ const HEX_COLOR = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
2
+ /**
3
+ * Coerce + clamp a candidate knob value to what its spec actually allows, so a
4
+ * stray `set_knob('windPressure', 9999)` can't silently corrupt the scene.
5
+ * Returns both the safe `final` value and whether it had to be changed, so the
6
+ * caller (harness / MCP) can tell the agent its input was out of range.
7
+ *
8
+ * number → coerce to finite, snap to `step` (if any), clamp to [min, max]
9
+ * int → coerce, round, clamp to [min, max]
10
+ * color → keep valid #rgb / #rrggbb, else fall back to the spec default
11
+ * boolean → coerce truthiness
12
+ * trigger → pass the pulse through untouched (no persisted value)
13
+ */
14
+ export function clampKnob(spec, value) {
15
+ switch (spec.type) {
16
+ case 'number': {
17
+ const n = Number(value);
18
+ if (!Number.isFinite(n))
19
+ return { clamped: true, final: spec.default };
20
+ let next = n;
21
+ if (spec.step && spec.step > 0) {
22
+ next = spec.min + Math.round((next - spec.min) / spec.step) * spec.step;
23
+ }
24
+ next = Math.min(spec.max, Math.max(spec.min, next));
25
+ return { clamped: !nearlyEqual(next, n), final: next };
26
+ }
27
+ case 'int': {
28
+ const n = Number(value);
29
+ if (!Number.isFinite(n))
30
+ return { clamped: true, final: spec.default };
31
+ const next = Math.min(spec.max, Math.max(spec.min, Math.round(n)));
32
+ return { clamped: next !== n, final: next };
33
+ }
34
+ case 'color': {
35
+ if (typeof value === 'string' && HEX_COLOR.test(value)) {
36
+ return { clamped: false, final: value };
37
+ }
38
+ return { clamped: true, final: spec.default };
39
+ }
40
+ case 'boolean': {
41
+ const next = Boolean(value);
42
+ return { clamped: typeof value !== 'boolean', final: next };
43
+ }
44
+ case 'trigger':
45
+ return { clamped: false, final: value };
46
+ }
47
+ }
48
+ function nearlyEqual(a, b) {
49
+ return Math.abs(a - b) < 1e-9;
50
+ }
51
+ //# sourceMappingURL=knob-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knob-utils.js","sourceRoot":"","sources":["../src/knob-utils.ts"],"names":[],"mappings":"AAUA,MAAM,SAAS,GAAG,sCAAsC,CAAC;AAEzD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,IAAU,EAAE,KAAgC;IACpE,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;YACvE,IAAI,IAAI,GAAG,CAAC,CAAC;YACb,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC/B,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YAC1E,CAAC;YACD,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YACpD,OAAO,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzD,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;YACvE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnE,OAAO,EAAE,OAAO,EAAE,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9C,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC1C,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QAChD,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,KAAK,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9D,CAAC;QACD,KAAK,SAAS;YACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;AAChC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Lab UI CSS, exported as a template string so consumers can inject it
3
+ * once via `mountLabDom()` instead of duplicating it in every per-element
4
+ * lab HTML page.
5
+ *
6
+ * Covers: full-bleed canvas, camera-label tags, HUD strip, boot overlay,
7
+ * knob-editor pane. The selectors match the DOM that `mountLabDom()`
8
+ * creates and that `runLab()` / `mountEditor()` populate.
9
+ */
10
+ export declare const LAB_CSS = "\nhtml, body { margin: 0; padding: 0; overflow: hidden; background: #000; color: #cfd6db; font-family: ui-monospace, monospace; }\n#app { position: fixed; inset: 0; }\ncanvas { display: block; width: 100%; height: 100%; }\n\n.triscope-label, .label {\n position: absolute;\n background: rgba(0,0,0,0.55);\n color: #cfd6db;\n padding: 4px 8px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.05em;\n pointer-events: none;\n border-radius: 3px;\n z-index: 5;\n}\n\n#hud { position: fixed; bottom: 8px; left: 8px; z-index: 10; font-size: 11px; padding: 4px 8px; background: rgba(0,0,0,0.55); border-radius: 3px; }\n#boot { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: #0a1a20; color: #cfd6db; font-size: 14px; z-index: 50; }\n\n#lab-controls {\n position: fixed;\n right: 8px;\n bottom: 8px;\n z-index: 20;\n width: min(320px, calc(100vw - 24px));\n padding: 10px 12px;\n background: rgba(5, 12, 16, 0.78);\n border: 1px solid rgba(210, 230, 240, 0.16);\n border-radius: 6px;\n backdrop-filter: blur(8px);\n box-sizing: border-box;\n}\n.triscope-editor__row {\n display: grid;\n grid-template-columns: 110px 1fr 56px;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: #cfd6db;\n margin: 4px 0;\n}\n.triscope-editor__row label { font-size: 10px; opacity: 0.85; }\n.triscope-editor__row input { width: 100%; accent-color: #8fc7d9; }\n.triscope-editor__row output { text-align: right; color: #f0f5f7; }\n";
11
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../src/lab/css.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,s+CA8CnB,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Lab UI CSS, exported as a template string so consumers can inject it
3
+ * once via `mountLabDom()` instead of duplicating it in every per-element
4
+ * lab HTML page.
5
+ *
6
+ * Covers: full-bleed canvas, camera-label tags, HUD strip, boot overlay,
7
+ * knob-editor pane. The selectors match the DOM that `mountLabDom()`
8
+ * creates and that `runLab()` / `mountEditor()` populate.
9
+ */
10
+ export const LAB_CSS = `
11
+ html, body { margin: 0; padding: 0; overflow: hidden; background: #000; color: #cfd6db; font-family: ui-monospace, monospace; }
12
+ #app { position: fixed; inset: 0; }
13
+ canvas { display: block; width: 100%; height: 100%; }
14
+
15
+ .triscope-label, .label {
16
+ position: absolute;
17
+ background: rgba(0,0,0,0.55);
18
+ color: #cfd6db;
19
+ padding: 4px 8px;
20
+ font-size: 11px;
21
+ font-weight: 600;
22
+ letter-spacing: 0.05em;
23
+ pointer-events: none;
24
+ border-radius: 3px;
25
+ z-index: 5;
26
+ }
27
+
28
+ #hud { position: fixed; bottom: 8px; left: 8px; z-index: 10; font-size: 11px; padding: 4px 8px; background: rgba(0,0,0,0.55); border-radius: 3px; }
29
+ #boot { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: #0a1a20; color: #cfd6db; font-size: 14px; z-index: 50; }
30
+
31
+ #lab-controls {
32
+ position: fixed;
33
+ right: 8px;
34
+ bottom: 8px;
35
+ z-index: 20;
36
+ width: min(320px, calc(100vw - 24px));
37
+ padding: 10px 12px;
38
+ background: rgba(5, 12, 16, 0.78);
39
+ border: 1px solid rgba(210, 230, 240, 0.16);
40
+ border-radius: 6px;
41
+ backdrop-filter: blur(8px);
42
+ box-sizing: border-box;
43
+ }
44
+ .triscope-editor__row {
45
+ display: grid;
46
+ grid-template-columns: 110px 1fr 56px;
47
+ align-items: center;
48
+ gap: 6px;
49
+ font-size: 11px;
50
+ color: #cfd6db;
51
+ margin: 4px 0;
52
+ }
53
+ .triscope-editor__row label { font-size: 10px; opacity: 0.85; }
54
+ .triscope-editor__row input { width: 100%; accent-color: #8fc7d9; }
55
+ .triscope-editor__row output { text-align: right; color: #f0f5f7; }
56
+ `;
57
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../../src/lab/css.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CtB,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface LabDomRefs {
2
+ canvas: HTMLCanvasElement;
3
+ hud: HTMLElement;
4
+ boot: HTMLElement;
5
+ labelContainer: HTMLElement;
6
+ editorContainer: HTMLElement;
7
+ }
8
+ /**
9
+ * Build (or reuse) the standard lab DOM and return the refs `runLab()`
10
+ * needs. Idempotent: calling twice does not duplicate nodes.
11
+ */
12
+ export declare function mountLabDom(): LabDomRefs;
13
+ //# sourceMappingURL=dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/lab/dom.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,cAAc,EAAE,WAAW,CAAC;IAC5B,eAAe,EAAE,WAAW,CAAC;CAC9B;AAsBD;;;GAGG;AACH,wBAAgB,WAAW,IAAI,UAAU,CAiCxC"}