@volter/editor-live 0.5.64 → 0.5.66
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 +4 -2
- package/dist/editor-document.d.ts +2 -0
- package/dist/editor.d.ts +18 -4
- package/dist/index.js +268 -24
- package/dist/index.js.map +4 -4
- package/package.json +3 -3
- package/src/editor-document.ts +2 -0
- package/src/editor.ts +28 -5
- package/src/session.ts +24 -4
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.
|
|
4
|
+
"version": "0.5.66",
|
|
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.
|
|
34
|
-
"@volter/editor-project": "0.5.
|
|
33
|
+
"@volter/editor-sdk": "0.5.66",
|
|
34
|
+
"@volter/editor-project": "0.5.66",
|
|
35
35
|
"undici": "^7.28.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
package/src/editor-document.ts
CHANGED
|
@@ -59,6 +59,8 @@ export interface DocumentKeyOptions extends DocumentGestureOptions {
|
|
|
59
59
|
metaKey?: boolean;
|
|
60
60
|
shiftKey?: boolean;
|
|
61
61
|
altKey?: boolean;
|
|
62
|
+
/** Hold the key this long before releasing it (a person holding W). */
|
|
63
|
+
holdMs?: number;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
export interface DocumentPasteOptions extends DocumentGestureOptions {
|
package/src/editor.ts
CHANGED
|
@@ -99,7 +99,7 @@ export function inferAssetKind(path: string): AssetKind {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export class LiveEditor {
|
|
102
|
-
/** `#`-private, not `private`: `volter-editor eval --list` enumerates this object's
|
|
102
|
+
/** `#`-private, not `private`: `volter-model-editor eval --list` enumerates this object's
|
|
103
103
|
* real runtime members, and TypeScript's erased `private` would leave the
|
|
104
104
|
* raw `EditorClient` advertised beside them. */
|
|
105
105
|
readonly #client: EditorClient;
|
|
@@ -120,7 +120,7 @@ export class LiveEditor {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
* THE BLENDER LANE'S VERBS, from `volter-editor eval`.
|
|
123
|
+
* THE BLENDER LANE'S VERBS, from `volter-model-editor eval`.
|
|
124
124
|
*
|
|
125
125
|
* Blender runs headless in the editor tab's worker (ARCHITECTURE-CORE, "THE
|
|
126
126
|
* BLENDER IN THE TAB IS BLENDER") and answers `blender-start`,
|
|
@@ -132,7 +132,7 @@ export class LiveEditor {
|
|
|
132
132
|
* per question — the same discovery failure `eval-surface.ts`'s header
|
|
133
133
|
* records, in a lane that had not noticed it yet.
|
|
134
134
|
*
|
|
135
|
-
* volter-editor eval "await editor.blender('blender-execute', { code: 'import bpy; print(len(bpy.data.objects))' })"
|
|
135
|
+
* volter-model-editor eval "await editor.blender('blender-execute', { code: 'import bpy; print(len(bpy.data.objects))' })"
|
|
136
136
|
*
|
|
137
137
|
* `blender-status` is the only verb that creates nothing: it answers whether
|
|
138
138
|
* this tab already has a session without starting one.
|
|
@@ -178,6 +178,9 @@ export class LiveEditor {
|
|
|
178
178
|
* `@volter/editor-sdk`'s `CaptureDimensions`.
|
|
179
179
|
* Supply a view to present and photograph it in one editor request.
|
|
180
180
|
*/
|
|
181
|
+
/** The active document's RENDER alone, at the size asked for: what the document draws,
|
|
182
|
+
* without what the viewport draws over it (its navigation gizmo, its readouts). To see a
|
|
183
|
+
* stage as the person does, use `captureEditorChrome({ region: 'document' })`. */
|
|
181
184
|
async captureActiveDocument(
|
|
182
185
|
size?: CaptureDimensions,
|
|
183
186
|
view?: EditorView,
|
|
@@ -325,8 +328,8 @@ export class LiveEditor {
|
|
|
325
328
|
}
|
|
326
329
|
|
|
327
330
|
/**
|
|
328
|
-
* Apply a STYLE BUNDLE by id — the chrome's palette, material
|
|
329
|
-
*
|
|
331
|
+
* Apply a STYLE BUNDLE by id — the chrome's palette, material and icon set in
|
|
332
|
+
* one gesture, the session door beside
|
|
330
333
|
* `View → <Style> Style`. A bundle the open project does not offer refuses
|
|
331
334
|
* and names the vocabulary; `currentView().style` reports the one worn.
|
|
332
335
|
*/
|
|
@@ -334,6 +337,21 @@ export class LiveEditor {
|
|
|
334
337
|
await this.#client.setStyle(id);
|
|
335
338
|
}
|
|
336
339
|
|
|
340
|
+
/**
|
|
341
|
+
* A document stage's viewport PRESENTATION — its draw mode, lighting, backdrop and overlays
|
|
342
|
+
* (`@volter/editor-sdk/kit/viewport-presentation`) — resolved. With `layer`, that choice is
|
|
343
|
+
* recorded for the view first, as a person's toolbar change would be, e.g.
|
|
344
|
+
* `presentation('model:src/models/cube.blend', { all: { lighting: { studioPreset: 'kit' } } })`.
|
|
345
|
+
* With a STRING, the named view of that id (`*.view.ts`, e.g. `'godot'`) is put on the view
|
|
346
|
+
* whole; the answer's `viewPresets` lists the ones registered.
|
|
347
|
+
*/
|
|
348
|
+
async presentation(
|
|
349
|
+
documentId: string,
|
|
350
|
+
layer?: Parameters<EditorClient['viewportPresentation']>[1],
|
|
351
|
+
): ReturnType<EditorClient['viewportPresentation']> {
|
|
352
|
+
return this.#client.viewportPresentation(documentId, layer);
|
|
353
|
+
}
|
|
354
|
+
|
|
337
355
|
/**
|
|
338
356
|
* Set the MATERIAL apart from the bundle that usually carries it.
|
|
339
357
|
* Appearance is palette × material, independent axes by ruling, so
|
|
@@ -651,6 +669,11 @@ export class LiveEditor {
|
|
|
651
669
|
return this.#client.redo();
|
|
652
670
|
}
|
|
653
671
|
|
|
672
|
+
/** Reload the editor's page and resolve once the new document answers. */
|
|
673
|
+
async reloadPage(): Promise<void> {
|
|
674
|
+
await this.#client.reloadPage();
|
|
675
|
+
}
|
|
676
|
+
|
|
654
677
|
/** Mirrors `vgai status` — the full live editor state as JSON. */
|
|
655
678
|
async status(): Promise<EditorState> {
|
|
656
679
|
return this.#client.getState();
|
package/src/session.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
7
7
|
import { dirname, join, resolve } from 'node:path';
|
|
8
8
|
import { resolveManifestPath } from '@volter/editor-project/manifest/locate';
|
|
9
|
+
import { resolveProductForProject } from '@volter/editor-sdk/session/product-locator';
|
|
9
10
|
import {
|
|
10
11
|
EDITOR_SESSION_DISCOVERY_TIMEOUT_MS,
|
|
11
12
|
type EditorSessionInfo,
|
|
@@ -176,14 +177,14 @@ function noMatchingSessionRefusal(
|
|
|
176
177
|
`@volter/editor-live: could not READ the editor session registry while looking for ${projectRoot} — ` +
|
|
177
178
|
`${discoveryFailure}. This is not the answer "no editor is running": the question went ` +
|
|
178
179
|
'unanswered, so nothing is known about what is live. Retry (a probe can time out while ' +
|
|
179
|
-
|
|
180
|
+
`the box is loaded); if it keeps failing, ${sessionsCommandFor(projectRoot)} asks the same question directly.`,
|
|
180
181
|
);
|
|
181
182
|
}
|
|
182
183
|
if (sessions.length === 0) {
|
|
183
184
|
return new Error(
|
|
184
185
|
`@volter/editor-live: the editor session registry is readable and lists NO live sessions, so none ` +
|
|
185
186
|
`covers ${projectRoot}. @volter/editor-live only attaches to an already-running session — it ` +
|
|
186
|
-
|
|
187
|
+
`never starts one — so run ${editCommandFor(projectRoot)} in that project first, then retry.`,
|
|
187
188
|
);
|
|
188
189
|
}
|
|
189
190
|
const listed = sessions
|
|
@@ -196,7 +197,7 @@ function noMatchingSessionRefusal(
|
|
|
196
197
|
` live sessions:\n${listed}\n` +
|
|
197
198
|
' If one of those is meant to be this project, the two paths differ after resolution — ' +
|
|
198
199
|
'the usual cause is a git worktree or a symlink, where the session was opened through a ' +
|
|
199
|
-
|
|
200
|
+
`different path to the same files. Run ${editCommandFor(projectRoot)} from THIS path, or use the path the ` +
|
|
200
201
|
'session lists.',
|
|
201
202
|
);
|
|
202
203
|
}
|
|
@@ -211,7 +212,7 @@ export async function resolveSession(
|
|
|
211
212
|
const projectRoot = findRoot(projectDir);
|
|
212
213
|
if (projectRoot === null) {
|
|
213
214
|
throw new Error(
|
|
214
|
-
`@volter/editor-live: no vgai.project.json found in ${projectDir} or any parent directory — is this a
|
|
215
|
+
`@volter/editor-live: no vgai.project.json found in ${projectDir} or any parent directory — is this a project?`,
|
|
215
216
|
);
|
|
216
217
|
}
|
|
217
218
|
|
|
@@ -265,3 +266,22 @@ export async function resolveSession(
|
|
|
265
266
|
|
|
266
267
|
return { port: match.port, projectRoot };
|
|
267
268
|
}
|
|
269
|
+
|
|
270
|
+
/** `` `<product> edit` `` for the product this project declares, or a generic
|
|
271
|
+
* phrase when it declares none — this package serves every product and
|
|
272
|
+
* names only the one the project installed. */
|
|
273
|
+
function editCommandFor(projectRoot: string): string {
|
|
274
|
+
return verbFor(projectRoot, 'edit');
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function sessionsCommandFor(projectRoot: string): string {
|
|
278
|
+
return verbFor(projectRoot, 'sessions');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function verbFor(projectRoot: string, verb: string): string {
|
|
282
|
+
try {
|
|
283
|
+
return `\`${resolveProductForProject(projectRoot).command} ${verb}\``;
|
|
284
|
+
} catch {
|
|
285
|
+
return `its product's \`${verb}\` command`;
|
|
286
|
+
}
|
|
287
|
+
}
|