@volter/editor-live 0.5.113 → 0.5.115

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/BUNDLED_NOTICES CHANGED
@@ -3,9 +3,9 @@ Bundled license notices
3
3
  These notices accompany code incorporated into this package. Separate npm dependencies retain their own licenses.
4
4
 
5
5
 
6
- @volter/editor-project@0.5.113
6
+ @volter/editor-project@0.5.115
7
7
  Declared license: Apache-2.0
8
- Source: the unmodified npm package @volter/editor-project@0.5.113, from https://github.com/volter-ai/editor.git
8
+ Source: the unmodified npm package @volter/editor-project@0.5.115, from https://github.com/volter-ai/editor.git
9
9
 
10
10
  --- packages/editor-project/LICENSE ---
11
11
 
@@ -213,9 +213,9 @@ Source: the unmodified npm package @volter/editor-project@0.5.113, from https://
213
213
  limitations under the License.
214
214
 
215
215
 
216
- @volter/editor-sdk@0.5.113
216
+ @volter/editor-sdk@0.5.115
217
217
  Declared license: Apache-2.0
218
- Source: the unmodified npm package @volter/editor-sdk@0.5.113, from https://github.com/volter-ai/editor.git
218
+ Source: the unmodified npm package @volter/editor-sdk@0.5.115, from https://github.com/volter-ai/editor.git
219
219
 
220
220
  --- packages/editor-sdk/LICENSE ---
221
221
 
package/dist/index.js CHANGED
@@ -76,6 +76,7 @@ var RETRYABLE_TRANSPORT_CODES = /* @__PURE__ */ new Set([
76
76
  var TRANSPORT_RETRY_DELAY_MS = 400;
77
77
  var EditorClient = class {
78
78
  baseUrl;
79
+ fetchOverride;
79
80
  /**
80
81
  * The running game's debug plane — see {@link GameDebugDoor}. It rides the
81
82
  * SAME `/__editor/command` relay every other method here uses (relay cases
@@ -105,7 +106,7 @@ var EditorClient = class {
105
106
  );
106
107
  }
107
108
  const unknownOptions = Object.keys(opts ?? {}).filter(
108
- (key) => key !== "url" && key !== "onEnvelope" && key !== "transport"
109
+ (key) => key !== "url" && key !== "onEnvelope" && key !== "transport" && key !== "fetch"
109
110
  );
110
111
  if (unknownOptions.length > 0) {
111
112
  throw new Error(
@@ -113,6 +114,7 @@ var EditorClient = class {
113
114
  );
114
115
  }
115
116
  this.baseUrl = (opts?.url ?? DEFAULT_URL).replace(/\/$/, "");
117
+ this.fetchOverride = opts?.fetch;
116
118
  this.onEnvelope = opts?.onEnvelope ?? null;
117
119
  this.transport = opts?.transport ?? null;
118
120
  this.game = {
@@ -161,7 +163,7 @@ var EditorClient = class {
161
163
  signal: AbortSignal.timeout(deadlineMs)
162
164
  };
163
165
  commandDispatcher = deadlineMs > UNDICI_DEFAULT_HEADERS_TIMEOUT_MS ? createDispatcher(deadlineMs + 3e4) : void 0;
164
- res = await dispatchFetch(url, init, commandDispatcher);
166
+ res = this.fetchOverride ? await this.fetchOverride(url, init) : await dispatchFetch(url, init, commandDispatcher);
165
167
  break;
166
168
  } catch (error) {
167
169
  await commandDispatcher?.destroy?.();
@@ -1072,7 +1074,7 @@ var EditorClient = class {
1072
1074
  */
1073
1075
  async httpFetch(url, init, dispatcher) {
1074
1076
  try {
1075
- return await dispatchFetch(url, init, dispatcher);
1077
+ return this.fetchOverride ? await this.fetchOverride(url, init) : await dispatchFetch(url, init, dispatcher);
1076
1078
  } catch (error) {
1077
1079
  if (error?.name === "TimeoutError") throw error;
1078
1080
  const { code, detail } = describeFetchFailure(error);
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../editor-sdk/src/http-transport.node.ts", "../../editor-sdk/src/client.ts", "../src/editor-document.ts", "../src/editor.ts", "../src/tools.ts", "../src/lazy-proxy.ts", "../src/session.ts", "../../editor-project/src/manifest/locate.ts", "../../editor-project/src/manifest/filename.ts", "../../editor-sdk/src/session/product-locator.ts", "../../editor-sdk/src/session/registry-format.ts", "../../editor-sdk/src/session/discovery.ts", "../src/singleton.ts", "../src/index.ts"],
4
- "sourcesContent": ["/** Node session clients need explicit header deadlines for long modeling calls.\n * Some runtimes supply an undici-compatible Agent without destroy(); callers\n * close explicitly when that lifecycle method exists. */\nimport { Agent, fetch as nodeFetch, type Dispatcher } from 'undici';\n\nexport function createDispatcher(timeoutMs: number): Dispatcher {\n return new Agent({ headersTimeout: timeoutMs, bodyTimeout: timeoutMs });\n}\n\nexport async function dispatchFetch(\n url: string,\n init?: RequestInit,\n dispatcher?: Dispatcher,\n): Promise<Response> {\n if (!dispatcher) return fetch(url, init);\n return await nodeFetch(url, {\n ...(init as object), dispatcher,\n }) as unknown as Response;\n}\n", "import type { GenerationJobsDocument } from '@volter/editor-sdk/generations';\nimport type { Dispatcher } from 'undici';\nimport { createDispatcher, dispatchFetch } from '#http-transport';\nimport type { DocumentProbeResult, DocumentProbeStep } from './document-probe.js';\nimport type {\n ActiveDocumentCapture,\n AssetCompareCapture,\n AssetCompareOptions,\n AssetKind,\n AssetPreviewCapture,\n AssetPreviewOptions,\n AssetPreviewShotSetDefinition,\n AssetPreviewSource,\n CaptureDimensions,\n DocumentCameraPose,\n DocumentLookOutcome,\n StageFrameCostReading,\n DocumentTableProjection,\n EditorChromeCapture,\n EditorChromeCaptureOptions,\n EditorState,\n EditorView,\n EditorWorkspaceName,\n GameCapture,\n GameplayRecordingCapture,\n GameplayRecordingOptions,\n GameplayRecordingStarted,\n GameplayRecordingTimeline,\n GameplayReplayCapture,\n HelperVisibility,\n InspectedFieldWrite,\n InspectedHierarchy,\n InspectedInspection,\n LabeledShotSetCapture,\n PlayStarted,\n PresentedEditorView,\n ProjectInfo,\n ProjectTemplate,\n ProjectToolCatalog,\n ProjectToolOutcome,\n RecentProject,\n ShadingMode,\n StoryCaptureOptions,\n StoryVariantCapture,\n StructureOp,\n StructureOpOptions,\n StructureOpResult,\n TransformMode,\n TransformSpace,\n Vec3Value,\n ViewPreset,\n ViewportCapture,\n ViewportTab,\n} from './types.js';\n\n// The editor's default origin, spelled out because this package deliberately\n// does not depend on `@volter/editor-project`. `DEFAULT_EDITOR_PORT` in\n// `packages/editor-project/src/manifest/editor-port.ts` is the owner of the number and\n// of the never-`localhost` rule; keep this in step with it.\nconst DEFAULT_URL = 'http://127.0.0.1:20173';\n\n/**\n * A refused editor command, carrying the relay's own STRUCTURED failure code\n * alongside the prose.\n *\n * `/__editor/command` has always answered `{ ok: false, error, code }` and\n * this client has always dropped the `code` on the floor, so every caller that\n * wanted to react to a specific refusal had to substring-match an English\n * sentence. the editor's `screenshot` command's loop-recovery fallback is the first caller that\n * genuinely must branch (`BRIDGE_SCREENSHOT_STALE` has a working recovery;\n * \"not in play mode\" does not), and a fallback keyed on prose would fire on\n * the wrong failure the first time someone rewords the message.\n */\nexport class EditorCommandError extends Error {\n readonly code: string | undefined;\n /**\n * True when the RELAY ended the command itself rather than the editor\n * answering it \u2014 the HTTP 504 that `server/server-utils.ts`'s\n * `commandResponseFor` gives any `timedOut` result, or this client's own\n * deadline below.\n *\n * Read it as \"no answer\", not as \"the budget expired\". `editor-server.ts`\n * raises `timedOut` for five conditions and only one of them takes the full\n * budget: the command's timer expiring, the controlling tab's socket dying,\n * the receipt window closing unanswered, a beating-but-dead tab, and no tab\n * present at all. The last four can fail in milliseconds.\n *\n * A caller that converges by retrying (the editor's `restart` command) needs the distinction\n * because a refusal the editor ANSWERED may go differently next time, while\n * a command the relay abandoned tells you nothing new on a second identical\n * attempt \u2014 and when the abandonment was a 120s budget, re-running it three\n * times is `restart-readiness.ts`'s 361-seconds-of-silence defect.\n */\n readonly timedOut: boolean;\n constructor(message: string, code?: string | undefined, timedOut = false) {\n super(message);\n this.name = 'EditorCommandError';\n this.code = code;\n this.timedOut = timedOut;\n }\n}\n\n/**\n * The client's own ceiling on ONE relayed command.\n *\n * A backstop for a LOST server, not a per-command budget: the server already\n * owns per-type budgets (`server/server-utils.ts`'s `relayCommandTimeoutMs`)\n * and its timer must always be the one that fires, because its message names\n * the tab and the remedy while this one can only say \"no answer\". So this is\n * deliberately ONE number, comfortably above the longest server budget\n * (120s, `play`/`capture-story-variants`) rather than a mirror of that table \u2014\n * a second copy of it would drift silently, and the drift would show up as\n * this timer winning a race it must always lose.\n *\n * Without it a `fetch` with no `AbortSignal` waits on the OS: a dev server\n * that stops answering mid-command holds the CLI open indefinitely, with no\n * output and nothing to read.\n */\nconst COMMAND_DEADLINE_MS = 150_000;\n/** The Blender lane's own ceiling: a chunk is a whole modeling step, not a tick. */\nconst BLENDER_DEADLINE_MS = 30 * 60_000;\n/** undici's default `headersTimeout`; a command deadline beyond it needs its own dispatcher (see `command`). */\nconst UNDICI_DEFAULT_HEADERS_TIMEOUT_MS = 300_000;\n\n/**\n * Ceiling on {@link EditorClient.getUnresolvedConsole}. The CLI drains this\n * on every verb, including ones that never wait for a command envelope, so\n * a silent hang here would become a silent hang on the editor's `sessions` command. The\n * server route is a plain in-process GET; 1.5s is already longer than it\n * should ever take.\n */\nconst CONSOLE_DRAIN_TIMEOUT_MS = 1_500;\n\n/**\n * Node's `fetch` collapses EVERY network-layer failure into one two-word\n * `TypeError: fetch failed`. The real reason \u2014 `ECONNREFUSED`, `ECONNRESET`,\n * `EPIPE`, a DNS miss \u2014 lives only on `error.cause` (sometimes two links down,\n * or inside an `AggregateError`), and nothing prints it unless something walks\n * the chain. That is the whole reason `project.bake.preview` was observed\n * failing with a bare \"fetch failed\" and no way to tell a dead editor from a\n * momentary one (WORK.md, cold barrel 2026-08-29): the code below used to\n * rethrow the `TypeError` untouched, on the belief \u2014 stated in a comment right\n * where it happened \u2014 that \"a connection refused / DNS failure still surfaces\n * as itself\". It does not. This walks the chain so the message can say which.\n */\nfunction describeFetchFailure(error: unknown): { code: string; detail: string } {\n const messages: string[] = [];\n let current: unknown = error;\n for (let depth = 0; depth < 8; depth++) {\n if (!(current instanceof Error)) break;\n if (current.message) messages.push(current.message);\n const code = (current as { code?: unknown }).code;\n if (typeof code === 'string' && code !== '') {\n return { code, detail: messages.join(' <- ') };\n }\n const aggregate = (current as { errors?: unknown }).errors;\n if (Array.isArray(aggregate) && aggregate.length > 0) {\n const inner = describeFetchFailure(aggregate[0]);\n return { code: inner.code, detail: [...messages, inner.detail].join(' <- ') };\n }\n current = (current as { cause?: unknown }).cause;\n }\n return { code: 'UNKNOWN', detail: messages.join(' <- ') || String(error) };\n}\n\n/**\n * Transport failures where a second attempt is worth making: the connection\n * itself failed or died, rather than the editor answering something unwelcome.\n * A dev server that is restarting (any watched source edit restarts it) is\n * unreachable for a fraction of a second and reachable again after \u2014 which is\n * exactly the \"fails, then succeeds unchanged\" shape that was reported.\n */\nconst RETRYABLE_TRANSPORT_CODES = new Set([\n 'ECONNREFUSED',\n 'ECONNRESET',\n 'EPIPE',\n 'ETIMEDOUT',\n 'EHOSTUNREACH',\n 'UND_ERR_SOCKET',\n 'UND_ERR_CONNECT_TIMEOUT',\n]);\n\n/** Gap before the one automatic retry \u2014 long enough for a dev-server restart's\n * listen socket to come back, short enough to stay invisible. */\nconst TRANSPORT_RETRY_DELAY_MS = 400;\n\n/** Context accompanying one {@link EditorClient} response observation. */\nexport interface EditorEnvelopeObservation {\n /** True only when this body came from the console-ledger endpoint and its\n * `entries` field is therefore the complete named console set. Command\n * payloads may also own an unrelated `entries` field. */\n readonly unresolvedConsoleComplete: boolean;\n}\n\n/**\n * The GAME DEBUG PLANE, as a contribution's client sees it.\n *\n * Deliberately the same two words `@volter/editor-live`'s session binding uses\n * (`game.state(name)` / `game.command(name, ...args)`), because it is the same\n * plane: whatever the running game registered through `ctx.debug` \u2014 a provider\n * read by name, a command invoked by name. A tool contribution that wants the\n * game's own vitals in its panel has this door and no other; there is\n * deliberately no per-capability method, because a game names its own\n * providers and commands.\n *\n * Both legs reject LOUDLY (`EditorCommandError`) rather than answer with a\n * placeholder: play not running is `'not in play mode \u2014 start play before\n * using the debug seam'`, and an unregistered command carries\n * `code: 'DEBUG_COMMAND_NOT_REGISTERED'`. A panel decides what to show for\n * those; the client never invents one.\n */\n/** What one undo/redo step reports back \u2014 `moved` is false when there was\n * nothing left in that direction, which is an answer, not an error. */\nexport interface HistoryStep {\n readonly moved: boolean;\n readonly canUndo: boolean;\n readonly canRedo: boolean;\n readonly undoLabel: string | null;\n readonly redoLabel: string | null;\n}\n\n/** What `open()` acknowledges: the workspace document the scene-table entry\n * resolved to, and the title its tab now carries \u2014 the game's own word for\n * that composition, not a filename. */\nexport interface OpenedDocument {\n readonly documentId: string;\n readonly title: string;\n /**\n * The GAME's own answer, present only when opening navigated a running game\n * (a scene the adapter declares reachable through the game's scenes\n * contract, or a native swap-slot remount): what was asked for, and which\n * scene the game reports it is in once its own navigation settled. `current`\n * can differ from `requested` \u2014 that is the game's reading, not a host claim.\n */\n readonly scene?: { readonly requested: string; readonly current: string | null };\n /**\n * Present when opening restarted play at a native swap-slot key rather than\n * navigating a live contract \u2014 the slot is a module-level const.\n */\n readonly restart?: true;\n}\n\nexport interface GameDebugDoor {\n /**\n * Read ONE registered state provider by name (`'bot.tester'`). `undefined`\n * when the running game registered no such provider \u2014 or no debug adapter at\n * all, which is an honest answer rather than a refusal.\n */\n state(name: string): Promise<unknown>;\n /** Invoke ONE registered debug command by name, with its own arguments. */\n command(name: string, ...args: unknown[]): Promise<unknown>;\n}\n\nexport class EditorClient {\n private readonly baseUrl: string;\n\n /**\n * The running game's debug plane \u2014 see {@link GameDebugDoor}. It rides the\n * SAME `/__editor/command` relay every other method here uses (relay cases\n * `inspect-gameplay-state` / `invoke-debug-command`, `command-listener.ts`),\n * so a tool contribution reaches the game through the client it already has\n * rather than a second channel of its own.\n */\n readonly game: GameDebugDoor;\n\n /**\n * Called with the raw body of EVERY response this client receives \u2014 command\n * envelopes and `/__editor/state` alike, on success AND on refusal.\n *\n * It exists for exactly one contract: the server stamps `unresolvedConsole`\n * onto every envelope (`server-utils.ts`'s `commandResponseFor`), and the CLI\n * has to see those counts to be loud about them. Routing that through a\n * single observer here \u2014 rather than teaching each of the CLI's output sites\n * to unpack a response \u2014 is what keeps the loudness contract ONE mechanism.\n * The observer must not throw; anything it raises is swallowed, because a\n * reporting hook may never break the command it is reporting on.\n */\n private readonly transport:\n | ((body: Record<string, unknown>) => Promise<Record<string, unknown>>)\n | null;\n private readonly onEnvelope:\n | ((body: unknown, observation: EditorEnvelopeObservation) => void)\n | null;\n\n constructor(opts?: {\n url?: string;\n onEnvelope?: (body: unknown, observation: EditorEnvelopeObservation) => void;\n /**\n * An IN-PAGE command channel, for a client that lives inside the editor\n * page itself and has no editor server to reach. Given, every command goes through it instead of\n * `POST /__editor/command`, and answers in the route's own body shape\n * (`{ ok: true, ...data }` / `{ ok: false, error, code? }`).\n */\n transport?: (body: Record<string, unknown>) => Promise<Record<string, unknown>>;\n }) {\n if (opts !== undefined && (typeof opts !== 'object' || opts === null || Array.isArray(opts))) {\n throw new TypeError(\n 'EditorClient options must be an object. Use new EditorClient({ url: \"http://127.0.0.1:20173\" }), not new EditorClient(\"...\").',\n );\n }\n const unknownOptions = Object.keys(opts ?? {}).filter(\n (key) => key !== 'url' && key !== 'onEnvelope' && key !== 'transport',\n );\n if (unknownOptions.length > 0) {\n throw new Error(\n `EditorClient: unknown option${unknownOptions.length === 1 ? '' : 's'} ${unknownOptions.map((key) => `\"${key}\"`).join(', ')}. Use { url: \"http://127.0.0.1:<port>\" } to target an editor.`,\n );\n }\n this.baseUrl = (opts?.url ?? DEFAULT_URL).replace(/\\/$/, '');\n this.onEnvelope = opts?.onEnvelope ?? null;\n this.transport = opts?.transport ?? null;\n this.game = {\n state: async (name: string): Promise<unknown> => {\n // `keys` narrows the relay to the one provider asked for, so a panel\n // polling one vital never drags the whole plane's `stateAll()` across\n // the wire. A game with no debug adapter answers `{ state: null }`.\n const data = await this.command<{ state: Record<string, unknown> | null }>({\n type: 'inspect-gameplay-state',\n keys: [name],\n });\n return data.state?.[name];\n },\n command: async (name: string, ...args: unknown[]): Promise<unknown> =>\n (await this.command<{ result: unknown }>({ type: 'invoke-debug-command', name, args }))\n .result,\n };\n }\n\n /**\n * `retryTransport` opts a command into ONE automatic retry after a transport\n * failure (see {@link RETRYABLE_TRANSPORT_CODES}). It is deliberately\n * OPT-IN and off by default: a socket that died after the request was written\n * cannot prove the editor did not already run the command, so a blanket retry\n * would risk playing/stopping/writing twice. Read-only relays \u2014 the captures \u2014\n * have no such hazard and turn it on.\n */\n private async command<T extends object = Record<string, never>>(\n body: Record<string, unknown>,\n options?: { retryTransport?: boolean; deadlineMs?: number },\n ): Promise<T> {\n const type = String(body['type'] ?? 'command');\n const deadlineMs = options?.deadlineMs ?? COMMAND_DEADLINE_MS;\n if (this.transport) {\n const answered = (await this.transport(body)) as {\n ok: boolean;\n error?: string;\n code?: string;\n } & T;\n if (!answered.ok) {\n throw new EditorCommandError(\n answered.error ?? `Editor command \"${type}\" failed`,\n answered.code,\n );\n }\n return answered;\n }\n const url = `${this.baseUrl}/__editor/command`;\n const request = JSON.stringify(body);\n let res: Response | undefined;\n let retried = false;\n let commandDispatcher: Dispatcher | undefined;\n for (;;) {\n try {\n const init: RequestInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: request,\n signal: AbortSignal.timeout(deadlineMs),\n };\n // The command route answers only when the command completes, and\n // Node's fetch (undici) gives a server 300 s to send response HEADERS\n // regardless of the abort signal: a modeling step measured at eleven\n // minutes in the tab died as UND_ERR_HEADERS_TIMEOUT well inside its\n // half-hour budget. A deadline past that default carries its own\n // dispatcher, through undici's own fetch so the two agree.\n commandDispatcher = deadlineMs > UNDICI_DEFAULT_HEADERS_TIMEOUT_MS\n ? createDispatcher(deadlineMs + 30_000)\n : undefined;\n res = await dispatchFetch(url, init, commandDispatcher);\n break;\n } catch (error) {\n await commandDispatcher?.destroy?.();\n commandDispatcher = undefined;\n // Only the deadline is reshaped into a \"no answer\" verdict; everything\n // else is a TRANSPORT failure, and Node hides its reason behind a bare\n // `fetch failed` (see `describeFetchFailure`).\n if ((error as { name?: string } | null)?.name === 'TimeoutError') {\n throw new EditorCommandError(\n `The editor at ${this.baseUrl} never answered \"${type}\" ` +\n `within ${Math.round(deadlineMs / 1000)}s \u2014 past every server-side budget, so ` +\n 'the server itself is not answering. Check the terminal that started this editor session.',\n undefined,\n true,\n );\n }\n const { code, detail } = describeFetchFailure(error);\n if (options?.retryTransport === true && !retried && RETRYABLE_TRANSPORT_CODES.has(code)) {\n retried = true;\n await new Promise((resolve) => setTimeout(resolve, TRANSPORT_RETRY_DELAY_MS));\n continue;\n }\n throw new EditorCommandError(\n `POST ${url} (\"${type}\") never reached the editor: ${code}${detail ? ` (${detail})` : ''}.` +\n (retried\n ? ` Retried once after ${TRANSPORT_RETRY_DELAY_MS}ms; it failed the same way.`\n : '') +\n (options?.retryTransport === true\n ? ''\n : ' Not retried automatically: this command can change editor state, and a socket that' +\n ' died after the request was written cannot prove the editor did not already run it.') +\n ' A transport failure means the port stopped answering, not that the editor refused \u2014' +\n ' the dev server restarts on any watched source edit, and it shuts itself down after an' +\n ' idle window. Check the terminal that started this editor session and confirm the port' +\n ' this client resolved.',\n code,\n false,\n );\n }\n }\n let data: { ok: boolean; error?: string; code?: string } & T;\n try {\n data = (await this.readJson(res)) as typeof data;\n } finally {\n await commandDispatcher?.destroy?.();\n }\n if (!data.ok) {\n throw new EditorCommandError(\n data.error ?? `Editor command failed: ${res.status}`,\n data.code,\n // 504 is every `timedOut` result (`commandResponseFor`) \u2014 the relay\n // gave up, on any of its five grounds. A 200 body with `ok: false` is\n // an ANSWER from the editor, however unwelcome. See `timedOut` above.\n res.status === 504,\n );\n }\n return data;\n }\n\n // --- Play control ---\n\n /** `opts.seed` (D15/T-D15.6, objection-4 fix) \u2014 the editor's `play --seed <n>` command's\n * explicit config leg, relayed as `cmd['seed']`; `handleCommand`'s\n * `'play'` case threads it into `enterPlayMode`'s highest-precedence seed\n * argument (beats manifest.determinism.defaultSeed/?volter-seed=). Omitted,\n * boot seeding falls back to that precedence unchanged.\n *\n * `opts.name` (the editor's `play --name <text>` command) \u2014 an OPTIONAL label for this run,\n * relayed as `cmd['name']` and slugified server-side into the run's\n * `logs/play-*.jsonl` filename and its session-journal line. Findability\n * only: no registry, no uniqueness, no lookup verb \u2014 grep and `ls` are the\n * query engine. Omitted, the filename keeps its exact unnamed shape. */\n /* `opts.record` (the editor's `play --record <name>` command) \u2014 NAMES this run's recording\n * file. It does not ENABLE recording: every relayed play records, with no\n * flag (see `@volter/editor-game`'s `src/play/play-recording.ts`). Omitted, the clip is named for\n * the durable Gameplay Session; named, it becomes an explicit keepsake in\n * `.volter/recordings/<name>.webm`. */\n async play(opts?: {\n seed?: number;\n name?: string | null;\n record?: string | null;\n }): Promise<PlayStarted> {\n return this.command<PlayStarted>({\n type: 'play',\n ...(opts?.seed !== undefined ? { seed: opts.seed } : {}),\n ...(opts?.name ? { name: opts.name } : {}),\n ...(opts?.record ? { record: opts.record } : {}),\n });\n }\n\n /** Dispose the current play session and mount it again from fresh project entry source. */\n async restart(): Promise<void> {\n await this.command({ type: 'play' });\n }\n\n /** Refuse shutdown if a document cannot be saved. Does not stop the server. */\n async prepareClose(): Promise<void> {\n await this.command({ type: 'session-prepare-close' });\n }\n\n /** Stops play, and finalizes this run's recording before the surface it was\n * photographing is torn down. The capture is absent when nothing recorded. */\n async stop(): Promise<{ recording?: GameplayRecordingCapture }> {\n return this.command<{ recording?: GameplayRecordingCapture }>({ type: 'stop' });\n }\n\n async pause(): Promise<void> {\n await this.command({ type: 'pause' });\n }\n\n async resume(): Promise<void> {\n await this.command({ type: 'resume' });\n }\n\n async step(): Promise<void> {\n await this.command({ type: 'step' });\n }\n\n // --- Selection ---\n\n async select(id: string | null): Promise<void> {\n await this.command({ type: 'select', id });\n }\n\n async selectMultiple(ids: string[]): Promise<void> {\n await this.command({ type: 'select-multiple', ids });\n }\n\n async selectAll(): Promise<void> {\n await this.command({ type: 'select-all' });\n }\n\n // --- Viewport ---\n\n async focusEntity(id: string): Promise<void> {\n await this.command({ type: 'focus-entity', id });\n }\n\n async focusSelection(): Promise<void> {\n await this.command({ type: 'focus-selection' });\n }\n\n /**\n * Frame the EDIT viewport camera on one entity \u2014 the strict sibling of\n * {@link focusEntity}. Same framing; an id the scene does not know is a\n * refusal naming the id (`EditorCommandError`, code `ENTITY_NOT_FOUND`)\n * rather than `focusEntity`'s silent no-op, so a caller that frames an\n * entity before capturing it cannot photograph the wrong thing.\n */\n async frameEntity(id: string): Promise<void> {\n await this.command({ type: 'frame-entity', id });\n }\n\n async viewPreset(preset: ViewPreset): Promise<void> {\n await this.command({ type: 'view-preset', preset });\n }\n\n /**\n * LOOK AROUND THE OPEN MODEL, visibly. Swings the active Object3D\n * document's camera \u2014 the one on the human's screen \u2014 by `azimuth`/\n * `elevation` radians, animated over `duration` seconds, and resolves when\n * the move ends. A human drag during the move cancels it where it stands\n * (`cancelledBy: 'human'`); the promise still resolves.\n */\n async orbitDocument(options: {\n azimuth?: number;\n elevation?: number;\n duration?: number;\n }): Promise<DocumentLookOutcome> {\n return this.command<DocumentLookOutcome>({ type: 'document-orbit', ...options });\n }\n\n /** What a frame of a 3D document's stage costs, uncapped (`document-frame-cost`). */\n async frameCostDocument(options?: { readonly frames?: number; readonly stage?: string }): Promise<StageFrameCostReading> {\n return this.command<StageFrameCostReading>({ type: 'document-frame-cost', ...options });\n }\n\n /** A slow full revolution around the open document's subject, at a constant rate. */\n async turntableDocument(options?: {\n seconds?: number;\n revolutions?: number;\n }): Promise<DocumentLookOutcome> {\n return this.command<DocumentLookOutcome>({ type: 'document-turntable', ...options });\n }\n\n /**\n * Frame the open document's subject (its selection if it has one). `fit`\n * scales the fitted distance: 1 is the toolbar Frame button's tight fit.\n */\n async frameDocument(fit?: number): Promise<DocumentCameraPose> {\n return this.command<DocumentCameraPose>({\n type: 'document-frame',\n ...(fit === undefined ? {} : { fit }),\n });\n }\n\n async setCamera(position: Vec3Value, target: Vec3Value, fov?: number): Promise<void> {\n await this.command({\n type: 'set-camera',\n position,\n target,\n ...(fov === undefined ? {} : { fov }),\n });\n }\n\n async captureViewport(size?: number): Promise<ViewportCapture> {\n const data = await this.command<ViewportCapture>({\n type: 'capture-viewport',\n ...(size === undefined ? {} : { size }),\n });\n return { base64: data.base64, mimeType: data.mimeType };\n }\n\n /**\n * Unit 4 (live-front-door wave) \u2014 capture the RUNNING GAME (the editor's\n * `screenshot`'s wire leg). Sends the SAME `bridge-screenshot` relay op\n * `@volter/game-live`'s `RelayTransport.screenshot` (and therefore\n * `game.screenshot()` on the relay path) already sends, so all three\n * surfaces composite the identical full game stack \u2014 canvas(es) plus the\n * HUD/react DOM layers \u2014 rather than any of them inventing a second,\n * subtly-different capture path. Contrast {@link captureViewport}, which\n * captures the EDITOR viewport's canvas and would silently hand back an\n * editor-only (HUD-less, possibly not-even-playing) image.\n *\n * Rejects \u2014 loudly, via `command`'s own `{ok:false}` unwrap \u2014 when play\n * mode isn't running (\"not in play mode \u2014 start play before using the\n * debug seam\") or no game canvas is mounted yet. Never returns a blank or\n * editor-only frame as a stand-in.\n *\n * `opts.refreshStarvedFrame` is the loop-starvation leg: without recent rAF\n * progress the canvas holds a provably stale frame and the relay\n * refuses it with `BRIDGE_SCREENSHOT_STALE` rather than pass it off as\n * current. Setting this asks the relay to render exactly ONE deterministic\n * tick (`runTicks(1, {render:'last'})`) first \u2014 the same escape\n * `@volter/game-live`'s `RelayTransport.screenshot` has always used, which is why\n * the editor's `eval` command could recover these frames while the editor's `screenshot` command could not.\n * Off by default: a caller who does not ask must never be handed a frame\n * that only exists because the capture drove the game.\n */\n async captureGame(opts?: { refreshStarvedFrame?: boolean }): Promise<GameCapture> {\n const data = await this.command<GameCapture>({\n type: 'bridge-screenshot',\n ...(opts?.refreshStarvedFrame === true ? { refreshStarvedFrame: true } : {}),\n });\n const layers = data.layers;\n const flatness = data.flatness;\n return {\n base64: data.base64,\n mimeType: data.mimeType,\n composite: data.composite === true,\n ...(layers && Number.isInteger(layers.canvases) && Number.isInteger(layers.domOverlays)\n ? { layers }\n : {}),\n // Pass the pixel-honesty fields through as the page reported them: the\n // warning sentence is written where the pixels are, so nothing here\n // re-derives (or softens) it.\n ...(flatness && typeof flatness.dominantFraction === 'number' ? { flatness } : {}),\n ...(data.loopRecoveryFrame === true ? { loopRecoveryFrame: true } : {}),\n // Same pass-through rule: the recorded-run notice is written where the\n // pixels are, so nothing here re-derives or softens it.\n ...(data.recording && typeof data.recording.notice === 'string'\n ? { recording: data.recording }\n : {}),\n };\n }\n\n /** Start recording the same clean running-game composite `captureGame`\n * photographs. Recording state lives in the editor page, so another process\n * may stop it later through the same project session. */\n async startGameplayRecording(\n options: GameplayRecordingOptions = {},\n ): Promise<GameplayRecordingStarted> {\n return this.command<GameplayRecordingStarted>({\n type: 'bridge-recording-start',\n ...(options.fps !== undefined ? { fps: options.fps } : {}),\n ...(options.name !== undefined ? { name: options.name } : {}),\n ...(options.format !== undefined ? { format: options.format } : {}),\n });\n }\n\n /** Export a paused run as fixed-step video. Advances game state; maximum\n * five minutes. `audio` describes the muxed track, or is `false` when the\n * world implements no `AudioAdapter.renderOffline` and the file is\n * genuinely silent \u2014 read it, never assume either. */\n async exportGameplayVideo(options: { frames: number; fps?: number; name?: string }): Promise<{\n path: string;\n frames: number;\n fps: number;\n durationMs: number;\n wallMs: number;\n width: number;\n height: number;\n audio:\n | false\n | {\n codec: 'opus';\n sampleRate: number;\n channels: number;\n durationSeconds: number;\n rms: number;\n peak: number;\n };\n }> {\n return this.command(\n { type: 'bridge-recording-export', ...options },\n { deadlineMs: 610_000, retryTransport: false },\n );\n }\n\n /** Stop the page-owned recorder and return its WebM path and metadata. */\n async stopGameplayRecording(): Promise<GameplayRecordingCapture> {\n return this.command<GameplayRecordingCapture>({ type: 'bridge-recording-stop' });\n }\n\n /** Read the active capture's monotonic media position. This is the only clock\n * suitable for selecting intervals inside the finalized recording. */\n async getGameplayRecordingTimeline(): Promise<GameplayRecordingTimeline> {\n const timeline = await this.command<GameplayRecordingTimeline>({\n type: 'bridge-recording-timeline',\n });\n return { startedAt: timeline.startedAt, elapsedMs: timeline.elapsedMs };\n }\n\n /** Encode a recorded canvas/DOM interval into a normal composite WebM. */\n async exportGameplayReplay(options: {\n replayPath: string;\n fps?: number;\n startMs?: number;\n endMs?: number;\n name?: string;\n }): Promise<{\n path: string;\n frames: number;\n fps: number;\n durationMs: number;\n width: number;\n height: number;\n audio: boolean;\n }> {\n return this.command(\n { type: 'bridge-recording-replay-export', ...options },\n { deadlineMs: 610_000, retryTransport: false },\n );\n }\n\n async captureGameplayReplay(\n replayPath: string,\n positionMs: number,\n ): Promise<GameplayReplayCapture> {\n return this.command<GameplayReplayCapture>({\n type: 'bridge-recording-replay-capture',\n replayPath,\n positionMs,\n });\n }\n\n /**\n * Capture an isolated, deterministic four-view preview through the editor's\n * native Asset Lab. The SDK delegates rendering to the editor; it never\n * loads, clones, or interprets Three.js assets itself.\n */\n async captureAssetPreview(\n source: AssetPreviewSource,\n options: AssetPreviewOptions = {},\n ): Promise<AssetPreviewCapture> {\n const data = await this.command<AssetPreviewCapture>(\n {\n type: 'capture-asset-preview',\n ...source,\n ...options,\n },\n // Photographing changes nothing, and this is the relay the editor's `screenshot\n // <module>` command and `project.bake.preview` ride \u2014 the lane where a momentary\n // transport failure cost a cold agent three probe modules.\n { retryTransport: true },\n );\n return {\n width: data.width,\n height: data.height,\n // Absent from editors that predate orientation reporting.\n ...(data.orientation ? { orientation: data.orientation } : {}),\n views: data.views,\n contactSheet: data.contactSheet,\n };\n }\n\n /**\n * A project-defined labeled shot set (the editor's `screenshot <target> --shots <set>` command):\n * the DEFINITION travels with the command (project data \u2014 see\n * `AssetPreviewShotSetDefinition`; the CLI resolves it from the registered\n * `project.<set>.previewShots` tool), and the editor's generic\n * capture engine renders it \u2014 see `packages/editor-threejs/src/kit/asset-preview.ts`'s\n * `captureShotSetAssetPreview`. Throws (via `command`'s `{ok:false}`\n * unwrap) with a clear message naming the missing joint(s) when the asset\n * lacks a bone the definition requires.\n */\n async captureShotSetPreview(\n source: AssetPreviewSource,\n definition: AssetPreviewShotSetDefinition,\n options: AssetPreviewOptions = {},\n ): Promise<LabeledShotSetCapture> {\n const data = await this.command<LabeledShotSetCapture>(\n {\n type: 'capture-asset-preview',\n ...source,\n ...options,\n shotSet: definition,\n },\n { retryTransport: true },\n );\n return {\n width: data.width,\n height: data.height,\n shots: data.shots,\n // An older editor predates the empty-frame guard and sends none.\n warnings: data.warnings ?? [],\n contactSheet: data.contactSheet,\n };\n }\n\n /**\n * B8.4 \u2014 score the asset against a reference GLB (the editor's `screenshot\n * <model.glb> --compare <ref.glb>` command): matched orthographic front + side silhouettes\n * (equal-height bounding-box framing, both yaw-normalized to face the\n * camera), per-view IoU numbers, and overlay evidence images. The\n * reference GLB's raw bytes travel base64 in the command; the editor\n * renders and scores \u2014 the SDK never interprets Three.js assets itself.\n */\n async captureAssetComparePreview(\n source: AssetPreviewSource,\n refGlbBase64: string,\n options: AssetCompareOptions = {},\n ): Promise<AssetCompareCapture> {\n const { refForward, ...dimensions } = options;\n const data = await this.command<AssetCompareCapture>({\n type: 'capture-asset-preview',\n ...source,\n ...dimensions,\n compare: { glbBase64: refGlbBase64, ...(refForward ? { forward: refForward } : {}) },\n });\n return { width: data.width, height: data.height, views: data.views };\n }\n\n /**\n * The STORY lane (the editor's `screenshot <file>.stories.tsx` command): every CSF export of\n * one project story file rendered in the live session's DOM and captured\n * through the same composite leg {@link captureGame} uses, returned as\n * per-export images plus one variant sheet. `options.story` narrows to a\n * single export.\n *\n * Rendering happens in the EDITOR \u2014 the SDK never imports, composes or\n * mounts a CSF module itself; the session already owns that machinery for\n * its Stories panel and this drives it.\n */\n async captureStoryVariants(\n modulePath: string,\n options: StoryCaptureOptions = {},\n ): Promise<StoryVariantCapture> {\n const data = await this.command<StoryVariantCapture>({\n type: 'capture-story-variants',\n modulePath,\n ...options,\n });\n return {\n modulePath: data.modulePath,\n width: data.width,\n height: data.height,\n variants: data.variants,\n contactSheet: data.contactSheet,\n };\n }\n\n // --- Panels ---\n\n async showViewport(tab: ViewportTab): Promise<void> {\n await this.command({ type: 'viewport-tab', tab });\n }\n\n /** Focus a static workspace panel by the key the editor's panel registry\n * holds; an unknown key refuses naming the keys it does hold. */\n async showPanel(panel: string): Promise<void> {\n await this.command({ type: 'show-panel', panel });\n }\n\n /** Show several instances of the running game split-screen \u2014 multiplayer\n * authoring. Pass a total `count` (default \"Player N\" labels) or an array of\n * `names` (its length is the count; index 0 is the primary). Requires a live\n * play session. */\n async setInstanceCount(countOrNames: number | string[]): Promise<void> {\n await this.command(\n Array.isArray(countOrNames)\n ? { type: 'set-instance-count', names: countOrNames }\n : { type: 'set-instance-count', count: countOrNames },\n );\n }\n\n async openAsset(path: string, kind: AssetKind): Promise<void> {\n await this.command({ type: 'open-asset-tab', path, kind });\n }\n\n /** SELECT a project asset \u2014 the other half of the browser's\n * selection-vs-open contract (single click selects and fills the\n * Inspector; double click opens a document). */\n async selectAsset(path: string): Promise<void> {\n await this.command({ type: 'select-asset', path });\n }\n\n async closeAsset(key: string): Promise<void> {\n await this.command({ type: 'close-asset-tab', key });\n }\n\n async toggleCommandPalette(): Promise<void> {\n await this.command({ type: 'toggle-command-palette' });\n }\n\n async toggleConsole(): Promise<void> {\n await this.command({ type: 'toggle-console' });\n }\n\n /** Switch the editor's NAMED WORKSPACE \u2014 the task-named layout memory\n * (`game`/`model`/`sculpt`/`texture`/`animate`/`look`). Resolves once the\n * dock has finished rebuilding, so a following capture photographs the\n * arrangement that was asked for. */\n async setWorkspace(workspace: EditorWorkspaceName): Promise<void> {\n await this.command({ type: 'set-workspace', workspace });\n }\n\n /** Apply a STYLE BUNDLE \u2014 palette, material, icon set and region defaults\n * in one gesture (`classic`/`glass`/`maya`/`substance`, or one a package\n * the project or product composes carries, such as `blender`). */\n async setStyle(style: string): Promise<void> {\n await this.command({ type: 'set-style', style });\n }\n\n /** A document stage's viewport PRESENTATION (`kit/viewport-presentation`), resolved; with a\n * `layer`, that choice is recorded for the view first, as the toolbar records it. */\n /** A view's presentation, answered resolved. With a LAYER the person's choice is recorded\n * first; with a STRING, the named view (`*.view.ts`) of that id is put on the view whole. */\n async viewportPresentation(\n documentId: string,\n layer?: import('./kit/viewport-presentation').PresentationLayer | string,\n ): Promise<{\n presentation: import('./kit/viewport-presentation').ViewportPresentation;\n binding: { stageKind: string; documentLayer: import('./kit/viewport-presentation').PresentationLayer | null } | null;\n bound: { viewId: string; stageKind: string }[];\n lastDraw: import('./kit/viewport-presentation').ViewDrawReport | null;\n presets: string[];\n viewPresets: string[];\n /** The environment images registered (`kit/environment-images`), for `lighting.preview.environment.image`. */\n environmentImages: string[];\n }> {\n return this.command({\n type: 'viewport-presentation',\n documentId,\n ...(typeof layer === 'string' ? { preset: layer } : layer ? { layer } : {}),\n });\n }\n\n /** Set the MATERIAL apart from the bundle that usually carries it.\n * Answers with what the chrome wears afterwards. */\n async setAppearance(appearance: {\n readonly material?: string;\n }): Promise<{ material: string; style: string | null }> {\n return this.command<{ material: string; style: string | null }>({\n type: 'set-appearance',\n ...appearance,\n });\n }\n\n async showBuild(): Promise<void> {\n await this.command({ type: 'show-build' });\n }\n\n /** Atomically present a durable editor view and return its shareable URL. */\n async present(view: EditorView): Promise<PresentedEditorView> {\n const presented = await this.command<PresentedEditorView>({ type: 'present-view', view });\n return { view: presented.view, url: presented.url, warnings: presented.warnings };\n }\n\n /**\n * The INSPECTION SUBJECT the editor is showing right now, as data \u2014 the\n * serialized projection of the inspection model (design:\n * `docs/ARCHITECTURE-CORE.md` \u00A7Editor chrome, \"The Inspection Model\").\n *\n * The same subject a human reads in the inspector: identity, presentation,\n * verbs, and the identified sections in display order \u2014 with a `fields`\n * section's CURRENT VALUES read through the same io the field rows edit\n * through. With nothing selected it answers the active surface's own\n * no-selection subject when it has one, exactly as the panel does; it never\n * reports another surface's, and when the panel itself is unmounted it\n * answers `{none: true}` rather than a subject nobody is looking at. A\n * `custom` section body is a named opaque (`{kind, id, title}`) \u2014 the editor\n * renders those with React \u2014 plus its displayed values under `data` when it\n * has any (the Transform section's position/rotation/scale).\n */\n async inspect(): Promise<InspectedInspection> {\n const data = await this.command<{ subject: InspectedInspection }>({ type: 'inspect' });\n return data.subject;\n }\n\n /** Run one verb exposed by the active Inspector subject, by its id. */\n async runInspectionAction(actionId: string): Promise<InspectedInspection> {\n const data = await this.command<{ subject: InspectedInspection }>({\n type: 'run-inspection-action',\n actionId,\n });\n return data.subject;\n }\n\n /**\n * Run ONE command by id \u2014 the door to everything the command palette lists.\n *\n * Under the Code-OSS frame this is the workbench's own `ICommandService`, so\n * any command id works: a view's `volter.<view>.<verb>`, an editor action's\n * `volter.action.<id>`, or one of VS Code's own. Standalone the editor's `edit` command has no\n * command service and answers the `volter.<view>.<verb>` shape directly off\n * the views registry, refusing anything else BY NAME.\n *\n * The result is whatever the command answered \u2014 a view verb's state, or\n * `null` for a command that returns nothing.\n */\n async runCommand(commandId: string, args?: unknown): Promise<unknown> {\n const data = await this.command<{ result: unknown }>({\n type: 'run-command',\n commandId,\n ...(args === undefined ? {} : { args }),\n });\n return data.result;\n }\n\n /**\n * One STRUCTURE op on the authored tree \u2014 the hierarchy context menu's own\n * verbs, on the same helpers, for a caller with no pointer to right-click\n * with. `id`/`ids` default to the current selection.\n */\n async structureOp(op: StructureOp, options: StructureOpOptions = {}): Promise<StructureOpResult> {\n return this.command<StructureOpResult>({ type: 'structure-op', op, ...options });\n }\n\n /** \"Extract Component\u2026\" \u2014 the hierarchy row's action, as a command. Answers\n * the action's own sentence, which NAMES the files it created. */\n async extractComponent(options: { id?: string; name?: string } = {}): Promise<{ hint: string }> {\n return this.command<{ hint: string }>({ type: 'extract-component', ...options });\n }\n\n /** \"Fork Component\u2026\" \u2014 extract's twin: one new file, one callsite retargeted. */\n async forkComponent(options: { id?: string } = {}): Promise<{ hint: string }> {\n return this.command<{ hint: string }>({ type: 'fork-component', ...options });\n }\n\n /**\n * The HIERARCHY PANEL's actual rendered row tree, as data.\n *\n * The same rows a human is looking at: the adapter's tree after the component\n * marks fold implementation subtrees, after the internals reveal, after the\n * document promotion, the child cap, the collapse state, the search filter\n * and the selection scope. Works in play mode and edit mode alike \u2014 the\n * answer reports which (`playState`, `activeViewportTab`), because a\n * play-mode tree and an edit-mode tree come from different adapters.\n *\n * Deliberately NOT `status().entities`, which walks the raw adapter tree and\n * therefore answers a different question: a panel defect is invisible in it.\n *\n * Each row carries `childCount` (what its caret opens), `internalChildCount`\n * (what is folded behind \"Reveal Internals\") and `expandable` (whether the\n * panel draws a caret at all) \u2014 so \"this subtree exists but the UI offers no\n * way to open it\" is a readable fact rather than something only a human\n * squinting at the panel can notice.\n *\n * Rejects, naming the panel, when no hierarchy panel is mounted: an empty\n * tree would be a fabricated answer about a surface nobody is being shown.\n */\n async hierarchy(): Promise<InspectedHierarchy> {\n const data = await this.command<{ hierarchy: InspectedHierarchy }>({ type: 'hierarchy' });\n return data.hierarchy;\n }\n\n /** Run the Hierarchy panel's own Expand All action. */\n async expandHierarchyAll(): Promise<void> {\n await this.command<Record<string, never>>({ type: 'expand-hierarchy-all' });\n }\n\n /** Run the Hierarchy panel's own Collapse All action \u2014 Expand All's other\n * half, and the only way back to the tree's rest state through the product\n * (see `HierarchyPanelSnapshot.collapseAll`). */\n async collapseHierarchyAll(): Promise<void> {\n await this.command<Record<string, never>>({ type: 'collapse-hierarchy-all' });\n }\n\n /**\n * Write one editable path through the active Inspector's own IO.\n *\n * The answer carries `write` as well as the subject, because an ack alone\n * cannot be believed: a write with no persistence route open succeeds and\n * changes no byte, and `write.persisted` is how the caller tells the two\n * apart without diffing the tree (`InspectedWriteDestination` in `types.ts`).\n */\n async setInspectionField(path: string, value: unknown): Promise<InspectedFieldWrite> {\n const data = await this.command<InspectedFieldWrite>({\n type: 'set-inspection-field',\n path,\n value,\n });\n return { subject: data.subject, write: data.write };\n }\n\n /**\n * REMOVE one editable path's authored override \u2014 the other half of the write\n * door, and the only one that can express byte-ABSENCE.\n *\n * {@link setInspectionField} writes a VALUE, so reverting a property an\n * authoring gesture ADDED puts the default back EXPLICITLY and leaves the\n * source one attribute heavier than it started. This drops the property, so\n * whatever governs it in its absence takes over \u2014 the same `io.remove` the\n * Inspector's revert arrow calls, the same persistence pipe, the same awaited\n * `{ destination, persisted }` ack.\n *\n * Rejects with `code: 'REMOVAL_UNAVAILABLE'` when the field does not declare\n * itself removable or the lane implements no removal door. That refusal is a\n * MISSING SEAM, not a failed removal, and it is coded rather than phrased\n * precisely so a caller can grade the two differently.\n */\n async removeInspectionField(path: string): Promise<InspectedFieldWrite> {\n const data = await this.command<InspectedFieldWrite>({\n type: 'remove-inspection-field',\n path,\n });\n return { subject: data.subject, write: data.write };\n }\n\n /**\n * OPEN one piece of the adapter's SCENE TABLE by id \u2014 a scene, a prefab, or\n * a story state, because the table makes them siblings (they differ only in\n * instance site). The ids are exactly what `getState().adapter.scenes.entries`\n * reports, so the table is both the menu and the address space.\n *\n * With a game LIVE in the session, opening a scene the adapter declares\n * reachable through that game's own scenes contract NAVIGATES it \u2014 the same\n * switch the editor's own scene picker makes \u2014 and the answer carries the\n * game's own reading (`scene`).\n *\n * Rejects with a coded reason rather than prose: `SCENE_NOT_FOUND` (and it\n * names the ids that DO exist), `SCENE_NOT_OPENABLE` carrying the adapter's\n * own declared reason for a scene it says nothing can reach,\n * `SCENE_NAVIGATION_NOT_RUNNING` for a live-only scene with no game running,\n * `SCENE_CONTRACT_UNAVAILABLE` / `SCENE_NOT_IN_CONTRACT` (naming the ids the\n * game itself publishes) / `SCENE_SWITCH_FAILED` when the running game's own\n * navigation cannot take it, `SCENE_NOT_OPENABLE_LIVE` when this session has\n * no remount for a native swap-slot scene,\n * `SCENE_TABLE_UNAVAILABLE` before the adapter has loaded, and\n * `SCENE_DOCUMENT_NOT_MOUNTED` when the host has no document for a piece the\n * table says is openable \u2014 a host gap, not a table statement.\n */\n async open(id: string): Promise<OpenedDocument> {\n return this.command<OpenedDocument>({ type: 'open', id });\n }\n\n /**\n * Undo / redo one project transaction \u2014 the same queue the keyboard shortcut\n * drives. `moved` is false when there was nothing left in that direction.\n */\n async undo(): Promise<HistoryStep> {\n return this.command<HistoryStep>({ type: 'undo' });\n }\n\n async redo(): Promise<HistoryStep> {\n return this.command<HistoryStep>({ type: 'redo' });\n }\n\n /** Read the editor's actual current durable projection. */\n async currentView(): Promise<EditorView> {\n const data = await this.command<{ view: EditorView }>({ type: 'current-view' });\n return data.view;\n }\n\n /**\n * Capture the active center document exactly as presented to the user.\n *\n * A number is a SQUARE of that size (the default shape); `{width, height}`\n * asks for a shaped frame \u2014 a video-aspect look that needs no crop. Both are\n * bounded by the relay budget; see {@link CaptureDimensions}.\n */\n /** Photograph the editor PAGE itself \u2014 every panel as the person sees it, at\n * `scale` output pixels per CSS pixel (default `devicePixelRatio`), which is\n * what a 1 px border or a glyph edge is judged through. */\n async captureEditorChrome(options?: EditorChromeCaptureOptions): Promise<EditorChromeCapture> {\n return this.command<EditorChromeCapture>({\n type: 'capture-editor-chrome',\n ...(options?.scale === undefined ? {} : { scale: options.scale }),\n ...(options?.region === undefined ? {} : { region: options.region }),\n });\n }\n\n /** With a view, present and capture it in one request so document discovery\n * cannot retarget the capture between two client calls. */\n async captureActiveDocument(\n size?: CaptureDimensions,\n view?: EditorView,\n ): Promise<ActiveDocumentCapture> {\n return this.command<ActiveDocumentCapture>({\n type: 'capture-active-document',\n ...(view ? { view } : {}),\n ...(typeof size === 'number' ? { size } : {}),\n ...(typeof size === 'object' && size !== null\n ? { width: size.width, height: size.height }\n : {}),\n });\n }\n\n /**\n * Read or drive the ACTIVE center document's own DOM \u2014 the scoped\n * editor-chrome door, and the read/gesture half of the same subject\n * {@link captureActiveDocument} photographs. NOT play-mode gated, and NOT\n * page automation: a target outside the active document's container is\n * refused by name. Design and scope contract:\n * `packages/editor-sdk/src/kit/editor-document-probe.ts`.\n */\n async documentProbe(step: DocumentProbeStep): Promise<DocumentProbeResult> {\n return this.command<DocumentProbeResult>({ type: 'document-probe', step });\n }\n\n /**\n * Run a wire-carried step against the ACTIVE document's published context\n * (`packages/editor-sdk/src/kit/document-context-registry.ts`) \u2014 the REPL door over\n * an open document, in Edit mode. `src` is the step's own `toString()`;\n * same serialization contract as `page-script` (no closures survive).\n */\n /**\n * The Blender lane's doors (`blender-execute`, `blender-scene-info`,\n * `blender-object-info`, `blender-screenshot-view`, `blender-read-file`,\n * `blender-write-file`, `blender-list-files`, `blender-start`,\n * `blender-status`): Blender runs in the editor tab's worker, and\n * `volter blender-mcp` is transport onto these. `blender-status` is the only\n * one that creates nothing \u2014 it answers whether this tab already has a\n * session, which is how a caller survives an editor restart.\n */\n async blender<T extends object = Record<string, unknown>>(\n type: `blender-${string}`,\n fields: Record<string, unknown> = {},\n ): Promise<T> {\n // One modeling chunk can run for minutes in the tab (an exact boolean\n // over a dense mesh measured 80-90 s under Wasm); the relay's server-side\n // budget for blender-execute is the same half hour.\n return this.command<T>({ type, ...fields }, { deadlineMs: BLENDER_DEADLINE_MS });\n }\n\n async documentScript<T = unknown>(src: string): Promise<T> {\n const outcome = await this.command<{ result: T }>({ type: 'document-script', src });\n return outcome.result;\n }\n\n // --- Display (set semantics) ---\n\n async setGrid(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-grid', enabled });\n }\n\n async setHelpers(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-helpers', enabled });\n }\n\n async setStats(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-stats', enabled });\n }\n\n async setShadingMode(mode: ShadingMode): Promise<void> {\n await this.command({ type: 'set-shading-mode', mode });\n }\n\n async setHelperType(helperType: keyof HelperVisibility, enabled: boolean): Promise<void> {\n await this.command({ type: 'set-helper-type', helperType, enabled });\n }\n\n // --- Transform tools (set semantics) ---\n\n async setTransformMode(mode: TransformMode): Promise<void> {\n await this.command({ type: 'set-transform-mode', mode });\n }\n\n async setTransformSpace(space: TransformSpace): Promise<void> {\n await this.command({ type: 'set-transform-space', space });\n }\n\n async setSnap(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-snap', enabled });\n }\n\n // --- Project management ---\n\n async createProject(\n name: string,\n location: string,\n template: ProjectTemplate = 'default',\n exampleId?: string,\n ): Promise<ProjectInfo> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/create-project`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name, location, template, ...(exampleId ? { exampleId } : {}) }),\n });\n const data = (await this.readJson(res)) as {\n ok?: boolean;\n error?: string;\n path?: string;\n config?: ProjectInfo['config'];\n };\n if (!res.ok) {\n throw new Error(data.error ?? `Create project failed: ${res.status}`);\n }\n return { path: data.path as string, config: data.config as ProjectInfo['config'] };\n }\n\n async openProject(path: string): Promise<void> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/open-project`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path }),\n });\n const body = (await this.readJson(res)) as { error?: string };\n if (!res.ok) {\n throw new Error(body.error ?? `Open project failed: ${res.status}`);\n }\n }\n\n async getProject(): Promise<ProjectInfo | null> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/project`);\n const data = (await this.readJson(res)) as { project: ProjectInfo | null; error?: string };\n if (!res.ok) throw new Error(data.error ?? `Failed to get project: ${res.status}`);\n return data.project;\n }\n\n async listRecentProjects(): Promise<RecentProject[]> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/recent-projects`);\n const data = (await this.readJson(res)) as { projects: RecentProject[]; error?: string };\n if (!res.ok) throw new Error(data.error ?? `Failed to list projects: ${res.status}`);\n return data.projects;\n }\n\n // --- Registered project tools ---\n\n /** List tools explicitly registered in `package.json#volter.tools`.\n * The editor server loads callable metadata in Node; modules never enter the\n * editor browser merely because they were listed. */\n async listProjectTools(): Promise<ProjectToolCatalog> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/project-tools`);\n const body = await this.readJson(res);\n if (!res.ok) throw new Error(`Failed to list project tools: ${res.status}`);\n return body as ProjectToolCatalog;\n }\n\n /** Execute one Node-hosted project tool through the shared validated\n * dispatcher. Write/destructive tools require `confirm:true`. */\n async runProjectTool(\n name: string,\n input: unknown = {},\n options: { confirm?: boolean; instance?: string } = {},\n ): Promise<ProjectToolOutcome> {\n // Provider subscriptions can outlive Node fetch's five-minute header limit.\n // Match browser fetch for this operation; dispose its sockets after reading the result.\n const dispatcher = createDispatcher(0);\n try {\n const res = await this.httpFetch(\n `${this.baseUrl}/__editor/project-tools/run`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n name,\n input,\n confirm: options.confirm === true,\n // Omitted (not null) when unset \u2014 the wire body is JSON and the tool\n // host reads absence as \"the sole instance\", same convention as the\n // relay's `instance`.\n ...(options.instance !== undefined ? { instance: options.instance } : {}),\n }),\n },\n dispatcher,\n );\n const body = (await this.readJson(res)) as ProjectToolOutcome;\n if (!body || typeof body !== 'object' || typeof body.ok !== 'boolean') {\n throw new Error(`Project tool returned an invalid response (${res.status}).`);\n }\n return body;\n } finally {\n await dispatcher?.destroy?.();\n }\n }\n\n // --- First-party generation job activity ---\n\n /** Read the one project-local generation job ledger. Provider-native\n * request/result shapes remain on their registered operations. */\n async listGenerationJobs(): Promise<GenerationJobsDocument> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/generations`);\n const body = await this.readJson(res);\n if (!res.ok) throw new Error(`Failed to list generation jobs: ${res.status}`);\n return body as GenerationJobsDocument;\n }\n\n /** Forget operational job state. Accepted provenance and project assets\n * are deliberately unaffected. */\n async forgetGenerationJob(id: string): Promise<boolean> {\n const res = await this.httpFetch(\n `${this.baseUrl}/__editor/generations/${encodeURIComponent(id)}`,\n {\n method: 'DELETE',\n },\n );\n const body = (await this.readJson(res)) as { removed?: boolean; error?: string };\n if (!res.ok) throw new Error(body.error ?? `Failed to forget generation job: ${res.status}`);\n return body.removed === true;\n }\n\n // --- Logs ---\n\n async getLogEntries(): Promise<\n Array<{ t: number; level: string; msg: string; source?: string }>\n > {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/log-entries`);\n const data = (await this.readJson(res)) as {\n entries: Array<{ t: number; level: string; msg: string; source?: string }>;\n };\n if (!res.ok) return [];\n return data.entries;\n }\n\n // --- State ---\n\n /**\n * The document table the host resolved \u2014 every scene, prefab, page, model,\n * shot, take \u2026 the project's finders produced (`getState().adapter.scenes`\n * is the same projection). A command, so it answers wherever the control\n * channel reaches, not only where `/__editor/state` is served.\n */\n async documentTable(): Promise<DocumentTableProjection> {\n return this.command<DocumentTableProjection>({ type: 'document-table' });\n }\n\n /**\n * Reload the editor's page and wait until the new document answers \u2014 the\n * host's `page-reload`, for a product with no game client (`@volter/game-live`'s\n * `page.reload()` is the same order with the same two witnesses). A tab's\n * epoch count rising proves a new document loaded; a host command answering\n * proves it can be driven. It is sent only once that tab reports its command\n * listener ready, because a command sent before is filed as a stall.\n */\n async reloadPage(timeoutMs = 60_000): Promise<void> {\n const epochs = async () => {\n const tabs = (await this.getState().catch(() => ({ tabs: [] }) as Partial<EditorState>)).tabs ?? [];\n const byTab = tabs as ReadonlyArray<{ tabId8: string; epochCount: number; commandListener?: unknown }>;\n return new Map(byTab.map((tab) => [tab.tabId8, tab] as const));\n };\n const pause = () => new Promise((settle) => setTimeout(settle, 250));\n const before = await epochs();\n const deadline = Date.now() + timeoutMs;\n await this.command({ type: 'page-reload' });\n let reloaded: string[] = [];\n while (reloaded.length === 0) {\n if (Date.now() > deadline) throw new Error('The reload was ordered and no tab of this session reported a new page load.');\n await pause();\n const now = await epochs();\n reloaded = [...now].filter(([tabId, tab]) => tab.epochCount > (before.get(tabId)?.epochCount ?? 0)).map(([tabId]) => tabId);\n }\n for (;;) {\n if (Date.now() > deadline) throw new Error('A new page loaded, but its command listener did not become ready.');\n const now = await epochs();\n if (reloaded.some((tabId) => {\n const listener = now.get(tabId)?.commandListener;\n return typeof listener !== 'string' || listener === 'ready';\n })) break;\n await pause();\n }\n for (;;) {\n try {\n await this.command({ type: 'current-view' });\n return;\n } catch (error) {\n if (Date.now() > deadline) throw error;\n await pause();\n }\n }\n }\n\n async getState(): Promise<EditorState> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/state`);\n const state = (await this.readJson(res)) as EditorState;\n if (!res.ok) throw new Error(`Failed to get editor state: ${res.status} ${res.statusText}`);\n return state;\n }\n\n /**\n * The complete unresolved console set the session is holding right now.\n *\n * Command envelopes only carry COUNTS (`unresolvedConsole` on\n * `commandResponseFor`). The named conditions live on GET `/__editor/console`.\n * This is the method that turns \"a command that exits before an envelope\n * arrives\" into a real reading: the CLI calls it at start and at exit\n * through the same {@link onEnvelope} observer every other response uses.\n * A session that does not answer within {@link CONSOLE_DRAIN_TIMEOUT_MS} is\n * a thrown error the caller treats as \"nothing learned\", never a hang.\n */\n async getUnresolvedConsole(opts?: { all?: boolean }): Promise<unknown> {\n const res = await this.httpFetch(\n `${this.baseUrl}/__editor/console${opts?.all === true ? '?all=1' : ''}`,\n { signal: AbortSignal.timeout(CONSOLE_DRAIN_TIMEOUT_MS) },\n );\n // Status first: a 404's empty body would otherwise die inside readJson\n // with a parse error that hides the one fact the caller classifies on\n // (does this server SERVE the console route at all?).\n if (!res.ok) {\n throw new Error(`Failed to read unresolved console: ${res.status}`);\n }\n return await this.readJson(res, true);\n }\n\n /** Acknowledge one named console condition. The response is observed and\n * hydrated through the same path as every other client response. */\n async acknowledgeConsole(input: {\n readonly id: string;\n readonly reason: string;\n readonly by: string;\n }): Promise<unknown> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/console/ack`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n signal: AbortSignal.timeout(CONSOLE_DRAIN_TIMEOUT_MS * 4),\n });\n const body = await this.readJson(res);\n return body;\n }\n\n /**\n * `fetch` for this client's plain routes, with the ONE thing Node's `fetch`\n * will not do: name why it failed.\n *\n * `readJson` below already owns \"the server answered the wrong thing\"; this\n * owns \"nothing answered at all\", which used to reach the caller as the bare\n * `TypeError: fetch failed` with the real code buried on `.cause`. No retry\n * here \u2014 these routes create projects, run tools and acknowledge console\n * conditions, so repeating one is the caller's decision. The relayed\n * `command` path above has its own opt-in retry for the read-only captures.\n */\n private async httpFetch(\n url: string,\n init?: RequestInit,\n dispatcher?: Dispatcher,\n ): Promise<Response> {\n try {\n return await dispatchFetch(url, init, dispatcher);\n } catch (error) {\n if ((error as { name?: string } | null)?.name === 'TimeoutError') throw error;\n const { code, detail } = describeFetchFailure(error);\n throw new EditorCommandError(\n `${init?.method ?? 'GET'} ${url} never reached the editor: ${code}` +\n `${detail ? ` (${detail})` : ''}. Nothing answered on that port \u2014 check the terminal ` +\n 'that started this editor session and confirm the port this client resolved.',\n code,\n false,\n );\n }\n }\n\n /** Parse one JSON body and hand it to {@link onEnvelope}.\n *\n * A command/state envelope carries current counts but not the named set. If\n * an observer is installed, do the bounded console GET before resolving the\n * original request. That makes a subsequent `process.exit()` safe: the\n * observer has already received every condition and occurrence count. */\n private async readJson(res: Response, consoleComplete = false): Promise<unknown> {\n // Every one of this client's twelve routes funnels through here, so this is\n // where \"did the editor server answer?\" is asked \u2014 the same question, and\n // the same JSON-content-type rule, that\n // `packages/editor-sdk/src/kit/editor-server-response.ts` owns on the browser side.\n // It is asked again rather than imported because THIS package is published\n // and depends on neither `@volter/editor-project` nor the editor bundle (see\n // `DEFAULT_URL` above for that policy).\n //\n // Not theoretical here: `baseUrl` is whatever `--url`/`VOLTER_EDITOR_URL`\n // says, so the CLI is routinely pointed at a SHARE TUNNEL or a static host\n // \u2014 both of which answer `200 text/html` for a route nothing serves, and\n // `res.json()` then died as `Unexpected token '<'`, naming neither the URL\n // nor the cause.\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('application/json')) {\n throw new Error(\n `The editor at ${this.baseUrl} answered with its page fallback ` +\n `(${contentType || 'no content-type'}) rather than JSON, so no editor server handled ` +\n 'the request. Check that this URL is a running editor session.',\n );\n }\n const body: unknown = await res.json();\n this.observe(body, { unresolvedConsoleComplete: consoleComplete });\n if (\n this.onEnvelope !== null &&\n !consoleComplete &&\n body !== null &&\n typeof body === 'object' &&\n 'unresolvedConsole' in body\n ) {\n try {\n const consoleRes = await this.httpFetch(`${this.baseUrl}/__editor/console`, {\n signal: AbortSignal.timeout(CONSOLE_DRAIN_TIMEOUT_MS),\n });\n if (consoleRes.ok) {\n const consoleBody: unknown = await consoleRes.json();\n this.observe(consoleBody, { unresolvedConsoleComplete: true });\n }\n } catch {\n // The original response remains authoritative. A reporting follow-up\n // may degrade to its count-only envelope, never break the command.\n }\n }\n return body;\n }\n\n /** Hand one response body to {@link onEnvelope}, never letting it throw. */\n private observe(body: unknown, observation: EditorEnvelopeObservation): void {\n if (this.onEnvelope === null) return;\n try {\n this.onEnvelope(body, observation);\n } catch {\n // A reporting hook may never break the command it is reporting on.\n }\n }\n\n /**\n * Whether an editor browser tab is connected to the server *right now*.\n * Unlike {@link getState}, this reflects live SSE connections, not cached\n * state \u2014 use it to check whether commands will actually reach an editor.\n */\n async isConnected(): Promise<boolean> {\n const state = await this.getState();\n return state.connected === true;\n }\n\n async waitForState(\n predicate: (s: EditorState) => boolean,\n timeoutMs = 10_000,\n ): Promise<EditorState> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const state = await this.getState();\n if (predicate(state)) return state;\n await new Promise((r) => setTimeout(r, 100));\n }\n throw new Error(`waitForState timed out after ${timeoutMs}ms`);\n }\n}\n", "/**\n * `editor.document` \u2014 the session binding for the scoped editor-chrome door.\n *\n * WHY IT IS A SEPARATE OBJECT, and why the verbs are these, is recorded once\n * in the implementation's header\n * (`packages/editor-sdk/src/kit/editor-document-probe.ts`); the short version is that\n * `game.page()` is play-mode-gated and rooted at the GAME container, so an\n * editor surface that is not a running game could be neither read nor driven\n * through the product.\n *\n * WHAT IT ADDRESSES is a closed VOCABULARY of named surfaces, passed as\n * `{ scope }` on every verb:\n *\n * `document` (default) the active centre document's whole box\n * `header` / `shelf` that document's toolbar strip / tool rail\n * `rail` the PROPERTIES view \u2014 its tabs, sections and fields\n * `outliner` the OUTLINER view \u2014 its rows and their controls\n * `content` the CONTENT view \u2014 its categories and asset rows\n * `menubar` the APPLICATION MENUS (Edit, View, \u2026) and the menus they open\n *\n * await editor.document.click('[data-testid=app-menu-edit]', { scope: 'menubar' });\n * await editor.document.query('[role=tab]', { scope: 'rail' });\n * await editor.document.click('[data-testid=properties-tab-modifiers]', { scope: 'rail' });\n * await editor.document.click('[data-ingest-name=Cube]', { scope: 'outliner', clicks: 2 });\n * await editor.document.type('Wheel', { scope: 'outliner' });\n *\n * It is not page automation: a selector resolving outside the named surface is\n * refused by a message naming the scope and listing the others. `rail` and\n * `outliner`, and `content` are editor chrome and stay readable while the Game document is\n * active; `editor.hierarchy()` / `editor.inspect()` keep answering what those\n * panels RESOLVED, where this door answers what they DREW.\n *\n * A field on `LiveEditor` rather than methods on it, so the editor's `eval --list` command\n * shows the verbs as one named surface \u2014 the same reason `game.input`\n * and `game.events` are instance fields.\n */\n\nimport type {\n DocumentProbeResult,\n DocumentProbeScope,\n DocumentProbeStep,\n EditorClient,\n} from '@volter/editor-sdk';\n\n/** Which named surface a verb runs against; `document` when omitted. */\nexport interface DocumentScopeOption {\n scope?: DocumentProbeScope;\n}\n\n/** Modifier/targeting options shared by the gesture verbs. */\nexport interface DocumentGestureOptions extends DocumentScopeOption {\n /** Which match to drive when the selector matches several (default 0). */\n index?: number;\n}\n\nexport interface DocumentKeyOptions extends DocumentGestureOptions {\n /** Target one element instead of whatever inside the scope has focus. */\n selector?: string;\n code?: string;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n altKey?: boolean;\n /** Hold the key this long before releasing it (a person holding W). */\n holdMs?: number;\n}\n\nexport interface DocumentPasteOptions extends DocumentGestureOptions {\n selector?: string;\n}\n\nexport interface DocumentTypeOptions extends DocumentGestureOptions {\n /** The field; omitted types into whatever inside the scope has focus. */\n selector?: string;\n /** Replace what the field holds first (default true). */\n replace?: boolean;\n /** Press Enter after the text (default true). */\n enter?: boolean;\n}\n\nexport class LiveEditorDocument {\n readonly #client: EditorClient;\n\n constructor(client: EditorClient) {\n this.#client = client;\n }\n\n /**\n * Read matching elements inside the active document: tag, text, attributes,\n * value/checked/disabled and rect. `matched` is the total before `limit`.\n *\n * `styles` additionally resolves named properties per match \u2014 and resolving\n * is the point, because a theme token is an expression until an element\n * paints it. Ask for the standard property to learn the colour a person\n * sees; ask for a `--volter-\u2026` custom property to learn what a rule WOULD\n * paint, which is the only way to measure a `:hover` colour (`:hover` is a\n * browser state no synthetic event can enter, so there is deliberately no\n * hover verb on this door).\n *\n * await editor.document.query('.volter-tree-row', {\n * styles: ['backgroundColor', '--volter-widget-regular-hover'],\n * });\n */\n async query(\n selector: string,\n options?: DocumentScopeOption & { limit?: number; styles?: readonly string[] },\n ): Promise<DocumentProbeResult> {\n return this.#probe({\n action: 'query',\n selector,\n ...(options?.scope === undefined ? {} : { scope: options.scope }),\n ...(options?.limit === undefined ? {} : { limit: options.limit }),\n ...(options?.styles === undefined ? {} : { styles: [...options.styles] }),\n });\n }\n\n /** A REAL pointer gesture (pointerdown/mousedown/focus/pointerup/mouseup/click)\n * \u2014 not `element.click()`, which a `pointerdown` listener never sees. */\n async click(\n selector: string,\n options?: DocumentGestureOptions & {\n clicks?: number;\n at?: [number, number];\n altKey?: boolean;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n },\n ): Promise<DocumentProbeResult> {\n // An option this door does not know is refused, never dropped: a dropped `position` clicked\n // the element's centre and answered as if it had clicked where it was asked.\n const known = ['scope', 'index', 'clicks', 'at', 'altKey', 'ctrlKey', 'metaKey', 'shiftKey'];\n const unknown = Object.keys(options ?? {}).filter((key) => !known.includes(key));\n if (unknown.length > 0) throw new Error(`click has no option ${unknown.map((key) => `\\`${key}\\``).join(', ')}; its options are scope, index, clicks, at ([x, y] fractions of the element's box) and the modifier keys altKey, ctrlKey, metaKey and shiftKey.`);\n return this.#probe({\n action: 'click',\n selector,\n ...(options?.scope === undefined ? {} : { scope: options.scope }),\n ...(options?.index === undefined ? {} : { index: options.index }),\n ...(options?.clicks === undefined ? {} : { clicks: options.clicks }),\n ...(options?.at === undefined ? {} : { at: options.at }),\n ...(options?.altKey ? { altKey: true } : {}),\n ...(options?.ctrlKey ? { ctrlKey: true } : {}),\n ...(options?.metaKey ? { metaKey: true } : {}),\n ...(options?.shiftKey ? { shiftKey: true } : {}),\n });\n }\n\n /**\n * TYPE into a field and commit with Enter, the way a person does \u2014 one\n * character at a time through the prototype's value setter, between real\n * `keydown`/`keyup`.\n *\n * `paste` is not a substitute: an untrusted `ClipboardEvent` performs no\n * default action, so a plain `<input>` with no paste handler keeps its old\n * value. Omit `selector` to type into whatever inside the scope has focus \u2014\n * which is what a rename field is, one gesture after\n * `click(row, { clicks: 2 })`.\n */\n async type(text: string, options?: DocumentTypeOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'type', text, ...(options ?? {}) });\n }\n\n /**\n * A real pointer DRAG across one matched element \u2014 press at `from`, move,\n * release at `to`. The gesture a direct-manipulation canvas needs; a\n * zero-length drag is a click at that fraction, which `click` (always the\n * center) cannot place.\n *\n * `from`, `to` and every point in `via` are `[x, y]` FRACTIONS OF THE\n * MATCHED ELEMENT'S BOX, 0..1 from its top-left \u2014 NEVER pixels and never\n * page coordinates. `[0.5, 0.5]` is its center, `[1, 0]` its top-right.\n * Compute a pixel target by measuring the element first: `query` answers\n * its `rect`, and `(px - rect.x) / rect.width` is the fraction to pass.\n */\n async drag(\n selector: string,\n options: DocumentGestureOptions & {\n from: [number, number];\n to: [number, number];\n via?: [number, number][];\n steps?: number;\n altKey?: boolean;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n /** 0 primary (default), 1 middle, 2 secondary. */\n button?: 0 | 1 | 2;\n /** `via`/`to` may leave the element's box after the press (a handle drag). */\n leave?: boolean;\n /** Keep the button down at `to`, for readings taken mid-gesture; {@link release} lets go. */\n hold?: boolean;\n },\n ): Promise<DocumentProbeResult> {\n return this.#probe({\n action: 'drag',\n selector,\n ...(options.scope === undefined ? {} : { scope: options.scope }),\n from: options.from,\n to: options.to,\n ...(options.via === undefined ? {} : { via: options.via }),\n ...(options.steps === undefined ? {} : { steps: options.steps }),\n ...(options.index === undefined ? {} : { index: options.index }),\n ...(options.altKey === undefined ? {} : { altKey: options.altKey }),\n ...(options.ctrlKey === undefined ? {} : { ctrlKey: options.ctrlKey }),\n ...(options.metaKey === undefined ? {} : { metaKey: options.metaKey }),\n ...(options.shiftKey === undefined ? {} : { shiftKey: options.shiftKey }),\n ...(options.button === undefined ? {} : { button: options.button }),\n ...(options.leave === undefined ? {} : { leave: options.leave }),\n ...(options.hold === undefined ? {} : { hold: options.hold }),\n });\n }\n\n /** Lets go of the drag `hold: true` left pressed, where it was left. */\n async release(options?: DocumentGestureOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'release', ...(options?.scope === undefined ? {} : { scope: options.scope }) });\n }\n\n /** A real keydown/keyup on the target, or on whatever inside the document has focus. */\n async key(key: string, options?: DocumentKeyOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'key', key, ...(options ?? {}) });\n }\n\n /** A real `ClipboardEvent` carrying `text/plain` \u2014 the gesture nothing else\n * in the product can produce. */\n async paste(text: string, options?: DocumentPasteOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'paste', text, ...(options ?? {}) });\n }\n\n /**\n * Choose `value` on a `<select>` \u2014 a native dropdown's options are drawn by\n * the OS, so `click` has nothing in the document to resolve, and a plain\n * `element.value =` is invisible to React. Set through the prototype's own\n * value setter plus `input`/`change`; `value` is the option's `value`, not\n * its label. An unknown value is refused with the options it does offer.\n */\n async select(\n selector: string,\n value: string,\n options?: DocumentGestureOptions,\n ): Promise<DocumentProbeResult> {\n return this.#probe({\n action: 'select',\n selector,\n value,\n ...(options?.scope === undefined ? {} : { scope: options.scope }),\n ...(options?.index === undefined ? {} : { index: options.index }),\n });\n }\n\n /**\n * THE REPL over the open document: run `step` in the editor page against the\n * object the ACTIVE document published as its context (the mesh document\n * publishes its `MeshEditSession`, whose `ctx` is the bpy-shaped edit\n * context \u2014 `ctx.ops.mesh.bevel({ offset: 0.1 })`, `ctx.selection`,\n * `ctx.history`, `session.commit()`). Edit mode, no play. Serialized like\n * `game.page`: the step's own source travels, so inline every value it\n * needs and return plain data.\n */\n async run<T = unknown>(\n step: (ctx: unknown, info: { documentId: string }) => T | Promise<T>,\n ): Promise<T> {\n return this.#client.documentScript<T>(step.toString());\n }\n\n #probe(step: DocumentProbeStep): Promise<DocumentProbeResult> {\n return this.#client.documentProbe(step);\n }\n}\n", "/** Editor and document automation over the shared session command wire.\n * Modeling executes in the editor tab; this client owns no model state. */\n\nimport type {\n ActiveDocumentCapture,\n AssetKind,\n AssetPreviewCapture,\n AssetPreviewOptions,\n AssetPreviewShotSetDefinition,\n AssetPreviewSource,\n CaptureDimensions,\n DocumentLookOutcome,\n StageFrameCostReading,\n EditorChromeCapture,\n EditorChromeCaptureOptions,\n EditorClient,\n EditorState,\n EditorView,\n EditorWorkspaceName,\n HistoryStep,\n InspectedFieldWrite,\n InspectedHierarchy,\n InspectedInspection,\n LabeledShotSetCapture,\n OpenedDocument,\n PresentedEditorView,\n ShadingMode,\n StructureOp,\n StructureOpOptions,\n StructureOpResult,\n ViewPreset,\n ViewportCapture,\n} from '@volter/editor-sdk';\nimport { LiveEditorDocument } from './editor-document.js';\n\n/** A panel `showPanel` can focus: the viewport tabs, the console, the build\n * surface, or any key the editor's own static-panel registry holds\n * (`hierarchy`, `assets`, `asset-library`, `inspector`, `history`, \u2026) \u2014 which\n * is why this is open: the registry, not this union, is the vocabulary. */\nexport type PanelName =\n | 'viewport-edit'\n | 'console'\n // Keeps the literals above in autocomplete while admitting every key the\n // editor's registry holds \u2014 the registry answers, this union only hints.\n | (string & {});\n\nconst EXTENSION_KIND: Record<string, AssetKind> = {\n '.glb': 'model',\n '.gltf': 'model',\n '.png': 'image',\n '.jpg': 'image',\n '.jpeg': 'image',\n '.webp': 'image',\n '.gif': 'image',\n '.svg': 'image',\n '.hdr': 'image',\n '.exr': 'image',\n '.mp4': 'video',\n '.webm': 'video',\n '.mp3': 'audio',\n '.ogg': 'audio',\n '.wav': 'audio',\n '.flac': 'audio',\n '.glsl': 'source',\n '.vert': 'source',\n '.frag': 'source',\n // PROJECT SCRIPTS ARE SOURCE. Without these the guess below falls through to\n // `'json'`, the asset-document router sends the file to the generic JSON\n // viewer (`asset-documents.tsx#assetDocumentViewerRoute`: `spec.kind ===\n // 'json'` is decided before any content routing), and the LIVE MODELING\n // DOCUMENT never mounts \u2014 `editor.openAsset('src/lib/fox/fox.model.ts')`\n // silently shows a text pane instead of the model. Only `kind: 'source'`\n // reaches `SourceAssetViewer`, which is what content-routes a project script\n // to `LiveModuleDocument`. The set matches that viewer's own\n // `isProjectScriptPath` regex, `/\\.(?:[cm]?[jt]sx?)$/`.\n '.ts': 'source',\n '.tsx': 'source',\n '.mts': 'source',\n '.cts': 'source',\n '.js': 'source',\n '.jsx': 'source',\n '.mjs': 'source',\n '.cjs': 'source',\n};\n\n/**\n * Lightweight extension-based `AssetKind` guess for `openAsset`'s optional\n * `kind` argument. Deliberately independent of (not shared with) the\n * editor's own `AssetBrowser.tsx#getAssetKind` \u2014 that function is a private,\n * React-component-local helper of a package `@volter/editor-live` has no dependency\n * on. Callers with an unusual extension can always pass `kind` explicitly.\n */\nexport function inferAssetKind(path: string): AssetKind {\n // `.prefab.json` is retired (PRs #578/#581/#589) but the `'prefab'`\n // AssetKind itself remains in `@volter/editor-sdk` for view-link compatibility.\n if (path.endsWith('.prefab.json')) return 'prefab';\n const dot = path.lastIndexOf('.');\n const ext = dot >= 0 ? path.slice(dot).toLowerCase() : '';\n return EXTENSION_KIND[ext] ?? 'json';\n}\n\nexport class LiveEditor {\n /** `#`-private, not `private`: `volter-model-editor eval --list` enumerates this object's\n * real runtime members, and TypeScript's erased `private` would leave the\n * raw `EditorClient` advertised beside them. */\n readonly #client: EditorClient;\n\n /**\n * The ACTIVE center document's own DOM: read it, click it, key it, paste\n * into it. The one door onto editor chrome that is not play-mode gated, and\n * deliberately scoped to that document alone \u2014\n * `packages/editor-sdk/src/kit/editor-document-probe.ts` carries the design and the\n * refusal contract. Screenshotting the same subject is\n * {@link LiveEditor.captureActiveDocument}, not a fifth verb here.\n */\n readonly document: LiveEditorDocument;\n\n constructor(client: EditorClient) {\n this.#client = client;\n this.document = new LiveEditorDocument(client);\n }\n\n /**\n * THE BLENDER LANE'S VERBS, from `volter-model-editor eval`.\n *\n * Blender runs headless in the editor tab's worker (ARCHITECTURE-CORE, \"THE\n * BLENDER IN THE TAB IS BLENDER\") and answers `blender-start`,\n * `blender-execute`, `blender-scene-info`, `blender-object-info`,\n * `blender-screenshot-view`, `blender-read-file`, `blender-write-file`,\n * `blender-list-files`, `blender-stop` and `blender-status`. They were\n * reachable from `@volter/editor-sdk` and through `volter blender-mcp` but from\n * no GENERAL door, so driving a session meant writing an MCP client script\n * per question \u2014 the same discovery failure `eval-surface.ts`'s header\n * records, in a lane that had not noticed it yet.\n *\n * volter-model-editor eval \"await editor.blender('blender-execute', { code: 'import bpy; print(len(bpy.data.objects))' })\"\n *\n * `blender-status` is the only verb that creates nothing: it answers whether\n * this tab already has a session without starting one.\n */\n async blender<T extends object = Record<string, unknown>>(\n type: `blender-${string}`,\n fields: Record<string, unknown> = {},\n ): Promise<T> {\n return this.#client.blender<T>(type, fields);\n }\n\n /**\n * The active authoring adapter's persistence destination \u2014 where a save would\n * land (`status().savePath`). A read only: a three root has no scene document\n * to open, and its root is activated instead.\n */\n async scene(): Promise<string | null> {\n const state = await this.#client.getState();\n return state.savePath;\n }\n\n /**\n * Make the connected human editor show the same subject/view as the agent.\n * The returned URL is a compact, shareable projection \u2014 not a serialized\n * workspace or document payload.\n */\n async present(view: EditorView): Promise<PresentedEditorView> {\n return this.#client.present(view);\n }\n\n /** The human editor's actual active document, selection, camera and utility. */\n async currentView(): Promise<EditorView> {\n return this.#client.currentView();\n }\n\n /**\n * Capture the same center document the human is currently looking at.\n *\n * A number is a SQUARE of that size \u2014 the default, and the right shape for\n * an unstaged look at a model. `{width, height}` asks for a shaped frame, so\n * a video-aspect look needs no crop afterwards. Both are bounded by the\n * relay budget (64-1024 per side, total no larger than a 1024 square); see\n * `@volter/editor-sdk`'s `CaptureDimensions`.\n * Supply a view to present and photograph it in one editor request.\n */\n /** The active document's RENDER alone, at the size asked for: what the document draws,\n * without what the viewport draws over it (its navigation gizmo, its readouts). To see a\n * stage as the person does, use `captureEditorChrome({ region: 'document' })`. */\n async captureActiveDocument(\n size?: CaptureDimensions,\n view?: EditorView,\n ): Promise<ActiveDocumentCapture> {\n return this.#client.captureActiveDocument(size, view);\n }\n\n /**\n * Photograph the editor PAGE \u2014 every panel, tab strip and viewport as the\n * person sees it. the editor's `screenshot editor` command is this verb from the shell. The\n * one door for judging chrome sighted: a skin, a workspace arrangement or a\n * contributed panel is looked at through this, never guessed at from DOM\n * probes. The page at its own layout, `scale` output pixels per CSS pixel\n * (default `devicePixelRatio`) \u2014 a 1 px border or a glyph stroke is only\n * judgeable at the scale the reference it is compared against was captured\n * at, and the result reports its own `size` and `scale`.\n */\n async captureEditorChrome(options?: EditorChromeCaptureOptions): Promise<EditorChromeCapture> {\n return this.#client.captureEditorChrome(options);\n }\n\n /** `'all'` -> `EditorClient.selectAll()` (mirrors `volter select --all`); otherwise `EditorClient.select(id)` (mirrors `volter select <entityId>`). */\n async select(id: string | 'all'): Promise<void> {\n if (id === 'all') {\n await this.#client.selectAll();\n return;\n }\n await this.#client.select(id);\n }\n\n /** Mirrors `volter deselect`. */\n async deselect(): Promise<void> {\n await this.#client.select(null);\n }\n\n /** No `id` -> focus the current selection (mirrors bare `volter focus`); `id` given -> focus that entity. */\n async focus(id?: string): Promise<void> {\n if (id !== undefined) {\n await this.#client.focusEntity(id);\n return;\n }\n await this.#client.focusSelection();\n }\n\n /**\n * Frame the edit viewport camera on one entity. Same framing as\n * `focus(id)`, but an entity id the scene does not know THROWS, naming the\n * id \u2014 where `focus` quietly does nothing. Reach for this whenever the next\n * step reads the viewport (`screenshot()`, an\n * `assetPreview(..., { stage: 'scene' })`): a framing that silently missed\n * would otherwise be indistinguishable from one that worked.\n */\n async frame(entityId: string): Promise<void>;\n /**\n * Bare `frame()` frames the OPEN Object3D document's subject instead \u2014 its\n * selection if it has one, else the whole model: the toolbar's own Frame\n * button, reachable from a script. `fit` scales the fitted distance (1 is\n * that button's tight fit, 1.5 stands back a little for a shot).\n */\n async frame(options?: { readonly fit?: number }): Promise<void>;\n async frame(target?: string | { readonly fit?: number }): Promise<void> {\n if (typeof target === 'string') {\n await this.#client.frameEntity(target);\n return;\n }\n await this.#client.frameDocument(target?.fit);\n }\n\n /**\n * WATCH THE AGENT LOOK AROUND THE MODEL.\n *\n * Swings the open Object3D document's camera \u2014 the camera the human's tab is\n * showing \u2014 around the framed subject by `azimuth`/`elevation` RADIANS,\n * animated over `duration` seconds (default 0.6), and resolves when the move\n * ends. This is deliberately not a jump cut: the point of the verb is that a\n * person watching sees the agent walk around the thing it is working on.\n *\n * `await editor.orbit({ azimuth: Math.PI / 2 })` \u2014 a quarter turn to the right.\n *\n * There is ONE camera, and the human owns it: a drag during the move cancels\n * it exactly where it is, and the resolved outcome says `cancelledBy:\n * 'human'` rather than throwing. A second look verb supersedes the first.\n * The move is drawn by the document's own frame loop, so a document that\n * isn't being drawn (background tab, inactive panel) doesn't orbit.\n */\n async orbit(options: {\n /** RADIANS, relative to where the camera is now. `Math.PI / 2` is a\n * quarter turn; degrees are not accepted and `90` is fourteen turns. */\n readonly azimuth?: number;\n /** RADIANS, relative to where the camera is now. */\n readonly elevation?: number;\n /** SECONDS the move takes (default 0.6). */\n readonly duration?: number;\n }): Promise<DocumentLookOutcome> {\n // AN UNKNOWN KEY IS REFUSED BY NAME. Every member here is optional, so a\n // misspelling \u2014 `yaw` for `azimuth`, `pitch` for `elevation` \u2014 used to\n // orbit by nothing at all while the outcome still reported a plausible\n // ABSOLUTE azimuth, which reads exactly like a move that happened\n // (measured 2026-09-21, and it cost a round). The keys and their unit are\n // in the refusal because that is the moment the caller needs them.\n const known = ['azimuth', 'elevation', 'duration'];\n const unknown = Object.keys(options ?? {}).filter((key) => !known.includes(key));\n if (unknown.length > 0)\n throw new Error(\n `editor.orbit: ${unknown.join(', ')} ${unknown.length === 1 ? 'is not a key' : 'are not keys'} ` +\n 'this verb takes. It takes azimuth and elevation in RADIANS (relative to where the ' +\n 'camera is now) and duration in SECONDS.',\n );\n return this.#client.orbitDocument(options);\n }\n\n /**\n * A slow full revolution of the open document's subject \u2014 {@link orbit} with\n * the turns spelled out and a constant angular rate. Resolves at the end of\n * the last revolution.\n */\n async turntable(options?: {\n readonly seconds?: number;\n readonly revolutions?: number;\n }): Promise<DocumentLookOutcome> {\n return this.#client.turntableDocument(options);\n }\n\n /**\n * What a frame of the open 3D document's stage costs when nothing caps it: `frames` of the\n * stage's own frame back to back, each waited out on the GPU (median, p95, min ms), the canvas\n * with its device pixel ratio, what was drawn after culling against what the scene holds, and\n * the draw mode. `stage` names another stage by its id (a split's second area,\n * `<documentId>#area-2`).\n */\n async frameCost(options?: { readonly frames?: number; readonly stage?: string }): Promise<StageFrameCostReading> {\n return this.#client.frameCostDocument(options);\n }\n\n async view(preset: ViewPreset): Promise<void> {\n await this.#client.viewPreset(preset);\n }\n\n /**\n * Switch the editor's NAMED WORKSPACE \u2014 `await editor.workspace('model')`.\n *\n * A workspace is a task-named LAYOUT MEMORY over the one dock\n * (ARCHITECTURE-CORE \u00A7Editor chrome): `game` (the default, the editor's\n * standing arrangement), `model`, `sculpt`, `texture`, `animate`, `look`.\n * Switching is an EXPLICIT act \u2014 nothing in the editor moves chrome on its\n * own, opening a document included \u2014 and this is the session door to it,\n * beside `Window \u2192 Workspace` and the registered actions.\n *\n * Resolves once the dock has finished rebuilding, so a capture taken\n * immediately after photographs the arrangement that was asked for. Each\n * workspace remembers the user's own hand-tuning per project, so switching\n * away and back is lossless.\n */\n async workspace(id: EditorWorkspaceName): Promise<void> {\n await this.#client.setWorkspace(id);\n }\n\n /**\n * Apply a STYLE BUNDLE by id \u2014 the chrome's palette, material and icon set in\n * one gesture, the session door beside\n * `View \u2192 <Style> Style`. A bundle the open project does not offer refuses\n * and names the vocabulary; `currentView().style` reports the one worn.\n */\n async style(id: string): Promise<void> {\n await this.#client.setStyle(id);\n }\n\n /**\n * A document stage's viewport PRESENTATION \u2014 its draw mode, lighting, backdrop and overlays\n * (`@volter/editor-sdk/kit/viewport-presentation`) \u2014 resolved. With `layer`, that choice is\n * recorded for the view first, as a person's toolbar change would be, e.g.\n * `presentation('model:src/models/cube.blend', { all: { lighting: { studioPreset: 'kit' } } })`.\n * With a STRING, the named view of that id (`*.view.ts`, e.g. `'godot'`) is put on the view\n * whole; the answer's `viewPresets` lists the ones registered.\n */\n async presentation(\n documentId: string,\n layer?: Parameters<EditorClient['viewportPresentation']>[1],\n ): ReturnType<EditorClient['viewportPresentation']> {\n return this.#client.viewportPresentation(documentId, layer);\n }\n\n /**\n * Set the MATERIAL apart from the bundle that usually carries it.\n * Appearance is palette \u00D7 material, independent axes by ruling, so\n * `style()` alone can never say whether a cost belongs to the blur or to\n * the palette. This is the door that measures them apart; it answers with\n * what the chrome wears afterwards (`style` is `null` when the mix matches\n * no registered bundle).\n */\n async appearance(appearance: {\n readonly material?: string;\n }): Promise<{ material: string; style: string | null }> {\n return this.#client.setAppearance(appearance);\n }\n\n /** Focus an editor panel: a viewport tab, the console, the build surface, or\n * any key the editor's static-panel registry holds \u2014 an unknown key refuses\n * naming the ones it does. */\n async showPanel(name: PanelName): Promise<void> {\n switch (name) {\n case 'viewport-edit':\n await this.#client.showViewport('edit');\n return;\n case 'console':\n await this.#client.toggleConsole();\n return;\n default:\n // Every other name is the EDITOR's to resolve, against its live panel\n // registry. A list kept here could only ever be a copy going stale.\n await this.#client.showPanel(name);\n return;\n }\n }\n\n /** `kind` inferred from `path`'s extension when omitted (`inferAssetKind`) \u2014 pass it explicitly to override. */\n async openAsset(path: string, kind?: AssetKind): Promise<void> {\n // A `.blend` is not an asset but a Model document the project's finder lists; opened as an\n // asset it fell to the extension guess's `json` and showed its bytes.\n if (kind === undefined && path.toLowerCase().endsWith('.blend'))\n throw new Error(\n `${path} is a Blender Model document, not an asset: open it with editor.open(\"model:${path}\").`,\n );\n await this.#client.openAsset(path, kind ?? inferAssetKind(path));\n }\n\n /**\n * SELECT a project asset \u2014 the browser's single click, which fills the\n * Inspector without opening a document. `openAsset` is the double click.\n *\n * This is how a project's own `asset.inspector` section is reached: select\n * the file it matches, then `inspect()` lists the verbs that section\n * declares and `runAction(id)` runs one. Selecting a path nothing matches\n * is not an error \u2014 the Inspector shows what it has, exactly as it does\n * for a human.\n */\n async selectAsset(path: string): Promise<void> {\n await this.#client.selectAsset(path);\n }\n\n /**\n * Captures the editor's native four-view preview. A bare string is a\n * project-relative asset path (the common case); an explicit source object\n * targets a path, a LIVE SCENE ENTITY (`assetPreview({ entityId }, \u2026)`) \u2014\n * which is what makes `options.stage: 'scene'`, the entity photographed\n * where it stands under the scene's own lighting, reachable from here \u2014 or\n * RAW GLB BYTES (`assetPreview({ glbBase64 }, \u2026)`), for a model that exists\n * only in the calling Node process's memory and has never been written to\n * disk. `stage` defaults to `'lab'`, the neutral Asset Lab staging this has\n * always produced, and the bytes form is lab-only.\n */\n async assetPreview(\n source: string | AssetPreviewSource,\n options?: AssetPreviewOptions,\n ): Promise<AssetPreviewCapture> {\n return this.#client.captureAssetPreview(\n typeof source === 'string' ? { assetPath: source } : source,\n options,\n );\n }\n\n /**\n * The same subject photographed as a LABELED SHOT SET instead of the four\n * views \u2014 a caller-supplied definition of turntable yaws and bone-anchored\n * crops, rendered against the asset's own skeleton, with a contact sheet.\n * Every source {@link assetPreview} takes works here, GLB bytes included:\n * a shot set stages its own subject, so it needs no place to stand.\n *\n * Sole in-repo caller today: `project.bake.preview`'s `--orbit` lane.\n */\n async assetPreviewShots(\n source: string | AssetPreviewSource,\n definition: AssetPreviewShotSetDefinition,\n options?: AssetPreviewOptions,\n ): Promise<LabeledShotSetCapture> {\n return this.#client.captureShotSetPreview(\n typeof source === 'string' ? { assetPath: source } : source,\n definition,\n options,\n );\n }\n\n async grid(on: boolean): Promise<void> {\n await this.#client.setGrid(on);\n }\n\n async helpers(on: boolean): Promise<void> {\n await this.#client.setHelpers(on);\n }\n\n async stats(on: boolean): Promise<void> {\n await this.#client.setStats(on);\n }\n\n async shading(mode: ShadingMode): Promise<void> {\n await this.#client.setShadingMode(mode);\n }\n\n /**\n * READ the inspector, as data \u2014 the serialized inspection subject\n * (`editor.inspect()`; design: `docs/ARCHITECTURE-CORE.md` \u00A7Editor chrome,\n * \"The Inspection Model\"). This is the Figma-Inspect analog: whatever a\n * human would see in the inspector right now \u2014 the subject's identity, its\n * verbs, and every identified section in display order, with a `fields`\n * section's CURRENT VALUES at their scriptable `path`s.\n *\n * Reach for it whenever the next step depends on what an object actually\n * IS: `await editor.select(id)` then `await editor.inspect()` answers \"what\n * properties does this thing have, and what are they set to\" in one call,\n * against the same model the panel renders \u2014 no scene-graph reads, no\n * guessing at property names.\n *\n * When the inspector is showing NOTHING \u2014 nothing selected on a surface\n * with no empty-state subject of its own, which is most of them \u2014 the answer\n * is `{none: true}`, so \"the human sees no inspector\" and \"the read failed\"\n * are never the same value. A surface whose empty space IS a real thing (an\n * open Asset Lab document) still answers with that subject, and never with\n * another surface's.\n *\n * A `custom` section body is a named opaque: the editor renders it with\n * React, so the wire reports its identity rather than pretending to describe\n * its rendering \u2014 plus, when the section can say what it DISPLAYS, a `data`\n * payload in its own vocabulary (`transform` carries\n * `{position, rotation, scale}`, rotation in Euler XYZ degrees).\n */\n async inspect(): Promise<InspectedInspection> {\n return this.#client.inspect();\n }\n\n /** Run one verb listed by `inspect().quickActions`, through the same action\n * the human Inspector button invokes. */\n async runAction(actionId: string): Promise<InspectedInspection> {\n return this.#client.runInspectionAction(actionId);\n }\n\n /**\n * Run ONE command by id \u2014 the door to everything the command palette lists.\n *\n * ONE NAME (orchestrator ruling 2026-09-19). There were briefly TWO doors\n * onto the one view-verb table \u2014 this one and `editor.viewVerb(view, verb)`,\n * which addressed the same registry by its two halves. A second addressing\n * of one table is a second name for one thing, and an agent reading\n * `--list` had to choose between them with nothing to choose on. This door\n * stays because it is strictly wider: it addresses a COMMAND ID, so under\n * the frame it reaches everything the workbench knows \u2014 a `volter.action.<id>`\n * editor action, one of VS Code's own \u2014 and not only a view. A VIEW is\n * reached by spelling its verb's command id:\n *\n * await editor.command('volter.blender-uv-view.state')\n * await editor.command('volter.blender-uv-view.zoom', { to: 600 })\n *\n * await editor.command('volter.blender-node-view.view-all')\n * await editor.command('volter.blender-node-view.look', { node: 'Principled BSDF' })\n *\n * Under the Code-OSS frame this is the workbench's own command service, so\n * any command id works \u2014 ours and VS Code's alike. Standalone the editor's `edit` command\n * has no command service and answers the `volter.<view>.<verb>` shape off the\n * SAME verb table the frame's commands call, refusing any other id by name.\n * One table, two doors, exactly like the keymap's.\n *\n * Answers with whatever the command returned \u2014 a view verb's own state, or\n * `null` for a command that returns nothing.\n */\n async command(commandId: string, args?: unknown): Promise<unknown> {\n return this.#client.runCommand(commandId, args);\n }\n\n /**\n * RESTRUCTURE the authored tree \u2014 the hierarchy context menu's own verbs.\n *\n * `create`, `delete`, `duplicate`, `reparent`, `reorder`, `wrap`, `unwrap`,\n * `group`, `ungroup`, `copy`, `cut`, `paste`; `extractComponent` and\n * `forkComponent` are the two that write whole new files and have their own\n * doors below. All of them run the SAME `authoring/consumer-actions.ts`\n * helpers the menu items call, so there is one implementation of each op and\n * not a second that can disagree with what a human gets.\n *\n * It exists because the menu is a POINTER surface: every one of these ops was\n * reachable only by right-clicking a hierarchy row, which is nothing an agent\n * can do \u2014 so for an ingest root, whose only authoring surface IS the editor,\n * structure was closed entirely.\n *\n * `id`/`ids` default to the current selection. The answer carries the same\n * per-edit `write` ack `setField` does, so `write.persisted` tells a saved\n * restructure from a live-only one. An op the active adapter does not provide\n * REJECTS by name \u2014 never a silent no-op.\n */\n async structure(op: StructureOp, options?: StructureOpOptions): Promise<StructureOpResult> {\n return this.#client.structureOp(op, options ?? {});\n }\n\n /**\n * \"Extract Component\u2026\" \u2014 lift the selected native subtree into its own\n * component file (plus a story) and replace the callsite with it.\n *\n * Answers the action's own sentence, which NAMES both new files, because\n * undo owns the callsite edit and will not remove them.\n */\n async extractComponent(options?: { id?: string; name?: string }): Promise<string> {\n return (await this.#client.extractComponent(options ?? {})).hint;\n }\n\n /**\n * \"Fork Component\u2026\" \u2014 copy the selected instance's component definition to a\n * new file and retarget THIS CALLSITE at it.\n *\n * One callsite is the unit of the edit; when that callsite sits inside a\n * component rendered many times, every one of those renders now renders the\n * fork.\n */\n async forkComponent(options?: { id?: string }): Promise<string> {\n return (await this.#client.forkComponent(options ?? {})).hint;\n }\n\n /**\n * READ the hierarchy panel, as data \u2014 the rows a human is looking at right\n * now, nested exactly as the panel nests them.\n *\n * The companion to {@link inspect}: that one answers \"what IS the selected\n * thing\", this one answers \"what does the tree LOOK LIKE\". It is the panel's\n * own output, not a fresh walk of the scene \u2014 the adapter's tree after the\n * component marks fold implementation subtrees (bones, particle renderers,\n * instanced pools), after the internals reveal, the document promotion, the\n * child cap, the collapse state, the search filter and the selection scope.\n *\n * Works in play mode and edit mode; the answer says which (`playState`,\n * `activeViewportTab`), because the two are different adapters and a tree\n * that looks wrong is very often the wrong adapter's tree.\n *\n * Prefer this over `status().entities`, which is deliberately a different\n * question \u2014 the RAW adapter tree, unprojected. A panel that renders the\n * wrong rows looks perfectly healthy in that facet.\n *\n * Each row carries `childCount` (what its caret opens), `internalChildCount`\n * (what is folded behind \"Reveal Internals\") and `expandable` (whether the\n * panel draws a caret at all), so \"this subtree exists but nothing in the UI\n * opens it\" is a fact you can read rather than one you have to notice.\n *\n * Rejects, naming the panel, when no hierarchy panel is mounted \u2014 an empty\n * tree would be a fabricated answer about a surface nobody is being shown.\n */\n async hierarchy(): Promise<InspectedHierarchy> {\n return this.#client.hierarchy();\n }\n\n /** Expand every branch through the Hierarchy panel's own action. */\n async expandHierarchyAll(): Promise<void> {\n await this.#client.expandHierarchyAll();\n }\n\n /** Collapse every branch through the same panel action. Expanding is\n * persisted per project, so without this the tree's REST STATE \u2014 what a\n * person sees on opening the project \u2014 is unreachable once any reader has\n * expanded it. */\n async collapseHierarchyAll(): Promise<void> {\n await this.#client.collapseHierarchyAll();\n }\n\n /**\n * Write one editable field from `inspect()` by its stable path, through the\n * same Inspector IO and persistence boundary the human control uses.\n *\n * The answer is `{ subject, write }`, and `write` is the half worth reading\n * first: a write with no persistence route open still succeeds \u2014 it lands on\n * the live object and journals live-only \u2014 so `write.persisted` is how you\n * tell a saved edit from one that will not survive the session, without\n * diffing the tree. `write.destination` is the adapter's own words for where\n * it went (\"live-only (not saved)\" is a destination, never silence).\n */\n async setField(path: string, value: unknown): Promise<InspectedFieldWrite> {\n return this.#client.setInspectionField(path, value);\n }\n\n /**\n * REMOVE one field's authored override \u2014 the revert arrow, as a command.\n *\n * Reach for this instead of `setField` whenever you are UNDOING an edit that\n * added a property the source did not carry: `setField` can only write a\n * value, so setting the default back leaves `position={[0, 0, 0]}` in the\n * file where there was nothing before. Only this door restores the bytes.\n *\n * The answer is the same `{ subject, write }` shape, awaited past the bytes.\n * It rejects with `code: 'REMOVAL_UNAVAILABLE'` when the field is not\n * declared removable or the lane has no removal door \u2014 which is a missing\n * seam to report, not a removal that failed.\n */\n async removeField(path: string): Promise<InspectedFieldWrite> {\n return this.#client.removeInspectionField(path);\n }\n\n /** Open a document by its adapter-declared id, through its registered owner. */\n async open(id: string): Promise<OpenedDocument> {\n return this.#client.open(id);\n }\n\n /** Undo / redo one project transaction, through the session's own history\n * queue \u2014 the same one the keyboard shortcut drives. */\n async undo(): Promise<HistoryStep> {\n return this.#client.undo();\n }\n\n async redo(): Promise<HistoryStep> {\n return this.#client.redo();\n }\n\n /** Reload the editor's page and resolve once the new document answers. */\n async reloadPage(): Promise<void> {\n await this.#client.reloadPage();\n }\n\n /** Mirrors the editor's `status` command \u2014 the full live editor state as JSON. */\n async status(): Promise<EditorState> {\n return this.#client.getState();\n }\n\n /** A live viewport PNG (`EditorClient.captureViewport`) \u2014 no direct CLI verb exists; this is the closest wire read. */\n async screenshot(size?: number): Promise<ViewportCapture> {\n return this.#client.captureViewport(size);\n }\n}\n", "/** Registered project tools over the current shared editor session. */\n\nimport type {\n EditorClient,\n ProjectToolCatalog,\n ProjectToolCatalogEntry,\n ProjectToolOutcome,\n} from '@volter/editor-sdk';\n\nexport class LiveTools {\n /** `#`-private for the same reason `LiveEditor.#client` is. */\n readonly #client: EditorClient;\n\n constructor(client: EditorClient) {\n this.#client = client;\n }\n\n /** Enumerate the exact `package.json#volter.tools` catalog without executing it. */\n async list(): Promise<ProjectToolCatalog> {\n return this.#client.listProjectTools();\n }\n\n /** Return one tool's discoverable metadata, or `null` when it is not registered. */\n async describe(name: string): Promise<ProjectToolCatalogEntry | null> {\n const catalog = await this.list();\n return catalog.tools.find((tool) => tool.name === name) ?? null;\n }\n\n /**\n * Invoke the same validated callable used by the editor and CLI.\n *\n * `instance` names WHICH mounted instance the tool should drive when several\n * are live (multiplayer authoring) \u2014 it reaches the tool as `ctx.instance`,\n * and a tool that drives the game binds\n * `game.instance(ctx.instance)` from it. Omitted is the single-instance case;\n * the tool then targets the sole live instance, exactly as before.\n */\n async run(\n name: string,\n input: unknown = {},\n options: { confirm?: boolean; instance?: string } = {},\n ): Promise<ProjectToolOutcome> {\n return this.#client.runProjectTool(name, input, options);\n }\n}\n", "/**\n * `lazyChainProxy` \u2014 turns an async \"resolve the real object\" function into\n * a synchronously-importable stand-in that supports the SAME call shape as\n * the real thing, including nested member access (`game.input.hold(...)`,\n * `editor.document.query(...)`), by recording the property-access PATH and only\n * resolving + walking it down at the point of an actual function CALL.\n *\n * This is what makes `index.ts`'s top-level `export const editor = ...` /\n * `game` / `page` work as plain values a script can `import { editor, game,\n * page } from '@volter/editor-live'` and call immediately \u2014 each call transparently\n * awaits the memoized `connect()` first.\n *\n * Limitation (by design, documented on `index.ts`'s exports too): only\n * FUNCTION-shaped access resolves through this proxy \u2014 `game.input.hold(x)`\n * works, but reading a plain data property (e.g. `game.fenceTick`) would\n * return another inert proxy, not the real number, since there is no\n * function CALL to trigger resolution. Every documented `editor`/`game`/\n * `page` member is a method, so this never bites the documented surface.\n */\n\ntype AnyFn = (...args: unknown[]) => unknown;\n\nfunction isFunction(value: unknown): value is AnyFn {\n return typeof value === 'function';\n}\n\nfunction walk(root: unknown, path: PropertyKey[]): { thisArg: unknown; fn: unknown } {\n if (path.length === 0) return { thisArg: undefined, fn: root };\n let obj: Record<PropertyKey, unknown> = root as Record<PropertyKey, unknown>;\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i] as PropertyKey;\n obj = obj[key] as Record<PropertyKey, unknown>;\n }\n const lastKey = path[path.length - 1] as PropertyKey;\n return { thisArg: obj, fn: obj[lastKey] };\n}\n\n/**\n * `resolveRoot` is called (and its result awaited) on every terminal\n * function call reached through the returned proxy \u2014 callers typically wire\n * it to a memoized `connect()` (see `index.ts`), so repeated calls across\n * many proxy invocations still resolve only once.\n */\nexport function lazyChainProxy<T>(\n resolveRoot: () => Promise<unknown>,\n path: PropertyKey[] = [],\n): T {\n const callableTarget = (() => {}) as unknown as object;\n return new Proxy(callableTarget, {\n get(_target, prop) {\n // Never look thenable \u2014 `await`ing a proxy (accidentally, or via a\n // generic helper checking `typeof x.then`) must not trigger resolution\n // or hang; there is no promise here, only a call-shaped stand-in.\n if (prop === 'then' || prop === 'catch' || prop === 'finally') return undefined;\n return lazyChainProxy(resolveRoot, [...path, prop]);\n },\n apply(_target, _thisArg, args) {\n return resolveRoot().then((root) => {\n const { thisArg, fn } = walk(root, path);\n if (!isFunction(fn)) {\n const label = path.length > 0 ? path.map(String).join('.') : '(the connected value)';\n throw new TypeError(`@volter/editor-live: ${label} is not a function on the connected session.`);\n }\n return fn.apply(thisArg, args);\n });\n },\n }) as T;\n}\n", "/** Resolve an existing session for exactly one project.\n * Prefer the project's hint, verify it against the served canonical path,\n * then consult the shared registry. Never fall back to another project.\n * Storage identifiers move with the server in the coordinated migration. */\n\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { resolveManifestPath } from '@volter/editor-project/manifest/locate';\nimport { resolveProductForProject } from '@volter/editor-sdk/session/product-locator';\nimport {\n EDITOR_SESSION_DISCOVERY_TIMEOUT_MS,\n type EditorSessionInfo,\n type SessionListingTransport as SessionDiscoveryTransport,\n HttpSessionDiscovery,\n servedProjectAnswer,\n withTimeout,\n} from '@volter/editor-sdk/session/discovery';\n\n/** Nearest ancestor containing the project's canonical manifest. */\nexport function findProjectRootFrom(dir: string): string | null {\n let cur = resolve(dir);\n for (;;) {\n if (existsSync(resolveManifestPath(cur))) return cur;\n const parent = dirname(cur);\n if (parent === cur) return null;\n cur = parent;\n }\n}\n\n/** The minimal slice of `EditorTransport` `resolveSession` actually needs \u2014 narrower than the full interface so a test double only has to implement one method. */\nexport type SessionListingTransport = SessionDiscoveryTransport;\n\nexport interface ResolvedSession {\n /** Editor dev-server port the resolved session is listening on. */\n port: number;\n /** Absolute project root \u2014 the nearest ancestor of the requested directory containing `volter.project.json`. */\n projectRoot: string;\n}\n\nexport interface SessionResolutionDeps {\n /** Session listing + liveness verification \u2014 defaults to a real `HttpSessionDiscovery`. Overridable for tests. */\n transport?: SessionListingTransport;\n /** Project-root discovery \u2014 defaults to the real fs walk (`findProjectRootFrom` above). Overridable for tests. */\n findProjectRootFrom?: (dir: string) => string | null;\n /** Project-local session hint reader. Defaults to `.volter/session.json`. */\n readProjectSession?: (projectRoot: string) => ProjectSessionHint | null;\n /** Exact-session verifier. Defaults to GET /__editor/project + canonical project matching. */\n verifyProjectSession?: (hint: ProjectSessionHint, projectRoot: string) => Promise<boolean>;\n}\n\nexport interface ProjectSessionHint {\n port: number;\n pid: number;\n url: string;\n startedAt: string;\n}\n\nfunction canonicalPath(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n return resolve(path);\n }\n}\n\nfunction readProjectSession(projectRoot: string): ProjectSessionHint | null {\n try {\n const value: unknown = JSON.parse(\n readFileSync(join(projectRoot, '.volter', 'session.json'), 'utf8'),\n );\n if (typeof value !== 'object' || value === null) return null;\n const hint = value as Record<string, unknown>;\n if (\n typeof hint['port'] !== 'number' ||\n !Number.isInteger(hint['port']) ||\n hint['port'] <= 0 ||\n typeof hint['pid'] !== 'number' ||\n typeof hint['url'] !== 'string' ||\n typeof hint['startedAt'] !== 'string'\n ) {\n return null;\n }\n return hint as unknown as ProjectSessionHint;\n } catch {\n return null;\n }\n}\n\n/**\n * WHICH PROJECT a `/__editor/project` body says its server is serving, and the\n * reason it cannot describe it.\n *\n * `serving` is the server's own statement of \"I AM serving this project, I\n * just cannot describe it\" \u2014 its manifest is unparseable or fails strict\n * validation. The route added it because a bare `{ project: null }` there is\n * indistinguishable from \"no project open\"; reading only `project.path`\n * reproduces that collapse on this side, and the cost is the worst kind of\n * wrong answer: this door refused a session that WAS open on the caller's\n * project with \"no live editor session found \u2026 (N other live session(s) found,\n * but none open this project)\" \u2014 sending the operator to start an editor that\n * was already running, with the real defect (their own manifest) never named.\n */\n\n/**\n * What the server on `port` says it serves \u2014 `undefined` when it did not\n * answer at all. One probe: the manifest failure arrives with the path, so\n * neither the hint path nor the refusal path pays a second round trip.\n */\nasync function probeServedProject(\n port: number,\n): Promise<{ path: string | null; manifestError: string | null } | undefined> {\n try {\n const response = await fetch(`http://127.0.0.1:${port}/__editor/project`, {\n signal: AbortSignal.timeout(EDITOR_SESSION_DISCOVERY_TIMEOUT_MS),\n });\n if (!response.ok) return undefined;\n return servedProjectAnswer(await response.json());\n } catch {\n return undefined;\n }\n}\n\n/**\n * The refusal for a session that IS this project's and cannot be driven,\n * because the project's manifest does not load.\n *\n * A refusal, not an attach: with no readable manifest the editor page itself\n * renders its startup-error screen, so there is no editor and no game behind\n * this door to bind `{ editor, game, page, tools, session }` to. What changed\n * is only that it now says the true thing \u2014 the failing file and key \u2014 instead\n * of \"no live editor session found\", which sent operators to start an editor\n * that was already running while their actual defect went unnamed.\n */\nfunction manifestRefusal(projectRoot: string, manifestError: string): Error {\n return new Error(\n `@volter/editor-live: the editor session for ${projectRoot} is live, but its volter.project.json does ` +\n 'not load, so there is no editor or game to drive \u2014 the editor page is showing this same ' +\n `error. Fix the manifest and retry; the session recovers on save, no restart needed.\\n${manifestError}`,\n );\n}\n\n/**\n * Resolve `projectDir` (default `process.cwd()`) to the port of its already-\n * running the editor's `edit` command session. Throws a descriptive error (never hangs\n * indefinitely \u2014 bounded by `EDITOR_SESSION_DISCOVERY_TIMEOUT_MS`, and never\n * silently attaches to an unrelated project's session \u2014 see the module doc\n * above) when no volter.project.json is found, or no live session covers it.\n */\n/**\n * THE REFUSAL WHEN NOTHING MATCHED \u2014 and it says WHICH nothing.\n *\n * \"No live editor session found \u2026 run the editor's `edit` command\" used to be the answer to\n * four different states, only one of which it described. The other three sent\n * the operator to start an editor that was already running:\n *\n * - discovery FAILED (a probe timeout under load) \u2014 nothing was learned, so\n * \"no session is running\" is not a fact anyone established;\n * - the registry was read and is genuinely empty \u2014 the one case the old text\n * was right about;\n * - sessions exist, but every one resolves to a different canonical path. In\n * a repo worked through git worktrees this is the ORDINARY miss: two\n * checkouts of the same project differ only in a path prefix, and a\n * symlinked worktree's `realpath` diverges from the path the caller typed.\n * Naming both sides is what makes it a two-second diagnosis instead of a\n * hunt.\n *\n * Each branch prescribes only what its own state supports.\n */\nfunction noMatchingSessionRefusal(\n projectRoot: string,\n canon: string,\n sessions: readonly EditorSessionInfo[],\n discoveryFailure: string | null,\n): Error {\n if (discoveryFailure !== null) {\n return new Error(\n `@volter/editor-live: could not READ the editor session registry while looking for ${projectRoot} \u2014 ` +\n `${discoveryFailure}. This is not the answer \"no editor is running\": the question went ` +\n 'unanswered, so nothing is known about what is live. Retry (a probe can time out while ' +\n `the box is loaded); if it keeps failing, ${sessionsCommandFor(projectRoot)} asks the same question directly.`,\n );\n }\n if (sessions.length === 0) {\n return new Error(\n `@volter/editor-live: the editor session registry is readable and lists NO live sessions, so none ` +\n `covers ${projectRoot}. @volter/editor-live only attaches to an already-running session \u2014 it ` +\n `never starts one \u2014 so run ${editCommandFor(projectRoot)} in that project first, then retry.`,\n );\n }\n const listed = sessions\n .map((s) => ` port ${s.port} \u2192 ${s.project === null ? '(no project)' : s.project}`)\n .join('\\n');\n return new Error(\n `@volter/editor-live: ${sessions.length} live editor session(s) are running, but none of them opens ` +\n `${projectRoot}. @volter/editor-live never silently attaches to a different project.\\n` +\n ` looking for (resolved): ${canon}\\n` +\n ` live sessions:\\n${listed}\\n` +\n ' If one of those is meant to be this project, the two paths differ after resolution \u2014 ' +\n 'the usual cause is a git worktree or a symlink, where the session was opened through a ' +\n `different path to the same files. Run ${editCommandFor(projectRoot)} from THIS path, or use the path the ` +\n 'session lists.',\n );\n}\n\nexport async function resolveSession(\n projectDir: string = process.cwd(),\n deps: SessionResolutionDeps = {},\n): Promise<ResolvedSession> {\n const findRoot = deps.findProjectRootFrom ?? findProjectRootFrom;\n const transport = deps.transport ?? new HttpSessionDiscovery();\n\n const projectRoot = findRoot(projectDir);\n if (projectRoot === null) {\n throw new Error(\n `@volter/editor-live: no volter.project.json found in ${projectDir} or any parent directory \u2014 is this a project?`,\n );\n }\n\n // The editor writes this exact-project hint at boot and removes it on\n // shutdown. Prefer it over a global all-session scan: it is both faster and\n // immune to an unrelated slow/dead registry entry consuming the discovery\n // deadline. The live probe remains authoritative, so a stale file cannot\n // attach us to the wrong project or port.\n const localHint = (deps.readProjectSession ?? readProjectSession)(projectRoot);\n if (localHint) {\n // `deps.verifyProjectSession` is the test-only override and keeps its\n // boolean meaning: \"this hint is this project's session, and healthy\".\n // With no override we read the probe ourselves, because the same response\n // carries WHY a served project cannot be described.\n if (deps.verifyProjectSession) {\n if (await deps.verifyProjectSession(localHint, projectRoot)) {\n return { port: localHint.port, projectRoot };\n }\n } else {\n const served = await probeServedProject(localHint.port);\n if (served?.path != null && canonicalPath(served.path) === canonicalPath(projectRoot)) {\n if (served.manifestError !== null) throw manifestRefusal(projectRoot, served.manifestError);\n return { port: localHint.port, projectRoot };\n }\n }\n }\n\n let sessions: EditorSessionInfo[];\n // A FAILED discovery is not an empty one. Collapsing the two into `[]` is\n // what made this door answer \"no live editor session found\" \u2014 and prescribe\n // the editor's `edit` command \u2014 for a probe that merely timed out under load, sending the\n // operator to start an editor that was already running while the real defect\n // went unnamed. The same collapse the manifest refusal above was added for.\n let discoveryFailure: string | null = null;\n try {\n sessions = await withTimeout(\n transport.listSessions(EDITOR_SESSION_DISCOVERY_TIMEOUT_MS),\n EDITOR_SESSION_DISCOVERY_TIMEOUT_MS,\n 'editor session discovery',\n );\n } catch (err) {\n sessions = [];\n discoveryFailure = err instanceof Error ? err.message : String(err);\n }\n\n const canon = canonicalPath(projectRoot);\n const match = sessions.find((s) => s.project !== null && canonicalPath(s.project) === canon);\n if (!match) throw noMatchingSessionRefusal(projectRoot, canon, sessions, discoveryFailure);\n\n if (match.manifestError != null) throw manifestRefusal(projectRoot, match.manifestError);\n\n return { port: match.port, projectRoot };\n}\n\n/** `` `<product> edit` `` for the product this project declares, or a generic\n * phrase when it declares none \u2014 this package serves every product and\n * names only the one the project installed. */\nfunction editCommandFor(projectRoot: string): string {\n return verbFor(projectRoot, 'edit');\n}\n\nfunction sessionsCommandFor(projectRoot: string): string {\n return verbFor(projectRoot, 'sessions');\n}\n\nfunction verbFor(projectRoot: string, verb: string): string {\n try {\n return `\\`${resolveProductForProject(projectRoot).command} ${verb}\\``;\n } catch {\n return `its product's \\`${verb}\\` command`;\n }\n}\n", "// Finding the project manifest ON DISK. There is ONE filename \u2014 see\n// `./filename.ts` for why the old one was removed rather than kept readable.\n//\n// Deliberately dependency-light \u2014 `node:fs` + `node:path` + `./filename` and\n// NOTHING else (no Zod, no `./load`). Several callers are explicitly\n// schema-free by design (`packages/editor-core/server/project-root-surface.ts`,\n// `packages/editor/vite-plugin-ui-oid.ts`) and must be able to locate a\n// manifest without dragging the validator in.\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport {\n MANIFEST_FILENAME,\n REMOVED_MANIFEST_FILENAME,\n removedManifestFilenameMessage,\n} from './filename';\n\n/**\n * Throw the rename instruction if `dir` carries only the REMOVED manifest\n * filename. The `assertNoRemoved*` shape: a removed thing must reject loudly\n * naming the exact fix, never be silently ignored (which would present as\n * \"this folder is not a project\" \u2014 a diagnosis pointing nowhere).\n *\n * Returns normally when `dir` holds the current manifest, or neither file.\n */\nexport function assertNoRemovedManifestFilename(dir: string): void {\n if (existsSync(join(dir, MANIFEST_FILENAME))) return;\n if (!existsSync(join(dir, REMOVED_MANIFEST_FILENAME))) return;\n throw new Error(removedManifestFilenameMessage(join(dir, REMOVED_MANIFEST_FILENAME)));\n}\n\n/**\n * The manifest path inside `dir`. Always `volter.project.json` \u2014 so a \"not\n * found\" message names the filename a project must be using \u2014 except that a\n * directory carrying only the removed `volter.game.json` THROWS the rename\n * instruction instead of reporting a phantom path.\n *\n * This is the drop-in replacement for a hand-written `join(dir, \u2026)` everywhere\n * a manifest is READ. Writers want {@link manifestWritePath}.\n */\nexport function resolveManifestPath(dir: string): string {\n assertNoRemovedManifestFilename(dir);\n return join(dir, MANIFEST_FILENAME);\n}\n\n/** True when `dir` holds a manifest. A lone `volter.game.json` throws. */\nexport function hasManifest(dir: string): boolean {\n assertNoRemovedManifestFilename(dir);\n return existsSync(join(dir, MANIFEST_FILENAME));\n}\n\n/** Where a manifest gets WRITTEN in `dir`. There is one answer. */\nexport function manifestWritePath(dir: string): string {\n return join(dir, MANIFEST_FILENAME);\n}\n", "// The project manifest's FILENAME. There is exactly ONE.\n//\n// The manifest is `volter.project.json`, and NOTHING reads a second spelling\n// (the legacy-removal doctrine, `docs/ARCHITECTURE-CORE.md` \u00A7Vocabulary). Two\n// accepted names is the defect, not the convenience: both get written, and\n// copies of the \"try both\" probe spread into modules that agree with the real\n// resolver only by coincidence.\n//\n// The removed name REJECTS LOUDLY, naming the exact one-line fix \u2014 never\n// silently ignored, never redirected. A directory\n// carrying only `volter.game.json` is an error with a `git mv` in the message,\n// not a project that quietly fails to open.\n//\n// This module is the ONE place either literal is spelled out, and it is\n// dependency-free (no `node:fs`) so browser bundles can import it. The\n// filesystem side lives in `./locate` (`resolveManifestPath`, `hasManifest`,\n// `assertNoRemovedManifestFilename`).\n\n/** The manifest filename. Every reader reads it; every writer writes it. */\nexport const MANIFEST_FILENAME = 'volter.project.json';\n\n/** The removed filename. Read by nothing \u2014 its only job is the error message. */\nexport const REMOVED_MANIFEST_FILENAME = 'volter.game.json';\n\n/** True for the manifest filename (basename comparison). */\nexport function isManifestFilename(name: string): boolean {\n return name === MANIFEST_FILENAME;\n}\n\n/**\n * The verbatim rejection an on-disk `volter.game.json` earns \u2014 the one-line fix\n * spelled out, per the removed-format contract. Shared by the Node\n * (`./locate`) and browser (storage-backend) halves so a project author sees\n * the same sentence wherever the stale name is found.\n */\nexport function removedManifestFilenameMessage(where: string): string {\n return (\n `${where}: found \\`${REMOVED_MANIFEST_FILENAME}\\` and no \\`${MANIFEST_FILENAME}\\`. ` +\n `\\`${REMOVED_MANIFEST_FILENAME}\\` was REMOVED (the legacy-removal doctrine, ` +\n 'docs/ARCHITECTURE-CORE.md \u00A7Vocabulary) \u2014 nothing reads it any more, and it is ' +\n 'deliberately NOT read as a fallback, because a second accepted name is the defect.\\n' +\n `Fix: rename it \u2014 \\`git mv ${REMOVED_MANIFEST_FILENAME} ${MANIFEST_FILENAME}\\`. ` +\n 'The contents are unchanged; only the filename moved.'\n );\n}\n", "/**\n * WHICH PRODUCT OPENS THIS PROJECT \u2014 one declaration, one resolver.\n *\n * A PRODUCT is the running program (ARCHITECTURE-CORE \u00A7The target shape, rule\n * 4): `@volter/game-editor` and `@volter/model-editor` each stitch packages onto\n * the editor kit in code and each carry a `bin`. **Which product runs is never\n * a switch** \u2014 there is no `--product` flag, no id in the manifest, no setting,\n * the same way a folder never names which VS Code opens it and a `.blend` never\n * names Blender.\n *\n * So the resolution is a DEPENDENCY resolution, exactly as\n * `assertEditorProjectInstalled` resolves `@volter/editor-core`: the project's\n * `dependencies` \u222A `devDependencies` are read, each `@volter/*` among them is\n * resolved from the project, and the one whose `package.json` carries\n * `volter.product` is the product. A project's `package.json` naming a product as\n * a devDependency is the person's convenience \u2014 what `npm run dev` launches \u2014\n * and not a rule about the project.\n *\n * NONE and TWO are both refusals by name, because either answer would otherwise\n * be guessed. None prints the `npm install --save-dev` line for both products;\n * two names both and says the project must resolve it, because a page runs one\n * product and nothing here can pick.\n *\n * WHO CALLS THIS, and why twice. The CLI resolves to REFUSE EARLY and to hand\n * the directory to the session; the session resolves to SERVE the product's\n * entry and to REPORT it (`EditorState.product`), because what it is serving is\n * its own fact. One function, one set of refusal texts.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n/** The manifest key a product declares. A DECLARATION, not a config: it says\n * what this package IS so the CLI and the session can find its entry without\n * running it (ARCHITECTURE-CORE \u00A7The target shape, rule 8). */\nexport const PRODUCT_DECLARATION_KEY = 'volter.product';\n\n/** Light or dark \u2014 the two the workbench's own `ColorScheme` has plain names\n * for, and the only two a product needs to state (a high-contrast scheme is a\n * person's accessibility choice, never a product's declaration). */\nexport type ProductColorTheme = 'dark' | 'light';\n\n/**\n * THE WORKBENCH THIS PRODUCT IS, named as a published release.\n *\n * A product is the running program, and the program is the Code-OSS workbench\n * its kit and its half were compiled INTO (ARCHITECTURE-CORE \u00A7The target\n * shape: \"one product number per release, pinning the fork, the kit, the API\n * and its media\"). So which release those bytes are is not a machine's setting\n * and not a person's choice \u2014 it is what the product IS, declared beside\n * `entry` and `colorTheme` and read without running anything (rule 8).\n *\n * `release` is the tag `scripts/workbench/build-release.mjs --publish` cuts on\n * the fork's own repository, `<product>-<fork sha 12>-<platform>`;\n * `tarballSha256` is the pin, verified against the downloaded bytes before a\n * single one of them is extracted. Both come out of that script's own\n * `BUILD.json`, and it prints this block to paste.\n *\n * A machine that has already fetched it keeps it in `~/.volter/workbenches/<tag>`\n * and a project that has one names it in `.volter/workbench.json`, so this is\n * consulted exactly once per machine per release \u2014 see\n * `workbench-locator.ts`'s `resolveWorkbenchForProject`.\n */\nexport interface ProductWorkbench {\n /** The GitHub Release tag on `volter-ai/code-oss`. */\n readonly release: string;\n /** The sha256 of that release's tarball asset, hex. */\n readonly tarballSha256: string;\n}\n\n/** A product package, as everything outside it needs to know it. */\nexport interface ProductIdentity {\n /** The package name \u2014 `@volter/game-editor`. */\n readonly name: string;\n /** Its version, reported beside the workbench by the editor's `status` command. */\n readonly version: string;\n /**\n * The command a person types to run it \u2014 the ONE key of its package.json\n * `bin` (`volter-game-editor`). Every message the kit writes about a verb\n * names this, because the kit itself has no command of its own.\n */\n readonly command: string;\n /** The name a person sees \u2014 `volter.product.displayName` (`Volter Game Editor`). */\n readonly displayName: string;\n /** Its package root, absolute. */\n readonly dir: string;\n /**\n * Its ONE source entry, package-relative and POSIX (`./src/index.ts`). That\n * entry IS the product's frame entry: it composes and re-exports `mountVolter`,\n * which is the name the fork's contribution reads off the served module.\n */\n readonly entry: string;\n /**\n * WHICH WAY ROUND THIS PRODUCT PAINTS, before one line of its code runs.\n *\n * Measured 2026-09-21 on both releases: the web workbench's FIRST PAINT is\n * LIGHT (`workbenchThemeService.ts`, `this.settings.getPreferredColorScheme()\n * ?? (isWeb ? ColorScheme.LIGHT : ColorScheme.DARK)`), so the product's\n * opening cover \u2014 which paints in `--vscode-*` variables, as it must \u2014 was\n * white for its whole life and flipped dark the instant the real theme\n * landed. The supported door is `IWorkbenchConstructionOptions\n * .initialColorTheme`, which is read out of the PAGE CONFIG, before any\n * extension or setting is available; the session's proxy injects it\n * (`packages/editor-core/server/frame-proxy.ts`).\n *\n * It is a DECLARATION and not a setting (ARCHITECTURE-CORE \u00A7The target\n * shape, rule 8): it says what the product IS, the same way `entry` does, and\n * it has to be readable without running the product because the proxy needs\n * it before the product exists. A person's own `workbench.colorTheme` still\n * wins on every open after the first \u2014 the workbench prefers its stored theme\n * over this and only falls back here when it has none.\n */\n readonly colorTheme: ProductColorTheme;\n /** WHICH WORKBENCH THIS PRODUCT IS \u2014 see {@link ProductWorkbench}. */\n readonly workbench: ProductWorkbench | null;\n}\n\n/** The install line a refusal quotes, for a project that already EXISTS. Both\n * products, because a person choosing between them is choosing what they are\n * building, not a flag. */\nexport const PRODUCT_INSTALL_LINES = [\n ' npm install --save-dev @volter/model-editor',\n ' npm install --save-dev @volter/game-editor',\n] as const;\n\n/**\n * The create line a refusal or a help screen quotes, for a project that does\n * not exist yet. CREATION IS THE PRODUCT'S (ARCHITECTURE-CORE \u00A7The target\n * shape, rule 1): a product scaffolds the project it opens, declaring its own\n * presets, and there is no create verb in the kit's CLI for either of them to\n * be an alias of.\n *\n * This is the ONE place the two product names are spelled outside the products\n * themselves; the CLI and the session quote it rather than keeping a copy.\n */\nexport const PRODUCT_CREATE_LINES = [' npx @volter/editor-core create <name>'] as const;\n\ninterface ProductManifestShape {\n private?: unknown;\n name?: unknown;\n version?: unknown;\n bin?: unknown;\n volter?: { product?: { entry?: unknown; colorTheme?: unknown; workbench?: unknown; displayName?: unknown } };\n}\n\nconst PRODUCT_COLOR_THEMES: readonly ProductColorTheme[] = ['dark', 'light'];\n\n/**\n * Read one product package's declaration, or `null` when the manifest is not a\n * product's. Throws when it declares `volter.product` and the declaration is\n * unusable \u2014 a half-written product must be named, never skipped.\n */\nexport function readProductManifest(packageDir: string): ProductIdentity | null {\n const manifestPath = join(packageDir, 'package.json');\n let manifest: ProductManifestShape;\n try {\n manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as ProductManifestShape;\n } catch {\n return null;\n }\n const declared = manifest.volter?.product;\n if (declared === undefined) return null;\n const entry = declared.entry;\n if (typeof entry !== 'string' || !entry.startsWith('./'))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"entry\" is ` +\n `${JSON.stringify(entry)}. It must be a ./-relative module \u2014 the product's ONE source ` +\n 'entry, which is also its frame entry (e.g. \"./src/index.ts\").',\n );\n const resolved = join(packageDir, entry);\n if (!existsSync(resolved))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY}.entry ${JSON.stringify(entry)}, ` +\n `which does not exist (${resolved}).`,\n );\n const colorTheme = declared.colorTheme;\n // REQUIRED, like `entry`, and for the same reason: a product that does not\n // say which way round it paints gets the workbench's web default, which is\n // LIGHT, and its cover is white until its real theme loads. There is no\n // defensible default to invent here \u2014 a dark product and a light product are\n // both ordinary \u2014 so an unstated one is named rather than guessed.\n if (typeof colorTheme !== 'string' || !PRODUCT_COLOR_THEMES.includes(colorTheme as never))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"colorTheme\" is ` +\n `${JSON.stringify(colorTheme)}. It must be ${PRODUCT_COLOR_THEMES.map((one) =>\n JSON.stringify(one),\n ).join(' or ')} \u2014 which way round this product paints, read before any of its code ` +\n \"runs so the workbench's first frame is already the product's own background.\",\n );\n // REQUIRED, for the same reason as `entry`: the kit names verbs in every\n // message it writes, and there is no command to name but the product's own.\n const bin = manifest.bin;\n const commands = bin !== null && typeof bin === 'object' ? Object.keys(bin) : [];\n if (commands.length !== 1)\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"bin\" names ` +\n `${commands.length === 0 ? 'no command' : `${commands.length} commands`}. A product has ` +\n 'exactly one command \u2014 the one every session message tells a person to run.',\n );\n const displayName = declared.displayName;\n if (typeof displayName !== 'string' || displayName.trim() === '')\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"displayName\" is ` +\n `${JSON.stringify(displayName)}. It must be the name a person sees (e.g. \"Volter Editor\").`,\n );\n return {\n name: typeof manifest.name === 'string' ? manifest.name : packageDir,\n version: typeof manifest.version === 'string' ? manifest.version : 'unknown',\n command: commands[0]!,\n displayName,\n dir: packageDir,\n entry,\n colorTheme: colorTheme as ProductColorTheme,\n // A private source product may use an explicitly selected matching checkout.\n // Public packages must always carry a downloadable, checksummed workbench.\n workbench: manifest.private === true && declared.workbench === undefined\n ? null : readProductWorkbench(manifestPath, declared.workbench),\n };\n}\n\n/** The sha256 a release pins its tarball with, as `BUILD.json` writes it. */\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\n/**\n * REQUIRED, like `entry` and `colorTheme`, and for the sharpest reason of the\n * three: a product that does not say which workbench it is cannot be INSTALLED\n * \u2014 `npx @volter/<product> create <name>` on a machine with nothing else on it\n * has no other way to find the bytes it runs in, and the person is left writing\n * a path to a directory they would have to build first. There is no default to\n * invent (the tag names a fork commit nobody can guess), so an unstated one is\n * named rather than guessed.\n */\nfunction readProductWorkbench(manifestPath: string, declared: unknown): ProductWorkbench {\n const example =\n ' \"volter\": { \"product\": { \"workbench\": { \"release\": \"<product>-<fork sha 12>-<platform>\", ' +\n '\"tarballSha256\": \"<64 hex>\" } } }\\n' +\n '`node scripts/workbench/build-release.mjs --publish --out <release dir>` cuts the release ' +\n 'and prints exactly that block.';\n if (typeof declared !== 'object' || declared === null || Array.isArray(declared))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"workbench\" is ` +\n `${JSON.stringify(declared)}. A product IS the Code-OSS workbench it was compiled into, ` +\n `so it names the published release those bytes are:\\n${example}`,\n );\n const record = declared as Record<string, unknown>;\n const extra = Object.keys(record).filter((key) => key !== 'release' && key !== 'tarballSha256');\n if (extra.length > 0)\n throw new Error(\n `${manifestPath}'s ${PRODUCT_DECLARATION_KEY}.workbench carries ` +\n `${extra.map((key) => `\"${key}\"`).join(', ')}, which this declaration has no meaning for. ` +\n `It names the release and the pin, and nothing else:\\n${example}`,\n );\n const release = record['release'];\n if (typeof release !== 'string' || release.trim() === '')\n throw new Error(\n `${manifestPath}'s ${PRODUCT_DECLARATION_KEY}.workbench names no \"release\" \u2014 the GitHub ` +\n `Release tag its workbench was published under:\\n${example}`,\n );\n const tarballSha256 = record['tarballSha256'];\n if (typeof tarballSha256 !== 'string' || !SHA256_HEX.test(tarballSha256))\n throw new Error(\n `${manifestPath}'s ${PRODUCT_DECLARATION_KEY}.workbench has tarballSha256 ` +\n `${JSON.stringify(tarballSha256)}, which is not 64 hex characters. It is the PIN \u2014 the ` +\n 'hash the downloaded tarball is checked against before a byte of it is extracted, so it ' +\n `is never approximate:\\n${example}`,\n );\n return { release, tarballSha256 };\n}\n\n/**\n * A product's SHORT id \u2014 `@volter/model-editor` \u2192 `model-editor`.\n *\n * It is the product's own `product({ id })`, the directory its workbench half\n * lives in (`packages/<id>/workbench`), the `--product` flag the overlay and the\n * release build take, and what a release records in `BUILD.json`. One derivation\n * rather than four literals: the package name is the only place the product is\n * NAMED, and everything else is that name's last segment.\n */\nexport function workbenchProductId(packageName: string): string {\n return packageName.split('/').pop() ?? packageName;\n}\n\n/** A product's entry as a path relative to `fromDir`, POSIX \u2014 the spelling a\n * Vite manifest key and a dev-server URL both use. */\nexport function productEntryPath(product: ProductIdentity, fromDir: string): string {\n const absolute = join(product.dir, product.entry);\n const prefix = fromDir.endsWith('/') ? fromDir : `${fromDir}/`;\n const relative = absolute.startsWith(prefix) ? absolute.slice(prefix.length) : absolute;\n return relative.split('\\\\').join('/');\n}\n\n/** Every `@volter/*` this project declares, in either section, sorted. */\nfunction declaredVolterPackages(projectRoot: string): string[] {\n let manifest: { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n try {\n manifest = JSON.parse(\n readFileSync(join(projectRoot, 'package.json'), 'utf8'),\n ) as typeof manifest;\n } catch {\n return [];\n }\n return Object.keys({ ...(manifest.dependencies ?? {}), ...(manifest.devDependencies ?? {}) })\n .filter((name) => name.startsWith('@volter/'))\n .sort();\n}\n\n/** Where a package resolves FROM THE PROJECT, or null when it is not installed. */\nfunction locatePackage(projectRoot: string, name: string): string | null {\n const require = createRequire(pathToFileURL(join(projectRoot, 'package.json')));\n try {\n return dirname(require.resolve(`${name}/package.json`));\n } catch {\n // No `./package.json` export: walk up from whatever the bare name resolves\n // to, which is what a package with a strict export map leaves reachable.\n try {\n let dir = dirname(require.resolve(name));\n for (;;) {\n const candidate = join(dir, 'package.json');\n try {\n if ((JSON.parse(readFileSync(candidate, 'utf8')) as { name?: string }).name === name)\n return dir;\n } catch {\n /* keep walking */\n }\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n } catch {\n return null;\n }\n }\n}\n\n/**\n * THE PACKAGES A PRODUCT COMPOSES \u2014 the `volter:contributions/<name>` imports of the product's\n * entry (`package.json#volter.product.entry`), each resolved from the product's own install and\n * declaring `package.json#volter.contributions`.\n *\n * COMPOSITIONS ARE CODE (ARCHITECTURE-CORE \u00A7The target shape, rule 8): that import IS the\n * composition, so it is what is read. The product's `dependencies` are not: they also carry\n * the packages a game's capabilities add (`add music` declares `@volter/editor-dawproject`,\n * which the runtime image must hold), and reading every dependency that declares contributions\n * as composed made the page load a capability's documents into every game, and from a checkout\n * fetch them from a folder the game's server does not serve.\n */\nexport function productComposedPackages(product: ProductIdentity): string[] {\n let entry: string;\n try {\n const manifest = JSON.parse(readFileSync(join(product.dir, 'package.json'), 'utf8')) as {\n volter?: { product?: { entry?: unknown } };\n };\n const path = manifest.volter?.product?.entry;\n if (typeof path !== 'string') return [];\n entry = readFileSync(join(product.dir, path), 'utf8');\n } catch {\n return [];\n }\n const found: string[] = [];\n for (const [, name] of entry.matchAll(/\\bfrom\\s+['\"]volter:contributions\\/([^'\"]+)['\"]/g)) {\n if (!name || found.includes(name)) continue;\n const dir = locatePackage(product.dir, name);\n if (dir === null) continue;\n let dependency: { volter?: { contributions?: unknown } };\n try {\n dependency = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as typeof dependency;\n } catch {\n continue;\n }\n if (Array.isArray(dependency.volter?.contributions)) found.push(name);\n }\n return found;\n}\n\n/** The products this project declares AND resolves, in declaration order. */\nexport function declaredProducts(projectRoot: string): ProductIdentity[] {\n const found: ProductIdentity[] = [];\n for (const name of declaredVolterPackages(projectRoot)) {\n const dir = locatePackage(projectRoot, name);\n if (dir === null) continue;\n const product = readProductManifest(dir);\n if (product !== null) found.push(product);\n }\n return found;\n}\n\n/**\n * THE product this project opens in, or a throw naming what is wrong.\n *\n * The refusals are the whole point: a project with none and a project with two\n * are both states a person can be in, and neither has an answer this code may\n * invent.\n */\nexport function resolveProductForProject(projectRoot: string): ProductIdentity {\n const products = declaredProducts(projectRoot);\n if (products.length === 1) return products[0] as ProductIdentity;\n if (products.length === 0)\n throw new Error(\n `${projectRoot} declares no editor product, so there is no editor to open it in.\\n` +\n 'The installed product supplies the editor,\\n' +\n 'and which one runs is what the project installed, never a flag.\\n' +\n 'For THIS folder, install the one you are building with:\\n' +\n `${PRODUCT_INSTALL_LINES.join('\\n')}\\n` +\n \"then run that product's `edit` command again. For a NEW project, the product creates it:\\n\" +\n `${PRODUCT_CREATE_LINES.join('\\n')}`,\n );\n throw new Error(\n `${projectRoot} declares ${products.length} editor products \u2014 ` +\n `${products.map((product) => product.name).join(' and ')}.\\n` +\n 'One page runs one product, and nothing here may choose between them. Remove the one you\\n' +\n 'are not building with:\\n' +\n products.map((product) => ` npm uninstall ${product.name}`).join('\\n'),\n );\n}\n", "/**\n * `~/.volter/editor-sessions.json` \u2014 the ONE spelling of the editor-session\n * registry contract, and the shared machinery every reader was hand-copying.\n *\n * The registry's WRITE half stays with its owner\n * (`packages/editor-core/server/session-registry.ts`); this module owns the\n * FORMAT: the entry shape, the shape guards, the file path, the\n * liveness-filtered read, the `/__editor/project` answer parser, and the\n * pending-launch coordination. It existed as FOUR drifting copies\n * (server registry, the CLI, and both volter-sdk transports) held together by\n * a \"the CLI has no editor dependency\" premise that had stopped being true \u2014\n * and the drift was already real: one copy's `/__editor/project` parser\n * dropped `manifestError`, reporting a degraded session as belonging to no\n * project.\n */\n\nimport {\n mkdirSync,\n readdirSync,\n readFileSync,\n realpathSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { setTimeout as delay } from 'node:timers/promises';\n\n/** One registry entry, exactly as the server's write half records it. */\nexport interface EditorSessionEntry {\n /** Canonical project root currently open, or null when none. */\n project: string | null;\n port: number;\n /** PID of the dev-server process. */\n pid: number;\n /** ISO timestamp of server start. */\n startedAt: string;\n sessionId: string | null;\n /** Private loopback control credential \u2014 never returned by an editor HTTP\n * route; exists only in this user-private registry. */\n controlSecret?: string | null;\n repositoryId: string | null;\n worktreeId: string | null;\n worktreeRoot: string | null;\n projectRelativePath: string | null;\n branch: string | null;\n headCommit: string | null;\n baseCommit: string | null;\n}\n\nexport const EDITOR_SESSIONS_REGISTRY_FILE = join(homedir(), '.volter', 'editor-sessions.json');\n\nexport function isEditorSessionEntry(v: unknown): v is EditorSessionEntry {\n if (typeof v !== 'object' || v === null) return false;\n const s = v as Record<string, unknown>;\n const optionalIdentity = (value: unknown) =>\n value === undefined || value === null || typeof value === 'string';\n return (\n (typeof s['project'] === 'string' || s['project'] === null) &&\n typeof s['port'] === 'number' &&\n typeof s['pid'] === 'number' &&\n typeof s['startedAt'] === 'string' &&\n optionalIdentity(s['sessionId']) &&\n optionalIdentity(s['controlSecret']) &&\n optionalIdentity(s['repositoryId']) &&\n optionalIdentity(s['worktreeId']) &&\n optionalIdentity(s['worktreeRoot']) &&\n optionalIdentity(s['projectRelativePath']) &&\n optionalIdentity(s['branch']) &&\n optionalIdentity(s['headCommit']) &&\n optionalIdentity(s['baseCommit'])\n );\n}\n\nexport function normalizeEditorSessionEntry(session: EditorSessionEntry): EditorSessionEntry {\n return {\n ...session,\n sessionId: session.sessionId ?? null,\n controlSecret: session.controlSecret ?? null,\n repositoryId: session.repositoryId ?? null,\n worktreeId: session.worktreeId ?? null,\n worktreeRoot: session.worktreeRoot ?? null,\n projectRelativePath: session.projectRelativePath ?? null,\n branch: session.branch ?? null,\n headCommit: session.headCommit ?? null,\n baseCommit: session.baseCommit ?? null,\n };\n}\n\nexport function pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/** The registry's live entries \u2014 shape-validated and PID-liveness-filtered. */\nexport function readLiveRegisteredSessions(): EditorSessionEntry[] {\n try {\n const raw: unknown = JSON.parse(readFileSync(EDITOR_SESSIONS_REGISTRY_FILE, 'utf8'));\n return Array.isArray(raw)\n ? raw\n .filter(isEditorSessionEntry)\n .map(normalizeEditorSessionEntry)\n .filter((s) => pidAlive(s.pid))\n : [];\n } catch {\n return [];\n }\n}\n\n/** Announce a launch before the server can register. Each launcher owns its file. */\nexport function announceEditorLaunch(project: string): () => void {\n const directory = join(project, '.volter', 'editor-launches');\n mkdirSync(directory, { recursive: true });\n const file = join(directory, `${process.pid}.json`);\n writeFileSync(file, JSON.stringify({ pid: process.pid }));\n const clear = () => {\n process.removeListener('exit', clear);\n try {\n unlinkSync(file);\n } catch {\n // Already cleared when the server became ready.\n }\n };\n process.once('exit', clear);\n return clear;\n}\n\nfunction hasPendingEditorLaunch(project: string): boolean {\n const directory = join(project, '.volter', 'editor-launches');\n try {\n return readdirSync(directory).some((name) => {\n if (!/^\\d+\\.json$/.test(name)) return false;\n const pid = Number(name.slice(0, -5));\n return pid !== process.pid && pidAlive(pid);\n });\n } catch {\n return false;\n }\n}\n\n/** Wait only for an observed live launcher, never for a missing editor. */\nexport async function waitForPendingEditorLaunch(project: string): Promise<void> {\n const canon = canonicalizeProjectPath(project);\n const ready = () =>\n readLiveRegisteredSessions().some(\n (session) => session.project !== null && canonicalizeProjectPath(session.project) === canon,\n );\n if (ready() || !hasPendingEditorLaunch(canon)) return;\n const deadline = Date.now() + 180_000;\n while (!ready()) {\n if (!hasPendingEditorLaunch(canon)) {\n // The launcher clears its announcement only after registration.\n if (ready()) return;\n throw new Error(`The editor launch for ${canon} ended before registering a session.`);\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `The editor launch for ${canon} is still running but has not registered within 180s.`,\n );\n }\n await delay(100);\n }\n}\n\n/**\n * WHICH PROJECT a `/__editor/project` body says its server is serving.\n *\n * `serving` is that server's own statement of \"I AM serving this project, I\n * just cannot describe it\" (its manifest is unparseable or fails strict\n * validation) \u2014 added to the route precisely because a bare\n * `{ project: null }` is indistinguishable from \"no project open\". Reading\n * only `project.path` collapses the two, and the cost is that every\n * project-matched command loses a live session the moment a save breaks its\n * manifest, reporting it as belonging to no project rather than as this\n * project's degraded session.\n */\nexport function servedProjectAnswer(body: unknown): {\n path: string | null;\n manifestError: string | null;\n} {\n const b = body as {\n project?: { path?: string } | null;\n serving?: { path?: string; error?: string } | null;\n };\n return {\n path: b.project?.path ?? b.serving?.path ?? null,\n manifestError: b.project ? null : (b.serving?.error ?? null),\n };\n}\n\n/** Canonical (realpathed when possible) absolute form of a project path. */\nfunction canonicalizeProjectPath(p: string): string {\n const absolute = resolve(p);\n try {\n return realpathSync(absolute);\n } catch {\n return absolute;\n }\n}\n", "/** Registered-session discovery; never selects another project's session. */\nimport { readLiveRegisteredSessions, servedProjectAnswer } from './registry-format.js';\nexport { servedProjectAnswer } from './registry-format.js';\n\nexport const EDITOR_SESSION_DISCOVERY_TIMEOUT_MS = 2000;\n\nexport const EDITOR_PROBE_TIMEOUT_MS = 1500;\n\nexport class EditorTimeoutError extends Error {\n constructor(label: string, ms: number) {\n super(`${label} timed out after ${ms}ms`);\n this.name = 'EditorTimeoutError';\n }\n}\n\nexport function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {\n return new Promise<T>((resolvePromise, reject) => {\n const timer = setTimeout(() => reject(new EditorTimeoutError(label, ms)), ms);\n promise.then(\n (v) => {\n clearTimeout(timer);\n resolvePromise(v);\n },\n (err) => {\n clearTimeout(timer);\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\nexport interface EditorSessionInfo {\n /** The port this session's dev server is bound to. */\n port: number;\n /** Canonical project root path currently open, or null when none. */\n project: string | null;\n /** Dev-server process id, when known from the local session registry (null for an unregistered/legacy server the caller only probed by port). */\n pid: number | null;\n /** Exact explicitly targeted editor origin/base URL, including protocol and host. */\n url?: string;\n /**\n * Why this server cannot DESCRIBE the `project` it is serving \u2014 its\n * manifest's own parse/validation failure, naming the failing key. `null`\n * when the project reads fine, and `undefined` from a probe that did not ask\n * (or a server too old to say). See {@link servedProjectAnswer}: a session in\n * this state is still THIS project's session, and callers must report the\n * reason rather than treat it as no session at all.\n */\n manifestError?: string | null;\n}\n\nasync function fetchJson(url: string, timeoutMs: number): Promise<unknown | undefined> {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n if (!res.ok) return undefined;\n return await res.json();\n } catch {\n return undefined;\n }\n}\n\nfunction baseUrl(session: EditorSessionInfo): string {\n return session.url ?? `http://127.0.0.1:${session.port}`;\n}\n\nexport interface SessionListingTransport { listSessions(timeoutMs: number): Promise<EditorSessionInfo[]>; }\nexport class HttpSessionDiscovery implements SessionListingTransport {\n async listSessions(timeoutMs: number): Promise<EditorSessionInfo[]> {\n const registered = readLiveRegisteredSessions();\n const perProbeTimeout = Math.min(EDITOR_PROBE_TIMEOUT_MS, Math.max(200, timeoutMs));\n const probes = await Promise.all(\n registered.map(async (s) => {\n const body = await fetchJson(\n `${baseUrl({ port: s.port, project: null, pid: s.pid })}/__editor/project`,\n perProbeTimeout,\n );\n if (body === undefined) return undefined;\n const served = servedProjectAnswer(body);\n const info: EditorSessionInfo = {\n port: s.port,\n project: served.path,\n pid: s.pid,\n manifestError: served.manifestError,\n };\n return info;\n }),\n );\n return probes.filter((p): p is EditorSessionInfo => p !== undefined);\n }\n}\n", "/**\n * A tiny memoized-async-factory primitive \u2014 the machinery behind\n * `index.ts`'s lazy top-level `editor`/`tools` singletons. Pulled into\n * its own module (rather than inlined) so it's independently unit-testable\n * with a fake factory, with no need to exercise a real `connect()` (session\n * discovery, network) just to prove \"two accesses, one connect\".\n *\n * Caches the in-flight PROMISE, not just the resolved value \u2014 two callers\n * racing `ensure()` before the first resolves still share the SAME\n * connection attempt, not two independent ones.\n */\nexport interface LazySession<T> {\n /** Returns the memoized promise, creating it via `factory()` on first call. */\n ensure(): Promise<T>;\n /** Clears the memo \u2014 the NEXT `ensure()` calls `factory()` again. Exposed for tests (and for a caller that deliberately wants to reconnect); not needed in ordinary use. */\n reset(): void;\n}\n\nexport function createLazySession<T>(factory: () => Promise<T>): LazySession<T> {\n let promise: Promise<T> | null = null;\n return {\n ensure(): Promise<T> {\n promise ??= factory();\n return promise;\n },\n reset(): void {\n promise = null;\n },\n };\n}\n", "/** Attach to an existing editor session; this package never launches one. */\nimport { EditorClient } from '@volter/editor-sdk/client';\nimport { LiveEditor } from './editor.js';\nimport { LiveTools } from './tools.js';\nimport { lazyChainProxy } from './lazy-proxy.js';\nimport { resolveSession, type ResolvedSession, type SessionResolutionDeps } from './session.js';\nimport { createLazySession } from './singleton.js';\n\nexport { LiveEditor, inferAssetKind, type PanelName } from './editor.js';\nexport { LiveEditorDocument } from './editor-document.js';\nexport type { DocumentGestureOptions, DocumentKeyOptions, DocumentPasteOptions } from './editor-document.js';\nexport { LiveTools } from './tools.js';\nexport { resolveSession, findProjectRootFrom } from './session.js';\nexport type { ResolvedSession, SessionResolutionDeps, SessionListingTransport, ProjectSessionHint } from './session.js';\nexport type { ActiveDocumentCapture, EditorView, PresentedEditorView } from '@volter/editor-sdk';\n\nexport interface LiveBindings {\n editor: LiveEditor;\n tools: LiveTools;\n}\nexport interface LiveSession extends LiveBindings {\n session: ResolvedSession;\n}\nfunction bindTo(port: number): LiveBindings {\n const client = new EditorClient({ url: `http://127.0.0.1:${port}` });\n return { editor: new LiveEditor(client), tools: new LiveTools(client) };\n}\n/** Inspect the callable surface without connecting; calls fail on port zero. */\nexport function unconnectedBindings(): LiveBindings { return bindTo(0); }\n\n/** Attach only to the session serving the requested project's canonical path. */\nexport async function connect(projectDir?: string, deps?: SessionResolutionDeps): Promise<LiveSession> {\n const session = await resolveSession(projectDir, deps);\n return { ...bindTo(session.port), session };\n}\nconst lazySession = createLazySession(() => connect());\nexport const editor: LiveEditor = lazyChainProxy<LiveEditor>(() => lazySession.ensure().then(s => s.editor));\nexport const tools: LiveTools = lazyChainProxy<LiveTools>(() => lazySession.ensure().then(s => s.tools));\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/** Node session clients need explicit header deadlines for long modeling calls.\n * Some runtimes supply an undici-compatible Agent without destroy(); callers\n * close explicitly when that lifecycle method exists. */\nimport { Agent, fetch as nodeFetch, type Dispatcher } from 'undici';\n\nexport function createDispatcher(timeoutMs: number): Dispatcher {\n return new Agent({ headersTimeout: timeoutMs, bodyTimeout: timeoutMs });\n}\n\nexport async function dispatchFetch(\n url: string,\n init?: RequestInit,\n dispatcher?: Dispatcher,\n): Promise<Response> {\n if (!dispatcher) return fetch(url, init);\n return await nodeFetch(url, {\n ...(init as object), dispatcher,\n }) as unknown as Response;\n}\n", "import type { GenerationJobsDocument } from '@volter/editor-sdk/generations';\nimport type { Dispatcher } from 'undici';\nimport { createDispatcher, dispatchFetch } from '#http-transport';\nimport type { DocumentProbeResult, DocumentProbeStep } from './document-probe.js';\nimport type {\n ActiveDocumentCapture,\n AssetCompareCapture,\n AssetCompareOptions,\n AssetKind,\n AssetPreviewCapture,\n AssetPreviewOptions,\n AssetPreviewShotSetDefinition,\n AssetPreviewSource,\n CaptureDimensions,\n DocumentCameraPose,\n DocumentLookOutcome,\n StageFrameCostReading,\n DocumentTableProjection,\n EditorChromeCapture,\n EditorChromeCaptureOptions,\n EditorState,\n EditorView,\n EditorWorkspaceName,\n GameCapture,\n GameplayRecordingCapture,\n GameplayRecordingOptions,\n GameplayRecordingStarted,\n GameplayRecordingTimeline,\n GameplayReplayCapture,\n HelperVisibility,\n InspectedFieldWrite,\n InspectedHierarchy,\n InspectedInspection,\n LabeledShotSetCapture,\n PlayStarted,\n PresentedEditorView,\n ProjectInfo,\n ProjectTemplate,\n ProjectToolCatalog,\n ProjectToolOutcome,\n RecentProject,\n ShadingMode,\n StoryCaptureOptions,\n StoryVariantCapture,\n StructureOp,\n StructureOpOptions,\n StructureOpResult,\n TransformMode,\n TransformSpace,\n Vec3Value,\n ViewPreset,\n ViewportCapture,\n ViewportTab,\n} from './types.js';\n\n// The editor's default origin, spelled out because this package deliberately\n// does not depend on `@volter/editor-project`. `DEFAULT_EDITOR_PORT` in\n// `packages/editor-project/src/manifest/editor-port.ts` is the owner of the number and\n// of the never-`localhost` rule; keep this in step with it.\nconst DEFAULT_URL = 'http://127.0.0.1:20173';\n\n/**\n * A refused editor command, carrying the relay's own STRUCTURED failure code\n * alongside the prose.\n *\n * `/__editor/command` has always answered `{ ok: false, error, code }` and\n * this client has always dropped the `code` on the floor, so every caller that\n * wanted to react to a specific refusal had to substring-match an English\n * sentence. the editor's `screenshot` command's loop-recovery fallback is the first caller that\n * genuinely must branch (`BRIDGE_SCREENSHOT_STALE` has a working recovery;\n * \"not in play mode\" does not), and a fallback keyed on prose would fire on\n * the wrong failure the first time someone rewords the message.\n */\nexport class EditorCommandError extends Error {\n readonly code: string | undefined;\n /**\n * True when the RELAY ended the command itself rather than the editor\n * answering it \u2014 the HTTP 504 that `server/server-utils.ts`'s\n * `commandResponseFor` gives any `timedOut` result, or this client's own\n * deadline below.\n *\n * Read it as \"no answer\", not as \"the budget expired\". `editor-server.ts`\n * raises `timedOut` for five conditions and only one of them takes the full\n * budget: the command's timer expiring, the controlling tab's socket dying,\n * the receipt window closing unanswered, a beating-but-dead tab, and no tab\n * present at all. The last four can fail in milliseconds.\n *\n * A caller that converges by retrying (the editor's `restart` command) needs the distinction\n * because a refusal the editor ANSWERED may go differently next time, while\n * a command the relay abandoned tells you nothing new on a second identical\n * attempt \u2014 and when the abandonment was a 120s budget, re-running it three\n * times is `restart-readiness.ts`'s 361-seconds-of-silence defect.\n */\n readonly timedOut: boolean;\n constructor(message: string, code?: string | undefined, timedOut = false) {\n super(message);\n this.name = 'EditorCommandError';\n this.code = code;\n this.timedOut = timedOut;\n }\n}\n\n/**\n * The client's own ceiling on ONE relayed command.\n *\n * A backstop for a LOST server, not a per-command budget: the server already\n * owns per-type budgets (`server/server-utils.ts`'s `relayCommandTimeoutMs`)\n * and its timer must always be the one that fires, because its message names\n * the tab and the remedy while this one can only say \"no answer\". So this is\n * deliberately ONE number, comfortably above the longest server budget\n * (120s, `play`/`capture-story-variants`) rather than a mirror of that table \u2014\n * a second copy of it would drift silently, and the drift would show up as\n * this timer winning a race it must always lose.\n *\n * Without it a `fetch` with no `AbortSignal` waits on the OS: a dev server\n * that stops answering mid-command holds the CLI open indefinitely, with no\n * output and nothing to read.\n */\nconst COMMAND_DEADLINE_MS = 150_000;\n/** The Blender lane's own ceiling: a chunk is a whole modeling step, not a tick. */\nconst BLENDER_DEADLINE_MS = 30 * 60_000;\n/** undici's default `headersTimeout`; a command deadline beyond it needs its own dispatcher (see `command`). */\nconst UNDICI_DEFAULT_HEADERS_TIMEOUT_MS = 300_000;\n\n/**\n * Ceiling on {@link EditorClient.getUnresolvedConsole}. The CLI drains this\n * on every verb, including ones that never wait for a command envelope, so\n * a silent hang here would become a silent hang on the editor's `sessions` command. The\n * server route is a plain in-process GET; 1.5s is already longer than it\n * should ever take.\n */\nconst CONSOLE_DRAIN_TIMEOUT_MS = 1_500;\n\n/**\n * Node's `fetch` collapses EVERY network-layer failure into one two-word\n * `TypeError: fetch failed`. The real reason \u2014 `ECONNREFUSED`, `ECONNRESET`,\n * `EPIPE`, a DNS miss \u2014 lives only on `error.cause` (sometimes two links down,\n * or inside an `AggregateError`), and nothing prints it unless something walks\n * the chain. That is the whole reason `project.bake.preview` was observed\n * failing with a bare \"fetch failed\" and no way to tell a dead editor from a\n * momentary one (WORK.md, cold barrel 2026-08-29): the code below used to\n * rethrow the `TypeError` untouched, on the belief \u2014 stated in a comment right\n * where it happened \u2014 that \"a connection refused / DNS failure still surfaces\n * as itself\". It does not. This walks the chain so the message can say which.\n */\nfunction describeFetchFailure(error: unknown): { code: string; detail: string } {\n const messages: string[] = [];\n let current: unknown = error;\n for (let depth = 0; depth < 8; depth++) {\n if (!(current instanceof Error)) break;\n if (current.message) messages.push(current.message);\n const code = (current as { code?: unknown }).code;\n if (typeof code === 'string' && code !== '') {\n return { code, detail: messages.join(' <- ') };\n }\n const aggregate = (current as { errors?: unknown }).errors;\n if (Array.isArray(aggregate) && aggregate.length > 0) {\n const inner = describeFetchFailure(aggregate[0]);\n return { code: inner.code, detail: [...messages, inner.detail].join(' <- ') };\n }\n current = (current as { cause?: unknown }).cause;\n }\n return { code: 'UNKNOWN', detail: messages.join(' <- ') || String(error) };\n}\n\n/**\n * Transport failures where a second attempt is worth making: the connection\n * itself failed or died, rather than the editor answering something unwelcome.\n * A dev server that is restarting (any watched source edit restarts it) is\n * unreachable for a fraction of a second and reachable again after \u2014 which is\n * exactly the \"fails, then succeeds unchanged\" shape that was reported.\n */\nconst RETRYABLE_TRANSPORT_CODES = new Set([\n 'ECONNREFUSED',\n 'ECONNRESET',\n 'EPIPE',\n 'ETIMEDOUT',\n 'EHOSTUNREACH',\n 'UND_ERR_SOCKET',\n 'UND_ERR_CONNECT_TIMEOUT',\n]);\n\n/** Gap before the one automatic retry \u2014 long enough for a dev-server restart's\n * listen socket to come back, short enough to stay invisible. */\nconst TRANSPORT_RETRY_DELAY_MS = 400;\n\n/** Context accompanying one {@link EditorClient} response observation. */\nexport interface EditorEnvelopeObservation {\n /** True only when this body came from the console-ledger endpoint and its\n * `entries` field is therefore the complete named console set. Command\n * payloads may also own an unrelated `entries` field. */\n readonly unresolvedConsoleComplete: boolean;\n}\n\n/**\n * The GAME DEBUG PLANE, as a contribution's client sees it.\n *\n * Deliberately the same two words `@volter/editor-live`'s session binding uses\n * (`game.state(name)` / `game.command(name, ...args)`), because it is the same\n * plane: whatever the running game registered through `ctx.debug` \u2014 a provider\n * read by name, a command invoked by name. A tool contribution that wants the\n * game's own vitals in its panel has this door and no other; there is\n * deliberately no per-capability method, because a game names its own\n * providers and commands.\n *\n * Both legs reject LOUDLY (`EditorCommandError`) rather than answer with a\n * placeholder: play not running is `'not in play mode \u2014 start play before\n * using the debug seam'`, and an unregistered command carries\n * `code: 'DEBUG_COMMAND_NOT_REGISTERED'`. A panel decides what to show for\n * those; the client never invents one.\n */\n/** What one undo/redo step reports back \u2014 `moved` is false when there was\n * nothing left in that direction, which is an answer, not an error. */\nexport interface HistoryStep {\n readonly moved: boolean;\n readonly canUndo: boolean;\n readonly canRedo: boolean;\n readonly undoLabel: string | null;\n readonly redoLabel: string | null;\n}\n\n/** What `open()` acknowledges: the workspace document the scene-table entry\n * resolved to, and the title its tab now carries \u2014 the game's own word for\n * that composition, not a filename. */\nexport interface OpenedDocument {\n readonly documentId: string;\n readonly title: string;\n /**\n * The GAME's own answer, present only when opening navigated a running game\n * (a scene the adapter declares reachable through the game's scenes\n * contract, or a native swap-slot remount): what was asked for, and which\n * scene the game reports it is in once its own navigation settled. `current`\n * can differ from `requested` \u2014 that is the game's reading, not a host claim.\n */\n readonly scene?: { readonly requested: string; readonly current: string | null };\n /**\n * Present when opening restarted play at a native swap-slot key rather than\n * navigating a live contract \u2014 the slot is a module-level const.\n */\n readonly restart?: true;\n}\n\nexport interface GameDebugDoor {\n /**\n * Read ONE registered state provider by name (`'bot.tester'`). `undefined`\n * when the running game registered no such provider \u2014 or no debug adapter at\n * all, which is an honest answer rather than a refusal.\n */\n state(name: string): Promise<unknown>;\n /** Invoke ONE registered debug command by name, with its own arguments. */\n command(name: string, ...args: unknown[]): Promise<unknown>;\n}\n\nexport class EditorClient {\n private readonly baseUrl: string;\n private readonly fetchOverride: typeof fetch | undefined;\n\n /**\n * The running game's debug plane \u2014 see {@link GameDebugDoor}. It rides the\n * SAME `/__editor/command` relay every other method here uses (relay cases\n * `inspect-gameplay-state` / `invoke-debug-command`, `command-listener.ts`),\n * so a tool contribution reaches the game through the client it already has\n * rather than a second channel of its own.\n */\n readonly game: GameDebugDoor;\n\n /**\n * Called with the raw body of EVERY response this client receives \u2014 command\n * envelopes and `/__editor/state` alike, on success AND on refusal.\n *\n * It exists for exactly one contract: the server stamps `unresolvedConsole`\n * onto every envelope (`server-utils.ts`'s `commandResponseFor`), and the CLI\n * has to see those counts to be loud about them. Routing that through a\n * single observer here \u2014 rather than teaching each of the CLI's output sites\n * to unpack a response \u2014 is what keeps the loudness contract ONE mechanism.\n * The observer must not throw; anything it raises is swallowed, because a\n * reporting hook may never break the command it is reporting on.\n */\n private readonly transport:\n | ((body: Record<string, unknown>) => Promise<Record<string, unknown>>)\n | null;\n private readonly onEnvelope:\n | ((body: unknown, observation: EditorEnvelopeObservation) => void)\n | null;\n\n constructor(opts?: {\n url?: string;\n /** An authenticated transport for the same HTTP routes (e.g. a hosted tab). */\n fetch?: typeof fetch;\n onEnvelope?: (body: unknown, observation: EditorEnvelopeObservation) => void;\n /**\n * An IN-PAGE command channel, for a client that lives inside the editor\n * page itself and has no editor server to reach. Given, every command goes through it instead of\n * `POST /__editor/command`, and answers in the route's own body shape\n * (`{ ok: true, ...data }` / `{ ok: false, error, code? }`).\n */\n transport?: (body: Record<string, unknown>) => Promise<Record<string, unknown>>;\n }) {\n if (opts !== undefined && (typeof opts !== 'object' || opts === null || Array.isArray(opts))) {\n throw new TypeError(\n 'EditorClient options must be an object. Use new EditorClient({ url: \"http://127.0.0.1:20173\" }), not new EditorClient(\"...\").',\n );\n }\n const unknownOptions = Object.keys(opts ?? {}).filter(\n (key) => key !== 'url' && key !== 'onEnvelope' && key !== 'transport' && key !== 'fetch',\n );\n if (unknownOptions.length > 0) {\n throw new Error(\n `EditorClient: unknown option${unknownOptions.length === 1 ? '' : 's'} ${unknownOptions.map((key) => `\"${key}\"`).join(', ')}. Use { url: \"http://127.0.0.1:<port>\" } to target an editor.`,\n );\n }\n this.baseUrl = (opts?.url ?? DEFAULT_URL).replace(/\\/$/, '');\n this.fetchOverride = opts?.fetch;\n this.onEnvelope = opts?.onEnvelope ?? null;\n this.transport = opts?.transport ?? null;\n this.game = {\n state: async (name: string): Promise<unknown> => {\n // `keys` narrows the relay to the one provider asked for, so a panel\n // polling one vital never drags the whole plane's `stateAll()` across\n // the wire. A game with no debug adapter answers `{ state: null }`.\n const data = await this.command<{ state: Record<string, unknown> | null }>({\n type: 'inspect-gameplay-state',\n keys: [name],\n });\n return data.state?.[name];\n },\n command: async (name: string, ...args: unknown[]): Promise<unknown> =>\n (await this.command<{ result: unknown }>({ type: 'invoke-debug-command', name, args }))\n .result,\n };\n }\n\n /**\n * `retryTransport` opts a command into ONE automatic retry after a transport\n * failure (see {@link RETRYABLE_TRANSPORT_CODES}). It is deliberately\n * OPT-IN and off by default: a socket that died after the request was written\n * cannot prove the editor did not already run the command, so a blanket retry\n * would risk playing/stopping/writing twice. Read-only relays \u2014 the captures \u2014\n * have no such hazard and turn it on.\n */\n private async command<T extends object = Record<string, never>>(\n body: Record<string, unknown>,\n options?: { retryTransport?: boolean; deadlineMs?: number },\n ): Promise<T> {\n const type = String(body['type'] ?? 'command');\n const deadlineMs = options?.deadlineMs ?? COMMAND_DEADLINE_MS;\n if (this.transport) {\n const answered = (await this.transport(body)) as {\n ok: boolean;\n error?: string;\n code?: string;\n } & T;\n if (!answered.ok) {\n throw new EditorCommandError(\n answered.error ?? `Editor command \"${type}\" failed`,\n answered.code,\n );\n }\n return answered;\n }\n const url = `${this.baseUrl}/__editor/command`;\n const request = JSON.stringify(body);\n let res: Response | undefined;\n let retried = false;\n let commandDispatcher: Dispatcher | undefined;\n for (;;) {\n try {\n const init: RequestInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: request,\n signal: AbortSignal.timeout(deadlineMs),\n };\n // The command route answers only when the command completes, and\n // Node's fetch (undici) gives a server 300 s to send response HEADERS\n // regardless of the abort signal: a modeling step measured at eleven\n // minutes in the tab died as UND_ERR_HEADERS_TIMEOUT well inside its\n // half-hour budget. A deadline past that default carries its own\n // dispatcher, through undici's own fetch so the two agree.\n commandDispatcher = deadlineMs > UNDICI_DEFAULT_HEADERS_TIMEOUT_MS\n ? createDispatcher(deadlineMs + 30_000)\n : undefined;\n res = this.fetchOverride ? await this.fetchOverride(url, init) : await dispatchFetch(url, init, commandDispatcher);\n break;\n } catch (error) {\n await commandDispatcher?.destroy?.();\n commandDispatcher = undefined;\n // Only the deadline is reshaped into a \"no answer\" verdict; everything\n // else is a TRANSPORT failure, and Node hides its reason behind a bare\n // `fetch failed` (see `describeFetchFailure`).\n if ((error as { name?: string } | null)?.name === 'TimeoutError') {\n throw new EditorCommandError(\n `The editor at ${this.baseUrl} never answered \"${type}\" ` +\n `within ${Math.round(deadlineMs / 1000)}s \u2014 past every server-side budget, so ` +\n 'the server itself is not answering. Check the terminal that started this editor session.',\n undefined,\n true,\n );\n }\n const { code, detail } = describeFetchFailure(error);\n if (options?.retryTransport === true && !retried && RETRYABLE_TRANSPORT_CODES.has(code)) {\n retried = true;\n await new Promise((resolve) => setTimeout(resolve, TRANSPORT_RETRY_DELAY_MS));\n continue;\n }\n throw new EditorCommandError(\n `POST ${url} (\"${type}\") never reached the editor: ${code}${detail ? ` (${detail})` : ''}.` +\n (retried\n ? ` Retried once after ${TRANSPORT_RETRY_DELAY_MS}ms; it failed the same way.`\n : '') +\n (options?.retryTransport === true\n ? ''\n : ' Not retried automatically: this command can change editor state, and a socket that' +\n ' died after the request was written cannot prove the editor did not already run it.') +\n ' A transport failure means the port stopped answering, not that the editor refused \u2014' +\n ' the dev server restarts on any watched source edit, and it shuts itself down after an' +\n ' idle window. Check the terminal that started this editor session and confirm the port' +\n ' this client resolved.',\n code,\n false,\n );\n }\n }\n let data: { ok: boolean; error?: string; code?: string } & T;\n try {\n data = (await this.readJson(res)) as typeof data;\n } finally {\n await commandDispatcher?.destroy?.();\n }\n if (!data.ok) {\n throw new EditorCommandError(\n data.error ?? `Editor command failed: ${res.status}`,\n data.code,\n // 504 is every `timedOut` result (`commandResponseFor`) \u2014 the relay\n // gave up, on any of its five grounds. A 200 body with `ok: false` is\n // an ANSWER from the editor, however unwelcome. See `timedOut` above.\n res.status === 504,\n );\n }\n return data;\n }\n\n // --- Play control ---\n\n /** `opts.seed` (D15/T-D15.6, objection-4 fix) \u2014 the editor's `play --seed <n>` command's\n * explicit config leg, relayed as `cmd['seed']`; `handleCommand`'s\n * `'play'` case threads it into `enterPlayMode`'s highest-precedence seed\n * argument (beats manifest.determinism.defaultSeed/?volter-seed=). Omitted,\n * boot seeding falls back to that precedence unchanged.\n *\n * `opts.name` (the editor's `play --name <text>` command) \u2014 an OPTIONAL label for this run,\n * relayed as `cmd['name']` and slugified server-side into the run's\n * `logs/play-*.jsonl` filename and its session-journal line. Findability\n * only: no registry, no uniqueness, no lookup verb \u2014 grep and `ls` are the\n * query engine. Omitted, the filename keeps its exact unnamed shape. */\n /* `opts.record` (the editor's `play --record <name>` command) \u2014 NAMES this run's recording\n * file. It does not ENABLE recording: every relayed play records, with no\n * flag (see `@volter/editor-game`'s `src/play/play-recording.ts`). Omitted, the clip is named for\n * the durable Gameplay Session; named, it becomes an explicit keepsake in\n * `.volter/recordings/<name>.webm`. */\n async play(opts?: {\n seed?: number;\n name?: string | null;\n record?: string | null;\n }): Promise<PlayStarted> {\n return this.command<PlayStarted>({\n type: 'play',\n ...(opts?.seed !== undefined ? { seed: opts.seed } : {}),\n ...(opts?.name ? { name: opts.name } : {}),\n ...(opts?.record ? { record: opts.record } : {}),\n });\n }\n\n /** Dispose the current play session and mount it again from fresh project entry source. */\n async restart(): Promise<void> {\n await this.command({ type: 'play' });\n }\n\n /** Refuse shutdown if a document cannot be saved. Does not stop the server. */\n async prepareClose(): Promise<void> {\n await this.command({ type: 'session-prepare-close' });\n }\n\n /** Stops play, and finalizes this run's recording before the surface it was\n * photographing is torn down. The capture is absent when nothing recorded. */\n async stop(): Promise<{ recording?: GameplayRecordingCapture }> {\n return this.command<{ recording?: GameplayRecordingCapture }>({ type: 'stop' });\n }\n\n async pause(): Promise<void> {\n await this.command({ type: 'pause' });\n }\n\n async resume(): Promise<void> {\n await this.command({ type: 'resume' });\n }\n\n async step(): Promise<void> {\n await this.command({ type: 'step' });\n }\n\n // --- Selection ---\n\n async select(id: string | null): Promise<void> {\n await this.command({ type: 'select', id });\n }\n\n async selectMultiple(ids: string[]): Promise<void> {\n await this.command({ type: 'select-multiple', ids });\n }\n\n async selectAll(): Promise<void> {\n await this.command({ type: 'select-all' });\n }\n\n // --- Viewport ---\n\n async focusEntity(id: string): Promise<void> {\n await this.command({ type: 'focus-entity', id });\n }\n\n async focusSelection(): Promise<void> {\n await this.command({ type: 'focus-selection' });\n }\n\n /**\n * Frame the EDIT viewport camera on one entity \u2014 the strict sibling of\n * {@link focusEntity}. Same framing; an id the scene does not know is a\n * refusal naming the id (`EditorCommandError`, code `ENTITY_NOT_FOUND`)\n * rather than `focusEntity`'s silent no-op, so a caller that frames an\n * entity before capturing it cannot photograph the wrong thing.\n */\n async frameEntity(id: string): Promise<void> {\n await this.command({ type: 'frame-entity', id });\n }\n\n async viewPreset(preset: ViewPreset): Promise<void> {\n await this.command({ type: 'view-preset', preset });\n }\n\n /**\n * LOOK AROUND THE OPEN MODEL, visibly. Swings the active Object3D\n * document's camera \u2014 the one on the human's screen \u2014 by `azimuth`/\n * `elevation` radians, animated over `duration` seconds, and resolves when\n * the move ends. A human drag during the move cancels it where it stands\n * (`cancelledBy: 'human'`); the promise still resolves.\n */\n async orbitDocument(options: {\n azimuth?: number;\n elevation?: number;\n duration?: number;\n }): Promise<DocumentLookOutcome> {\n return this.command<DocumentLookOutcome>({ type: 'document-orbit', ...options });\n }\n\n /** What a frame of a 3D document's stage costs, uncapped (`document-frame-cost`). */\n async frameCostDocument(options?: { readonly frames?: number; readonly stage?: string }): Promise<StageFrameCostReading> {\n return this.command<StageFrameCostReading>({ type: 'document-frame-cost', ...options });\n }\n\n /** A slow full revolution around the open document's subject, at a constant rate. */\n async turntableDocument(options?: {\n seconds?: number;\n revolutions?: number;\n }): Promise<DocumentLookOutcome> {\n return this.command<DocumentLookOutcome>({ type: 'document-turntable', ...options });\n }\n\n /**\n * Frame the open document's subject (its selection if it has one). `fit`\n * scales the fitted distance: 1 is the toolbar Frame button's tight fit.\n */\n async frameDocument(fit?: number): Promise<DocumentCameraPose> {\n return this.command<DocumentCameraPose>({\n type: 'document-frame',\n ...(fit === undefined ? {} : { fit }),\n });\n }\n\n async setCamera(position: Vec3Value, target: Vec3Value, fov?: number): Promise<void> {\n await this.command({\n type: 'set-camera',\n position,\n target,\n ...(fov === undefined ? {} : { fov }),\n });\n }\n\n async captureViewport(size?: number): Promise<ViewportCapture> {\n const data = await this.command<ViewportCapture>({\n type: 'capture-viewport',\n ...(size === undefined ? {} : { size }),\n });\n return { base64: data.base64, mimeType: data.mimeType };\n }\n\n /**\n * Unit 4 (live-front-door wave) \u2014 capture the RUNNING GAME (the editor's\n * `screenshot`'s wire leg). Sends the SAME `bridge-screenshot` relay op\n * `@volter/game-live`'s `RelayTransport.screenshot` (and therefore\n * `game.screenshot()` on the relay path) already sends, so all three\n * surfaces composite the identical full game stack \u2014 canvas(es) plus the\n * HUD/react DOM layers \u2014 rather than any of them inventing a second,\n * subtly-different capture path. Contrast {@link captureViewport}, which\n * captures the EDITOR viewport's canvas and would silently hand back an\n * editor-only (HUD-less, possibly not-even-playing) image.\n *\n * Rejects \u2014 loudly, via `command`'s own `{ok:false}` unwrap \u2014 when play\n * mode isn't running (\"not in play mode \u2014 start play before using the\n * debug seam\") or no game canvas is mounted yet. Never returns a blank or\n * editor-only frame as a stand-in.\n *\n * `opts.refreshStarvedFrame` is the loop-starvation leg: without recent rAF\n * progress the canvas holds a provably stale frame and the relay\n * refuses it with `BRIDGE_SCREENSHOT_STALE` rather than pass it off as\n * current. Setting this asks the relay to render exactly ONE deterministic\n * tick (`runTicks(1, {render:'last'})`) first \u2014 the same escape\n * `@volter/game-live`'s `RelayTransport.screenshot` has always used, which is why\n * the editor's `eval` command could recover these frames while the editor's `screenshot` command could not.\n * Off by default: a caller who does not ask must never be handed a frame\n * that only exists because the capture drove the game.\n */\n async captureGame(opts?: { refreshStarvedFrame?: boolean }): Promise<GameCapture> {\n const data = await this.command<GameCapture>({\n type: 'bridge-screenshot',\n ...(opts?.refreshStarvedFrame === true ? { refreshStarvedFrame: true } : {}),\n });\n const layers = data.layers;\n const flatness = data.flatness;\n return {\n base64: data.base64,\n mimeType: data.mimeType,\n composite: data.composite === true,\n ...(layers && Number.isInteger(layers.canvases) && Number.isInteger(layers.domOverlays)\n ? { layers }\n : {}),\n // Pass the pixel-honesty fields through as the page reported them: the\n // warning sentence is written where the pixels are, so nothing here\n // re-derives (or softens) it.\n ...(flatness && typeof flatness.dominantFraction === 'number' ? { flatness } : {}),\n ...(data.loopRecoveryFrame === true ? { loopRecoveryFrame: true } : {}),\n // Same pass-through rule: the recorded-run notice is written where the\n // pixels are, so nothing here re-derives or softens it.\n ...(data.recording && typeof data.recording.notice === 'string'\n ? { recording: data.recording }\n : {}),\n };\n }\n\n /** Start recording the same clean running-game composite `captureGame`\n * photographs. Recording state lives in the editor page, so another process\n * may stop it later through the same project session. */\n async startGameplayRecording(\n options: GameplayRecordingOptions = {},\n ): Promise<GameplayRecordingStarted> {\n return this.command<GameplayRecordingStarted>({\n type: 'bridge-recording-start',\n ...(options.fps !== undefined ? { fps: options.fps } : {}),\n ...(options.name !== undefined ? { name: options.name } : {}),\n ...(options.format !== undefined ? { format: options.format } : {}),\n });\n }\n\n /** Export a paused run as fixed-step video. Advances game state; maximum\n * five minutes. `audio` describes the muxed track, or is `false` when the\n * world implements no `AudioAdapter.renderOffline` and the file is\n * genuinely silent \u2014 read it, never assume either. */\n async exportGameplayVideo(options: { frames: number; fps?: number; name?: string }): Promise<{\n path: string;\n frames: number;\n fps: number;\n durationMs: number;\n wallMs: number;\n width: number;\n height: number;\n audio:\n | false\n | {\n codec: 'opus';\n sampleRate: number;\n channels: number;\n durationSeconds: number;\n rms: number;\n peak: number;\n };\n }> {\n return this.command(\n { type: 'bridge-recording-export', ...options },\n { deadlineMs: 610_000, retryTransport: false },\n );\n }\n\n /** Stop the page-owned recorder and return its WebM path and metadata. */\n async stopGameplayRecording(): Promise<GameplayRecordingCapture> {\n return this.command<GameplayRecordingCapture>({ type: 'bridge-recording-stop' });\n }\n\n /** Read the active capture's monotonic media position. This is the only clock\n * suitable for selecting intervals inside the finalized recording. */\n async getGameplayRecordingTimeline(): Promise<GameplayRecordingTimeline> {\n const timeline = await this.command<GameplayRecordingTimeline>({\n type: 'bridge-recording-timeline',\n });\n return { startedAt: timeline.startedAt, elapsedMs: timeline.elapsedMs };\n }\n\n /** Encode a recorded canvas/DOM interval into a normal composite WebM. */\n async exportGameplayReplay(options: {\n replayPath: string;\n fps?: number;\n startMs?: number;\n endMs?: number;\n name?: string;\n }): Promise<{\n path: string;\n frames: number;\n fps: number;\n durationMs: number;\n width: number;\n height: number;\n audio: boolean;\n }> {\n return this.command(\n { type: 'bridge-recording-replay-export', ...options },\n { deadlineMs: 610_000, retryTransport: false },\n );\n }\n\n async captureGameplayReplay(\n replayPath: string,\n positionMs: number,\n ): Promise<GameplayReplayCapture> {\n return this.command<GameplayReplayCapture>({\n type: 'bridge-recording-replay-capture',\n replayPath,\n positionMs,\n });\n }\n\n /**\n * Capture an isolated, deterministic four-view preview through the editor's\n * native Asset Lab. The SDK delegates rendering to the editor; it never\n * loads, clones, or interprets Three.js assets itself.\n */\n async captureAssetPreview(\n source: AssetPreviewSource,\n options: AssetPreviewOptions = {},\n ): Promise<AssetPreviewCapture> {\n const data = await this.command<AssetPreviewCapture>(\n {\n type: 'capture-asset-preview',\n ...source,\n ...options,\n },\n // Photographing changes nothing, and this is the relay the editor's `screenshot\n // <module>` command and `project.bake.preview` ride \u2014 the lane where a momentary\n // transport failure cost a cold agent three probe modules.\n { retryTransport: true },\n );\n return {\n width: data.width,\n height: data.height,\n // Absent from editors that predate orientation reporting.\n ...(data.orientation ? { orientation: data.orientation } : {}),\n views: data.views,\n contactSheet: data.contactSheet,\n };\n }\n\n /**\n * A project-defined labeled shot set (the editor's `screenshot <target> --shots <set>` command):\n * the DEFINITION travels with the command (project data \u2014 see\n * `AssetPreviewShotSetDefinition`; the CLI resolves it from the registered\n * `project.<set>.previewShots` tool), and the editor's generic\n * capture engine renders it \u2014 see `packages/editor-threejs/src/kit/asset-preview.ts`'s\n * `captureShotSetAssetPreview`. Throws (via `command`'s `{ok:false}`\n * unwrap) with a clear message naming the missing joint(s) when the asset\n * lacks a bone the definition requires.\n */\n async captureShotSetPreview(\n source: AssetPreviewSource,\n definition: AssetPreviewShotSetDefinition,\n options: AssetPreviewOptions = {},\n ): Promise<LabeledShotSetCapture> {\n const data = await this.command<LabeledShotSetCapture>(\n {\n type: 'capture-asset-preview',\n ...source,\n ...options,\n shotSet: definition,\n },\n { retryTransport: true },\n );\n return {\n width: data.width,\n height: data.height,\n shots: data.shots,\n // An older editor predates the empty-frame guard and sends none.\n warnings: data.warnings ?? [],\n contactSheet: data.contactSheet,\n };\n }\n\n /**\n * B8.4 \u2014 score the asset against a reference GLB (the editor's `screenshot\n * <model.glb> --compare <ref.glb>` command): matched orthographic front + side silhouettes\n * (equal-height bounding-box framing, both yaw-normalized to face the\n * camera), per-view IoU numbers, and overlay evidence images. The\n * reference GLB's raw bytes travel base64 in the command; the editor\n * renders and scores \u2014 the SDK never interprets Three.js assets itself.\n */\n async captureAssetComparePreview(\n source: AssetPreviewSource,\n refGlbBase64: string,\n options: AssetCompareOptions = {},\n ): Promise<AssetCompareCapture> {\n const { refForward, ...dimensions } = options;\n const data = await this.command<AssetCompareCapture>({\n type: 'capture-asset-preview',\n ...source,\n ...dimensions,\n compare: { glbBase64: refGlbBase64, ...(refForward ? { forward: refForward } : {}) },\n });\n return { width: data.width, height: data.height, views: data.views };\n }\n\n /**\n * The STORY lane (the editor's `screenshot <file>.stories.tsx` command): every CSF export of\n * one project story file rendered in the live session's DOM and captured\n * through the same composite leg {@link captureGame} uses, returned as\n * per-export images plus one variant sheet. `options.story` narrows to a\n * single export.\n *\n * Rendering happens in the EDITOR \u2014 the SDK never imports, composes or\n * mounts a CSF module itself; the session already owns that machinery for\n * its Stories panel and this drives it.\n */\n async captureStoryVariants(\n modulePath: string,\n options: StoryCaptureOptions = {},\n ): Promise<StoryVariantCapture> {\n const data = await this.command<StoryVariantCapture>({\n type: 'capture-story-variants',\n modulePath,\n ...options,\n });\n return {\n modulePath: data.modulePath,\n width: data.width,\n height: data.height,\n variants: data.variants,\n contactSheet: data.contactSheet,\n };\n }\n\n // --- Panels ---\n\n async showViewport(tab: ViewportTab): Promise<void> {\n await this.command({ type: 'viewport-tab', tab });\n }\n\n /** Focus a static workspace panel by the key the editor's panel registry\n * holds; an unknown key refuses naming the keys it does hold. */\n async showPanel(panel: string): Promise<void> {\n await this.command({ type: 'show-panel', panel });\n }\n\n /** Show several instances of the running game split-screen \u2014 multiplayer\n * authoring. Pass a total `count` (default \"Player N\" labels) or an array of\n * `names` (its length is the count; index 0 is the primary). Requires a live\n * play session. */\n async setInstanceCount(countOrNames: number | string[]): Promise<void> {\n await this.command(\n Array.isArray(countOrNames)\n ? { type: 'set-instance-count', names: countOrNames }\n : { type: 'set-instance-count', count: countOrNames },\n );\n }\n\n async openAsset(path: string, kind: AssetKind): Promise<void> {\n await this.command({ type: 'open-asset-tab', path, kind });\n }\n\n /** SELECT a project asset \u2014 the other half of the browser's\n * selection-vs-open contract (single click selects and fills the\n * Inspector; double click opens a document). */\n async selectAsset(path: string): Promise<void> {\n await this.command({ type: 'select-asset', path });\n }\n\n async closeAsset(key: string): Promise<void> {\n await this.command({ type: 'close-asset-tab', key });\n }\n\n async toggleCommandPalette(): Promise<void> {\n await this.command({ type: 'toggle-command-palette' });\n }\n\n async toggleConsole(): Promise<void> {\n await this.command({ type: 'toggle-console' });\n }\n\n /** Switch the editor's NAMED WORKSPACE \u2014 the task-named layout memory\n * (`game`/`model`/`sculpt`/`texture`/`animate`/`look`). Resolves once the\n * dock has finished rebuilding, so a following capture photographs the\n * arrangement that was asked for. */\n async setWorkspace(workspace: EditorWorkspaceName): Promise<void> {\n await this.command({ type: 'set-workspace', workspace });\n }\n\n /** Apply a STYLE BUNDLE \u2014 palette, material, icon set and region defaults\n * in one gesture (`classic`/`glass`/`maya`/`substance`, or one a package\n * the project or product composes carries, such as `blender`). */\n async setStyle(style: string): Promise<void> {\n await this.command({ type: 'set-style', style });\n }\n\n /** A document stage's viewport PRESENTATION (`kit/viewport-presentation`), resolved; with a\n * `layer`, that choice is recorded for the view first, as the toolbar records it. */\n /** A view's presentation, answered resolved. With a LAYER the person's choice is recorded\n * first; with a STRING, the named view (`*.view.ts`) of that id is put on the view whole. */\n async viewportPresentation(\n documentId: string,\n layer?: import('./kit/viewport-presentation').PresentationLayer | string,\n ): Promise<{\n presentation: import('./kit/viewport-presentation').ViewportPresentation;\n binding: { stageKind: string; documentLayer: import('./kit/viewport-presentation').PresentationLayer | null } | null;\n bound: { viewId: string; stageKind: string }[];\n lastDraw: import('./kit/viewport-presentation').ViewDrawReport | null;\n presets: string[];\n viewPresets: string[];\n /** The environment images registered (`kit/environment-images`), for `lighting.preview.environment.image`. */\n environmentImages: string[];\n }> {\n return this.command({\n type: 'viewport-presentation',\n documentId,\n ...(typeof layer === 'string' ? { preset: layer } : layer ? { layer } : {}),\n });\n }\n\n /** Set the MATERIAL apart from the bundle that usually carries it.\n * Answers with what the chrome wears afterwards. */\n async setAppearance(appearance: {\n readonly material?: string;\n }): Promise<{ material: string; style: string | null }> {\n return this.command<{ material: string; style: string | null }>({\n type: 'set-appearance',\n ...appearance,\n });\n }\n\n async showBuild(): Promise<void> {\n await this.command({ type: 'show-build' });\n }\n\n /** Atomically present a durable editor view and return its shareable URL. */\n async present(view: EditorView): Promise<PresentedEditorView> {\n const presented = await this.command<PresentedEditorView>({ type: 'present-view', view });\n return { view: presented.view, url: presented.url, warnings: presented.warnings };\n }\n\n /**\n * The INSPECTION SUBJECT the editor is showing right now, as data \u2014 the\n * serialized projection of the inspection model (design:\n * `docs/ARCHITECTURE-CORE.md` \u00A7Editor chrome, \"The Inspection Model\").\n *\n * The same subject a human reads in the inspector: identity, presentation,\n * verbs, and the identified sections in display order \u2014 with a `fields`\n * section's CURRENT VALUES read through the same io the field rows edit\n * through. With nothing selected it answers the active surface's own\n * no-selection subject when it has one, exactly as the panel does; it never\n * reports another surface's, and when the panel itself is unmounted it\n * answers `{none: true}` rather than a subject nobody is looking at. A\n * `custom` section body is a named opaque (`{kind, id, title}`) \u2014 the editor\n * renders those with React \u2014 plus its displayed values under `data` when it\n * has any (the Transform section's position/rotation/scale).\n */\n async inspect(): Promise<InspectedInspection> {\n const data = await this.command<{ subject: InspectedInspection }>({ type: 'inspect' });\n return data.subject;\n }\n\n /** Run one verb exposed by the active Inspector subject, by its id. */\n async runInspectionAction(actionId: string): Promise<InspectedInspection> {\n const data = await this.command<{ subject: InspectedInspection }>({\n type: 'run-inspection-action',\n actionId,\n });\n return data.subject;\n }\n\n /**\n * Run ONE command by id \u2014 the door to everything the command palette lists.\n *\n * Under the Code-OSS frame this is the workbench's own `ICommandService`, so\n * any command id works: a view's `volter.<view>.<verb>`, an editor action's\n * `volter.action.<id>`, or one of VS Code's own. Standalone the editor's `edit` command has no\n * command service and answers the `volter.<view>.<verb>` shape directly off\n * the views registry, refusing anything else BY NAME.\n *\n * The result is whatever the command answered \u2014 a view verb's state, or\n * `null` for a command that returns nothing.\n */\n async runCommand(commandId: string, args?: unknown): Promise<unknown> {\n const data = await this.command<{ result: unknown }>({\n type: 'run-command',\n commandId,\n ...(args === undefined ? {} : { args }),\n });\n return data.result;\n }\n\n /**\n * One STRUCTURE op on the authored tree \u2014 the hierarchy context menu's own\n * verbs, on the same helpers, for a caller with no pointer to right-click\n * with. `id`/`ids` default to the current selection.\n */\n async structureOp(op: StructureOp, options: StructureOpOptions = {}): Promise<StructureOpResult> {\n return this.command<StructureOpResult>({ type: 'structure-op', op, ...options });\n }\n\n /** \"Extract Component\u2026\" \u2014 the hierarchy row's action, as a command. Answers\n * the action's own sentence, which NAMES the files it created. */\n async extractComponent(options: { id?: string; name?: string } = {}): Promise<{ hint: string }> {\n return this.command<{ hint: string }>({ type: 'extract-component', ...options });\n }\n\n /** \"Fork Component\u2026\" \u2014 extract's twin: one new file, one callsite retargeted. */\n async forkComponent(options: { id?: string } = {}): Promise<{ hint: string }> {\n return this.command<{ hint: string }>({ type: 'fork-component', ...options });\n }\n\n /**\n * The HIERARCHY PANEL's actual rendered row tree, as data.\n *\n * The same rows a human is looking at: the adapter's tree after the component\n * marks fold implementation subtrees, after the internals reveal, after the\n * document promotion, the child cap, the collapse state, the search filter\n * and the selection scope. Works in play mode and edit mode alike \u2014 the\n * answer reports which (`playState`, `activeViewportTab`), because a\n * play-mode tree and an edit-mode tree come from different adapters.\n *\n * Deliberately NOT `status().entities`, which walks the raw adapter tree and\n * therefore answers a different question: a panel defect is invisible in it.\n *\n * Each row carries `childCount` (what its caret opens), `internalChildCount`\n * (what is folded behind \"Reveal Internals\") and `expandable` (whether the\n * panel draws a caret at all) \u2014 so \"this subtree exists but the UI offers no\n * way to open it\" is a readable fact rather than something only a human\n * squinting at the panel can notice.\n *\n * Rejects, naming the panel, when no hierarchy panel is mounted: an empty\n * tree would be a fabricated answer about a surface nobody is being shown.\n */\n async hierarchy(): Promise<InspectedHierarchy> {\n const data = await this.command<{ hierarchy: InspectedHierarchy }>({ type: 'hierarchy' });\n return data.hierarchy;\n }\n\n /** Run the Hierarchy panel's own Expand All action. */\n async expandHierarchyAll(): Promise<void> {\n await this.command<Record<string, never>>({ type: 'expand-hierarchy-all' });\n }\n\n /** Run the Hierarchy panel's own Collapse All action \u2014 Expand All's other\n * half, and the only way back to the tree's rest state through the product\n * (see `HierarchyPanelSnapshot.collapseAll`). */\n async collapseHierarchyAll(): Promise<void> {\n await this.command<Record<string, never>>({ type: 'collapse-hierarchy-all' });\n }\n\n /**\n * Write one editable path through the active Inspector's own IO.\n *\n * The answer carries `write` as well as the subject, because an ack alone\n * cannot be believed: a write with no persistence route open succeeds and\n * changes no byte, and `write.persisted` is how the caller tells the two\n * apart without diffing the tree (`InspectedWriteDestination` in `types.ts`).\n */\n async setInspectionField(path: string, value: unknown): Promise<InspectedFieldWrite> {\n const data = await this.command<InspectedFieldWrite>({\n type: 'set-inspection-field',\n path,\n value,\n });\n return { subject: data.subject, write: data.write };\n }\n\n /**\n * REMOVE one editable path's authored override \u2014 the other half of the write\n * door, and the only one that can express byte-ABSENCE.\n *\n * {@link setInspectionField} writes a VALUE, so reverting a property an\n * authoring gesture ADDED puts the default back EXPLICITLY and leaves the\n * source one attribute heavier than it started. This drops the property, so\n * whatever governs it in its absence takes over \u2014 the same `io.remove` the\n * Inspector's revert arrow calls, the same persistence pipe, the same awaited\n * `{ destination, persisted }` ack.\n *\n * Rejects with `code: 'REMOVAL_UNAVAILABLE'` when the field does not declare\n * itself removable or the lane implements no removal door. That refusal is a\n * MISSING SEAM, not a failed removal, and it is coded rather than phrased\n * precisely so a caller can grade the two differently.\n */\n async removeInspectionField(path: string): Promise<InspectedFieldWrite> {\n const data = await this.command<InspectedFieldWrite>({\n type: 'remove-inspection-field',\n path,\n });\n return { subject: data.subject, write: data.write };\n }\n\n /**\n * OPEN one piece of the adapter's SCENE TABLE by id \u2014 a scene, a prefab, or\n * a story state, because the table makes them siblings (they differ only in\n * instance site). The ids are exactly what `getState().adapter.scenes.entries`\n * reports, so the table is both the menu and the address space.\n *\n * With a game LIVE in the session, opening a scene the adapter declares\n * reachable through that game's own scenes contract NAVIGATES it \u2014 the same\n * switch the editor's own scene picker makes \u2014 and the answer carries the\n * game's own reading (`scene`).\n *\n * Rejects with a coded reason rather than prose: `SCENE_NOT_FOUND` (and it\n * names the ids that DO exist), `SCENE_NOT_OPENABLE` carrying the adapter's\n * own declared reason for a scene it says nothing can reach,\n * `SCENE_NAVIGATION_NOT_RUNNING` for a live-only scene with no game running,\n * `SCENE_CONTRACT_UNAVAILABLE` / `SCENE_NOT_IN_CONTRACT` (naming the ids the\n * game itself publishes) / `SCENE_SWITCH_FAILED` when the running game's own\n * navigation cannot take it, `SCENE_NOT_OPENABLE_LIVE` when this session has\n * no remount for a native swap-slot scene,\n * `SCENE_TABLE_UNAVAILABLE` before the adapter has loaded, and\n * `SCENE_DOCUMENT_NOT_MOUNTED` when the host has no document for a piece the\n * table says is openable \u2014 a host gap, not a table statement.\n */\n async open(id: string): Promise<OpenedDocument> {\n return this.command<OpenedDocument>({ type: 'open', id });\n }\n\n /**\n * Undo / redo one project transaction \u2014 the same queue the keyboard shortcut\n * drives. `moved` is false when there was nothing left in that direction.\n */\n async undo(): Promise<HistoryStep> {\n return this.command<HistoryStep>({ type: 'undo' });\n }\n\n async redo(): Promise<HistoryStep> {\n return this.command<HistoryStep>({ type: 'redo' });\n }\n\n /** Read the editor's actual current durable projection. */\n async currentView(): Promise<EditorView> {\n const data = await this.command<{ view: EditorView }>({ type: 'current-view' });\n return data.view;\n }\n\n /**\n * Capture the active center document exactly as presented to the user.\n *\n * A number is a SQUARE of that size (the default shape); `{width, height}`\n * asks for a shaped frame \u2014 a video-aspect look that needs no crop. Both are\n * bounded by the relay budget; see {@link CaptureDimensions}.\n */\n /** Photograph the editor PAGE itself \u2014 every panel as the person sees it, at\n * `scale` output pixels per CSS pixel (default `devicePixelRatio`), which is\n * what a 1 px border or a glyph edge is judged through. */\n async captureEditorChrome(options?: EditorChromeCaptureOptions): Promise<EditorChromeCapture> {\n return this.command<EditorChromeCapture>({\n type: 'capture-editor-chrome',\n ...(options?.scale === undefined ? {} : { scale: options.scale }),\n ...(options?.region === undefined ? {} : { region: options.region }),\n });\n }\n\n /** With a view, present and capture it in one request so document discovery\n * cannot retarget the capture between two client calls. */\n async captureActiveDocument(\n size?: CaptureDimensions,\n view?: EditorView,\n ): Promise<ActiveDocumentCapture> {\n return this.command<ActiveDocumentCapture>({\n type: 'capture-active-document',\n ...(view ? { view } : {}),\n ...(typeof size === 'number' ? { size } : {}),\n ...(typeof size === 'object' && size !== null\n ? { width: size.width, height: size.height }\n : {}),\n });\n }\n\n /**\n * Read or drive the ACTIVE center document's own DOM \u2014 the scoped\n * editor-chrome door, and the read/gesture half of the same subject\n * {@link captureActiveDocument} photographs. NOT play-mode gated, and NOT\n * page automation: a target outside the active document's container is\n * refused by name. Design and scope contract:\n * `packages/editor-sdk/src/kit/editor-document-probe.ts`.\n */\n async documentProbe(step: DocumentProbeStep): Promise<DocumentProbeResult> {\n return this.command<DocumentProbeResult>({ type: 'document-probe', step });\n }\n\n /**\n * Run a wire-carried step against the ACTIVE document's published context\n * (`packages/editor-sdk/src/kit/document-context-registry.ts`) \u2014 the REPL door over\n * an open document, in Edit mode. `src` is the step's own `toString()`;\n * same serialization contract as `page-script` (no closures survive).\n */\n /**\n * The Blender lane's doors (`blender-execute`, `blender-scene-info`,\n * `blender-object-info`, `blender-screenshot-view`, `blender-read-file`,\n * `blender-write-file`, `blender-list-files`, `blender-start`,\n * `blender-status`): Blender runs in the editor tab's worker, and\n * `volter blender-mcp` is transport onto these. `blender-status` is the only\n * one that creates nothing \u2014 it answers whether this tab already has a\n * session, which is how a caller survives an editor restart.\n */\n async blender<T extends object = Record<string, unknown>>(\n type: `blender-${string}`,\n fields: Record<string, unknown> = {},\n ): Promise<T> {\n // One modeling chunk can run for minutes in the tab (an exact boolean\n // over a dense mesh measured 80-90 s under Wasm); the relay's server-side\n // budget for blender-execute is the same half hour.\n return this.command<T>({ type, ...fields }, { deadlineMs: BLENDER_DEADLINE_MS });\n }\n\n async documentScript<T = unknown>(src: string): Promise<T> {\n const outcome = await this.command<{ result: T }>({ type: 'document-script', src });\n return outcome.result;\n }\n\n // --- Display (set semantics) ---\n\n async setGrid(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-grid', enabled });\n }\n\n async setHelpers(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-helpers', enabled });\n }\n\n async setStats(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-stats', enabled });\n }\n\n async setShadingMode(mode: ShadingMode): Promise<void> {\n await this.command({ type: 'set-shading-mode', mode });\n }\n\n async setHelperType(helperType: keyof HelperVisibility, enabled: boolean): Promise<void> {\n await this.command({ type: 'set-helper-type', helperType, enabled });\n }\n\n // --- Transform tools (set semantics) ---\n\n async setTransformMode(mode: TransformMode): Promise<void> {\n await this.command({ type: 'set-transform-mode', mode });\n }\n\n async setTransformSpace(space: TransformSpace): Promise<void> {\n await this.command({ type: 'set-transform-space', space });\n }\n\n async setSnap(enabled: boolean): Promise<void> {\n await this.command({ type: 'set-snap', enabled });\n }\n\n // --- Project management ---\n\n async createProject(\n name: string,\n location: string,\n template: ProjectTemplate = 'default',\n exampleId?: string,\n ): Promise<ProjectInfo> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/create-project`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name, location, template, ...(exampleId ? { exampleId } : {}) }),\n });\n const data = (await this.readJson(res)) as {\n ok?: boolean;\n error?: string;\n path?: string;\n config?: ProjectInfo['config'];\n };\n if (!res.ok) {\n throw new Error(data.error ?? `Create project failed: ${res.status}`);\n }\n return { path: data.path as string, config: data.config as ProjectInfo['config'] };\n }\n\n async openProject(path: string): Promise<void> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/open-project`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path }),\n });\n const body = (await this.readJson(res)) as { error?: string };\n if (!res.ok) {\n throw new Error(body.error ?? `Open project failed: ${res.status}`);\n }\n }\n\n async getProject(): Promise<ProjectInfo | null> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/project`);\n const data = (await this.readJson(res)) as { project: ProjectInfo | null; error?: string };\n if (!res.ok) throw new Error(data.error ?? `Failed to get project: ${res.status}`);\n return data.project;\n }\n\n async listRecentProjects(): Promise<RecentProject[]> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/recent-projects`);\n const data = (await this.readJson(res)) as { projects: RecentProject[]; error?: string };\n if (!res.ok) throw new Error(data.error ?? `Failed to list projects: ${res.status}`);\n return data.projects;\n }\n\n // --- Registered project tools ---\n\n /** List tools explicitly registered in `package.json#volter.tools`.\n * The editor server loads callable metadata in Node; modules never enter the\n * editor browser merely because they were listed. */\n async listProjectTools(): Promise<ProjectToolCatalog> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/project-tools`);\n const body = await this.readJson(res);\n if (!res.ok) throw new Error(`Failed to list project tools: ${res.status}`);\n return body as ProjectToolCatalog;\n }\n\n /** Execute one Node-hosted project tool through the shared validated\n * dispatcher. Write/destructive tools require `confirm:true`. */\n async runProjectTool(\n name: string,\n input: unknown = {},\n options: { confirm?: boolean; instance?: string } = {},\n ): Promise<ProjectToolOutcome> {\n // Provider subscriptions can outlive Node fetch's five-minute header limit.\n // Match browser fetch for this operation; dispose its sockets after reading the result.\n const dispatcher = createDispatcher(0);\n try {\n const res = await this.httpFetch(\n `${this.baseUrl}/__editor/project-tools/run`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n name,\n input,\n confirm: options.confirm === true,\n // Omitted (not null) when unset \u2014 the wire body is JSON and the tool\n // host reads absence as \"the sole instance\", same convention as the\n // relay's `instance`.\n ...(options.instance !== undefined ? { instance: options.instance } : {}),\n }),\n },\n dispatcher,\n );\n const body = (await this.readJson(res)) as ProjectToolOutcome;\n if (!body || typeof body !== 'object' || typeof body.ok !== 'boolean') {\n throw new Error(`Project tool returned an invalid response (${res.status}).`);\n }\n return body;\n } finally {\n await dispatcher?.destroy?.();\n }\n }\n\n // --- First-party generation job activity ---\n\n /** Read the one project-local generation job ledger. Provider-native\n * request/result shapes remain on their registered operations. */\n async listGenerationJobs(): Promise<GenerationJobsDocument> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/generations`);\n const body = await this.readJson(res);\n if (!res.ok) throw new Error(`Failed to list generation jobs: ${res.status}`);\n return body as GenerationJobsDocument;\n }\n\n /** Forget operational job state. Accepted provenance and project assets\n * are deliberately unaffected. */\n async forgetGenerationJob(id: string): Promise<boolean> {\n const res = await this.httpFetch(\n `${this.baseUrl}/__editor/generations/${encodeURIComponent(id)}`,\n {\n method: 'DELETE',\n },\n );\n const body = (await this.readJson(res)) as { removed?: boolean; error?: string };\n if (!res.ok) throw new Error(body.error ?? `Failed to forget generation job: ${res.status}`);\n return body.removed === true;\n }\n\n // --- Logs ---\n\n async getLogEntries(): Promise<\n Array<{ t: number; level: string; msg: string; source?: string }>\n > {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/log-entries`);\n const data = (await this.readJson(res)) as {\n entries: Array<{ t: number; level: string; msg: string; source?: string }>;\n };\n if (!res.ok) return [];\n return data.entries;\n }\n\n // --- State ---\n\n /**\n * The document table the host resolved \u2014 every scene, prefab, page, model,\n * shot, take \u2026 the project's finders produced (`getState().adapter.scenes`\n * is the same projection). A command, so it answers wherever the control\n * channel reaches, not only where `/__editor/state` is served.\n */\n async documentTable(): Promise<DocumentTableProjection> {\n return this.command<DocumentTableProjection>({ type: 'document-table' });\n }\n\n /**\n * Reload the editor's page and wait until the new document answers \u2014 the\n * host's `page-reload`, for a product with no game client (`@volter/game-live`'s\n * `page.reload()` is the same order with the same two witnesses). A tab's\n * epoch count rising proves a new document loaded; a host command answering\n * proves it can be driven. It is sent only once that tab reports its command\n * listener ready, because a command sent before is filed as a stall.\n */\n async reloadPage(timeoutMs = 60_000): Promise<void> {\n const epochs = async () => {\n const tabs = (await this.getState().catch(() => ({ tabs: [] }) as Partial<EditorState>)).tabs ?? [];\n const byTab = tabs as ReadonlyArray<{ tabId8: string; epochCount: number; commandListener?: unknown }>;\n return new Map(byTab.map((tab) => [tab.tabId8, tab] as const));\n };\n const pause = () => new Promise((settle) => setTimeout(settle, 250));\n const before = await epochs();\n const deadline = Date.now() + timeoutMs;\n await this.command({ type: 'page-reload' });\n let reloaded: string[] = [];\n while (reloaded.length === 0) {\n if (Date.now() > deadline) throw new Error('The reload was ordered and no tab of this session reported a new page load.');\n await pause();\n const now = await epochs();\n reloaded = [...now].filter(([tabId, tab]) => tab.epochCount > (before.get(tabId)?.epochCount ?? 0)).map(([tabId]) => tabId);\n }\n for (;;) {\n if (Date.now() > deadline) throw new Error('A new page loaded, but its command listener did not become ready.');\n const now = await epochs();\n if (reloaded.some((tabId) => {\n const listener = now.get(tabId)?.commandListener;\n return typeof listener !== 'string' || listener === 'ready';\n })) break;\n await pause();\n }\n for (;;) {\n try {\n await this.command({ type: 'current-view' });\n return;\n } catch (error) {\n if (Date.now() > deadline) throw error;\n await pause();\n }\n }\n }\n\n async getState(): Promise<EditorState> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/state`);\n const state = (await this.readJson(res)) as EditorState;\n if (!res.ok) throw new Error(`Failed to get editor state: ${res.status} ${res.statusText}`);\n return state;\n }\n\n /**\n * The complete unresolved console set the session is holding right now.\n *\n * Command envelopes only carry COUNTS (`unresolvedConsole` on\n * `commandResponseFor`). The named conditions live on GET `/__editor/console`.\n * This is the method that turns \"a command that exits before an envelope\n * arrives\" into a real reading: the CLI calls it at start and at exit\n * through the same {@link onEnvelope} observer every other response uses.\n * A session that does not answer within {@link CONSOLE_DRAIN_TIMEOUT_MS} is\n * a thrown error the caller treats as \"nothing learned\", never a hang.\n */\n async getUnresolvedConsole(opts?: { all?: boolean }): Promise<unknown> {\n const res = await this.httpFetch(\n `${this.baseUrl}/__editor/console${opts?.all === true ? '?all=1' : ''}`,\n { signal: AbortSignal.timeout(CONSOLE_DRAIN_TIMEOUT_MS) },\n );\n // Status first: a 404's empty body would otherwise die inside readJson\n // with a parse error that hides the one fact the caller classifies on\n // (does this server SERVE the console route at all?).\n if (!res.ok) {\n throw new Error(`Failed to read unresolved console: ${res.status}`);\n }\n return await this.readJson(res, true);\n }\n\n /** Acknowledge one named console condition. The response is observed and\n * hydrated through the same path as every other client response. */\n async acknowledgeConsole(input: {\n readonly id: string;\n readonly reason: string;\n readonly by: string;\n }): Promise<unknown> {\n const res = await this.httpFetch(`${this.baseUrl}/__editor/console/ack`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n signal: AbortSignal.timeout(CONSOLE_DRAIN_TIMEOUT_MS * 4),\n });\n const body = await this.readJson(res);\n return body;\n }\n\n /**\n * `fetch` for this client's plain routes, with the ONE thing Node's `fetch`\n * will not do: name why it failed.\n *\n * `readJson` below already owns \"the server answered the wrong thing\"; this\n * owns \"nothing answered at all\", which used to reach the caller as the bare\n * `TypeError: fetch failed` with the real code buried on `.cause`. No retry\n * here \u2014 these routes create projects, run tools and acknowledge console\n * conditions, so repeating one is the caller's decision. The relayed\n * `command` path above has its own opt-in retry for the read-only captures.\n */\n private async httpFetch(\n url: string,\n init?: RequestInit,\n dispatcher?: Dispatcher,\n ): Promise<Response> {\n try {\n return this.fetchOverride ? await this.fetchOverride(url, init) : await dispatchFetch(url, init, dispatcher);\n } catch (error) {\n if ((error as { name?: string } | null)?.name === 'TimeoutError') throw error;\n const { code, detail } = describeFetchFailure(error);\n throw new EditorCommandError(\n `${init?.method ?? 'GET'} ${url} never reached the editor: ${code}` +\n `${detail ? ` (${detail})` : ''}. Nothing answered on that port \u2014 check the terminal ` +\n 'that started this editor session and confirm the port this client resolved.',\n code,\n false,\n );\n }\n }\n\n /** Parse one JSON body and hand it to {@link onEnvelope}.\n *\n * A command/state envelope carries current counts but not the named set. If\n * an observer is installed, do the bounded console GET before resolving the\n * original request. That makes a subsequent `process.exit()` safe: the\n * observer has already received every condition and occurrence count. */\n private async readJson(res: Response, consoleComplete = false): Promise<unknown> {\n // Every one of this client's twelve routes funnels through here, so this is\n // where \"did the editor server answer?\" is asked \u2014 the same question, and\n // the same JSON-content-type rule, that\n // `packages/editor-sdk/src/kit/editor-server-response.ts` owns on the browser side.\n // It is asked again rather than imported because THIS package is published\n // and depends on neither `@volter/editor-project` nor the editor bundle (see\n // `DEFAULT_URL` above for that policy).\n //\n // Not theoretical here: `baseUrl` is whatever `--url`/`VOLTER_EDITOR_URL`\n // says, so the CLI is routinely pointed at a SHARE TUNNEL or a static host\n // \u2014 both of which answer `200 text/html` for a route nothing serves, and\n // `res.json()` then died as `Unexpected token '<'`, naming neither the URL\n // nor the cause.\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('application/json')) {\n throw new Error(\n `The editor at ${this.baseUrl} answered with its page fallback ` +\n `(${contentType || 'no content-type'}) rather than JSON, so no editor server handled ` +\n 'the request. Check that this URL is a running editor session.',\n );\n }\n const body: unknown = await res.json();\n this.observe(body, { unresolvedConsoleComplete: consoleComplete });\n if (\n this.onEnvelope !== null &&\n !consoleComplete &&\n body !== null &&\n typeof body === 'object' &&\n 'unresolvedConsole' in body\n ) {\n try {\n const consoleRes = await this.httpFetch(`${this.baseUrl}/__editor/console`, {\n signal: AbortSignal.timeout(CONSOLE_DRAIN_TIMEOUT_MS),\n });\n if (consoleRes.ok) {\n const consoleBody: unknown = await consoleRes.json();\n this.observe(consoleBody, { unresolvedConsoleComplete: true });\n }\n } catch {\n // The original response remains authoritative. A reporting follow-up\n // may degrade to its count-only envelope, never break the command.\n }\n }\n return body;\n }\n\n /** Hand one response body to {@link onEnvelope}, never letting it throw. */\n private observe(body: unknown, observation: EditorEnvelopeObservation): void {\n if (this.onEnvelope === null) return;\n try {\n this.onEnvelope(body, observation);\n } catch {\n // A reporting hook may never break the command it is reporting on.\n }\n }\n\n /**\n * Whether an editor browser tab is connected to the server *right now*.\n * Unlike {@link getState}, this reflects live SSE connections, not cached\n * state \u2014 use it to check whether commands will actually reach an editor.\n */\n async isConnected(): Promise<boolean> {\n const state = await this.getState();\n return state.connected === true;\n }\n\n async waitForState(\n predicate: (s: EditorState) => boolean,\n timeoutMs = 10_000,\n ): Promise<EditorState> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const state = await this.getState();\n if (predicate(state)) return state;\n await new Promise((r) => setTimeout(r, 100));\n }\n throw new Error(`waitForState timed out after ${timeoutMs}ms`);\n }\n}\n", "/**\n * `editor.document` \u2014 the session binding for the scoped editor-chrome door.\n *\n * WHY IT IS A SEPARATE OBJECT, and why the verbs are these, is recorded once\n * in the implementation's header\n * (`packages/editor-sdk/src/kit/editor-document-probe.ts`); the short version is that\n * `game.page()` is play-mode-gated and rooted at the GAME container, so an\n * editor surface that is not a running game could be neither read nor driven\n * through the product.\n *\n * WHAT IT ADDRESSES is a closed VOCABULARY of named surfaces, passed as\n * `{ scope }` on every verb:\n *\n * `document` (default) the active centre document's whole box\n * `header` / `shelf` that document's toolbar strip / tool rail\n * `rail` the PROPERTIES view \u2014 its tabs, sections and fields\n * `outliner` the OUTLINER view \u2014 its rows and their controls\n * `content` the CONTENT view \u2014 its categories and asset rows\n * `menubar` the APPLICATION MENUS (Edit, View, \u2026) and the menus they open\n *\n * await editor.document.click('[data-testid=app-menu-edit]', { scope: 'menubar' });\n * await editor.document.query('[role=tab]', { scope: 'rail' });\n * await editor.document.click('[data-testid=properties-tab-modifiers]', { scope: 'rail' });\n * await editor.document.click('[data-ingest-name=Cube]', { scope: 'outliner', clicks: 2 });\n * await editor.document.type('Wheel', { scope: 'outliner' });\n *\n * It is not page automation: a selector resolving outside the named surface is\n * refused by a message naming the scope and listing the others. `rail` and\n * `outliner`, and `content` are editor chrome and stay readable while the Game document is\n * active; `editor.hierarchy()` / `editor.inspect()` keep answering what those\n * panels RESOLVED, where this door answers what they DREW.\n *\n * A field on `LiveEditor` rather than methods on it, so the editor's `eval --list` command\n * shows the verbs as one named surface \u2014 the same reason `game.input`\n * and `game.events` are instance fields.\n */\n\nimport type {\n DocumentProbeResult,\n DocumentProbeScope,\n DocumentProbeStep,\n EditorClient,\n} from '@volter/editor-sdk';\n\n/** Which named surface a verb runs against; `document` when omitted. */\nexport interface DocumentScopeOption {\n scope?: DocumentProbeScope;\n}\n\n/** Modifier/targeting options shared by the gesture verbs. */\nexport interface DocumentGestureOptions extends DocumentScopeOption {\n /** Which match to drive when the selector matches several (default 0). */\n index?: number;\n}\n\nexport interface DocumentKeyOptions extends DocumentGestureOptions {\n /** Target one element instead of whatever inside the scope has focus. */\n selector?: string;\n code?: string;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n altKey?: boolean;\n /** Hold the key this long before releasing it (a person holding W). */\n holdMs?: number;\n}\n\nexport interface DocumentPasteOptions extends DocumentGestureOptions {\n selector?: string;\n}\n\nexport interface DocumentTypeOptions extends DocumentGestureOptions {\n /** The field; omitted types into whatever inside the scope has focus. */\n selector?: string;\n /** Replace what the field holds first (default true). */\n replace?: boolean;\n /** Press Enter after the text (default true). */\n enter?: boolean;\n}\n\nexport class LiveEditorDocument {\n readonly #client: EditorClient;\n\n constructor(client: EditorClient) {\n this.#client = client;\n }\n\n /**\n * Read matching elements inside the active document: tag, text, attributes,\n * value/checked/disabled and rect. `matched` is the total before `limit`.\n *\n * `styles` additionally resolves named properties per match \u2014 and resolving\n * is the point, because a theme token is an expression until an element\n * paints it. Ask for the standard property to learn the colour a person\n * sees; ask for a `--volter-\u2026` custom property to learn what a rule WOULD\n * paint, which is the only way to measure a `:hover` colour (`:hover` is a\n * browser state no synthetic event can enter, so there is deliberately no\n * hover verb on this door).\n *\n * await editor.document.query('.volter-tree-row', {\n * styles: ['backgroundColor', '--volter-widget-regular-hover'],\n * });\n */\n async query(\n selector: string,\n options?: DocumentScopeOption & { limit?: number; styles?: readonly string[] },\n ): Promise<DocumentProbeResult> {\n return this.#probe({\n action: 'query',\n selector,\n ...(options?.scope === undefined ? {} : { scope: options.scope }),\n ...(options?.limit === undefined ? {} : { limit: options.limit }),\n ...(options?.styles === undefined ? {} : { styles: [...options.styles] }),\n });\n }\n\n /** A REAL pointer gesture (pointerdown/mousedown/focus/pointerup/mouseup/click)\n * \u2014 not `element.click()`, which a `pointerdown` listener never sees. */\n async click(\n selector: string,\n options?: DocumentGestureOptions & {\n clicks?: number;\n at?: [number, number];\n altKey?: boolean;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n },\n ): Promise<DocumentProbeResult> {\n // An option this door does not know is refused, never dropped: a dropped `position` clicked\n // the element's centre and answered as if it had clicked where it was asked.\n const known = ['scope', 'index', 'clicks', 'at', 'altKey', 'ctrlKey', 'metaKey', 'shiftKey'];\n const unknown = Object.keys(options ?? {}).filter((key) => !known.includes(key));\n if (unknown.length > 0) throw new Error(`click has no option ${unknown.map((key) => `\\`${key}\\``).join(', ')}; its options are scope, index, clicks, at ([x, y] fractions of the element's box) and the modifier keys altKey, ctrlKey, metaKey and shiftKey.`);\n return this.#probe({\n action: 'click',\n selector,\n ...(options?.scope === undefined ? {} : { scope: options.scope }),\n ...(options?.index === undefined ? {} : { index: options.index }),\n ...(options?.clicks === undefined ? {} : { clicks: options.clicks }),\n ...(options?.at === undefined ? {} : { at: options.at }),\n ...(options?.altKey ? { altKey: true } : {}),\n ...(options?.ctrlKey ? { ctrlKey: true } : {}),\n ...(options?.metaKey ? { metaKey: true } : {}),\n ...(options?.shiftKey ? { shiftKey: true } : {}),\n });\n }\n\n /**\n * TYPE into a field and commit with Enter, the way a person does \u2014 one\n * character at a time through the prototype's value setter, between real\n * `keydown`/`keyup`.\n *\n * `paste` is not a substitute: an untrusted `ClipboardEvent` performs no\n * default action, so a plain `<input>` with no paste handler keeps its old\n * value. Omit `selector` to type into whatever inside the scope has focus \u2014\n * which is what a rename field is, one gesture after\n * `click(row, { clicks: 2 })`.\n */\n async type(text: string, options?: DocumentTypeOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'type', text, ...(options ?? {}) });\n }\n\n /**\n * A real pointer DRAG across one matched element \u2014 press at `from`, move,\n * release at `to`. The gesture a direct-manipulation canvas needs; a\n * zero-length drag is a click at that fraction, which `click` (always the\n * center) cannot place.\n *\n * `from`, `to` and every point in `via` are `[x, y]` FRACTIONS OF THE\n * MATCHED ELEMENT'S BOX, 0..1 from its top-left \u2014 NEVER pixels and never\n * page coordinates. `[0.5, 0.5]` is its center, `[1, 0]` its top-right.\n * Compute a pixel target by measuring the element first: `query` answers\n * its `rect`, and `(px - rect.x) / rect.width` is the fraction to pass.\n */\n async drag(\n selector: string,\n options: DocumentGestureOptions & {\n from: [number, number];\n to: [number, number];\n via?: [number, number][];\n steps?: number;\n altKey?: boolean;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n /** 0 primary (default), 1 middle, 2 secondary. */\n button?: 0 | 1 | 2;\n /** `via`/`to` may leave the element's box after the press (a handle drag). */\n leave?: boolean;\n /** Keep the button down at `to`, for readings taken mid-gesture; {@link release} lets go. */\n hold?: boolean;\n },\n ): Promise<DocumentProbeResult> {\n return this.#probe({\n action: 'drag',\n selector,\n ...(options.scope === undefined ? {} : { scope: options.scope }),\n from: options.from,\n to: options.to,\n ...(options.via === undefined ? {} : { via: options.via }),\n ...(options.steps === undefined ? {} : { steps: options.steps }),\n ...(options.index === undefined ? {} : { index: options.index }),\n ...(options.altKey === undefined ? {} : { altKey: options.altKey }),\n ...(options.ctrlKey === undefined ? {} : { ctrlKey: options.ctrlKey }),\n ...(options.metaKey === undefined ? {} : { metaKey: options.metaKey }),\n ...(options.shiftKey === undefined ? {} : { shiftKey: options.shiftKey }),\n ...(options.button === undefined ? {} : { button: options.button }),\n ...(options.leave === undefined ? {} : { leave: options.leave }),\n ...(options.hold === undefined ? {} : { hold: options.hold }),\n });\n }\n\n /** Lets go of the drag `hold: true` left pressed, where it was left. */\n async release(options?: DocumentGestureOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'release', ...(options?.scope === undefined ? {} : { scope: options.scope }) });\n }\n\n /** A real keydown/keyup on the target, or on whatever inside the document has focus. */\n async key(key: string, options?: DocumentKeyOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'key', key, ...(options ?? {}) });\n }\n\n /** A real `ClipboardEvent` carrying `text/plain` \u2014 the gesture nothing else\n * in the product can produce. */\n async paste(text: string, options?: DocumentPasteOptions): Promise<DocumentProbeResult> {\n return this.#probe({ action: 'paste', text, ...(options ?? {}) });\n }\n\n /**\n * Choose `value` on a `<select>` \u2014 a native dropdown's options are drawn by\n * the OS, so `click` has nothing in the document to resolve, and a plain\n * `element.value =` is invisible to React. Set through the prototype's own\n * value setter plus `input`/`change`; `value` is the option's `value`, not\n * its label. An unknown value is refused with the options it does offer.\n */\n async select(\n selector: string,\n value: string,\n options?: DocumentGestureOptions,\n ): Promise<DocumentProbeResult> {\n return this.#probe({\n action: 'select',\n selector,\n value,\n ...(options?.scope === undefined ? {} : { scope: options.scope }),\n ...(options?.index === undefined ? {} : { index: options.index }),\n });\n }\n\n /**\n * THE REPL over the open document: run `step` in the editor page against the\n * object the ACTIVE document published as its context (the mesh document\n * publishes its `MeshEditSession`, whose `ctx` is the bpy-shaped edit\n * context \u2014 `ctx.ops.mesh.bevel({ offset: 0.1 })`, `ctx.selection`,\n * `ctx.history`, `session.commit()`). Edit mode, no play. Serialized like\n * `game.page`: the step's own source travels, so inline every value it\n * needs and return plain data.\n */\n async run<T = unknown>(\n step: (ctx: unknown, info: { documentId: string }) => T | Promise<T>,\n ): Promise<T> {\n return this.#client.documentScript<T>(step.toString());\n }\n\n #probe(step: DocumentProbeStep): Promise<DocumentProbeResult> {\n return this.#client.documentProbe(step);\n }\n}\n", "/** Editor and document automation over the shared session command wire.\n * Modeling executes in the editor tab; this client owns no model state. */\n\nimport type {\n ActiveDocumentCapture,\n AssetKind,\n AssetPreviewCapture,\n AssetPreviewOptions,\n AssetPreviewShotSetDefinition,\n AssetPreviewSource,\n CaptureDimensions,\n DocumentLookOutcome,\n StageFrameCostReading,\n EditorChromeCapture,\n EditorChromeCaptureOptions,\n EditorClient,\n EditorState,\n EditorView,\n EditorWorkspaceName,\n HistoryStep,\n InspectedFieldWrite,\n InspectedHierarchy,\n InspectedInspection,\n LabeledShotSetCapture,\n OpenedDocument,\n PresentedEditorView,\n ShadingMode,\n StructureOp,\n StructureOpOptions,\n StructureOpResult,\n ViewPreset,\n ViewportCapture,\n} from '@volter/editor-sdk';\nimport { LiveEditorDocument } from './editor-document.js';\n\n/** A panel `showPanel` can focus: the viewport tabs, the console, the build\n * surface, or any key the editor's own static-panel registry holds\n * (`hierarchy`, `assets`, `asset-library`, `inspector`, `history`, \u2026) \u2014 which\n * is why this is open: the registry, not this union, is the vocabulary. */\nexport type PanelName =\n | 'viewport-edit'\n | 'console'\n // Keeps the literals above in autocomplete while admitting every key the\n // editor's registry holds \u2014 the registry answers, this union only hints.\n | (string & {});\n\nconst EXTENSION_KIND: Record<string, AssetKind> = {\n '.glb': 'model',\n '.gltf': 'model',\n '.png': 'image',\n '.jpg': 'image',\n '.jpeg': 'image',\n '.webp': 'image',\n '.gif': 'image',\n '.svg': 'image',\n '.hdr': 'image',\n '.exr': 'image',\n '.mp4': 'video',\n '.webm': 'video',\n '.mp3': 'audio',\n '.ogg': 'audio',\n '.wav': 'audio',\n '.flac': 'audio',\n '.glsl': 'source',\n '.vert': 'source',\n '.frag': 'source',\n // PROJECT SCRIPTS ARE SOURCE. Without these the guess below falls through to\n // `'json'`, the asset-document router sends the file to the generic JSON\n // viewer (`asset-documents.tsx#assetDocumentViewerRoute`: `spec.kind ===\n // 'json'` is decided before any content routing), and the LIVE MODELING\n // DOCUMENT never mounts \u2014 `editor.openAsset('src/lib/fox/fox.model.ts')`\n // silently shows a text pane instead of the model. Only `kind: 'source'`\n // reaches `SourceAssetViewer`, which is what content-routes a project script\n // to `LiveModuleDocument`. The set matches that viewer's own\n // `isProjectScriptPath` regex, `/\\.(?:[cm]?[jt]sx?)$/`.\n '.ts': 'source',\n '.tsx': 'source',\n '.mts': 'source',\n '.cts': 'source',\n '.js': 'source',\n '.jsx': 'source',\n '.mjs': 'source',\n '.cjs': 'source',\n};\n\n/**\n * Lightweight extension-based `AssetKind` guess for `openAsset`'s optional\n * `kind` argument. Deliberately independent of (not shared with) the\n * editor's own `AssetBrowser.tsx#getAssetKind` \u2014 that function is a private,\n * React-component-local helper of a package `@volter/editor-live` has no dependency\n * on. Callers with an unusual extension can always pass `kind` explicitly.\n */\nexport function inferAssetKind(path: string): AssetKind {\n // `.prefab.json` is retired (PRs #578/#581/#589) but the `'prefab'`\n // AssetKind itself remains in `@volter/editor-sdk` for view-link compatibility.\n if (path.endsWith('.prefab.json')) return 'prefab';\n const dot = path.lastIndexOf('.');\n const ext = dot >= 0 ? path.slice(dot).toLowerCase() : '';\n return EXTENSION_KIND[ext] ?? 'json';\n}\n\nexport class LiveEditor {\n /** `#`-private, not `private`: `volter-model-editor eval --list` enumerates this object's\n * real runtime members, and TypeScript's erased `private` would leave the\n * raw `EditorClient` advertised beside them. */\n readonly #client: EditorClient;\n\n /**\n * The ACTIVE center document's own DOM: read it, click it, key it, paste\n * into it. The one door onto editor chrome that is not play-mode gated, and\n * deliberately scoped to that document alone \u2014\n * `packages/editor-sdk/src/kit/editor-document-probe.ts` carries the design and the\n * refusal contract. Screenshotting the same subject is\n * {@link LiveEditor.captureActiveDocument}, not a fifth verb here.\n */\n readonly document: LiveEditorDocument;\n\n constructor(client: EditorClient) {\n this.#client = client;\n this.document = new LiveEditorDocument(client);\n }\n\n /**\n * THE BLENDER LANE'S VERBS, from `volter-model-editor eval`.\n *\n * Blender runs headless in the editor tab's worker (ARCHITECTURE-CORE, \"THE\n * BLENDER IN THE TAB IS BLENDER\") and answers `blender-start`,\n * `blender-execute`, `blender-scene-info`, `blender-object-info`,\n * `blender-screenshot-view`, `blender-read-file`, `blender-write-file`,\n * `blender-list-files`, `blender-stop` and `blender-status`. They were\n * reachable from `@volter/editor-sdk` and through `volter blender-mcp` but from\n * no GENERAL door, so driving a session meant writing an MCP client script\n * per question \u2014 the same discovery failure `eval-surface.ts`'s header\n * records, in a lane that had not noticed it yet.\n *\n * volter-model-editor eval \"await editor.blender('blender-execute', { code: 'import bpy; print(len(bpy.data.objects))' })\"\n *\n * `blender-status` is the only verb that creates nothing: it answers whether\n * this tab already has a session without starting one.\n */\n async blender<T extends object = Record<string, unknown>>(\n type: `blender-${string}`,\n fields: Record<string, unknown> = {},\n ): Promise<T> {\n return this.#client.blender<T>(type, fields);\n }\n\n /**\n * The active authoring adapter's persistence destination \u2014 where a save would\n * land (`status().savePath`). A read only: a three root has no scene document\n * to open, and its root is activated instead.\n */\n async scene(): Promise<string | null> {\n const state = await this.#client.getState();\n return state.savePath;\n }\n\n /**\n * Make the connected human editor show the same subject/view as the agent.\n * The returned URL is a compact, shareable projection \u2014 not a serialized\n * workspace or document payload.\n */\n async present(view: EditorView): Promise<PresentedEditorView> {\n return this.#client.present(view);\n }\n\n /** The human editor's actual active document, selection, camera and utility. */\n async currentView(): Promise<EditorView> {\n return this.#client.currentView();\n }\n\n /**\n * Capture the same center document the human is currently looking at.\n *\n * A number is a SQUARE of that size \u2014 the default, and the right shape for\n * an unstaged look at a model. `{width, height}` asks for a shaped frame, so\n * a video-aspect look needs no crop afterwards. Both are bounded by the\n * relay budget (64-1024 per side, total no larger than a 1024 square); see\n * `@volter/editor-sdk`'s `CaptureDimensions`.\n * Supply a view to present and photograph it in one editor request.\n */\n /** The active document's RENDER alone, at the size asked for: what the document draws,\n * without what the viewport draws over it (its navigation gizmo, its readouts). To see a\n * stage as the person does, use `captureEditorChrome({ region: 'document' })`. */\n async captureActiveDocument(\n size?: CaptureDimensions,\n view?: EditorView,\n ): Promise<ActiveDocumentCapture> {\n return this.#client.captureActiveDocument(size, view);\n }\n\n /**\n * Photograph the editor PAGE \u2014 every panel, tab strip and viewport as the\n * person sees it. the editor's `screenshot editor` command is this verb from the shell. The\n * one door for judging chrome sighted: a skin, a workspace arrangement or a\n * contributed panel is looked at through this, never guessed at from DOM\n * probes. The page at its own layout, `scale` output pixels per CSS pixel\n * (default `devicePixelRatio`) \u2014 a 1 px border or a glyph stroke is only\n * judgeable at the scale the reference it is compared against was captured\n * at, and the result reports its own `size` and `scale`.\n */\n async captureEditorChrome(options?: EditorChromeCaptureOptions): Promise<EditorChromeCapture> {\n return this.#client.captureEditorChrome(options);\n }\n\n /** `'all'` -> `EditorClient.selectAll()` (mirrors `volter select --all`); otherwise `EditorClient.select(id)` (mirrors `volter select <entityId>`). */\n async select(id: string | 'all'): Promise<void> {\n if (id === 'all') {\n await this.#client.selectAll();\n return;\n }\n await this.#client.select(id);\n }\n\n /** Mirrors `volter deselect`. */\n async deselect(): Promise<void> {\n await this.#client.select(null);\n }\n\n /** No `id` -> focus the current selection (mirrors bare `volter focus`); `id` given -> focus that entity. */\n async focus(id?: string): Promise<void> {\n if (id !== undefined) {\n await this.#client.focusEntity(id);\n return;\n }\n await this.#client.focusSelection();\n }\n\n /**\n * Frame the edit viewport camera on one entity. Same framing as\n * `focus(id)`, but an entity id the scene does not know THROWS, naming the\n * id \u2014 where `focus` quietly does nothing. Reach for this whenever the next\n * step reads the viewport (`screenshot()`, an\n * `assetPreview(..., { stage: 'scene' })`): a framing that silently missed\n * would otherwise be indistinguishable from one that worked.\n */\n async frame(entityId: string): Promise<void>;\n /**\n * Bare `frame()` frames the OPEN Object3D document's subject instead \u2014 its\n * selection if it has one, else the whole model: the toolbar's own Frame\n * button, reachable from a script. `fit` scales the fitted distance (1 is\n * that button's tight fit, 1.5 stands back a little for a shot).\n */\n async frame(options?: { readonly fit?: number }): Promise<void>;\n async frame(target?: string | { readonly fit?: number }): Promise<void> {\n if (typeof target === 'string') {\n await this.#client.frameEntity(target);\n return;\n }\n await this.#client.frameDocument(target?.fit);\n }\n\n /**\n * WATCH THE AGENT LOOK AROUND THE MODEL.\n *\n * Swings the open Object3D document's camera \u2014 the camera the human's tab is\n * showing \u2014 around the framed subject by `azimuth`/`elevation` RADIANS,\n * animated over `duration` seconds (default 0.6), and resolves when the move\n * ends. This is deliberately not a jump cut: the point of the verb is that a\n * person watching sees the agent walk around the thing it is working on.\n *\n * `await editor.orbit({ azimuth: Math.PI / 2 })` \u2014 a quarter turn to the right.\n *\n * There is ONE camera, and the human owns it: a drag during the move cancels\n * it exactly where it is, and the resolved outcome says `cancelledBy:\n * 'human'` rather than throwing. A second look verb supersedes the first.\n * The move is drawn by the document's own frame loop, so a document that\n * isn't being drawn (background tab, inactive panel) doesn't orbit.\n */\n async orbit(options: {\n /** RADIANS, relative to where the camera is now. `Math.PI / 2` is a\n * quarter turn; degrees are not accepted and `90` is fourteen turns. */\n readonly azimuth?: number;\n /** RADIANS, relative to where the camera is now. */\n readonly elevation?: number;\n /** SECONDS the move takes (default 0.6). */\n readonly duration?: number;\n }): Promise<DocumentLookOutcome> {\n // AN UNKNOWN KEY IS REFUSED BY NAME. Every member here is optional, so a\n // misspelling \u2014 `yaw` for `azimuth`, `pitch` for `elevation` \u2014 used to\n // orbit by nothing at all while the outcome still reported a plausible\n // ABSOLUTE azimuth, which reads exactly like a move that happened\n // (measured 2026-09-21, and it cost a round). The keys and their unit are\n // in the refusal because that is the moment the caller needs them.\n const known = ['azimuth', 'elevation', 'duration'];\n const unknown = Object.keys(options ?? {}).filter((key) => !known.includes(key));\n if (unknown.length > 0)\n throw new Error(\n `editor.orbit: ${unknown.join(', ')} ${unknown.length === 1 ? 'is not a key' : 'are not keys'} ` +\n 'this verb takes. It takes azimuth and elevation in RADIANS (relative to where the ' +\n 'camera is now) and duration in SECONDS.',\n );\n return this.#client.orbitDocument(options);\n }\n\n /**\n * A slow full revolution of the open document's subject \u2014 {@link orbit} with\n * the turns spelled out and a constant angular rate. Resolves at the end of\n * the last revolution.\n */\n async turntable(options?: {\n readonly seconds?: number;\n readonly revolutions?: number;\n }): Promise<DocumentLookOutcome> {\n return this.#client.turntableDocument(options);\n }\n\n /**\n * What a frame of the open 3D document's stage costs when nothing caps it: `frames` of the\n * stage's own frame back to back, each waited out on the GPU (median, p95, min ms), the canvas\n * with its device pixel ratio, what was drawn after culling against what the scene holds, and\n * the draw mode. `stage` names another stage by its id (a split's second area,\n * `<documentId>#area-2`).\n */\n async frameCost(options?: { readonly frames?: number; readonly stage?: string }): Promise<StageFrameCostReading> {\n return this.#client.frameCostDocument(options);\n }\n\n async view(preset: ViewPreset): Promise<void> {\n await this.#client.viewPreset(preset);\n }\n\n /**\n * Switch the editor's NAMED WORKSPACE \u2014 `await editor.workspace('model')`.\n *\n * A workspace is a task-named LAYOUT MEMORY over the one dock\n * (ARCHITECTURE-CORE \u00A7Editor chrome): `game` (the default, the editor's\n * standing arrangement), `model`, `sculpt`, `texture`, `animate`, `look`.\n * Switching is an EXPLICIT act \u2014 nothing in the editor moves chrome on its\n * own, opening a document included \u2014 and this is the session door to it,\n * beside `Window \u2192 Workspace` and the registered actions.\n *\n * Resolves once the dock has finished rebuilding, so a capture taken\n * immediately after photographs the arrangement that was asked for. Each\n * workspace remembers the user's own hand-tuning per project, so switching\n * away and back is lossless.\n */\n async workspace(id: EditorWorkspaceName): Promise<void> {\n await this.#client.setWorkspace(id);\n }\n\n /**\n * Apply a STYLE BUNDLE by id \u2014 the chrome's palette, material and icon set in\n * one gesture, the session door beside\n * `View \u2192 <Style> Style`. A bundle the open project does not offer refuses\n * and names the vocabulary; `currentView().style` reports the one worn.\n */\n async style(id: string): Promise<void> {\n await this.#client.setStyle(id);\n }\n\n /**\n * A document stage's viewport PRESENTATION \u2014 its draw mode, lighting, backdrop and overlays\n * (`@volter/editor-sdk/kit/viewport-presentation`) \u2014 resolved. With `layer`, that choice is\n * recorded for the view first, as a person's toolbar change would be, e.g.\n * `presentation('model:src/models/cube.blend', { all: { lighting: { studioPreset: 'kit' } } })`.\n * With a STRING, the named view of that id (`*.view.ts`, e.g. `'godot'`) is put on the view\n * whole; the answer's `viewPresets` lists the ones registered.\n */\n async presentation(\n documentId: string,\n layer?: Parameters<EditorClient['viewportPresentation']>[1],\n ): ReturnType<EditorClient['viewportPresentation']> {\n return this.#client.viewportPresentation(documentId, layer);\n }\n\n /**\n * Set the MATERIAL apart from the bundle that usually carries it.\n * Appearance is palette \u00D7 material, independent axes by ruling, so\n * `style()` alone can never say whether a cost belongs to the blur or to\n * the palette. This is the door that measures them apart; it answers with\n * what the chrome wears afterwards (`style` is `null` when the mix matches\n * no registered bundle).\n */\n async appearance(appearance: {\n readonly material?: string;\n }): Promise<{ material: string; style: string | null }> {\n return this.#client.setAppearance(appearance);\n }\n\n /** Focus an editor panel: a viewport tab, the console, the build surface, or\n * any key the editor's static-panel registry holds \u2014 an unknown key refuses\n * naming the ones it does. */\n async showPanel(name: PanelName): Promise<void> {\n switch (name) {\n case 'viewport-edit':\n await this.#client.showViewport('edit');\n return;\n case 'console':\n await this.#client.toggleConsole();\n return;\n default:\n // Every other name is the EDITOR's to resolve, against its live panel\n // registry. A list kept here could only ever be a copy going stale.\n await this.#client.showPanel(name);\n return;\n }\n }\n\n /** `kind` inferred from `path`'s extension when omitted (`inferAssetKind`) \u2014 pass it explicitly to override. */\n async openAsset(path: string, kind?: AssetKind): Promise<void> {\n // A `.blend` is not an asset but a Model document the project's finder lists; opened as an\n // asset it fell to the extension guess's `json` and showed its bytes.\n if (kind === undefined && path.toLowerCase().endsWith('.blend'))\n throw new Error(\n `${path} is a Blender Model document, not an asset: open it with editor.open(\"model:${path}\").`,\n );\n await this.#client.openAsset(path, kind ?? inferAssetKind(path));\n }\n\n /**\n * SELECT a project asset \u2014 the browser's single click, which fills the\n * Inspector without opening a document. `openAsset` is the double click.\n *\n * This is how a project's own `asset.inspector` section is reached: select\n * the file it matches, then `inspect()` lists the verbs that section\n * declares and `runAction(id)` runs one. Selecting a path nothing matches\n * is not an error \u2014 the Inspector shows what it has, exactly as it does\n * for a human.\n */\n async selectAsset(path: string): Promise<void> {\n await this.#client.selectAsset(path);\n }\n\n /**\n * Captures the editor's native four-view preview. A bare string is a\n * project-relative asset path (the common case); an explicit source object\n * targets a path, a LIVE SCENE ENTITY (`assetPreview({ entityId }, \u2026)`) \u2014\n * which is what makes `options.stage: 'scene'`, the entity photographed\n * where it stands under the scene's own lighting, reachable from here \u2014 or\n * RAW GLB BYTES (`assetPreview({ glbBase64 }, \u2026)`), for a model that exists\n * only in the calling Node process's memory and has never been written to\n * disk. `stage` defaults to `'lab'`, the neutral Asset Lab staging this has\n * always produced, and the bytes form is lab-only.\n */\n async assetPreview(\n source: string | AssetPreviewSource,\n options?: AssetPreviewOptions,\n ): Promise<AssetPreviewCapture> {\n return this.#client.captureAssetPreview(\n typeof source === 'string' ? { assetPath: source } : source,\n options,\n );\n }\n\n /**\n * The same subject photographed as a LABELED SHOT SET instead of the four\n * views \u2014 a caller-supplied definition of turntable yaws and bone-anchored\n * crops, rendered against the asset's own skeleton, with a contact sheet.\n * Every source {@link assetPreview} takes works here, GLB bytes included:\n * a shot set stages its own subject, so it needs no place to stand.\n *\n * Sole in-repo caller today: `project.bake.preview`'s `--orbit` lane.\n */\n async assetPreviewShots(\n source: string | AssetPreviewSource,\n definition: AssetPreviewShotSetDefinition,\n options?: AssetPreviewOptions,\n ): Promise<LabeledShotSetCapture> {\n return this.#client.captureShotSetPreview(\n typeof source === 'string' ? { assetPath: source } : source,\n definition,\n options,\n );\n }\n\n async grid(on: boolean): Promise<void> {\n await this.#client.setGrid(on);\n }\n\n async helpers(on: boolean): Promise<void> {\n await this.#client.setHelpers(on);\n }\n\n async stats(on: boolean): Promise<void> {\n await this.#client.setStats(on);\n }\n\n async shading(mode: ShadingMode): Promise<void> {\n await this.#client.setShadingMode(mode);\n }\n\n /**\n * READ the inspector, as data \u2014 the serialized inspection subject\n * (`editor.inspect()`; design: `docs/ARCHITECTURE-CORE.md` \u00A7Editor chrome,\n * \"The Inspection Model\"). This is the Figma-Inspect analog: whatever a\n * human would see in the inspector right now \u2014 the subject's identity, its\n * verbs, and every identified section in display order, with a `fields`\n * section's CURRENT VALUES at their scriptable `path`s.\n *\n * Reach for it whenever the next step depends on what an object actually\n * IS: `await editor.select(id)` then `await editor.inspect()` answers \"what\n * properties does this thing have, and what are they set to\" in one call,\n * against the same model the panel renders \u2014 no scene-graph reads, no\n * guessing at property names.\n *\n * When the inspector is showing NOTHING \u2014 nothing selected on a surface\n * with no empty-state subject of its own, which is most of them \u2014 the answer\n * is `{none: true}`, so \"the human sees no inspector\" and \"the read failed\"\n * are never the same value. A surface whose empty space IS a real thing (an\n * open Asset Lab document) still answers with that subject, and never with\n * another surface's.\n *\n * A `custom` section body is a named opaque: the editor renders it with\n * React, so the wire reports its identity rather than pretending to describe\n * its rendering \u2014 plus, when the section can say what it DISPLAYS, a `data`\n * payload in its own vocabulary (`transform` carries\n * `{position, rotation, scale}`, rotation in Euler XYZ degrees).\n */\n async inspect(): Promise<InspectedInspection> {\n return this.#client.inspect();\n }\n\n /** Run one verb listed by `inspect().quickActions`, through the same action\n * the human Inspector button invokes. */\n async runAction(actionId: string): Promise<InspectedInspection> {\n return this.#client.runInspectionAction(actionId);\n }\n\n /**\n * Run ONE command by id \u2014 the door to everything the command palette lists.\n *\n * ONE NAME (orchestrator ruling 2026-09-19). There were briefly TWO doors\n * onto the one view-verb table \u2014 this one and `editor.viewVerb(view, verb)`,\n * which addressed the same registry by its two halves. A second addressing\n * of one table is a second name for one thing, and an agent reading\n * `--list` had to choose between them with nothing to choose on. This door\n * stays because it is strictly wider: it addresses a COMMAND ID, so under\n * the frame it reaches everything the workbench knows \u2014 a `volter.action.<id>`\n * editor action, one of VS Code's own \u2014 and not only a view. A VIEW is\n * reached by spelling its verb's command id:\n *\n * await editor.command('volter.blender-uv-view.state')\n * await editor.command('volter.blender-uv-view.zoom', { to: 600 })\n *\n * await editor.command('volter.blender-node-view.view-all')\n * await editor.command('volter.blender-node-view.look', { node: 'Principled BSDF' })\n *\n * Under the Code-OSS frame this is the workbench's own command service, so\n * any command id works \u2014 ours and VS Code's alike. Standalone the editor's `edit` command\n * has no command service and answers the `volter.<view>.<verb>` shape off the\n * SAME verb table the frame's commands call, refusing any other id by name.\n * One table, two doors, exactly like the keymap's.\n *\n * Answers with whatever the command returned \u2014 a view verb's own state, or\n * `null` for a command that returns nothing.\n */\n async command(commandId: string, args?: unknown): Promise<unknown> {\n return this.#client.runCommand(commandId, args);\n }\n\n /**\n * RESTRUCTURE the authored tree \u2014 the hierarchy context menu's own verbs.\n *\n * `create`, `delete`, `duplicate`, `reparent`, `reorder`, `wrap`, `unwrap`,\n * `group`, `ungroup`, `copy`, `cut`, `paste`; `extractComponent` and\n * `forkComponent` are the two that write whole new files and have their own\n * doors below. All of them run the SAME `authoring/consumer-actions.ts`\n * helpers the menu items call, so there is one implementation of each op and\n * not a second that can disagree with what a human gets.\n *\n * It exists because the menu is a POINTER surface: every one of these ops was\n * reachable only by right-clicking a hierarchy row, which is nothing an agent\n * can do \u2014 so for an ingest root, whose only authoring surface IS the editor,\n * structure was closed entirely.\n *\n * `id`/`ids` default to the current selection. The answer carries the same\n * per-edit `write` ack `setField` does, so `write.persisted` tells a saved\n * restructure from a live-only one. An op the active adapter does not provide\n * REJECTS by name \u2014 never a silent no-op.\n */\n async structure(op: StructureOp, options?: StructureOpOptions): Promise<StructureOpResult> {\n return this.#client.structureOp(op, options ?? {});\n }\n\n /**\n * \"Extract Component\u2026\" \u2014 lift the selected native subtree into its own\n * component file (plus a story) and replace the callsite with it.\n *\n * Answers the action's own sentence, which NAMES both new files, because\n * undo owns the callsite edit and will not remove them.\n */\n async extractComponent(options?: { id?: string; name?: string }): Promise<string> {\n return (await this.#client.extractComponent(options ?? {})).hint;\n }\n\n /**\n * \"Fork Component\u2026\" \u2014 copy the selected instance's component definition to a\n * new file and retarget THIS CALLSITE at it.\n *\n * One callsite is the unit of the edit; when that callsite sits inside a\n * component rendered many times, every one of those renders now renders the\n * fork.\n */\n async forkComponent(options?: { id?: string }): Promise<string> {\n return (await this.#client.forkComponent(options ?? {})).hint;\n }\n\n /**\n * READ the hierarchy panel, as data \u2014 the rows a human is looking at right\n * now, nested exactly as the panel nests them.\n *\n * The companion to {@link inspect}: that one answers \"what IS the selected\n * thing\", this one answers \"what does the tree LOOK LIKE\". It is the panel's\n * own output, not a fresh walk of the scene \u2014 the adapter's tree after the\n * component marks fold implementation subtrees (bones, particle renderers,\n * instanced pools), after the internals reveal, the document promotion, the\n * child cap, the collapse state, the search filter and the selection scope.\n *\n * Works in play mode and edit mode; the answer says which (`playState`,\n * `activeViewportTab`), because the two are different adapters and a tree\n * that looks wrong is very often the wrong adapter's tree.\n *\n * Prefer this over `status().entities`, which is deliberately a different\n * question \u2014 the RAW adapter tree, unprojected. A panel that renders the\n * wrong rows looks perfectly healthy in that facet.\n *\n * Each row carries `childCount` (what its caret opens), `internalChildCount`\n * (what is folded behind \"Reveal Internals\") and `expandable` (whether the\n * panel draws a caret at all), so \"this subtree exists but nothing in the UI\n * opens it\" is a fact you can read rather than one you have to notice.\n *\n * Rejects, naming the panel, when no hierarchy panel is mounted \u2014 an empty\n * tree would be a fabricated answer about a surface nobody is being shown.\n */\n async hierarchy(): Promise<InspectedHierarchy> {\n return this.#client.hierarchy();\n }\n\n /** Expand every branch through the Hierarchy panel's own action. */\n async expandHierarchyAll(): Promise<void> {\n await this.#client.expandHierarchyAll();\n }\n\n /** Collapse every branch through the same panel action. Expanding is\n * persisted per project, so without this the tree's REST STATE \u2014 what a\n * person sees on opening the project \u2014 is unreachable once any reader has\n * expanded it. */\n async collapseHierarchyAll(): Promise<void> {\n await this.#client.collapseHierarchyAll();\n }\n\n /**\n * Write one editable field from `inspect()` by its stable path, through the\n * same Inspector IO and persistence boundary the human control uses.\n *\n * The answer is `{ subject, write }`, and `write` is the half worth reading\n * first: a write with no persistence route open still succeeds \u2014 it lands on\n * the live object and journals live-only \u2014 so `write.persisted` is how you\n * tell a saved edit from one that will not survive the session, without\n * diffing the tree. `write.destination` is the adapter's own words for where\n * it went (\"live-only (not saved)\" is a destination, never silence).\n */\n async setField(path: string, value: unknown): Promise<InspectedFieldWrite> {\n return this.#client.setInspectionField(path, value);\n }\n\n /**\n * REMOVE one field's authored override \u2014 the revert arrow, as a command.\n *\n * Reach for this instead of `setField` whenever you are UNDOING an edit that\n * added a property the source did not carry: `setField` can only write a\n * value, so setting the default back leaves `position={[0, 0, 0]}` in the\n * file where there was nothing before. Only this door restores the bytes.\n *\n * The answer is the same `{ subject, write }` shape, awaited past the bytes.\n * It rejects with `code: 'REMOVAL_UNAVAILABLE'` when the field is not\n * declared removable or the lane has no removal door \u2014 which is a missing\n * seam to report, not a removal that failed.\n */\n async removeField(path: string): Promise<InspectedFieldWrite> {\n return this.#client.removeInspectionField(path);\n }\n\n /** Open a document by its adapter-declared id, through its registered owner. */\n async open(id: string): Promise<OpenedDocument> {\n return this.#client.open(id);\n }\n\n /** Undo / redo one project transaction, through the session's own history\n * queue \u2014 the same one the keyboard shortcut drives. */\n async undo(): Promise<HistoryStep> {\n return this.#client.undo();\n }\n\n async redo(): Promise<HistoryStep> {\n return this.#client.redo();\n }\n\n /** Reload the editor's page and resolve once the new document answers. */\n async reloadPage(): Promise<void> {\n await this.#client.reloadPage();\n }\n\n /** Mirrors the editor's `status` command \u2014 the full live editor state as JSON. */\n async status(): Promise<EditorState> {\n return this.#client.getState();\n }\n\n /** A live viewport PNG (`EditorClient.captureViewport`) \u2014 no direct CLI verb exists; this is the closest wire read. */\n async screenshot(size?: number): Promise<ViewportCapture> {\n return this.#client.captureViewport(size);\n }\n}\n", "/** Registered project tools over the current shared editor session. */\n\nimport type {\n EditorClient,\n ProjectToolCatalog,\n ProjectToolCatalogEntry,\n ProjectToolOutcome,\n} from '@volter/editor-sdk';\n\nexport class LiveTools {\n /** `#`-private for the same reason `LiveEditor.#client` is. */\n readonly #client: EditorClient;\n\n constructor(client: EditorClient) {\n this.#client = client;\n }\n\n /** Enumerate the exact `package.json#volter.tools` catalog without executing it. */\n async list(): Promise<ProjectToolCatalog> {\n return this.#client.listProjectTools();\n }\n\n /** Return one tool's discoverable metadata, or `null` when it is not registered. */\n async describe(name: string): Promise<ProjectToolCatalogEntry | null> {\n const catalog = await this.list();\n return catalog.tools.find((tool) => tool.name === name) ?? null;\n }\n\n /**\n * Invoke the same validated callable used by the editor and CLI.\n *\n * `instance` names WHICH mounted instance the tool should drive when several\n * are live (multiplayer authoring) \u2014 it reaches the tool as `ctx.instance`,\n * and a tool that drives the game binds\n * `game.instance(ctx.instance)` from it. Omitted is the single-instance case;\n * the tool then targets the sole live instance, exactly as before.\n */\n async run(\n name: string,\n input: unknown = {},\n options: { confirm?: boolean; instance?: string } = {},\n ): Promise<ProjectToolOutcome> {\n return this.#client.runProjectTool(name, input, options);\n }\n}\n", "/**\n * `lazyChainProxy` \u2014 turns an async \"resolve the real object\" function into\n * a synchronously-importable stand-in that supports the SAME call shape as\n * the real thing, including nested member access (`game.input.hold(...)`,\n * `editor.document.query(...)`), by recording the property-access PATH and only\n * resolving + walking it down at the point of an actual function CALL.\n *\n * This is what makes `index.ts`'s top-level `export const editor = ...` /\n * `game` / `page` work as plain values a script can `import { editor, game,\n * page } from '@volter/editor-live'` and call immediately \u2014 each call transparently\n * awaits the memoized `connect()` first.\n *\n * Limitation (by design, documented on `index.ts`'s exports too): only\n * FUNCTION-shaped access resolves through this proxy \u2014 `game.input.hold(x)`\n * works, but reading a plain data property (e.g. `game.fenceTick`) would\n * return another inert proxy, not the real number, since there is no\n * function CALL to trigger resolution. Every documented `editor`/`game`/\n * `page` member is a method, so this never bites the documented surface.\n */\n\ntype AnyFn = (...args: unknown[]) => unknown;\n\nfunction isFunction(value: unknown): value is AnyFn {\n return typeof value === 'function';\n}\n\nfunction walk(root: unknown, path: PropertyKey[]): { thisArg: unknown; fn: unknown } {\n if (path.length === 0) return { thisArg: undefined, fn: root };\n let obj: Record<PropertyKey, unknown> = root as Record<PropertyKey, unknown>;\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i] as PropertyKey;\n obj = obj[key] as Record<PropertyKey, unknown>;\n }\n const lastKey = path[path.length - 1] as PropertyKey;\n return { thisArg: obj, fn: obj[lastKey] };\n}\n\n/**\n * `resolveRoot` is called (and its result awaited) on every terminal\n * function call reached through the returned proxy \u2014 callers typically wire\n * it to a memoized `connect()` (see `index.ts`), so repeated calls across\n * many proxy invocations still resolve only once.\n */\nexport function lazyChainProxy<T>(\n resolveRoot: () => Promise<unknown>,\n path: PropertyKey[] = [],\n): T {\n const callableTarget = (() => {}) as unknown as object;\n return new Proxy(callableTarget, {\n get(_target, prop) {\n // Never look thenable \u2014 `await`ing a proxy (accidentally, or via a\n // generic helper checking `typeof x.then`) must not trigger resolution\n // or hang; there is no promise here, only a call-shaped stand-in.\n if (prop === 'then' || prop === 'catch' || prop === 'finally') return undefined;\n return lazyChainProxy(resolveRoot, [...path, prop]);\n },\n apply(_target, _thisArg, args) {\n return resolveRoot().then((root) => {\n const { thisArg, fn } = walk(root, path);\n if (!isFunction(fn)) {\n const label = path.length > 0 ? path.map(String).join('.') : '(the connected value)';\n throw new TypeError(`@volter/editor-live: ${label} is not a function on the connected session.`);\n }\n return fn.apply(thisArg, args);\n });\n },\n }) as T;\n}\n", "/** Resolve an existing session for exactly one project.\n * Prefer the project's hint, verify it against the served canonical path,\n * then consult the shared registry. Never fall back to another project.\n * Storage identifiers move with the server in the coordinated migration. */\n\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { resolveManifestPath } from '@volter/editor-project/manifest/locate';\nimport { resolveProductForProject } from '@volter/editor-sdk/session/product-locator';\nimport {\n EDITOR_SESSION_DISCOVERY_TIMEOUT_MS,\n type EditorSessionInfo,\n type SessionListingTransport as SessionDiscoveryTransport,\n HttpSessionDiscovery,\n servedProjectAnswer,\n withTimeout,\n} from '@volter/editor-sdk/session/discovery';\n\n/** Nearest ancestor containing the project's canonical manifest. */\nexport function findProjectRootFrom(dir: string): string | null {\n let cur = resolve(dir);\n for (;;) {\n if (existsSync(resolveManifestPath(cur))) return cur;\n const parent = dirname(cur);\n if (parent === cur) return null;\n cur = parent;\n }\n}\n\n/** The minimal slice of `EditorTransport` `resolveSession` actually needs \u2014 narrower than the full interface so a test double only has to implement one method. */\nexport type SessionListingTransport = SessionDiscoveryTransport;\n\nexport interface ResolvedSession {\n /** Editor dev-server port the resolved session is listening on. */\n port: number;\n /** Absolute project root \u2014 the nearest ancestor of the requested directory containing `volter.project.json`. */\n projectRoot: string;\n}\n\nexport interface SessionResolutionDeps {\n /** Session listing + liveness verification \u2014 defaults to a real `HttpSessionDiscovery`. Overridable for tests. */\n transport?: SessionListingTransport;\n /** Project-root discovery \u2014 defaults to the real fs walk (`findProjectRootFrom` above). Overridable for tests. */\n findProjectRootFrom?: (dir: string) => string | null;\n /** Project-local session hint reader. Defaults to `.volter/session.json`. */\n readProjectSession?: (projectRoot: string) => ProjectSessionHint | null;\n /** Exact-session verifier. Defaults to GET /__editor/project + canonical project matching. */\n verifyProjectSession?: (hint: ProjectSessionHint, projectRoot: string) => Promise<boolean>;\n}\n\nexport interface ProjectSessionHint {\n port: number;\n pid: number;\n url: string;\n startedAt: string;\n}\n\nfunction canonicalPath(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n return resolve(path);\n }\n}\n\nfunction readProjectSession(projectRoot: string): ProjectSessionHint | null {\n try {\n const value: unknown = JSON.parse(\n readFileSync(join(projectRoot, '.volter', 'session.json'), 'utf8'),\n );\n if (typeof value !== 'object' || value === null) return null;\n const hint = value as Record<string, unknown>;\n if (\n typeof hint['port'] !== 'number' ||\n !Number.isInteger(hint['port']) ||\n hint['port'] <= 0 ||\n typeof hint['pid'] !== 'number' ||\n typeof hint['url'] !== 'string' ||\n typeof hint['startedAt'] !== 'string'\n ) {\n return null;\n }\n return hint as unknown as ProjectSessionHint;\n } catch {\n return null;\n }\n}\n\n/**\n * WHICH PROJECT a `/__editor/project` body says its server is serving, and the\n * reason it cannot describe it.\n *\n * `serving` is the server's own statement of \"I AM serving this project, I\n * just cannot describe it\" \u2014 its manifest is unparseable or fails strict\n * validation. The route added it because a bare `{ project: null }` there is\n * indistinguishable from \"no project open\"; reading only `project.path`\n * reproduces that collapse on this side, and the cost is the worst kind of\n * wrong answer: this door refused a session that WAS open on the caller's\n * project with \"no live editor session found \u2026 (N other live session(s) found,\n * but none open this project)\" \u2014 sending the operator to start an editor that\n * was already running, with the real defect (their own manifest) never named.\n */\n\n/**\n * What the server on `port` says it serves \u2014 `undefined` when it did not\n * answer at all. One probe: the manifest failure arrives with the path, so\n * neither the hint path nor the refusal path pays a second round trip.\n */\nasync function probeServedProject(\n port: number,\n): Promise<{ path: string | null; manifestError: string | null } | undefined> {\n try {\n const response = await fetch(`http://127.0.0.1:${port}/__editor/project`, {\n signal: AbortSignal.timeout(EDITOR_SESSION_DISCOVERY_TIMEOUT_MS),\n });\n if (!response.ok) return undefined;\n return servedProjectAnswer(await response.json());\n } catch {\n return undefined;\n }\n}\n\n/**\n * The refusal for a session that IS this project's and cannot be driven,\n * because the project's manifest does not load.\n *\n * A refusal, not an attach: with no readable manifest the editor page itself\n * renders its startup-error screen, so there is no editor and no game behind\n * this door to bind `{ editor, game, page, tools, session }` to. What changed\n * is only that it now says the true thing \u2014 the failing file and key \u2014 instead\n * of \"no live editor session found\", which sent operators to start an editor\n * that was already running while their actual defect went unnamed.\n */\nfunction manifestRefusal(projectRoot: string, manifestError: string): Error {\n return new Error(\n `@volter/editor-live: the editor session for ${projectRoot} is live, but its volter.project.json does ` +\n 'not load, so there is no editor or game to drive \u2014 the editor page is showing this same ' +\n `error. Fix the manifest and retry; the session recovers on save, no restart needed.\\n${manifestError}`,\n );\n}\n\n/**\n * Resolve `projectDir` (default `process.cwd()`) to the port of its already-\n * running the editor's `edit` command session. Throws a descriptive error (never hangs\n * indefinitely \u2014 bounded by `EDITOR_SESSION_DISCOVERY_TIMEOUT_MS`, and never\n * silently attaches to an unrelated project's session \u2014 see the module doc\n * above) when no volter.project.json is found, or no live session covers it.\n */\n/**\n * THE REFUSAL WHEN NOTHING MATCHED \u2014 and it says WHICH nothing.\n *\n * \"No live editor session found \u2026 run the editor's `edit` command\" used to be the answer to\n * four different states, only one of which it described. The other three sent\n * the operator to start an editor that was already running:\n *\n * - discovery FAILED (a probe timeout under load) \u2014 nothing was learned, so\n * \"no session is running\" is not a fact anyone established;\n * - the registry was read and is genuinely empty \u2014 the one case the old text\n * was right about;\n * - sessions exist, but every one resolves to a different canonical path. In\n * a repo worked through git worktrees this is the ORDINARY miss: two\n * checkouts of the same project differ only in a path prefix, and a\n * symlinked worktree's `realpath` diverges from the path the caller typed.\n * Naming both sides is what makes it a two-second diagnosis instead of a\n * hunt.\n *\n * Each branch prescribes only what its own state supports.\n */\nfunction noMatchingSessionRefusal(\n projectRoot: string,\n canon: string,\n sessions: readonly EditorSessionInfo[],\n discoveryFailure: string | null,\n): Error {\n if (discoveryFailure !== null) {\n return new Error(\n `@volter/editor-live: could not READ the editor session registry while looking for ${projectRoot} \u2014 ` +\n `${discoveryFailure}. This is not the answer \"no editor is running\": the question went ` +\n 'unanswered, so nothing is known about what is live. Retry (a probe can time out while ' +\n `the box is loaded); if it keeps failing, ${sessionsCommandFor(projectRoot)} asks the same question directly.`,\n );\n }\n if (sessions.length === 0) {\n return new Error(\n `@volter/editor-live: the editor session registry is readable and lists NO live sessions, so none ` +\n `covers ${projectRoot}. @volter/editor-live only attaches to an already-running session \u2014 it ` +\n `never starts one \u2014 so run ${editCommandFor(projectRoot)} in that project first, then retry.`,\n );\n }\n const listed = sessions\n .map((s) => ` port ${s.port} \u2192 ${s.project === null ? '(no project)' : s.project}`)\n .join('\\n');\n return new Error(\n `@volter/editor-live: ${sessions.length} live editor session(s) are running, but none of them opens ` +\n `${projectRoot}. @volter/editor-live never silently attaches to a different project.\\n` +\n ` looking for (resolved): ${canon}\\n` +\n ` live sessions:\\n${listed}\\n` +\n ' If one of those is meant to be this project, the two paths differ after resolution \u2014 ' +\n 'the usual cause is a git worktree or a symlink, where the session was opened through a ' +\n `different path to the same files. Run ${editCommandFor(projectRoot)} from THIS path, or use the path the ` +\n 'session lists.',\n );\n}\n\nexport async function resolveSession(\n projectDir: string = process.cwd(),\n deps: SessionResolutionDeps = {},\n): Promise<ResolvedSession> {\n const findRoot = deps.findProjectRootFrom ?? findProjectRootFrom;\n const transport = deps.transport ?? new HttpSessionDiscovery();\n\n const projectRoot = findRoot(projectDir);\n if (projectRoot === null) {\n throw new Error(\n `@volter/editor-live: no volter.project.json found in ${projectDir} or any parent directory \u2014 is this a project?`,\n );\n }\n\n // The editor writes this exact-project hint at boot and removes it on\n // shutdown. Prefer it over a global all-session scan: it is both faster and\n // immune to an unrelated slow/dead registry entry consuming the discovery\n // deadline. The live probe remains authoritative, so a stale file cannot\n // attach us to the wrong project or port.\n const localHint = (deps.readProjectSession ?? readProjectSession)(projectRoot);\n if (localHint) {\n // `deps.verifyProjectSession` is the test-only override and keeps its\n // boolean meaning: \"this hint is this project's session, and healthy\".\n // With no override we read the probe ourselves, because the same response\n // carries WHY a served project cannot be described.\n if (deps.verifyProjectSession) {\n if (await deps.verifyProjectSession(localHint, projectRoot)) {\n return { port: localHint.port, projectRoot };\n }\n } else {\n const served = await probeServedProject(localHint.port);\n if (served?.path != null && canonicalPath(served.path) === canonicalPath(projectRoot)) {\n if (served.manifestError !== null) throw manifestRefusal(projectRoot, served.manifestError);\n return { port: localHint.port, projectRoot };\n }\n }\n }\n\n let sessions: EditorSessionInfo[];\n // A FAILED discovery is not an empty one. Collapsing the two into `[]` is\n // what made this door answer \"no live editor session found\" \u2014 and prescribe\n // the editor's `edit` command \u2014 for a probe that merely timed out under load, sending the\n // operator to start an editor that was already running while the real defect\n // went unnamed. The same collapse the manifest refusal above was added for.\n let discoveryFailure: string | null = null;\n try {\n sessions = await withTimeout(\n transport.listSessions(EDITOR_SESSION_DISCOVERY_TIMEOUT_MS),\n EDITOR_SESSION_DISCOVERY_TIMEOUT_MS,\n 'editor session discovery',\n );\n } catch (err) {\n sessions = [];\n discoveryFailure = err instanceof Error ? err.message : String(err);\n }\n\n const canon = canonicalPath(projectRoot);\n const match = sessions.find((s) => s.project !== null && canonicalPath(s.project) === canon);\n if (!match) throw noMatchingSessionRefusal(projectRoot, canon, sessions, discoveryFailure);\n\n if (match.manifestError != null) throw manifestRefusal(projectRoot, match.manifestError);\n\n return { port: match.port, projectRoot };\n}\n\n/** `` `<product> edit` `` for the product this project declares, or a generic\n * phrase when it declares none \u2014 this package serves every product and\n * names only the one the project installed. */\nfunction editCommandFor(projectRoot: string): string {\n return verbFor(projectRoot, 'edit');\n}\n\nfunction sessionsCommandFor(projectRoot: string): string {\n return verbFor(projectRoot, 'sessions');\n}\n\nfunction verbFor(projectRoot: string, verb: string): string {\n try {\n return `\\`${resolveProductForProject(projectRoot).command} ${verb}\\``;\n } catch {\n return `its product's \\`${verb}\\` command`;\n }\n}\n", "// Finding the project manifest ON DISK. There is ONE filename \u2014 see\n// `./filename.ts` for why the old one was removed rather than kept readable.\n//\n// Deliberately dependency-light \u2014 `node:fs` + `node:path` + `./filename` and\n// NOTHING else (no Zod, no `./load`). Several callers are explicitly\n// schema-free by design (`packages/editor-core/server/project-root-surface.ts`,\n// `packages/editor/vite-plugin-ui-oid.ts`) and must be able to locate a\n// manifest without dragging the validator in.\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport {\n MANIFEST_FILENAME,\n REMOVED_MANIFEST_FILENAME,\n removedManifestFilenameMessage,\n} from './filename';\n\n/**\n * Throw the rename instruction if `dir` carries only the REMOVED manifest\n * filename. The `assertNoRemoved*` shape: a removed thing must reject loudly\n * naming the exact fix, never be silently ignored (which would present as\n * \"this folder is not a project\" \u2014 a diagnosis pointing nowhere).\n *\n * Returns normally when `dir` holds the current manifest, or neither file.\n */\nexport function assertNoRemovedManifestFilename(dir: string): void {\n if (existsSync(join(dir, MANIFEST_FILENAME))) return;\n if (!existsSync(join(dir, REMOVED_MANIFEST_FILENAME))) return;\n throw new Error(removedManifestFilenameMessage(join(dir, REMOVED_MANIFEST_FILENAME)));\n}\n\n/**\n * The manifest path inside `dir`. Always `volter.project.json` \u2014 so a \"not\n * found\" message names the filename a project must be using \u2014 except that a\n * directory carrying only the removed `volter.game.json` THROWS the rename\n * instruction instead of reporting a phantom path.\n *\n * This is the drop-in replacement for a hand-written `join(dir, \u2026)` everywhere\n * a manifest is READ. Writers want {@link manifestWritePath}.\n */\nexport function resolveManifestPath(dir: string): string {\n assertNoRemovedManifestFilename(dir);\n return join(dir, MANIFEST_FILENAME);\n}\n\n/** True when `dir` holds a manifest. A lone `volter.game.json` throws. */\nexport function hasManifest(dir: string): boolean {\n assertNoRemovedManifestFilename(dir);\n return existsSync(join(dir, MANIFEST_FILENAME));\n}\n\n/** Where a manifest gets WRITTEN in `dir`. There is one answer. */\nexport function manifestWritePath(dir: string): string {\n return join(dir, MANIFEST_FILENAME);\n}\n", "// The project manifest's FILENAME. There is exactly ONE.\n//\n// The manifest is `volter.project.json`, and NOTHING reads a second spelling\n// (the legacy-removal doctrine, `docs/ARCHITECTURE-CORE.md` \u00A7Vocabulary). Two\n// accepted names is the defect, not the convenience: both get written, and\n// copies of the \"try both\" probe spread into modules that agree with the real\n// resolver only by coincidence.\n//\n// The removed name REJECTS LOUDLY, naming the exact one-line fix \u2014 never\n// silently ignored, never redirected. A directory\n// carrying only `volter.game.json` is an error with a `git mv` in the message,\n// not a project that quietly fails to open.\n//\n// This module is the ONE place either literal is spelled out, and it is\n// dependency-free (no `node:fs`) so browser bundles can import it. The\n// filesystem side lives in `./locate` (`resolveManifestPath`, `hasManifest`,\n// `assertNoRemovedManifestFilename`).\n\n/** The manifest filename. Every reader reads it; every writer writes it. */\nexport const MANIFEST_FILENAME = 'volter.project.json';\n\n/** The removed filename. Read by nothing \u2014 its only job is the error message. */\nexport const REMOVED_MANIFEST_FILENAME = 'volter.game.json';\n\n/** True for the manifest filename (basename comparison). */\nexport function isManifestFilename(name: string): boolean {\n return name === MANIFEST_FILENAME;\n}\n\n/**\n * The verbatim rejection an on-disk `volter.game.json` earns \u2014 the one-line fix\n * spelled out, per the removed-format contract. Shared by the Node\n * (`./locate`) and browser (storage-backend) halves so a project author sees\n * the same sentence wherever the stale name is found.\n */\nexport function removedManifestFilenameMessage(where: string): string {\n return (\n `${where}: found \\`${REMOVED_MANIFEST_FILENAME}\\` and no \\`${MANIFEST_FILENAME}\\`. ` +\n `\\`${REMOVED_MANIFEST_FILENAME}\\` was REMOVED (the legacy-removal doctrine, ` +\n 'docs/ARCHITECTURE-CORE.md \u00A7Vocabulary) \u2014 nothing reads it any more, and it is ' +\n 'deliberately NOT read as a fallback, because a second accepted name is the defect.\\n' +\n `Fix: rename it \u2014 \\`git mv ${REMOVED_MANIFEST_FILENAME} ${MANIFEST_FILENAME}\\`. ` +\n 'The contents are unchanged; only the filename moved.'\n );\n}\n", "/**\n * WHICH PRODUCT OPENS THIS PROJECT \u2014 one declaration, one resolver.\n *\n * A PRODUCT is the running program (ARCHITECTURE-CORE \u00A7The target shape, rule\n * 4): `@volter/game-editor` and `@volter/model-editor` each stitch packages onto\n * the editor kit in code and each carry a `bin`. **Which product runs is never\n * a switch** \u2014 there is no `--product` flag, no id in the manifest, no setting,\n * the same way a folder never names which VS Code opens it and a `.blend` never\n * names Blender.\n *\n * So the resolution is a DEPENDENCY resolution, exactly as\n * `assertEditorProjectInstalled` resolves `@volter/editor-core`: the project's\n * `dependencies` \u222A `devDependencies` are read, each `@volter/*` among them is\n * resolved from the project, and the one whose `package.json` carries\n * `volter.product` is the product. A project's `package.json` naming a product as\n * a devDependency is the person's convenience \u2014 what `npm run dev` launches \u2014\n * and not a rule about the project.\n *\n * NONE and TWO are both refusals by name, because either answer would otherwise\n * be guessed. None prints the `npm install --save-dev` line for both products;\n * two names both and says the project must resolve it, because a page runs one\n * product and nothing here can pick.\n *\n * WHO CALLS THIS, and why twice. The CLI resolves to REFUSE EARLY and to hand\n * the directory to the session; the session resolves to SERVE the product's\n * entry and to REPORT it (`EditorState.product`), because what it is serving is\n * its own fact. One function, one set of refusal texts.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\n/** The manifest key a product declares. A DECLARATION, not a config: it says\n * what this package IS so the CLI and the session can find its entry without\n * running it (ARCHITECTURE-CORE \u00A7The target shape, rule 8). */\nexport const PRODUCT_DECLARATION_KEY = 'volter.product';\n\n/** Light or dark \u2014 the two the workbench's own `ColorScheme` has plain names\n * for, and the only two a product needs to state (a high-contrast scheme is a\n * person's accessibility choice, never a product's declaration). */\nexport type ProductColorTheme = 'dark' | 'light';\n\n/**\n * THE WORKBENCH THIS PRODUCT IS, named as a published release.\n *\n * A product is the running program, and the program is the Code-OSS workbench\n * its kit and its half were compiled INTO (ARCHITECTURE-CORE \u00A7The target\n * shape: \"one product number per release, pinning the fork, the kit, the API\n * and its media\"). So which release those bytes are is not a machine's setting\n * and not a person's choice \u2014 it is what the product IS, declared beside\n * `entry` and `colorTheme` and read without running anything (rule 8).\n *\n * `release` is the tag `scripts/workbench/build-release.mjs --publish` cuts on\n * the fork's own repository, `<product>-<fork sha 12>-<platform>`;\n * `tarballSha256` is the pin, verified against the downloaded bytes before a\n * single one of them is extracted. Both come out of that script's own\n * `BUILD.json`, and it prints this block to paste.\n *\n * A machine that has already fetched it keeps it in `~/.volter/workbenches/<tag>`\n * and a project that has one names it in `.volter/workbench.json`, so this is\n * consulted exactly once per machine per release \u2014 see\n * `workbench-locator.ts`'s `resolveWorkbenchForProject`.\n */\nexport interface ProductWorkbench {\n /** The GitHub Release tag on `volter-ai/code-oss`. */\n readonly release: string;\n /** The sha256 of that release's tarball asset, hex. */\n readonly tarballSha256: string;\n}\n\n/** A product package, as everything outside it needs to know it. */\nexport interface ProductIdentity {\n /** The package name \u2014 `@volter/game-editor`. */\n readonly name: string;\n /** Its version, reported beside the workbench by the editor's `status` command. */\n readonly version: string;\n /**\n * The command a person types to run it \u2014 the ONE key of its package.json\n * `bin` (`volter-game-editor`). Every message the kit writes about a verb\n * names this, because the kit itself has no command of its own.\n */\n readonly command: string;\n /** The name a person sees \u2014 `volter.product.displayName` (`Volter Game Editor`). */\n readonly displayName: string;\n /** Its package root, absolute. */\n readonly dir: string;\n /**\n * Its ONE source entry, package-relative and POSIX (`./src/index.ts`). That\n * entry IS the product's frame entry: it composes and re-exports `mountVolter`,\n * which is the name the fork's contribution reads off the served module.\n */\n readonly entry: string;\n /**\n * WHICH WAY ROUND THIS PRODUCT PAINTS, before one line of its code runs.\n *\n * Measured 2026-09-21 on both releases: the web workbench's FIRST PAINT is\n * LIGHT (`workbenchThemeService.ts`, `this.settings.getPreferredColorScheme()\n * ?? (isWeb ? ColorScheme.LIGHT : ColorScheme.DARK)`), so the product's\n * opening cover \u2014 which paints in `--vscode-*` variables, as it must \u2014 was\n * white for its whole life and flipped dark the instant the real theme\n * landed. The supported door is `IWorkbenchConstructionOptions\n * .initialColorTheme`, which is read out of the PAGE CONFIG, before any\n * extension or setting is available; the session's proxy injects it\n * (`packages/editor-core/server/frame-proxy.ts`).\n *\n * It is a DECLARATION and not a setting (ARCHITECTURE-CORE \u00A7The target\n * shape, rule 8): it says what the product IS, the same way `entry` does, and\n * it has to be readable without running the product because the proxy needs\n * it before the product exists. A person's own `workbench.colorTheme` still\n * wins on every open after the first \u2014 the workbench prefers its stored theme\n * over this and only falls back here when it has none.\n */\n readonly colorTheme: ProductColorTheme;\n /** WHICH WORKBENCH THIS PRODUCT IS \u2014 see {@link ProductWorkbench}. */\n readonly workbench: ProductWorkbench | null;\n}\n\n/** The install line a refusal quotes, for a project that already EXISTS. Both\n * products, because a person choosing between them is choosing what they are\n * building, not a flag. */\nexport const PRODUCT_INSTALL_LINES = [\n ' npm install --save-dev @volter/model-editor',\n ' npm install --save-dev @volter/game-editor',\n] as const;\n\n/**\n * The create line a refusal or a help screen quotes, for a project that does\n * not exist yet. CREATION IS THE PRODUCT'S (ARCHITECTURE-CORE \u00A7The target\n * shape, rule 1): a product scaffolds the project it opens, declaring its own\n * presets, and there is no create verb in the kit's CLI for either of them to\n * be an alias of.\n *\n * This is the ONE place the two product names are spelled outside the products\n * themselves; the CLI and the session quote it rather than keeping a copy.\n */\nexport const PRODUCT_CREATE_LINES = [' npx @volter/editor-core create <name>'] as const;\n\ninterface ProductManifestShape {\n private?: unknown;\n name?: unknown;\n version?: unknown;\n bin?: unknown;\n volter?: { product?: { entry?: unknown; colorTheme?: unknown; workbench?: unknown; displayName?: unknown } };\n}\n\nconst PRODUCT_COLOR_THEMES: readonly ProductColorTheme[] = ['dark', 'light'];\n\n/**\n * Read one product package's declaration, or `null` when the manifest is not a\n * product's. Throws when it declares `volter.product` and the declaration is\n * unusable \u2014 a half-written product must be named, never skipped.\n */\nexport function readProductManifest(packageDir: string): ProductIdentity | null {\n const manifestPath = join(packageDir, 'package.json');\n let manifest: ProductManifestShape;\n try {\n manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as ProductManifestShape;\n } catch {\n return null;\n }\n const declared = manifest.volter?.product;\n if (declared === undefined) return null;\n const entry = declared.entry;\n if (typeof entry !== 'string' || !entry.startsWith('./'))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"entry\" is ` +\n `${JSON.stringify(entry)}. It must be a ./-relative module \u2014 the product's ONE source ` +\n 'entry, which is also its frame entry (e.g. \"./src/index.ts\").',\n );\n const resolved = join(packageDir, entry);\n if (!existsSync(resolved))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY}.entry ${JSON.stringify(entry)}, ` +\n `which does not exist (${resolved}).`,\n );\n const colorTheme = declared.colorTheme;\n // REQUIRED, like `entry`, and for the same reason: a product that does not\n // say which way round it paints gets the workbench's web default, which is\n // LIGHT, and its cover is white until its real theme loads. There is no\n // defensible default to invent here \u2014 a dark product and a light product are\n // both ordinary \u2014 so an unstated one is named rather than guessed.\n if (typeof colorTheme !== 'string' || !PRODUCT_COLOR_THEMES.includes(colorTheme as never))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"colorTheme\" is ` +\n `${JSON.stringify(colorTheme)}. It must be ${PRODUCT_COLOR_THEMES.map((one) =>\n JSON.stringify(one),\n ).join(' or ')} \u2014 which way round this product paints, read before any of its code ` +\n \"runs so the workbench's first frame is already the product's own background.\",\n );\n // REQUIRED, for the same reason as `entry`: the kit names verbs in every\n // message it writes, and there is no command to name but the product's own.\n const bin = manifest.bin;\n const commands = bin !== null && typeof bin === 'object' ? Object.keys(bin) : [];\n if (commands.length !== 1)\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"bin\" names ` +\n `${commands.length === 0 ? 'no command' : `${commands.length} commands`}. A product has ` +\n 'exactly one command \u2014 the one every session message tells a person to run.',\n );\n const displayName = declared.displayName;\n if (typeof displayName !== 'string' || displayName.trim() === '')\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"displayName\" is ` +\n `${JSON.stringify(displayName)}. It must be the name a person sees (e.g. \"Volter Editor\").`,\n );\n return {\n name: typeof manifest.name === 'string' ? manifest.name : packageDir,\n version: typeof manifest.version === 'string' ? manifest.version : 'unknown',\n command: commands[0]!,\n displayName,\n dir: packageDir,\n entry,\n colorTheme: colorTheme as ProductColorTheme,\n // A private source product may use an explicitly selected matching checkout.\n // Public packages must always carry a downloadable, checksummed workbench.\n workbench: manifest.private === true && declared.workbench === undefined\n ? null : readProductWorkbench(manifestPath, declared.workbench),\n };\n}\n\n/** The sha256 a release pins its tarball with, as `BUILD.json` writes it. */\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\n/**\n * REQUIRED, like `entry` and `colorTheme`, and for the sharpest reason of the\n * three: a product that does not say which workbench it is cannot be INSTALLED\n * \u2014 `npx @volter/<product> create <name>` on a machine with nothing else on it\n * has no other way to find the bytes it runs in, and the person is left writing\n * a path to a directory they would have to build first. There is no default to\n * invent (the tag names a fork commit nobody can guess), so an unstated one is\n * named rather than guessed.\n */\nfunction readProductWorkbench(manifestPath: string, declared: unknown): ProductWorkbench {\n const example =\n ' \"volter\": { \"product\": { \"workbench\": { \"release\": \"<product>-<fork sha 12>-<platform>\", ' +\n '\"tarballSha256\": \"<64 hex>\" } } }\\n' +\n '`node scripts/workbench/build-release.mjs --publish --out <release dir>` cuts the release ' +\n 'and prints exactly that block.';\n if (typeof declared !== 'object' || declared === null || Array.isArray(declared))\n throw new Error(\n `${manifestPath} declares ${PRODUCT_DECLARATION_KEY} but its \"workbench\" is ` +\n `${JSON.stringify(declared)}. A product IS the Code-OSS workbench it was compiled into, ` +\n `so it names the published release those bytes are:\\n${example}`,\n );\n const record = declared as Record<string, unknown>;\n const extra = Object.keys(record).filter((key) => key !== 'release' && key !== 'tarballSha256');\n if (extra.length > 0)\n throw new Error(\n `${manifestPath}'s ${PRODUCT_DECLARATION_KEY}.workbench carries ` +\n `${extra.map((key) => `\"${key}\"`).join(', ')}, which this declaration has no meaning for. ` +\n `It names the release and the pin, and nothing else:\\n${example}`,\n );\n const release = record['release'];\n if (typeof release !== 'string' || release.trim() === '')\n throw new Error(\n `${manifestPath}'s ${PRODUCT_DECLARATION_KEY}.workbench names no \"release\" \u2014 the GitHub ` +\n `Release tag its workbench was published under:\\n${example}`,\n );\n const tarballSha256 = record['tarballSha256'];\n if (typeof tarballSha256 !== 'string' || !SHA256_HEX.test(tarballSha256))\n throw new Error(\n `${manifestPath}'s ${PRODUCT_DECLARATION_KEY}.workbench has tarballSha256 ` +\n `${JSON.stringify(tarballSha256)}, which is not 64 hex characters. It is the PIN \u2014 the ` +\n 'hash the downloaded tarball is checked against before a byte of it is extracted, so it ' +\n `is never approximate:\\n${example}`,\n );\n return { release, tarballSha256 };\n}\n\n/**\n * A product's SHORT id \u2014 `@volter/model-editor` \u2192 `model-editor`.\n *\n * It is the product's own `product({ id })`, the directory its workbench half\n * lives in (`packages/<id>/workbench`), the `--product` flag the overlay and the\n * release build take, and what a release records in `BUILD.json`. One derivation\n * rather than four literals: the package name is the only place the product is\n * NAMED, and everything else is that name's last segment.\n */\nexport function workbenchProductId(packageName: string): string {\n return packageName.split('/').pop() ?? packageName;\n}\n\n/** A product's entry as a path relative to `fromDir`, POSIX \u2014 the spelling a\n * Vite manifest key and a dev-server URL both use. */\nexport function productEntryPath(product: ProductIdentity, fromDir: string): string {\n const absolute = join(product.dir, product.entry);\n const prefix = fromDir.endsWith('/') ? fromDir : `${fromDir}/`;\n const relative = absolute.startsWith(prefix) ? absolute.slice(prefix.length) : absolute;\n return relative.split('\\\\').join('/');\n}\n\n/** Every `@volter/*` this project declares, in either section, sorted. */\nfunction declaredVolterPackages(projectRoot: string): string[] {\n let manifest: { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n try {\n manifest = JSON.parse(\n readFileSync(join(projectRoot, 'package.json'), 'utf8'),\n ) as typeof manifest;\n } catch {\n return [];\n }\n return Object.keys({ ...(manifest.dependencies ?? {}), ...(manifest.devDependencies ?? {}) })\n .filter((name) => name.startsWith('@volter/'))\n .sort();\n}\n\n/** Where a package resolves FROM THE PROJECT, or null when it is not installed. */\nfunction locatePackage(projectRoot: string, name: string): string | null {\n const require = createRequire(pathToFileURL(join(projectRoot, 'package.json')));\n try {\n return dirname(require.resolve(`${name}/package.json`));\n } catch {\n // No `./package.json` export: walk up from whatever the bare name resolves\n // to, which is what a package with a strict export map leaves reachable.\n try {\n let dir = dirname(require.resolve(name));\n for (;;) {\n const candidate = join(dir, 'package.json');\n try {\n if ((JSON.parse(readFileSync(candidate, 'utf8')) as { name?: string }).name === name)\n return dir;\n } catch {\n /* keep walking */\n }\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n } catch {\n return null;\n }\n }\n}\n\n/**\n * THE PACKAGES A PRODUCT COMPOSES \u2014 the `volter:contributions/<name>` imports of the product's\n * entry (`package.json#volter.product.entry`), each resolved from the product's own install and\n * declaring `package.json#volter.contributions`.\n *\n * COMPOSITIONS ARE CODE (ARCHITECTURE-CORE \u00A7The target shape, rule 8): that import IS the\n * composition, so it is what is read. The product's `dependencies` are not: they also carry\n * the packages a game's capabilities add (`add music` declares `@volter/editor-dawproject`,\n * which the runtime image must hold), and reading every dependency that declares contributions\n * as composed made the page load a capability's documents into every game, and from a checkout\n * fetch them from a folder the game's server does not serve.\n */\nexport function productComposedPackages(product: ProductIdentity): string[] {\n let entry: string;\n try {\n const manifest = JSON.parse(readFileSync(join(product.dir, 'package.json'), 'utf8')) as {\n volter?: { product?: { entry?: unknown } };\n };\n const path = manifest.volter?.product?.entry;\n if (typeof path !== 'string') return [];\n entry = readFileSync(join(product.dir, path), 'utf8');\n } catch {\n return [];\n }\n const found: string[] = [];\n for (const [, name] of entry.matchAll(/\\bfrom\\s+['\"]volter:contributions\\/([^'\"]+)['\"]/g)) {\n if (!name || found.includes(name)) continue;\n const dir = locatePackage(product.dir, name);\n if (dir === null) continue;\n let dependency: { volter?: { contributions?: unknown } };\n try {\n dependency = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as typeof dependency;\n } catch {\n continue;\n }\n if (Array.isArray(dependency.volter?.contributions)) found.push(name);\n }\n return found;\n}\n\n/** The products this project declares AND resolves, in declaration order. */\nexport function declaredProducts(projectRoot: string): ProductIdentity[] {\n const found: ProductIdentity[] = [];\n for (const name of declaredVolterPackages(projectRoot)) {\n const dir = locatePackage(projectRoot, name);\n if (dir === null) continue;\n const product = readProductManifest(dir);\n if (product !== null) found.push(product);\n }\n return found;\n}\n\n/**\n * THE product this project opens in, or a throw naming what is wrong.\n *\n * The refusals are the whole point: a project with none and a project with two\n * are both states a person can be in, and neither has an answer this code may\n * invent.\n */\nexport function resolveProductForProject(projectRoot: string): ProductIdentity {\n const products = declaredProducts(projectRoot);\n if (products.length === 1) return products[0] as ProductIdentity;\n if (products.length === 0)\n throw new Error(\n `${projectRoot} declares no editor product, so there is no editor to open it in.\\n` +\n 'The installed product supplies the editor,\\n' +\n 'and which one runs is what the project installed, never a flag.\\n' +\n 'For THIS folder, install the one you are building with:\\n' +\n `${PRODUCT_INSTALL_LINES.join('\\n')}\\n` +\n \"then run that product's `edit` command again. For a NEW project, the product creates it:\\n\" +\n `${PRODUCT_CREATE_LINES.join('\\n')}`,\n );\n throw new Error(\n `${projectRoot} declares ${products.length} editor products \u2014 ` +\n `${products.map((product) => product.name).join(' and ')}.\\n` +\n 'One page runs one product, and nothing here may choose between them. Remove the one you\\n' +\n 'are not building with:\\n' +\n products.map((product) => ` npm uninstall ${product.name}`).join('\\n'),\n );\n}\n", "/**\n * `~/.volter/editor-sessions.json` \u2014 the ONE spelling of the editor-session\n * registry contract, and the shared machinery every reader was hand-copying.\n *\n * The registry's WRITE half stays with its owner\n * (`packages/editor-core/server/session-registry.ts`); this module owns the\n * FORMAT: the entry shape, the shape guards, the file path, the\n * liveness-filtered read, the `/__editor/project` answer parser, and the\n * pending-launch coordination. It existed as FOUR drifting copies\n * (server registry, the CLI, and both volter-sdk transports) held together by\n * a \"the CLI has no editor dependency\" premise that had stopped being true \u2014\n * and the drift was already real: one copy's `/__editor/project` parser\n * dropped `manifestError`, reporting a degraded session as belonging to no\n * project.\n */\n\nimport {\n mkdirSync,\n readdirSync,\n readFileSync,\n realpathSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { setTimeout as delay } from 'node:timers/promises';\n\n/** One registry entry, exactly as the server's write half records it. */\nexport interface EditorSessionEntry {\n /** Canonical project root currently open, or null when none. */\n project: string | null;\n port: number;\n /** PID of the dev-server process. */\n pid: number;\n /** ISO timestamp of server start. */\n startedAt: string;\n sessionId: string | null;\n /** Private loopback control credential \u2014 never returned by an editor HTTP\n * route; exists only in this user-private registry. */\n controlSecret?: string | null;\n repositoryId: string | null;\n worktreeId: string | null;\n worktreeRoot: string | null;\n projectRelativePath: string | null;\n branch: string | null;\n headCommit: string | null;\n baseCommit: string | null;\n}\n\nexport const EDITOR_SESSIONS_REGISTRY_FILE = join(homedir(), '.volter', 'editor-sessions.json');\n\nexport function isEditorSessionEntry(v: unknown): v is EditorSessionEntry {\n if (typeof v !== 'object' || v === null) return false;\n const s = v as Record<string, unknown>;\n const optionalIdentity = (value: unknown) =>\n value === undefined || value === null || typeof value === 'string';\n return (\n (typeof s['project'] === 'string' || s['project'] === null) &&\n typeof s['port'] === 'number' &&\n typeof s['pid'] === 'number' &&\n typeof s['startedAt'] === 'string' &&\n optionalIdentity(s['sessionId']) &&\n optionalIdentity(s['controlSecret']) &&\n optionalIdentity(s['repositoryId']) &&\n optionalIdentity(s['worktreeId']) &&\n optionalIdentity(s['worktreeRoot']) &&\n optionalIdentity(s['projectRelativePath']) &&\n optionalIdentity(s['branch']) &&\n optionalIdentity(s['headCommit']) &&\n optionalIdentity(s['baseCommit'])\n );\n}\n\nexport function normalizeEditorSessionEntry(session: EditorSessionEntry): EditorSessionEntry {\n return {\n ...session,\n sessionId: session.sessionId ?? null,\n controlSecret: session.controlSecret ?? null,\n repositoryId: session.repositoryId ?? null,\n worktreeId: session.worktreeId ?? null,\n worktreeRoot: session.worktreeRoot ?? null,\n projectRelativePath: session.projectRelativePath ?? null,\n branch: session.branch ?? null,\n headCommit: session.headCommit ?? null,\n baseCommit: session.baseCommit ?? null,\n };\n}\n\nexport function pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/** The registry's live entries \u2014 shape-validated and PID-liveness-filtered. */\nexport function readLiveRegisteredSessions(): EditorSessionEntry[] {\n try {\n const raw: unknown = JSON.parse(readFileSync(EDITOR_SESSIONS_REGISTRY_FILE, 'utf8'));\n return Array.isArray(raw)\n ? raw\n .filter(isEditorSessionEntry)\n .map(normalizeEditorSessionEntry)\n .filter((s) => pidAlive(s.pid))\n : [];\n } catch {\n return [];\n }\n}\n\n/** Announce a launch before the server can register. Each launcher owns its file. */\nexport function announceEditorLaunch(project: string): () => void {\n const directory = join(project, '.volter', 'editor-launches');\n mkdirSync(directory, { recursive: true });\n const file = join(directory, `${process.pid}.json`);\n writeFileSync(file, JSON.stringify({ pid: process.pid }));\n const clear = () => {\n process.removeListener('exit', clear);\n try {\n unlinkSync(file);\n } catch {\n // Already cleared when the server became ready.\n }\n };\n process.once('exit', clear);\n return clear;\n}\n\nfunction hasPendingEditorLaunch(project: string): boolean {\n const directory = join(project, '.volter', 'editor-launches');\n try {\n return readdirSync(directory).some((name) => {\n if (!/^\\d+\\.json$/.test(name)) return false;\n const pid = Number(name.slice(0, -5));\n return pid !== process.pid && pidAlive(pid);\n });\n } catch {\n return false;\n }\n}\n\n/** Wait only for an observed live launcher, never for a missing editor. */\nexport async function waitForPendingEditorLaunch(project: string): Promise<void> {\n const canon = canonicalizeProjectPath(project);\n const ready = () =>\n readLiveRegisteredSessions().some(\n (session) => session.project !== null && canonicalizeProjectPath(session.project) === canon,\n );\n if (ready() || !hasPendingEditorLaunch(canon)) return;\n const deadline = Date.now() + 180_000;\n while (!ready()) {\n if (!hasPendingEditorLaunch(canon)) {\n // The launcher clears its announcement only after registration.\n if (ready()) return;\n throw new Error(`The editor launch for ${canon} ended before registering a session.`);\n }\n if (Date.now() >= deadline) {\n throw new Error(\n `The editor launch for ${canon} is still running but has not registered within 180s.`,\n );\n }\n await delay(100);\n }\n}\n\n/**\n * WHICH PROJECT a `/__editor/project` body says its server is serving.\n *\n * `serving` is that server's own statement of \"I AM serving this project, I\n * just cannot describe it\" (its manifest is unparseable or fails strict\n * validation) \u2014 added to the route precisely because a bare\n * `{ project: null }` is indistinguishable from \"no project open\". Reading\n * only `project.path` collapses the two, and the cost is that every\n * project-matched command loses a live session the moment a save breaks its\n * manifest, reporting it as belonging to no project rather than as this\n * project's degraded session.\n */\nexport function servedProjectAnswer(body: unknown): {\n path: string | null;\n manifestError: string | null;\n} {\n const b = body as {\n project?: { path?: string } | null;\n serving?: { path?: string; error?: string } | null;\n };\n return {\n path: b.project?.path ?? b.serving?.path ?? null,\n manifestError: b.project ? null : (b.serving?.error ?? null),\n };\n}\n\n/** Canonical (realpathed when possible) absolute form of a project path. */\nfunction canonicalizeProjectPath(p: string): string {\n const absolute = resolve(p);\n try {\n return realpathSync(absolute);\n } catch {\n return absolute;\n }\n}\n", "/** Registered-session discovery; never selects another project's session. */\nimport { readLiveRegisteredSessions, servedProjectAnswer } from './registry-format.js';\nexport { servedProjectAnswer } from './registry-format.js';\n\nexport const EDITOR_SESSION_DISCOVERY_TIMEOUT_MS = 2000;\n\nexport const EDITOR_PROBE_TIMEOUT_MS = 1500;\n\nexport class EditorTimeoutError extends Error {\n constructor(label: string, ms: number) {\n super(`${label} timed out after ${ms}ms`);\n this.name = 'EditorTimeoutError';\n }\n}\n\nexport function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {\n return new Promise<T>((resolvePromise, reject) => {\n const timer = setTimeout(() => reject(new EditorTimeoutError(label, ms)), ms);\n promise.then(\n (v) => {\n clearTimeout(timer);\n resolvePromise(v);\n },\n (err) => {\n clearTimeout(timer);\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\nexport interface EditorSessionInfo {\n /** The port this session's dev server is bound to. */\n port: number;\n /** Canonical project root path currently open, or null when none. */\n project: string | null;\n /** Dev-server process id, when known from the local session registry (null for an unregistered/legacy server the caller only probed by port). */\n pid: number | null;\n /** Exact explicitly targeted editor origin/base URL, including protocol and host. */\n url?: string;\n /**\n * Why this server cannot DESCRIBE the `project` it is serving \u2014 its\n * manifest's own parse/validation failure, naming the failing key. `null`\n * when the project reads fine, and `undefined` from a probe that did not ask\n * (or a server too old to say). See {@link servedProjectAnswer}: a session in\n * this state is still THIS project's session, and callers must report the\n * reason rather than treat it as no session at all.\n */\n manifestError?: string | null;\n}\n\nasync function fetchJson(url: string, timeoutMs: number): Promise<unknown | undefined> {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n if (!res.ok) return undefined;\n return await res.json();\n } catch {\n return undefined;\n }\n}\n\nfunction baseUrl(session: EditorSessionInfo): string {\n return session.url ?? `http://127.0.0.1:${session.port}`;\n}\n\nexport interface SessionListingTransport { listSessions(timeoutMs: number): Promise<EditorSessionInfo[]>; }\nexport class HttpSessionDiscovery implements SessionListingTransport {\n async listSessions(timeoutMs: number): Promise<EditorSessionInfo[]> {\n const registered = readLiveRegisteredSessions();\n const perProbeTimeout = Math.min(EDITOR_PROBE_TIMEOUT_MS, Math.max(200, timeoutMs));\n const probes = await Promise.all(\n registered.map(async (s) => {\n const body = await fetchJson(\n `${baseUrl({ port: s.port, project: null, pid: s.pid })}/__editor/project`,\n perProbeTimeout,\n );\n if (body === undefined) return undefined;\n const served = servedProjectAnswer(body);\n const info: EditorSessionInfo = {\n port: s.port,\n project: served.path,\n pid: s.pid,\n manifestError: served.manifestError,\n };\n return info;\n }),\n );\n return probes.filter((p): p is EditorSessionInfo => p !== undefined);\n }\n}\n", "/**\n * A tiny memoized-async-factory primitive \u2014 the machinery behind\n * `index.ts`'s lazy top-level `editor`/`tools` singletons. Pulled into\n * its own module (rather than inlined) so it's independently unit-testable\n * with a fake factory, with no need to exercise a real `connect()` (session\n * discovery, network) just to prove \"two accesses, one connect\".\n *\n * Caches the in-flight PROMISE, not just the resolved value \u2014 two callers\n * racing `ensure()` before the first resolves still share the SAME\n * connection attempt, not two independent ones.\n */\nexport interface LazySession<T> {\n /** Returns the memoized promise, creating it via `factory()` on first call. */\n ensure(): Promise<T>;\n /** Clears the memo \u2014 the NEXT `ensure()` calls `factory()` again. Exposed for tests (and for a caller that deliberately wants to reconnect); not needed in ordinary use. */\n reset(): void;\n}\n\nexport function createLazySession<T>(factory: () => Promise<T>): LazySession<T> {\n let promise: Promise<T> | null = null;\n return {\n ensure(): Promise<T> {\n promise ??= factory();\n return promise;\n },\n reset(): void {\n promise = null;\n },\n };\n}\n", "/** Attach to an existing editor session; this package never launches one. */\nimport { EditorClient } from '@volter/editor-sdk/client';\nimport { LiveEditor } from './editor.js';\nimport { LiveTools } from './tools.js';\nimport { lazyChainProxy } from './lazy-proxy.js';\nimport { resolveSession, type ResolvedSession, type SessionResolutionDeps } from './session.js';\nimport { createLazySession } from './singleton.js';\n\nexport { LiveEditor, inferAssetKind, type PanelName } from './editor.js';\nexport { LiveEditorDocument } from './editor-document.js';\nexport type { DocumentGestureOptions, DocumentKeyOptions, DocumentPasteOptions } from './editor-document.js';\nexport { LiveTools } from './tools.js';\nexport { resolveSession, findProjectRootFrom } from './session.js';\nexport type { ResolvedSession, SessionResolutionDeps, SessionListingTransport, ProjectSessionHint } from './session.js';\nexport type { ActiveDocumentCapture, EditorView, PresentedEditorView } from '@volter/editor-sdk';\n\nexport interface LiveBindings {\n editor: LiveEditor;\n tools: LiveTools;\n}\nexport interface LiveSession extends LiveBindings {\n session: ResolvedSession;\n}\nfunction bindTo(port: number): LiveBindings {\n const client = new EditorClient({ url: `http://127.0.0.1:${port}` });\n return { editor: new LiveEditor(client), tools: new LiveTools(client) };\n}\n/** Inspect the callable surface without connecting; calls fail on port zero. */\nexport function unconnectedBindings(): LiveBindings { return bindTo(0); }\n\n/** Attach only to the session serving the requested project's canonical path. */\nexport async function connect(projectDir?: string, deps?: SessionResolutionDeps): Promise<LiveSession> {\n const session = await resolveSession(projectDir, deps);\n return { ...bindTo(session.port), session };\n}\nconst lazySession = createLazySession(() => connect());\nexport const editor: LiveEditor = lazyChainProxy<LiveEditor>(() => lazySession.ensure().then(s => s.editor));\nexport const tools: LiveTools = lazyChainProxy<LiveTools>(() => lazySession.ensure().then(s => s.tools));\n"],
5
+ "mappings": "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",
6
6
  "names": ["resolve", "existsSync", "readFileSync", "realpathSync", "dirname", "join", "resolve", "existsSync", "join", "join", "require", "readFileSync", "join", "join", "readFileSync", "resolve", "existsSync", "dirname", "realpathSync", "readFileSync", "join"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volter/editor-live",
3
3
  "author": "Volter AI, Inc.",
4
- "version": "0.5.113",
4
+ "version": "0.5.115",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,8 +30,8 @@
30
30
  "node": ">=22"
31
31
  },
32
32
  "dependencies": {
33
- "@volter/editor-sdk": "0.5.113",
34
- "@volter/editor-project": "0.5.113",
33
+ "@volter/editor-sdk": "0.5.115",
34
+ "@volter/editor-project": "0.5.115",
35
35
  "undici": "^7.28.0"
36
36
  },
37
37
  "devDependencies": {