@volter/editor-live 0.5.67 → 0.5.69
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 +6 -5
- package/dist/editor-document.d.ts +8 -4
- package/dist/editor.d.ts +13 -13
- package/dist/index.js +59 -54
- package/dist/index.js.map +2 -2
- package/dist/session.d.ts +2 -2
- package/dist/tools.d.ts +1 -1
- package/package.json +3 -3
- package/src/editor-document.ts +19 -7
- package/src/editor.ts +13 -13
- package/src/session.ts +9 -9
- package/src/tools.ts +1 -1
package/dist/session.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type SessionListingTransport = SessionDiscoveryTransport;
|
|
|
10
10
|
export interface ResolvedSession {
|
|
11
11
|
/** Editor dev-server port the resolved session is listening on. */
|
|
12
12
|
port: number;
|
|
13
|
-
/** Absolute project root — the nearest ancestor of the requested directory containing `
|
|
13
|
+
/** Absolute project root — the nearest ancestor of the requested directory containing `volter.project.json`. */
|
|
14
14
|
projectRoot: string;
|
|
15
15
|
}
|
|
16
16
|
export interface SessionResolutionDeps {
|
|
@@ -18,7 +18,7 @@ export interface SessionResolutionDeps {
|
|
|
18
18
|
transport?: SessionListingTransport;
|
|
19
19
|
/** Project-root discovery — defaults to the real fs walk (`findProjectRootFrom` above). Overridable for tests. */
|
|
20
20
|
findProjectRootFrom?: (dir: string) => string | null;
|
|
21
|
-
/** Project-local session hint reader. Defaults to `.
|
|
21
|
+
/** Project-local session hint reader. Defaults to `.volter/session.json`. */
|
|
22
22
|
readProjectSession?: (projectRoot: string) => ProjectSessionHint | null;
|
|
23
23
|
/** Exact-session verifier. Defaults to GET /__editor/project + canonical project matching. */
|
|
24
24
|
verifyProjectSession?: (hint: ProjectSessionHint, projectRoot: string) => Promise<boolean>;
|
package/dist/tools.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { EditorClient, ProjectToolCatalog, ProjectToolCatalogEntry, Project
|
|
|
3
3
|
export declare class LiveTools {
|
|
4
4
|
#private;
|
|
5
5
|
constructor(client: EditorClient);
|
|
6
|
-
/** Enumerate the exact `package.json#
|
|
6
|
+
/** Enumerate the exact `package.json#volter.tools` catalog without executing it. */
|
|
7
7
|
list(): Promise<ProjectToolCatalog>;
|
|
8
8
|
/** Return one tool's discoverable metadata, or `null` when it is not registered. */
|
|
9
9
|
describe(name: string): Promise<ProjectToolCatalogEntry | null>;
|
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.69",
|
|
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.69",
|
|
34
|
+
"@volter/editor-project": "0.5.69",
|
|
35
35
|
"undici": "^7.28.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
package/src/editor-document.ts
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* active; `editor.hierarchy()` / `editor.inspect()` keep answering what those
|
|
29
29
|
* panels RESOLVED, where this door answers what they DREW.
|
|
30
30
|
*
|
|
31
|
-
* A field on `LiveEditor` rather than methods on it, so `
|
|
31
|
+
* A field on `LiveEditor` rather than methods on it, so the editor's `eval --list` command
|
|
32
32
|
* shows the verbs as one named surface — the same reason `game.input`
|
|
33
33
|
* and `game.events` are instance fields.
|
|
34
34
|
*/
|
|
@@ -90,13 +90,13 @@ export class LiveEditorDocument {
|
|
|
90
90
|
* `styles` additionally resolves named properties per match — and resolving
|
|
91
91
|
* is the point, because a theme token is an expression until an element
|
|
92
92
|
* paints it. Ask for the standard property to learn the colour a person
|
|
93
|
-
* sees; ask for a `--
|
|
93
|
+
* sees; ask for a `--volter-…` custom property to learn what a rule WOULD
|
|
94
94
|
* paint, which is the only way to measure a `:hover` colour (`:hover` is a
|
|
95
95
|
* browser state no synthetic event can enter, so there is deliberately no
|
|
96
96
|
* hover verb on this door).
|
|
97
97
|
*
|
|
98
|
-
* await editor.document.query('.
|
|
99
|
-
* styles: ['backgroundColor', '--
|
|
98
|
+
* await editor.document.query('.volter-tree-row', {
|
|
99
|
+
* styles: ['backgroundColor', '--volter-widget-regular-hover'],
|
|
100
100
|
* });
|
|
101
101
|
*/
|
|
102
102
|
async query(
|
|
@@ -116,12 +116,20 @@ export class LiveEditorDocument {
|
|
|
116
116
|
* — not `element.click()`, which a `pointerdown` listener never sees. */
|
|
117
117
|
async click(
|
|
118
118
|
selector: string,
|
|
119
|
-
options?: DocumentGestureOptions & {
|
|
119
|
+
options?: DocumentGestureOptions & {
|
|
120
|
+
clicks?: number;
|
|
121
|
+
at?: [number, number];
|
|
122
|
+
altKey?: boolean;
|
|
123
|
+
ctrlKey?: boolean;
|
|
124
|
+
metaKey?: boolean;
|
|
125
|
+
shiftKey?: boolean;
|
|
126
|
+
},
|
|
120
127
|
): Promise<DocumentProbeResult> {
|
|
121
128
|
// An option this door does not know is refused, never dropped: a dropped `position` clicked
|
|
122
129
|
// the element's centre and answered as if it had clicked where it was asked.
|
|
123
|
-
const
|
|
124
|
-
|
|
130
|
+
const known = ['scope', 'index', 'clicks', 'at', 'altKey', 'ctrlKey', 'metaKey', 'shiftKey'];
|
|
131
|
+
const unknown = Object.keys(options ?? {}).filter((key) => !known.includes(key));
|
|
132
|
+
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.`);
|
|
125
133
|
return this.#probe({
|
|
126
134
|
action: 'click',
|
|
127
135
|
selector,
|
|
@@ -129,6 +137,10 @@ export class LiveEditorDocument {
|
|
|
129
137
|
...(options?.index === undefined ? {} : { index: options.index }),
|
|
130
138
|
...(options?.clicks === undefined ? {} : { clicks: options.clicks }),
|
|
131
139
|
...(options?.at === undefined ? {} : { at: options.at }),
|
|
140
|
+
...(options?.altKey ? { altKey: true } : {}),
|
|
141
|
+
...(options?.ctrlKey ? { ctrlKey: true } : {}),
|
|
142
|
+
...(options?.metaKey ? { metaKey: true } : {}),
|
|
143
|
+
...(options?.shiftKey ? { shiftKey: true } : {}),
|
|
132
144
|
});
|
|
133
145
|
}
|
|
134
146
|
|
package/src/editor.ts
CHANGED
|
@@ -127,7 +127,7 @@ export class LiveEditor {
|
|
|
127
127
|
* `blender-execute`, `blender-scene-info`, `blender-object-info`,
|
|
128
128
|
* `blender-screenshot-view`, `blender-read-file`, `blender-write-file`,
|
|
129
129
|
* `blender-list-files`, `blender-stop` and `blender-status`. They were
|
|
130
|
-
* reachable from `@volter/editor-sdk` and through `
|
|
130
|
+
* reachable from `@volter/editor-sdk` and through `volter blender-mcp` but from
|
|
131
131
|
* no GENERAL door, so driving a session meant writing an MCP client script
|
|
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.
|
|
@@ -190,7 +190,7 @@ export class LiveEditor {
|
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* Photograph the editor PAGE — every panel, tab strip and viewport as the
|
|
193
|
-
* person sees it. `
|
|
193
|
+
* person sees it. the editor's `screenshot editor` command is this verb from the shell. The
|
|
194
194
|
* one door for judging chrome sighted: a skin, a workspace arrangement or a
|
|
195
195
|
* contributed panel is looked at through this, never guessed at from DOM
|
|
196
196
|
* probes. The page at its own layout, `scale` output pixels per CSS pixel
|
|
@@ -202,7 +202,7 @@ export class LiveEditor {
|
|
|
202
202
|
return this.#client.captureEditorChrome(options);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
/** `'all'` -> `EditorClient.selectAll()` (mirrors `
|
|
205
|
+
/** `'all'` -> `EditorClient.selectAll()` (mirrors `volter select --all`); otherwise `EditorClient.select(id)` (mirrors `volter select <entityId>`). */
|
|
206
206
|
async select(id: string | 'all'): Promise<void> {
|
|
207
207
|
if (id === 'all') {
|
|
208
208
|
await this.#client.selectAll();
|
|
@@ -211,12 +211,12 @@ export class LiveEditor {
|
|
|
211
211
|
await this.#client.select(id);
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
/** Mirrors `
|
|
214
|
+
/** Mirrors `volter deselect`. */
|
|
215
215
|
async deselect(): Promise<void> {
|
|
216
216
|
await this.#client.select(null);
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
/** No `id` -> focus the current selection (mirrors bare `
|
|
219
|
+
/** No `id` -> focus the current selection (mirrors bare `volter focus`); `id` given -> focus that entity. */
|
|
220
220
|
async focus(id?: string): Promise<void> {
|
|
221
221
|
if (id !== undefined) {
|
|
222
222
|
await this.#client.focusEntity(id);
|
|
@@ -508,19 +508,19 @@ export class LiveEditor {
|
|
|
508
508
|
* of one table is a second name for one thing, and an agent reading
|
|
509
509
|
* `--list` had to choose between them with nothing to choose on. This door
|
|
510
510
|
* stays because it is strictly wider: it addresses a COMMAND ID, so under
|
|
511
|
-
* the frame it reaches everything the workbench knows — a `
|
|
511
|
+
* the frame it reaches everything the workbench knows — a `volter.action.<id>`
|
|
512
512
|
* editor action, one of VS Code's own — and not only a view. A VIEW is
|
|
513
513
|
* reached by spelling its verb's command id:
|
|
514
514
|
*
|
|
515
|
-
* await editor.command('
|
|
516
|
-
* await editor.command('
|
|
515
|
+
* await editor.command('volter.blender-uv-view.state')
|
|
516
|
+
* await editor.command('volter.blender-uv-view.zoom', { to: 600 })
|
|
517
517
|
*
|
|
518
|
-
* await editor.command('
|
|
519
|
-
* await editor.command('
|
|
518
|
+
* await editor.command('volter.blender-node-view.view-all')
|
|
519
|
+
* await editor.command('volter.blender-node-view.look', { node: 'Principled BSDF' })
|
|
520
520
|
*
|
|
521
521
|
* Under the Code-OSS frame this is the workbench's own command service, so
|
|
522
|
-
* any command id works — ours and VS Code's alike. Standalone `
|
|
523
|
-
* has no command service and answers the `
|
|
522
|
+
* any command id works — ours and VS Code's alike. Standalone the editor's `edit` command
|
|
523
|
+
* has no command service and answers the `volter.<view>.<verb>` shape off the
|
|
524
524
|
* SAME verb table the frame's commands call, refusing any other id by name.
|
|
525
525
|
* One table, two doors, exactly like the keymap's.
|
|
526
526
|
*
|
|
@@ -674,7 +674,7 @@ export class LiveEditor {
|
|
|
674
674
|
await this.#client.reloadPage();
|
|
675
675
|
}
|
|
676
676
|
|
|
677
|
-
/** Mirrors `
|
|
677
|
+
/** Mirrors the editor's `status` command — the full live editor state as JSON. */
|
|
678
678
|
async status(): Promise<EditorState> {
|
|
679
679
|
return this.#client.getState();
|
|
680
680
|
}
|
package/src/session.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type SessionListingTransport = SessionDiscoveryTransport;
|
|
|
33
33
|
export interface ResolvedSession {
|
|
34
34
|
/** Editor dev-server port the resolved session is listening on. */
|
|
35
35
|
port: number;
|
|
36
|
-
/** Absolute project root — the nearest ancestor of the requested directory containing `
|
|
36
|
+
/** Absolute project root — the nearest ancestor of the requested directory containing `volter.project.json`. */
|
|
37
37
|
projectRoot: string;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ export interface SessionResolutionDeps {
|
|
|
42
42
|
transport?: SessionListingTransport;
|
|
43
43
|
/** Project-root discovery — defaults to the real fs walk (`findProjectRootFrom` above). Overridable for tests. */
|
|
44
44
|
findProjectRootFrom?: (dir: string) => string | null;
|
|
45
|
-
/** Project-local session hint reader. Defaults to `.
|
|
45
|
+
/** Project-local session hint reader. Defaults to `.volter/session.json`. */
|
|
46
46
|
readProjectSession?: (projectRoot: string) => ProjectSessionHint | null;
|
|
47
47
|
/** Exact-session verifier. Defaults to GET /__editor/project + canonical project matching. */
|
|
48
48
|
verifyProjectSession?: (hint: ProjectSessionHint, projectRoot: string) => Promise<boolean>;
|
|
@@ -66,7 +66,7 @@ function canonicalPath(path: string): string {
|
|
|
66
66
|
function readProjectSession(projectRoot: string): ProjectSessionHint | null {
|
|
67
67
|
try {
|
|
68
68
|
const value: unknown = JSON.parse(
|
|
69
|
-
readFileSync(join(projectRoot, '.
|
|
69
|
+
readFileSync(join(projectRoot, '.volter', 'session.json'), 'utf8'),
|
|
70
70
|
);
|
|
71
71
|
if (typeof value !== 'object' || value === null) return null;
|
|
72
72
|
const hint = value as Record<string, unknown>;
|
|
@@ -133,7 +133,7 @@ async function probeServedProject(
|
|
|
133
133
|
*/
|
|
134
134
|
function manifestRefusal(projectRoot: string, manifestError: string): Error {
|
|
135
135
|
return new Error(
|
|
136
|
-
`@volter/editor-live: the editor session for ${projectRoot} is live, but its
|
|
136
|
+
`@volter/editor-live: the editor session for ${projectRoot} is live, but its volter.project.json does ` +
|
|
137
137
|
'not load, so there is no editor or game to drive — the editor page is showing this same ' +
|
|
138
138
|
`error. Fix the manifest and retry; the session recovers on save, no restart needed.\n${manifestError}`,
|
|
139
139
|
);
|
|
@@ -141,15 +141,15 @@ function manifestRefusal(projectRoot: string, manifestError: string): Error {
|
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* Resolve `projectDir` (default `process.cwd()`) to the port of its already-
|
|
144
|
-
* running `
|
|
144
|
+
* running the editor's `edit` command session. Throws a descriptive error (never hangs
|
|
145
145
|
* indefinitely — bounded by `EDITOR_SESSION_DISCOVERY_TIMEOUT_MS`, and never
|
|
146
146
|
* silently attaches to an unrelated project's session — see the module doc
|
|
147
|
-
* above) when no
|
|
147
|
+
* above) when no volter.project.json is found, or no live session covers it.
|
|
148
148
|
*/
|
|
149
149
|
/**
|
|
150
150
|
* THE REFUSAL WHEN NOTHING MATCHED — and it says WHICH nothing.
|
|
151
151
|
*
|
|
152
|
-
* "No live editor session found … run `
|
|
152
|
+
* "No live editor session found … run the editor's `edit` command" used to be the answer to
|
|
153
153
|
* four different states, only one of which it described. The other three sent
|
|
154
154
|
* the operator to start an editor that was already running:
|
|
155
155
|
*
|
|
@@ -212,7 +212,7 @@ export async function resolveSession(
|
|
|
212
212
|
const projectRoot = findRoot(projectDir);
|
|
213
213
|
if (projectRoot === null) {
|
|
214
214
|
throw new Error(
|
|
215
|
-
`@volter/editor-live: no
|
|
215
|
+
`@volter/editor-live: no volter.project.json found in ${projectDir} or any parent directory — is this a project?`,
|
|
216
216
|
);
|
|
217
217
|
}
|
|
218
218
|
|
|
@@ -243,7 +243,7 @@ export async function resolveSession(
|
|
|
243
243
|
let sessions: EditorSessionInfo[];
|
|
244
244
|
// A FAILED discovery is not an empty one. Collapsing the two into `[]` is
|
|
245
245
|
// what made this door answer "no live editor session found" — and prescribe
|
|
246
|
-
// `
|
|
246
|
+
// the editor's `edit` command — for a probe that merely timed out under load, sending the
|
|
247
247
|
// operator to start an editor that was already running while the real defect
|
|
248
248
|
// went unnamed. The same collapse the manifest refusal above was added for.
|
|
249
249
|
let discoveryFailure: string | null = null;
|
package/src/tools.ts
CHANGED
|
@@ -15,7 +15,7 @@ export class LiveTools {
|
|
|
15
15
|
this.#client = client;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/** Enumerate the exact `package.json#
|
|
18
|
+
/** Enumerate the exact `package.json#volter.tools` catalog without executing it. */
|
|
19
19
|
async list(): Promise<ProjectToolCatalog> {
|
|
20
20
|
return this.#client.listProjectTools();
|
|
21
21
|
}
|