@kheleshikhi/studio-agent 0.6.1 → 0.8.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.
- package/README.md +215 -13
- package/dist/browser.d.ts +74 -2
- package/dist/browser.js +472 -12
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +515 -55
- package/dist/cli.js.map +1 -1
- package/dist/context.d.ts +66 -0
- package/dist/context.js +207 -0
- package/dist/context.js.map +1 -0
- package/dist/daemon.js +41 -3
- package/dist/daemon.js.map +1 -1
- package/dist/presence.d.ts +49 -0
- package/dist/presence.js +141 -0
- package/dist/presence.js.map +1 -0
- package/dist/scenario.d.ts +33 -1
- package/dist/scenario.js +143 -5
- package/dist/scenario.js.map +1 -1
- package/dist/video.d.ts +164 -0
- package/dist/video.js +385 -0
- package/dist/video.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,10 +13,140 @@ nerdbro connect
|
|
|
13
13
|
mkdir my-kheleshikhi-work
|
|
14
14
|
cd my-kheleshikhi-work
|
|
15
15
|
nerdbro agent init --provider codex # or claude / generic
|
|
16
|
-
nerdbro studio create --title "Ball Lab" --
|
|
16
|
+
nerdbro studio create --title "Ball Lab" --concept "Projectile range" \
|
|
17
|
+
--graph-purpose "Range against launch angle" # target defaults to sceneComposition
|
|
17
18
|
nerdbro studio checkout <asset-id>
|
|
18
19
|
```
|
|
19
20
|
|
|
21
|
+
## Mental model: Scene + Experience
|
|
22
|
+
|
|
23
|
+
Since 0.8.0 the CLI follows ADR-0003, the unified model the server projects:
|
|
24
|
+
|
|
25
|
+
- **Everything visual is a Scene** (`sceneComposition`). A graph is not a
|
|
26
|
+
separate asset or target: it is a **Scene math plane** (`mathPlanes`, Scene
|
|
27
|
+
Source v15, manifest v19) inside the Scene. A graph-only lesson is a Scene
|
|
28
|
+
holding one plane; a physical + graph lesson is one Scene holding both.
|
|
29
|
+
- **Interaction is an Experience** (`kheleshikhi.experience.v3`): final learner
|
|
30
|
+
content containing one or more Scenes, with `interaction` (inputs, requests,
|
|
31
|
+
handlers, readouts, exports, tools), `rounds`, `presentation` and
|
|
32
|
+
`assessment.outcomes`. `game` carries scoring only (sections and metrics).
|
|
33
|
+
`requiredCapabilities` are derived by the server, never authored; every
|
|
34
|
+
canonical capability is available in every host.
|
|
35
|
+
- **Frozen:** the `interactiveScene` part shape and the `mathGraph` and
|
|
36
|
+
`combined` targets are read so existing assets keep playing, but are never
|
|
37
|
+
authored for new work. Experience V2 is read through one normalizer and never
|
|
38
|
+
authored again.
|
|
39
|
+
|
|
40
|
+
The CLI does not bundle these lists. `nerdbro context` returns the live
|
|
41
|
+
projection — `authoring_targets`, `frozen_authoring_targets`, `deprecations`,
|
|
42
|
+
`scene_schema`, `scene_manifest_schema`, `experience_schema`,
|
|
43
|
+
`experience_capabilities`, `experience_tools` — plus a `summary` with the
|
|
44
|
+
compatibility verdict. `studio create` defaults `--target` to `sceneComposition`
|
|
45
|
+
and refuses a target only when the server's context lists it as frozen
|
|
46
|
+
(`STUDIO_TARGET_FROZEN`, exit `2`, with the server's deprecation text); any
|
|
47
|
+
other target is sent to the server, which remains the authority. Graph intent
|
|
48
|
+
(`--math-plane`, or `--graph-purpose`/`--graph-x`/`--graph-y`/`--graph-sync`)
|
|
49
|
+
sets the brief's `requires_graph`, meaning "this Scene holds a math plane",
|
|
50
|
+
whatever the target.
|
|
51
|
+
|
|
52
|
+
`nerdbro schema experience` returns the live V3 contract with the universal
|
|
53
|
+
capability list attached (`universal_capabilities`), and
|
|
54
|
+
`nerdbro capabilities` returns that list and the canonical tools beside the
|
|
55
|
+
Studio capability registry. A schema topic the server marks deprecated (for
|
|
56
|
+
example `mathGraph.config`) carries `deprecated` in its result.
|
|
57
|
+
|
|
58
|
+
A Scene holding a math plane (validated and compiled by the server's Scene
|
|
59
|
+
parser; the plane fields are documented by `nerdbro docs open mathgraph`, and
|
|
60
|
+
`nerdbro schema scene.versions` names the current authoring schema):
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"schema": "kheleshikhi.scene-source.v15",
|
|
65
|
+
"id": "parabola-lab",
|
|
66
|
+
"titleEn": "Parabola",
|
|
67
|
+
"titleBn": "পরাবৃত্ত",
|
|
68
|
+
"instructionEn": "Change k and watch the curve.",
|
|
69
|
+
"instructionBn": "k বদলাও, বক্ররেখা দেখো।",
|
|
70
|
+
"canvas": { "width": 960, "height": 540 },
|
|
71
|
+
"variables": [{ "name": "k", "type": "number", "value": 1, "min": -3, "max": 3 }],
|
|
72
|
+
"bands": [{ "id": "graphs", "kind": "mathPath", "placement": "compiled" }],
|
|
73
|
+
"instances": [],
|
|
74
|
+
"bindings": [],
|
|
75
|
+
"mathPlanes": [
|
|
76
|
+
{
|
|
77
|
+
"id": "graph",
|
|
78
|
+
"band": "graphs",
|
|
79
|
+
"title": "y equals k x squared",
|
|
80
|
+
"rect": { "x": 280, "y": 120, "width": 400, "height": 300 },
|
|
81
|
+
"viewport": { "minX": -5, "maxX": 5, "minY": -4, "maxY": 4 },
|
|
82
|
+
"axes": { "xLabel": "x", "yLabel": "y" },
|
|
83
|
+
"series": [{ "id": "curve", "kind": "explicit", "formula": "k*x^2", "label": "y = kx²" }]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
An Experience V3 using that kind of Scene, with inputs, requests, readouts,
|
|
90
|
+
exports, a tool, a round, presentation and assessment outcomes (validated by
|
|
91
|
+
the server's Experience parser; read `nerdbro schema experience` for the live
|
|
92
|
+
field lists and `nerdbro capabilities` for tool types):
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"schema": "kheleshikhi.experience.v3",
|
|
97
|
+
"id": "ramp",
|
|
98
|
+
"kind": "lesson",
|
|
99
|
+
"title": "Ramp",
|
|
100
|
+
"language": "bn",
|
|
101
|
+
"scenes": { "main": { "asset": "<approved Scene asset id>" } },
|
|
102
|
+
"variables": { "placed": false },
|
|
103
|
+
"interaction": {
|
|
104
|
+
"inputs": [
|
|
105
|
+
{ "type": "directional2d", "axes": ["moveX"] },
|
|
106
|
+
{ "type": "action", "action": "primary", "labelEn": "Go", "labelBn": "চলো" }
|
|
107
|
+
],
|
|
108
|
+
"requests": {
|
|
109
|
+
"speed": { "type": "number", "presentation": "dial", "min": 0, "max": 10, "step": 1 },
|
|
110
|
+
"hint": { "type": "hint", "textEn": "Look at the slope." }
|
|
111
|
+
},
|
|
112
|
+
"handlers": [
|
|
113
|
+
{ "topic": "input.action.primary.pressed", "kind": "event", "sceneEvent": "begin" }
|
|
114
|
+
],
|
|
115
|
+
"readouts": [
|
|
116
|
+
{
|
|
117
|
+
"topic": "ramp.speed",
|
|
118
|
+
"kind": "state",
|
|
119
|
+
"from": { "scene": "main", "variable": "speed" },
|
|
120
|
+
"display": { "labelEn": "Speed", "labelBn": "বেগ", "unit": "m/s" }
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"exports": [{ "topic": "session.complete", "kind": "event", "on": "allPlaced" }],
|
|
124
|
+
"tools": [{ "id": "replay", "type": "replay-scrubber", "config": {} }]
|
|
125
|
+
},
|
|
126
|
+
"rounds": {
|
|
127
|
+
"count": 1,
|
|
128
|
+
"pool": [{ "id": "one", "promptEn": "Place it", "promptBn": "রাখো", "value": 1 }]
|
|
129
|
+
},
|
|
130
|
+
"presentation": { "orientation": "landscape", "aspectRatio": "16:9", "controlsLayout": "standard" },
|
|
131
|
+
"assessment": {
|
|
132
|
+
"outcomes": [
|
|
133
|
+
{ "id": "placed", "on": "targetMatched", "status": "correct", "evidence": "placed" },
|
|
134
|
+
{ "id": "missed", "on": "targetMissed", "status": "incorrect", "retry": true },
|
|
135
|
+
{ "id": "done", "on": "allPlaced", "status": "completed" }
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Version negotiation
|
|
142
|
+
|
|
143
|
+
Every command first reads `/v1/agent/context`. A different `agent_protocol`
|
|
144
|
+
or a CLI older than `minimum_cli_version` exits `5`
|
|
145
|
+
(`AGENT_PROTOCOL_INCOMPATIBLE`, `AGENT_CLI_UPGRADE_REQUIRED`) with the exact
|
|
146
|
+
`npm install -g @kheleshikhi/studio-agent@<version>` to run. A CLI older than
|
|
147
|
+
`recommended_cli_version` keeps working and prints one upgrade notice on
|
|
148
|
+
stderr. The server currently recommends 0.8.0.
|
|
149
|
+
|
|
20
150
|
The browser pairing page uses the normal NerdBro login. The daemon stores the
|
|
21
151
|
scoped production credential only in memory. It binds to `127.0.0.1` on a
|
|
22
152
|
random port and protects local RPC with a random discovery secret. The
|
|
@@ -30,7 +160,7 @@ are CSS layout sizes; they do not simulate a low-density display. Headless mode
|
|
|
30
160
|
uses the same explicit responsive viewports for automated inspection, but its
|
|
31
161
|
screenshot pixels are not promised to be byte-identical across hardware.
|
|
32
162
|
Chrome's device-metrics API applies the CSS size while leaving the host device
|
|
33
|
-
scale native; NerdBro does not force a DPR value.
|
|
163
|
+
scale native; NerdBro does not force a DPR value. Since 0.6.2 the CLI keeps the
|
|
34
164
|
Chrome DevTools viewport session alive for the browser tab, so a requested
|
|
35
165
|
desktop, mobile, or custom CSS size remains in effect through inspection and
|
|
36
166
|
capture.
|
|
@@ -81,15 +211,61 @@ Use `nerdbro schema experience` for the final learner content contract and
|
|
|
81
211
|
`nerdbro docs open experiences` for one-Scene, narrated, mixed, and multi-Band
|
|
82
212
|
examples. Use `nerdbro schema scene.variables`, `scene.events`, `scene.gestures`, `scene.diagram`,
|
|
83
213
|
`scene.motions`, `scene.captions`, `scene.audio`, `scene.stateMachines`,
|
|
84
|
-
`
|
|
85
|
-
`assessment`, or the
|
|
86
|
-
the parser/runtime contract. `nerdbro schema` returns the topic index and
|
|
87
|
-
summary contracts.
|
|
214
|
+
`scene.versions`, `scene.limits`, `expressions`, `stateMachine.actions`,
|
|
215
|
+
`assessment`, or the other listed topics to request a narrow projection of
|
|
216
|
+
the parser/runtime contract. `nerdbro schema` returns the live topic index and
|
|
217
|
+
summary contracts. The `mathGraph.*` and `runtime.*` topics describe frozen
|
|
218
|
+
shapes kept for existing assets; new graphs are Scene math planes.
|
|
88
219
|
Search Components and Behaviors narrowly. Example search rejects an empty
|
|
89
220
|
query, returns ranked summaries with a small default limit, and leaves full
|
|
90
221
|
source to `example inspect <id>`; normally inspect no more than three relevant
|
|
91
222
|
examples.
|
|
92
223
|
|
|
224
|
+
`nerdbro experience inspect-browser <id>` opens the canonical Experience
|
|
225
|
+
workspace. `nerdbro experience drive <id> --scenario scenario.json` runs a
|
|
226
|
+
bounded scenario against the mounted Experience Preview of **your local
|
|
227
|
+
`source.json`, saved or not** (0.7.0+): the exact candidate is mounted in the
|
|
228
|
+
daemon's own browser through the non-persisting Draft Preview and bound by its
|
|
229
|
+
canonical hash (`source_origin: "local"`, `source_hash`); nothing is stored.
|
|
230
|
+
`--saved` drives the saved revision instead. It accepts master
|
|
231
|
+
events (`fire`), Scene semantic events (`fireSceneEvent`), learner presses of
|
|
232
|
+
the active Scene's available events (`press`), Timeline play/pause/seek, Cue
|
|
233
|
+
dispatch, `previewState` (a bare master State id with master-variable
|
|
234
|
+
`setup`, or `machine/state` in the active Scene with `setup` naming variables
|
|
235
|
+
that Scene declares — type and min/max checked, reported as
|
|
236
|
+
`probe.sceneSetup`), `select` (`state:repair`), restart,
|
|
237
|
+
waits, assertions, and captures. It never saves or publishes the source.
|
|
238
|
+
Observation paths read the shared `kheleshikhi.studio-observation.v2`
|
|
239
|
+
domains the Maker's Observatory shows — `experience.activeState`,
|
|
240
|
+
`experience.masterVariables.<name>`, `scene.activeStates.<machine>`,
|
|
241
|
+
`timeline.ms`, `probe.active`, `probe.setup.<name>`, `selection.sourcePath` —
|
|
242
|
+
and the older flat keys (`active_state`, `master_variables`, `timeline_ms`,
|
|
243
|
+
`scene_active_states`, `preview_override`, …) still work.
|
|
244
|
+
|
|
245
|
+
### Source is the authority; probes are not journeys
|
|
246
|
+
|
|
247
|
+
You author the same canonical Source as the Maker. Every drive returns
|
|
248
|
+
`evidence_mode`: `probe` when it jumped to a State, used synthetic `setup`,
|
|
249
|
+
fired an event a learner could not press, or seeked — useful development
|
|
250
|
+
evidence that never proves a learner path or certifies anything — and
|
|
251
|
+
`journey` when it ran from the initial State with learner-reachable actions
|
|
252
|
+
only. Certification refuses a probed runtime observation.
|
|
253
|
+
|
|
254
|
+
### Agent Presence
|
|
255
|
+
|
|
256
|
+
The Maker's open Studio shows what you are doing, through
|
|
257
|
+
`PUT /v1/agent/presence` (scope `STUDIO_OBSERVE`): status, changed source
|
|
258
|
+
paths, the last semantic command and result, where your runtime is, your
|
|
259
|
+
selection, your last capture. The CLI reports it around each
|
|
260
|
+
validate/compile/preview/save/certify/capture/drive and per drive step.
|
|
261
|
+
`nerdbro studio watch <asset> [--once]` and `nerdbro experience watch <id>
|
|
262
|
+
[--once]` report which JSON Pointers your local `source.json` changed
|
|
263
|
+
against the saved head, debounced; they never send the source. Presence is
|
|
264
|
+
overwritten in place, expires after 90 seconds, is cleared on disconnect, and
|
|
265
|
+
carries no reasoning, credentials or local paths. A Maker may **Follow
|
|
266
|
+
Agent**: their Studio mirrors your selection, source path and runtime
|
|
267
|
+
position, but you never control their browser or runtime.
|
|
268
|
+
|
|
93
269
|
The daemon reuses the authenticated context response for at most 30 seconds,
|
|
94
270
|
then revalidates it; connecting or disconnecting clears the cache. This cuts
|
|
95
271
|
repeated compatibility reads without caching mutable drafts.
|
|
@@ -97,9 +273,9 @@ repeated compatibility reads without caching mutable drafts.
|
|
|
97
273
|
Check out once, edit only `source.json`, and use `studio status` for later
|
|
98
274
|
synchronization. Validate, compile, preview when useful, save, then inspect the
|
|
99
275
|
real Studio. The daemon reuses its short-lived read-only browser credential in
|
|
100
|
-
memory and clears it on disconnect, stop, reconnect, or origin change. A
|
|
101
|
-
requirement without a teaching purpose or axis/synchronization meaning is
|
|
102
|
-
clarification request, not permission to invent filler.
|
|
276
|
+
memory and clears it on disconnect, stop, reconnect, or origin change. A math
|
|
277
|
+
plane requirement without a teaching purpose or axis/synchronization meaning is
|
|
278
|
+
a clarification request, not permission to invent filler.
|
|
103
279
|
|
|
104
280
|
`studio create` needs the `STUDIO_ASSET_CREATE` pairing scope and returns a
|
|
105
281
|
Maker-owned draft identity and its server starter-source hash. `--scratch`
|
|
@@ -107,7 +283,8 @@ only labels the intent to use an ordinary new, unapproved asset as a disposable
|
|
|
107
283
|
spike. It has no separate lifecycle, automatic expiry, promotion, or garbage
|
|
108
284
|
collection. Save its exact ID for explicit cleanup after success. Use
|
|
109
285
|
`studio brief <asset>` and `studio brief update <asset> --graph-purpose ...`
|
|
110
|
-
to inspect or update authoring intent
|
|
286
|
+
(or `--math-plane` / `--no-math-plane`) to inspect or update authoring intent
|
|
287
|
+
with a concurrency check.
|
|
111
288
|
|
|
112
289
|
`studio save` creates a draft. `studio certify` records technical evidence.
|
|
113
290
|
Neither approves or publishes. `studio export --revision ...` accepts only the
|
|
@@ -147,8 +324,28 @@ and has at most 64 steps and a two-minute run budget:
|
|
|
147
324
|
}
|
|
148
325
|
```
|
|
149
326
|
|
|
150
|
-
|
|
151
|
-
|
|
327
|
+
To start mid-flow without replaying the Scene, jump to a State of one
|
|
328
|
+
machine — always `machine/state`, because two machines may share a State id —
|
|
329
|
+
optionally with synthetic setup for 1–16 declared variables:
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{"version": 1, "steps": [
|
|
333
|
+
{"op": "previewState", "target": "launch/armed", "setup": {"force": 9, "armed": true}},
|
|
334
|
+
{"op": "assert", "path": "probe.active", "equals": true},
|
|
335
|
+
{"op": "select", "target": "instance:cart"},
|
|
336
|
+
{"op": "assert", "path": "selection.sourcePath", "equals": "/sources/mainScene/document/instances/0"},
|
|
337
|
+
{"op": "press", "target": "disarmPressed"},
|
|
338
|
+
{"op": "wait", "path": "scene.activeStates.launch", "equals": "idle"},
|
|
339
|
+
{"op": "capture", "name": "after-disarm"},
|
|
340
|
+
{"op": "restart"}
|
|
341
|
+
]}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
`set`, `fire`, `press`, `tap`, `drag`, `play`, `pause`, `seek`, `reset`,
|
|
345
|
+
`restart`, `previewState` and `select` address only declared variables,
|
|
346
|
+
events, instances, gestures, machines and States. A `set` on a variable the
|
|
347
|
+
learner has no visible control for is synthetic setup and makes the run a
|
|
348
|
+
probe. `press`
|
|
152
349
|
honours conditional availability; `drag` derives a Scene point from the
|
|
153
350
|
authored gesture range. `wait` and `assert` read allowlisted observation paths,
|
|
154
351
|
never arbitrary code. `capture` records the actual browser pixels. The result
|
|
@@ -199,7 +396,12 @@ edits without `--force`. `status` reports `local_changed`, `remote_changed` and
|
|
|
199
396
|
saving unchanged content creates no draft but still refreshes the lock, and a
|
|
200
397
|
stale base exits `3` (`VOCABULARY_DRAFT_CONFLICT`) with `source.json` untouched.
|
|
201
398
|
`validate` and `certify` default to the lock's head revision. `preview` sends
|
|
202
|
-
the local, unsaved `source.json` and writes `preview.json` beside it
|
|
399
|
+
the local, unsaved `source.json` and writes `preview.json` beside it; for an
|
|
400
|
+
Experience its summary reports the schema, Scene and audio counts, V3
|
|
401
|
+
interaction block counts, rounds, outcomes and the server-derived
|
|
402
|
+
`required_capabilities`. When a checked-out Experience is not the context's
|
|
403
|
+
`experience_schema` (for example a V2 document), `checkout`, `status` and
|
|
404
|
+
`preview` add a `schema_notice` with the server's deprecation text.
|
|
203
405
|
`inspect-browser` captures the Studio Library workspace to `screenshot.png` and
|
|
204
406
|
`browser.json` in the checkout directory; its bounded `browser.capture` activity
|
|
205
407
|
record is reported locally in the command result only.
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { type RenderRecipe } from "./video.js";
|
|
1
2
|
import { type Page } from "playwright";
|
|
2
3
|
import { AgentApi } from "./protocol.js";
|
|
3
|
-
import { type DriveScenario } from "./scenario.js";
|
|
4
|
+
import { type DriveScenario, type ExperienceScenario } from "./scenario.js";
|
|
5
|
+
/** One semantic step as it happened, for Agent Presence and the activity feed. */
|
|
6
|
+
export type DriveStepReport = {
|
|
7
|
+
index: number;
|
|
8
|
+
summary: Record<string, unknown>;
|
|
9
|
+
observation?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
/** Called after each semantic step; failures inside it never fail the drive. */
|
|
12
|
+
export type DriveStepListener = (report: DriveStepReport) => void | Promise<void>;
|
|
4
13
|
export declare function studioBrowserLaunchOptions(headless: boolean): {
|
|
5
14
|
readonly headless: boolean;
|
|
6
15
|
readonly viewport: null;
|
|
@@ -19,7 +28,7 @@ export declare function waitForCapturePaint(page: Page): Promise<void>;
|
|
|
19
28
|
export declare function applyCssViewport(page: Page, dimensions: {
|
|
20
29
|
width: number;
|
|
21
30
|
height: number;
|
|
22
|
-
}): Promise<void>;
|
|
31
|
+
}, deviceScaleFactor?: number): Promise<void>;
|
|
23
32
|
export declare function renderingDiagnostics(page: Page, screenshot: Buffer): Promise<Record<string, unknown>>;
|
|
24
33
|
export declare const VIEW_QUERY: Record<string, Record<string, string>>;
|
|
25
34
|
export declare function viewRequiresRuntimeObservation(view: string): boolean;
|
|
@@ -58,6 +67,8 @@ export interface BrowserCaptureRequest {
|
|
|
58
67
|
timeoutMs?: number;
|
|
59
68
|
observation?: boolean;
|
|
60
69
|
drive?: boolean;
|
|
70
|
+
/** An Experience drive that will mount an unsaved candidate itself. */
|
|
71
|
+
awaitsCandidate?: boolean;
|
|
61
72
|
/** Library workspace route (`?workspace=<name>&selection=<stable id>`) instead of a Scene asset. */
|
|
62
73
|
library?: {
|
|
63
74
|
workspace: string;
|
|
@@ -65,6 +76,12 @@ export interface BrowserCaptureRequest {
|
|
|
65
76
|
revision?: string;
|
|
66
77
|
definitionHash?: string;
|
|
67
78
|
};
|
|
79
|
+
/** Semantic step reports for presence; never part of the request sent to the page. */
|
|
80
|
+
onStep?: DriveStepListener;
|
|
81
|
+
/** The presentation render host (`studio_present=1`): the learner stage alone, filling the viewport. */
|
|
82
|
+
present?: boolean;
|
|
83
|
+
/** CSS-to-device pixel scale; 0 keeps the display's own. */
|
|
84
|
+
deviceScaleFactor?: number;
|
|
68
85
|
}
|
|
69
86
|
export interface PreviewObservationRequest extends BrowserCaptureRequest {
|
|
70
87
|
mode?: string;
|
|
@@ -96,6 +113,61 @@ export declare class StudioBrowser {
|
|
|
96
113
|
candidate: Record<string, unknown>;
|
|
97
114
|
candidateHash: string;
|
|
98
115
|
}): Promise<Record<string, unknown>>;
|
|
116
|
+
driveExperience(request: BrowserCaptureRequest & {
|
|
117
|
+
scenario: ExperienceScenario;
|
|
118
|
+
candidate?: unknown;
|
|
119
|
+
candidateHash?: string;
|
|
120
|
+
}): Promise<Record<string, unknown>>;
|
|
121
|
+
/**
|
|
122
|
+
* Presentation frames (STU-001) of a Scene, from the presentation host.
|
|
123
|
+
*
|
|
124
|
+
* Mounts and verifies the candidate exactly as `drive` does, but in the
|
|
125
|
+
* presentation host (`studio_present=1`) at a viewport of exactly the
|
|
126
|
+
* output size and device scale 1. `renderBegin` silences the Scene's
|
|
127
|
+
* sounds into a log and restarts it at 0 s; then for every frame video
|
|
128
|
+
* time is stepped to `start + k / fps`, the runtime confirms that instant
|
|
129
|
+
* and a paint, and the whole viewport is captured: one PNG of exactly the
|
|
130
|
+
* output size, proved before it is kept. Scheduled learner actions happen
|
|
131
|
+
* at their own seconds. Afterwards the audio log and each logged sound's
|
|
132
|
+
* canonical bytes are collected for the mixer.
|
|
133
|
+
*/
|
|
134
|
+
renderFrames(request: BrowserCaptureRequest & {
|
|
135
|
+
candidate: Record<string, unknown>;
|
|
136
|
+
candidateHash: string;
|
|
137
|
+
recipe: RenderRecipe;
|
|
138
|
+
framesDirectory: string;
|
|
139
|
+
audioDirectory: string;
|
|
140
|
+
/** Optional: afterwards, play in real time and sample frame intervals. */
|
|
141
|
+
measurePlaybackSeconds?: number;
|
|
142
|
+
}): Promise<Record<string, unknown>>;
|
|
143
|
+
/**
|
|
144
|
+
* Presentation frames of an Experience: the canonical Experience player
|
|
145
|
+
* in the presentation host, driven by video time (`renderBegin`, then
|
|
146
|
+
* `step` per frame). The master timeline advances with video time only
|
|
147
|
+
* while it runs, so a learner pause or a wait for a choice stays paused,
|
|
148
|
+
* as it would in playback; Scenes change, cues fire and sounds start at
|
|
149
|
+
* the exact video second they would.
|
|
150
|
+
*/
|
|
151
|
+
renderExperienceFrames(request: BrowserCaptureRequest & {
|
|
152
|
+
candidate?: unknown;
|
|
153
|
+
candidateHash?: string;
|
|
154
|
+
recipe: RenderRecipe;
|
|
155
|
+
framesDirectory: string;
|
|
156
|
+
audioDirectory: string;
|
|
157
|
+
}): Promise<Record<string, unknown>>;
|
|
158
|
+
private requirePage;
|
|
159
|
+
/** The page's runtime observation and its one-at-a-time drive channel. */
|
|
160
|
+
private renderChannel;
|
|
161
|
+
/** The newest observation once [ready] holds (the page publishes every 150 ms). */
|
|
162
|
+
private waitForRender;
|
|
163
|
+
/**
|
|
164
|
+
* The frame loop both subjects share: actions at their seconds, a step to
|
|
165
|
+
* each frame's exact second, the subject's own arrival check, a paint,
|
|
166
|
+
* and a whole-viewport PNG proved to be exactly the output size.
|
|
167
|
+
*/
|
|
168
|
+
private captureFrames;
|
|
169
|
+
/** Every logged sound's canonical bytes, written once by key; checked against the logged SHA-256. */
|
|
170
|
+
private collectAudio;
|
|
99
171
|
/** Local-agent capture from the same browser page and renderer the Maker sees. */
|
|
100
172
|
capturePreview(request: PreviewObservationRequest): Promise<Record<string, unknown>>;
|
|
101
173
|
}
|