@vgai/sdk 0.5.0 → 0.5.2
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/package.json +2 -2
- package/src/account.ts +5 -4
- package/src/cinematic/capabilities-operations.ts +3 -3
- package/src/cinematic/cue-operations.ts +11 -11
- package/src/cinematic/gsap-operations.ts +5 -5
- package/src/cinematic/index.ts +3 -3
- package/src/cinematic/preview-operations.ts +10 -10
- package/src/cinematic/preview-transport.ts +2 -2
- package/src/cinematic/render-operations.ts +15 -15
- package/src/cinematic/render-transport.ts +2 -2
- package/src/cinematic/theatre-operations.ts +17 -17
- package/src/editor/camera-operations.ts +7 -7
- package/src/editor/console-operations.ts +5 -5
- package/src/editor/hierarchy-operations.ts +5 -5
- package/src/editor/index.ts +3 -3
- package/src/editor/open-operations.ts +10 -10
- package/src/editor/screenshot-operations.ts +5 -5
- package/src/editor/selection-operations.ts +7 -7
- package/src/editor/session-operations.ts +3 -3
- package/src/editor/source-location-operations.ts +6 -6
- package/src/editor/transport.ts +24 -11
- package/src/errors.ts +8 -8
- package/src/generations.ts +12 -1
- package/src/http/http-projection.ts +26 -26
- package/src/index.ts +22 -30
- package/src/mcp/index.ts +2 -2
- package/src/mcp/mcp-projection.ts +25 -25
- package/src/mcp/mcp-server.ts +2 -2
- package/src/operations.ts +5 -5
- package/src/play/control-operations.ts +10 -10
- package/src/play/debug-command-operations.ts +12 -12
- package/src/play/index.ts +3 -3
- package/src/play/input-operations.ts +10 -10
- package/src/play/lifecycle-operations.ts +11 -11
- package/src/play/log-operations.ts +7 -7
- package/src/play/run-ticks-operations.ts +8 -8
- package/src/play/state-operations.ts +9 -9
- package/src/play/status-operations.ts +7 -7
- package/src/play/transport.ts +93 -22
- package/src/project/asset-operations.ts +8 -8
- package/src/project/component-operations.ts +10 -10
- package/src/project/discovery-operations.ts +9 -9
- package/src/project/entity-operations.ts +8 -8
- package/src/project/index.ts +4 -4
- package/src/project/input-map-operations.ts +9 -9
- package/src/project/inspection-operation.ts +3 -3
- package/src/project/manifest-operations.ts +9 -9
- package/src/project/scene-operations.ts +14 -14
- package/src/project/shared.ts +17 -17
- package/src/project-tool-catalog.ts +21 -5
- package/src/registry.ts +39 -39
- package/src/render/render-cinematic.ts +24 -1
- package/src/tools.ts +19 -12
- package/src/types.ts +4 -4
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { z } from 'zod';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { ToolError } from '../errors.js';
|
|
16
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
17
17
|
import {
|
|
18
18
|
EDITOR_NOT_RUNNING_ERROR,
|
|
19
19
|
EDITOR_READ_TIMEOUT_MS,
|
|
@@ -56,7 +56,7 @@ const EditorHierarchyInspectResult = z.object({
|
|
|
56
56
|
),
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
export const editorHierarchyInspect =
|
|
59
|
+
export const editorHierarchyInspect = defineTool({
|
|
60
60
|
name: 'editor.hierarchy.inspect',
|
|
61
61
|
summary: "Inspect the entity hierarchy of the target editor session's currently loaded scene.",
|
|
62
62
|
description:
|
|
@@ -80,7 +80,7 @@ export const editorHierarchyInspect = defineOperation({
|
|
|
80
80
|
'editor.hierarchy.inspect',
|
|
81
81
|
).catch(() => undefined);
|
|
82
82
|
if (!hierarchy) {
|
|
83
|
-
throw new
|
|
83
|
+
throw new ToolError(
|
|
84
84
|
'HIERARCHY_UNAVAILABLE',
|
|
85
85
|
'The connected editor session did not answer the hierarchy-state read in time.',
|
|
86
86
|
{},
|
|
@@ -90,6 +90,6 @@ export const editorHierarchyInspect = defineOperation({
|
|
|
90
90
|
},
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
export function registerHierarchyOperations(registry:
|
|
93
|
+
export function registerHierarchyOperations(registry: ToolRegistry): void {
|
|
94
94
|
registry.register(editorHierarchyInspect);
|
|
95
95
|
}
|
package/src/editor/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* B3 — `editor.*` operations
|
|
3
3
|
* (docs/AI-NATIVE-AUTHORING-IMPLEMENTATION-SPEC.md §8 B3). Registered
|
|
4
|
-
* separately from B1's `
|
|
4
|
+
* separately from B1's `registerBuiltinTools` (`../operations.ts`) and
|
|
5
5
|
* B2's `registerProjectOperations` (`../project/index.ts`) — the default
|
|
6
6
|
* `operations` singleton (`../index.ts`) calls all three.
|
|
7
7
|
*/
|
|
@@ -39,7 +39,7 @@ export {
|
|
|
39
39
|
withTimeout,
|
|
40
40
|
} from './transport.js';
|
|
41
41
|
|
|
42
|
-
import type {
|
|
42
|
+
import type { ToolRegistry } from '../registry.js';
|
|
43
43
|
import { registerCameraOperations } from './camera-operations.js';
|
|
44
44
|
import { registerConsoleOperations } from './console-operations.js';
|
|
45
45
|
import { registerHierarchyOperations } from './hierarchy-operations.js';
|
|
@@ -50,7 +50,7 @@ import { registerSessionOperations } from './session-operations.js';
|
|
|
50
50
|
import { registerSourceLocationOperations } from './source-location-operations.js';
|
|
51
51
|
|
|
52
52
|
/** Register every B3 `editor.*` operation onto `registry`. */
|
|
53
|
-
export function registerEditorOperations(registry:
|
|
53
|
+
export function registerEditorOperations(registry: ToolRegistry): void {
|
|
54
54
|
registerSessionOperations(registry);
|
|
55
55
|
registerSelectionOperations(registry);
|
|
56
56
|
registerHierarchyOperations(registry);
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import { z } from 'zod';
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
25
|
+
import { ToolError } from '../errors.js';
|
|
26
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
27
27
|
import {
|
|
28
28
|
EDITOR_COMMAND_TIMEOUT_MS,
|
|
29
29
|
EDITOR_NOT_RUNNING_ERROR,
|
|
@@ -58,7 +58,7 @@ const EditorSceneOpenInput = z.object({
|
|
|
58
58
|
.describe('Project-relative path to a .vscn.json scene file to open in the editor.'),
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
export const editorSceneOpen =
|
|
61
|
+
export const editorSceneOpen = defineTool({
|
|
62
62
|
name: 'editor.scene.open',
|
|
63
63
|
summary: 'Open a scene file in a connected editor session.',
|
|
64
64
|
description:
|
|
@@ -87,7 +87,7 @@ export const editorSceneOpen = defineOperation({
|
|
|
87
87
|
error: err instanceof Error ? err.message : String(err),
|
|
88
88
|
}));
|
|
89
89
|
if (!result.ok) {
|
|
90
|
-
throw new
|
|
90
|
+
throw new ToolError('COMMAND_FAILED', result.error ?? 'open-scene command failed', {
|
|
91
91
|
message: result.error ?? 'open-scene command failed',
|
|
92
92
|
});
|
|
93
93
|
}
|
|
@@ -115,7 +115,7 @@ const EditorAssetOpenInput = z.object({
|
|
|
115
115
|
kind: AssetKindSchema,
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
export const editorAssetOpen =
|
|
118
|
+
export const editorAssetOpen = defineTool({
|
|
119
119
|
name: 'editor.asset.open',
|
|
120
120
|
summary: 'Open an asset as a tab in a connected editor session.',
|
|
121
121
|
description:
|
|
@@ -144,7 +144,7 @@ export const editorAssetOpen = defineOperation({
|
|
|
144
144
|
error: err instanceof Error ? err.message : String(err),
|
|
145
145
|
}));
|
|
146
146
|
if (!result.ok) {
|
|
147
|
-
throw new
|
|
147
|
+
throw new ToolError('COMMAND_FAILED', result.error ?? 'open-asset-tab command failed', {
|
|
148
148
|
message: result.error ?? 'open-asset-tab command failed',
|
|
149
149
|
});
|
|
150
150
|
}
|
|
@@ -160,7 +160,7 @@ const EditorStoryOpenInput = z.object({
|
|
|
160
160
|
path: z.string().describe('Project-relative path to a *.stories.tsx/*.stories.ts module.'),
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
export const editorStoryOpen =
|
|
163
|
+
export const editorStoryOpen = defineTool({
|
|
164
164
|
name: 'editor.story.open',
|
|
165
165
|
summary: 'Open a Storybook CSF story in a connected editor session.',
|
|
166
166
|
description:
|
|
@@ -187,14 +187,14 @@ export const editorStoryOpen = defineOperation({
|
|
|
187
187
|
'editor.story.open',
|
|
188
188
|
).catch(() => undefined);
|
|
189
189
|
if (!result) {
|
|
190
|
-
throw new
|
|
190
|
+
throw new ToolError(
|
|
191
191
|
'STORY_OPEN_UNSUPPORTED',
|
|
192
192
|
'The connected editor has no wire-level command to open a story today.',
|
|
193
193
|
{},
|
|
194
194
|
);
|
|
195
195
|
}
|
|
196
196
|
if (!result.ok) {
|
|
197
|
-
throw new
|
|
197
|
+
throw new ToolError('COMMAND_FAILED', result.error ?? 'open-story command failed', {
|
|
198
198
|
message: result.error ?? 'open-story command failed',
|
|
199
199
|
});
|
|
200
200
|
}
|
|
@@ -202,7 +202,7 @@ export const editorStoryOpen = defineOperation({
|
|
|
202
202
|
},
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
-
export function registerOpenOperations(registry:
|
|
205
|
+
export function registerOpenOperations(registry: ToolRegistry): void {
|
|
206
206
|
registry.register(editorSceneOpen);
|
|
207
207
|
registry.register(editorAssetOpen);
|
|
208
208
|
registry.register(editorStoryOpen);
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { z } from 'zod';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
19
|
+
import { ToolError } from '../errors.js';
|
|
20
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
21
21
|
import {
|
|
22
22
|
EDITOR_NOT_RUNNING_ERROR,
|
|
23
23
|
EDITOR_READ_TIMEOUT_MS,
|
|
@@ -56,7 +56,7 @@ const EditorViewportScreenshotCaptureResult = z
|
|
|
56
56
|
})
|
|
57
57
|
.describe('A viewport image — fresh when possible, the last-saved thumbnail otherwise.');
|
|
58
58
|
|
|
59
|
-
export const editorViewportScreenshotCapture =
|
|
59
|
+
export const editorViewportScreenshotCapture = defineTool({
|
|
60
60
|
name: 'editor.viewport.screenshot.capture',
|
|
61
61
|
summary: "Capture the target editor session's live viewport (falls back to its saved thumbnail).",
|
|
62
62
|
description:
|
|
@@ -84,7 +84,7 @@ export const editorViewportScreenshotCapture = defineOperation({
|
|
|
84
84
|
'editor.viewport.screenshot.capture',
|
|
85
85
|
).catch(() => undefined);
|
|
86
86
|
if (!shot) {
|
|
87
|
-
throw new
|
|
87
|
+
throw new ToolError(
|
|
88
88
|
'SCREENSHOT_UNAVAILABLE',
|
|
89
89
|
'No fresh capture or saved thumbnail is available for this session, or the read timed out.',
|
|
90
90
|
{},
|
|
@@ -94,6 +94,6 @@ export const editorViewportScreenshotCapture = defineOperation({
|
|
|
94
94
|
},
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
export function registerScreenshotOperations(registry:
|
|
97
|
+
export function registerScreenshotOperations(registry: ToolRegistry): void {
|
|
98
98
|
registry.register(editorViewportScreenshotCapture);
|
|
99
99
|
}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { z } from 'zod';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { ToolError } from '../errors.js';
|
|
14
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
15
15
|
import {
|
|
16
16
|
EDITOR_COMMAND_TIMEOUT_MS,
|
|
17
17
|
EDITOR_NOT_RUNNING_ERROR,
|
|
@@ -51,7 +51,7 @@ const EditorSelectionGetResult = z
|
|
|
51
51
|
})
|
|
52
52
|
.describe('Live selection snapshot from the resolved editor session.');
|
|
53
53
|
|
|
54
|
-
export const editorSelectionGet =
|
|
54
|
+
export const editorSelectionGet = defineTool({
|
|
55
55
|
name: 'editor.selection.get',
|
|
56
56
|
summary: 'Read the current entity selection from a connected editor session.',
|
|
57
57
|
description:
|
|
@@ -75,7 +75,7 @@ export const editorSelectionGet = defineOperation({
|
|
|
75
75
|
'editor.selection.get',
|
|
76
76
|
).catch(() => undefined);
|
|
77
77
|
if (!selection) {
|
|
78
|
-
throw new
|
|
78
|
+
throw new ToolError(
|
|
79
79
|
'SELECTION_UNAVAILABLE',
|
|
80
80
|
'The connected editor session did not answer the selection-state read in time.',
|
|
81
81
|
{},
|
|
@@ -97,7 +97,7 @@ const EditorSelectionSetInput = z
|
|
|
97
97
|
|
|
98
98
|
const EditorSelectionSetResult = z.object({ ok: z.literal(true) });
|
|
99
99
|
|
|
100
|
-
export const editorSelectionSet =
|
|
100
|
+
export const editorSelectionSet = defineTool({
|
|
101
101
|
name: 'editor.selection.set',
|
|
102
102
|
summary: 'Set the entity selection in a connected editor session.',
|
|
103
103
|
description:
|
|
@@ -130,7 +130,7 @@ export const editorSelectionSet = defineOperation({
|
|
|
130
130
|
error: err instanceof Error ? err.message : String(err),
|
|
131
131
|
}));
|
|
132
132
|
if (!result.ok) {
|
|
133
|
-
throw new
|
|
133
|
+
throw new ToolError('COMMAND_FAILED', result.error ?? 'select command failed', {
|
|
134
134
|
message: result.error ?? 'select command failed',
|
|
135
135
|
});
|
|
136
136
|
}
|
|
@@ -138,7 +138,7 @@ export const editorSelectionSet = defineOperation({
|
|
|
138
138
|
},
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
export function registerSelectionOperations(registry:
|
|
141
|
+
export function registerSelectionOperations(registry: ToolRegistry): void {
|
|
142
142
|
registry.register(editorSelectionGet);
|
|
143
143
|
registry.register(editorSelectionSet);
|
|
144
144
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { z } from 'zod';
|
|
22
|
-
import {
|
|
22
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
23
23
|
import { EDITOR_SESSION_DISCOVERY_TIMEOUT_MS, getTransport } from './transport.js';
|
|
24
24
|
|
|
25
25
|
const EditorSessionListInput = z
|
|
@@ -41,7 +41,7 @@ const EditorSessionListResult = z.object({
|
|
|
41
41
|
.describe('Every live session that answered a liveness probe, in no particular order.'),
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
export const editorSessionList =
|
|
44
|
+
export const editorSessionList = defineTool({
|
|
45
45
|
name: 'editor.session.list',
|
|
46
46
|
summary: 'List every live, probe-verified editor dev-server session on this machine.',
|
|
47
47
|
description:
|
|
@@ -68,6 +68,6 @@ export const editorSessionList = defineOperation({
|
|
|
68
68
|
},
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
export function registerSessionOperations(registry:
|
|
71
|
+
export function registerSessionOperations(registry: ToolRegistry): void {
|
|
72
72
|
registry.register(editorSessionList);
|
|
73
73
|
}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { z } from 'zod';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { ToolError } from '../errors.js';
|
|
18
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
19
19
|
import {
|
|
20
20
|
EDITOR_NOT_RUNNING_ERROR,
|
|
21
21
|
EDITOR_READ_TIMEOUT_MS,
|
|
@@ -50,7 +50,7 @@ const EditorSourceLocationLookupResult = z
|
|
|
50
50
|
})
|
|
51
51
|
.describe('Source location for the given oid. Never mutates anything.');
|
|
52
52
|
|
|
53
|
-
export const editorSourceLocationLookup =
|
|
53
|
+
export const editorSourceLocationLookup = defineTool({
|
|
54
54
|
name: 'editor.sourceLocation.lookup',
|
|
55
55
|
summary: "Map an inspected React element's oid to its exact component/source location.",
|
|
56
56
|
description:
|
|
@@ -81,7 +81,7 @@ export const editorSourceLocationLookup = defineOperation({
|
|
|
81
81
|
'editor.sourceLocation.lookup',
|
|
82
82
|
).catch(() => undefined);
|
|
83
83
|
if (!index) {
|
|
84
|
-
throw new
|
|
84
|
+
throw new ToolError(
|
|
85
85
|
'SOURCE_INDEX_UNAVAILABLE',
|
|
86
86
|
'The connected editor session did not answer the source-location index read in time.',
|
|
87
87
|
{},
|
|
@@ -89,7 +89,7 @@ export const editorSourceLocationLookup = defineOperation({
|
|
|
89
89
|
}
|
|
90
90
|
const entry = index[input.oid];
|
|
91
91
|
if (!entry) {
|
|
92
|
-
throw new
|
|
92
|
+
throw new ToolError(
|
|
93
93
|
'SOURCE_LOCATION_NOT_FOUND',
|
|
94
94
|
`No source location for oid "${input.oid}".`,
|
|
95
95
|
{
|
|
@@ -101,6 +101,6 @@ export const editorSourceLocationLookup = defineOperation({
|
|
|
101
101
|
},
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
export function registerSourceLocationOperations(registry:
|
|
104
|
+
export function registerSourceLocationOperations(registry: ToolRegistry): void {
|
|
105
105
|
registry.register(editorSourceLocationLookup);
|
|
106
106
|
}
|
package/src/editor/transport.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* EDITOR_NOT_RUNNING rather than hanging").
|
|
22
22
|
*
|
|
23
23
|
* `EditorTransport` is INJECTABLE via `ctx['editorTransport']` (a plain
|
|
24
|
-
* bag key on `
|
|
24
|
+
* bag key on `ToolContext`'s open `[key: string]: unknown` — no change
|
|
25
25
|
* to `types.ts` needed) so tests can swap in a mock/fake transport and
|
|
26
26
|
* exercise every op headlessly, with no real browser or dev server
|
|
27
27
|
* (see `../../test/editor-operations.test.ts`).
|
|
@@ -109,9 +109,9 @@ import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
|
109
109
|
import { homedir } from 'node:os';
|
|
110
110
|
import { join, resolve } from 'node:path';
|
|
111
111
|
import { z } from 'zod';
|
|
112
|
-
import {
|
|
113
|
-
import type {
|
|
114
|
-
import type {
|
|
112
|
+
import { ToolError } from '../errors.js';
|
|
113
|
+
import type { ToolErrorDefinition } from '../registry.js';
|
|
114
|
+
import type { ToolContext } from '../types.js';
|
|
115
115
|
|
|
116
116
|
// ---------------------------------------------------------------------------
|
|
117
117
|
// Named timeouts (§8 B3 AC: "enforce a named timeout, don't block forever")
|
|
@@ -172,6 +172,8 @@ export interface EditorSessionInfo {
|
|
|
172
172
|
project: string | null;
|
|
173
173
|
/** Dev-server process id, when known from the local session registry (null for an unregistered/legacy server the caller only probed by port). */
|
|
174
174
|
pid: number | null;
|
|
175
|
+
/** Registry discriminator. `kind: 'e2e'` is a standalone proof server, never an editor-control target. */
|
|
176
|
+
kind?: string;
|
|
175
177
|
/** Exact explicitly targeted editor origin/base URL, including protocol and host. */
|
|
176
178
|
url?: string;
|
|
177
179
|
}
|
|
@@ -295,6 +297,7 @@ interface RegistrySessionEntry {
|
|
|
295
297
|
port: number;
|
|
296
298
|
pid: number;
|
|
297
299
|
startedAt: string;
|
|
300
|
+
kind?: string;
|
|
298
301
|
}
|
|
299
302
|
|
|
300
303
|
function isRegistrySessionEntry(v: unknown): v is RegistrySessionEntry {
|
|
@@ -304,7 +307,8 @@ function isRegistrySessionEntry(v: unknown): v is RegistrySessionEntry {
|
|
|
304
307
|
(typeof s['project'] === 'string' || s['project'] === null) &&
|
|
305
308
|
typeof s['port'] === 'number' &&
|
|
306
309
|
typeof s['pid'] === 'number' &&
|
|
307
|
-
typeof s['startedAt'] === 'string'
|
|
310
|
+
typeof s['startedAt'] === 'string' &&
|
|
311
|
+
(s['kind'] === undefined || typeof s['kind'] === 'string')
|
|
308
312
|
);
|
|
309
313
|
}
|
|
310
314
|
|
|
@@ -328,7 +332,10 @@ function readRegisteredSessions(): RegistrySessionEntry[] {
|
|
|
328
332
|
try {
|
|
329
333
|
const raw: unknown = JSON.parse(readFileSync(registryFile, 'utf8'));
|
|
330
334
|
return Array.isArray(raw)
|
|
331
|
-
? raw
|
|
335
|
+
? raw
|
|
336
|
+
.filter(isRegistrySessionEntry)
|
|
337
|
+
.filter((s) => s.kind !== 'e2e')
|
|
338
|
+
.filter((s) => pidAlive(s.pid))
|
|
332
339
|
: [];
|
|
333
340
|
} catch {
|
|
334
341
|
return [];
|
|
@@ -400,7 +407,12 @@ export class HttpEditorTransport implements EditorTransport {
|
|
|
400
407
|
);
|
|
401
408
|
if (body === undefined) return undefined;
|
|
402
409
|
const project = (body as { project?: { path?: string } | null }).project?.path ?? null;
|
|
403
|
-
const info: EditorSessionInfo = {
|
|
410
|
+
const info: EditorSessionInfo = {
|
|
411
|
+
port: s.port,
|
|
412
|
+
project,
|
|
413
|
+
pid: s.pid,
|
|
414
|
+
...(s.kind !== undefined ? { kind: s.kind } : {}),
|
|
415
|
+
};
|
|
404
416
|
return info;
|
|
405
417
|
}),
|
|
406
418
|
);
|
|
@@ -577,7 +589,7 @@ export class HttpEditorTransport implements EditorTransport {
|
|
|
577
589
|
const defaultTransport = new HttpEditorTransport();
|
|
578
590
|
|
|
579
591
|
/** Resolve the transport to use: `ctx['editorTransport']` when injected (tests), else the shared real transport. */
|
|
580
|
-
export function getTransport(ctx:
|
|
592
|
+
export function getTransport(ctx: ToolContext): EditorTransport {
|
|
581
593
|
const injected = ctx['editorTransport'];
|
|
582
594
|
return (injected as EditorTransport | undefined) ?? defaultTransport;
|
|
583
595
|
}
|
|
@@ -586,7 +598,7 @@ export function getTransport(ctx: OperationContext): EditorTransport {
|
|
|
586
598
|
// EDITOR_NOT_RUNNING + deterministic session resolution
|
|
587
599
|
// ---------------------------------------------------------------------------
|
|
588
600
|
|
|
589
|
-
export const EDITOR_NOT_RUNNING_ERROR:
|
|
601
|
+
export const EDITOR_NOT_RUNNING_ERROR: ToolErrorDefinition = {
|
|
590
602
|
code: 'EDITOR_NOT_RUNNING',
|
|
591
603
|
summary:
|
|
592
604
|
'No live, responsive editor session is available to target (none running, none matching ' +
|
|
@@ -637,12 +649,12 @@ function portOf(url: string): number | undefined {
|
|
|
637
649
|
* surfaces EDITOR_NOT_RUNNING within that bound, never a hang.
|
|
638
650
|
*/
|
|
639
651
|
export async function resolveEditorSession(
|
|
640
|
-
ctx:
|
|
652
|
+
ctx: ToolContext,
|
|
641
653
|
transport: EditorTransport,
|
|
642
654
|
): Promise<EditorSessionInfo> {
|
|
643
655
|
const editorUrl = ctx.editorUrl;
|
|
644
656
|
const notRunning = (): never => {
|
|
645
|
-
throw new
|
|
657
|
+
throw new ToolError('EDITOR_NOT_RUNNING', 'No editor connected.', {
|
|
646
658
|
...(editorUrl !== undefined ? { editorUrl } : {}),
|
|
647
659
|
});
|
|
648
660
|
};
|
|
@@ -669,6 +681,7 @@ export async function resolveEditorSession(
|
|
|
669
681
|
} catch {
|
|
670
682
|
return notRunning();
|
|
671
683
|
}
|
|
684
|
+
sessions = sessions.filter((session) => session.kind !== 'e2e');
|
|
672
685
|
if (sessions.length === 0) return notRunning();
|
|
673
686
|
|
|
674
687
|
if (editorUrl !== undefined) {
|
package/src/errors.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { z } from 'zod';
|
|
|
3
3
|
/**
|
|
4
4
|
* Core, registry-level error codes — always available regardless of which
|
|
5
5
|
* operation was dispatched. Operation-specific codes are declared per
|
|
6
|
-
* operation on `
|
|
6
|
+
* operation on `ToolDefinition.errors` (see `registry.ts`).
|
|
7
7
|
*/
|
|
8
8
|
export const CORE_ERROR_CODES = {
|
|
9
9
|
/** `dispatch()` was called with a name no operation is registered under. */
|
|
@@ -11,7 +11,7 @@ export const CORE_ERROR_CODES = {
|
|
|
11
11
|
/** Input failed the operation's Zod input schema. */
|
|
12
12
|
INVALID_INPUT: 'INVALID_INPUT',
|
|
13
13
|
/** The impl's return value failed the operation's Zod result schema, or a
|
|
14
|
-
* thrown
|
|
14
|
+
* thrown ToolError's `data` failed its declared error-code schema —
|
|
15
15
|
* either way, an implementation bug, not a caller bug. */
|
|
16
16
|
INVALID_OUTPUT: 'INVALID_OUTPUT',
|
|
17
17
|
/** The impl threw something that isn't a declared, structured error. */
|
|
@@ -46,32 +46,32 @@ export interface StructuredOperationError {
|
|
|
46
46
|
* copies of @vgai/sdk (for example, an editor host dispatching a standalone
|
|
47
47
|
* project's tool). `instanceof` alone cannot cross that package boundary.
|
|
48
48
|
*/
|
|
49
|
-
export const OPERATION_ERROR_BRAND = Symbol.for('@vgai/sdk.
|
|
49
|
+
export const OPERATION_ERROR_BRAND = Symbol.for('@vgai/sdk.ToolError');
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* The only way an operation `impl` should signal an EXPECTED, contractual
|
|
53
53
|
* failure (as opposed to an unexpected bug/exception). `code` must be one
|
|
54
|
-
* the operation's `
|
|
54
|
+
* the operation's `ToolDefinition.errors` declares — `dispatch()`
|
|
55
55
|
* cross-checks it and validates `data` against that code's schema, so an
|
|
56
56
|
* undeclared code or mismatched data is itself normalized into a structured
|
|
57
57
|
* error rather than silently forwarded (see `registry.ts`'s
|
|
58
58
|
* `normalizeThrown`).
|
|
59
59
|
*/
|
|
60
|
-
export class
|
|
60
|
+
export class ToolError extends Error {
|
|
61
61
|
readonly [OPERATION_ERROR_BRAND] = true;
|
|
62
62
|
readonly code: string;
|
|
63
63
|
readonly data: unknown;
|
|
64
64
|
|
|
65
65
|
constructor(code: string, message: string, data?: unknown) {
|
|
66
66
|
super(message);
|
|
67
|
-
this.name = '
|
|
67
|
+
this.name = 'ToolError';
|
|
68
68
|
this.code = code;
|
|
69
69
|
this.data = data;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function isOperationError(value: unknown): value is
|
|
74
|
-
if (value instanceof
|
|
73
|
+
export function isOperationError(value: unknown): value is ToolError {
|
|
74
|
+
if (value instanceof ToolError) return true;
|
|
75
75
|
if (value === null || typeof value !== 'object') return false;
|
|
76
76
|
const candidate = value as Record<PropertyKey, unknown>;
|
|
77
77
|
return (
|
package/src/generations.ts
CHANGED
|
@@ -48,13 +48,18 @@ export const GenerationJobSchema = z.object({
|
|
|
48
48
|
createdAt: z.string().datetime(),
|
|
49
49
|
updatedAt: z.string().datetime(),
|
|
50
50
|
progress: z.number().min(0).max(1).optional(),
|
|
51
|
+
providerStatus: z.string().optional(),
|
|
52
|
+
queuePosition: z.number().int().nonnegative().optional(),
|
|
51
53
|
message: z.string().optional(),
|
|
54
|
+
lastPolledAt: z.string().datetime().optional(),
|
|
55
|
+
lastProviderChangeAt: z.string().datetime().optional(),
|
|
52
56
|
pollError: z.string().optional(),
|
|
53
57
|
pollErrorAt: z.string().datetime().optional(),
|
|
54
58
|
pollFailureCount: z.number().int().nonnegative().optional(),
|
|
55
59
|
nextPollAt: z.string().datetime().optional(),
|
|
56
60
|
billing: GenerationBillingSchema,
|
|
57
61
|
poll: GenerationOperationReferenceSchema,
|
|
62
|
+
cancel: GenerationOperationReferenceSchema.optional(),
|
|
58
63
|
accept: GenerationOperationReferenceSchema.optional(),
|
|
59
64
|
acceptedAt: z.string().datetime().optional(),
|
|
60
65
|
provenanceOperationId: z.string().optional(),
|
|
@@ -79,9 +84,12 @@ export interface GenerationJobDraft {
|
|
|
79
84
|
mode: 'mock' | 'direct' | 'managed';
|
|
80
85
|
status: GenerationJobStatus;
|
|
81
86
|
progress?: number;
|
|
87
|
+
providerStatus?: string;
|
|
88
|
+
queuePosition?: number;
|
|
82
89
|
message?: string;
|
|
83
90
|
billing: GenerationBilling;
|
|
84
91
|
poll: { tool: string; input: unknown };
|
|
92
|
+
cancel?: { tool: string; input: unknown };
|
|
85
93
|
accept?: { tool: string; input: unknown };
|
|
86
94
|
}
|
|
87
95
|
|
|
@@ -90,8 +98,11 @@ export interface GenerationJobUpdate {
|
|
|
90
98
|
externalId: string;
|
|
91
99
|
status?: GenerationJobStatus;
|
|
92
100
|
progress?: number;
|
|
101
|
+
providerStatus?: string;
|
|
102
|
+
queuePosition?: number;
|
|
93
103
|
message?: string;
|
|
94
104
|
billing?: GenerationBilling;
|
|
105
|
+
cancel?: { tool: string; input: unknown };
|
|
95
106
|
accepted?: {
|
|
96
107
|
provenanceOperationId: string;
|
|
97
108
|
outputPaths: string[];
|
|
@@ -106,7 +117,7 @@ export type GenerationToolContribution =
|
|
|
106
117
|
toJob(input: unknown, result: unknown): GenerationJobDraft;
|
|
107
118
|
}
|
|
108
119
|
| {
|
|
109
|
-
role: 'poll' | 'accept';
|
|
120
|
+
role: 'poll' | 'cancel' | 'accept';
|
|
110
121
|
provider: string;
|
|
111
122
|
toUpdate(input: unknown, result: unknown): GenerationJobUpdate;
|
|
112
123
|
};
|