@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
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';
|
|
12
12
|
import { dirname, extname, join, relative } from 'node:path';
|
|
13
13
|
import { z } from 'zod';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { ToolError } from '../errors.js';
|
|
15
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
16
16
|
import {
|
|
17
17
|
DryRunField,
|
|
18
18
|
mutationResultSchema,
|
|
@@ -49,7 +49,7 @@ const AssetEntrySchema = z.object({
|
|
|
49
49
|
ext: z.string().describe('Lowercased file extension including the leading dot, or "" if none.'),
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
export const projectAssetList =
|
|
52
|
+
export const projectAssetList = defineTool({
|
|
53
53
|
name: 'project.asset.list',
|
|
54
54
|
summary: 'List every file under the project’s public/ asset root (or a subdirectory of it).',
|
|
55
55
|
description:
|
|
@@ -99,7 +99,7 @@ const ProjectAssetInspectInput = z.object({
|
|
|
99
99
|
assetPath: z.string().describe('public/-relative path to inspect.'),
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
export const projectAssetInspect =
|
|
102
|
+
export const projectAssetInspect = defineTool({
|
|
103
103
|
name: 'project.asset.inspect',
|
|
104
104
|
summary:
|
|
105
105
|
'Inspect one asset under public/ — existence, size, mtime, and a content hash for small files.',
|
|
@@ -174,7 +174,7 @@ const ProjectAssetImportInput = z.object({
|
|
|
174
174
|
dryRun: DryRunField,
|
|
175
175
|
});
|
|
176
176
|
|
|
177
|
-
export const projectAssetImport =
|
|
177
|
+
export const projectAssetImport = defineTool({
|
|
178
178
|
name: 'project.asset.import',
|
|
179
179
|
summary: 'Copy an external file into the project’s public/ asset root.',
|
|
180
180
|
description:
|
|
@@ -203,7 +203,7 @@ export const projectAssetImport = defineOperation({
|
|
|
203
203
|
async impl(input, ctx) {
|
|
204
204
|
const projectRoot = requireProjectRoot(ctx);
|
|
205
205
|
if (!existsSync(input.sourcePath) || statSync(input.sourcePath).isDirectory()) {
|
|
206
|
-
throw new
|
|
206
|
+
throw new ToolError('SOURCE_NOT_FOUND', `Source file not found: ${input.sourcePath}`, {
|
|
207
207
|
sourcePath: input.sourcePath,
|
|
208
208
|
});
|
|
209
209
|
}
|
|
@@ -211,7 +211,7 @@ export const projectAssetImport = defineOperation({
|
|
|
211
211
|
const destAbs = resolveProjectPath(publicRoot, input.destPath);
|
|
212
212
|
const destExists = existsSync(destAbs);
|
|
213
213
|
if (destExists && !input.overwrite) {
|
|
214
|
-
throw new
|
|
214
|
+
throw new ToolError(
|
|
215
215
|
'DEST_EXISTS',
|
|
216
216
|
`${input.destPath} already exists — pass overwrite:true to replace it.`,
|
|
217
217
|
{
|
|
@@ -239,7 +239,7 @@ export const projectAssetImport = defineOperation({
|
|
|
239
239
|
});
|
|
240
240
|
|
|
241
241
|
/** Register every B2 `project.asset.*` operation onto `registry`. */
|
|
242
|
-
export function registerAssetOperations(registry:
|
|
242
|
+
export function registerAssetOperations(registry: ToolRegistry): void {
|
|
243
243
|
registry.register(projectAssetList);
|
|
244
244
|
registry.register(projectAssetInspect);
|
|
245
245
|
registry.register(projectAssetImport);
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import type { SceneEntity } from '@vgai/engine/scene/scene-types';
|
|
15
15
|
import { z } from 'zod';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { ToolError } from '../errors.js';
|
|
17
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
18
18
|
import { finalizeSceneMutation } from './entity-operations.js';
|
|
19
19
|
import {
|
|
20
20
|
APPLY_DIFF_FAILED_ERROR,
|
|
@@ -77,7 +77,7 @@ const ProjectSceneComponentListInput = z.object({
|
|
|
77
77
|
entityId: z.string().describe('Entity to list components for.'),
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
export const projectSceneComponentList =
|
|
80
|
+
export const projectSceneComponentList = defineTool({
|
|
81
81
|
name: 'project.scene.component.list',
|
|
82
82
|
summary: 'List every component (by name) attached to an entity.',
|
|
83
83
|
description: 'Read-only. Resolves the entity by stable id.',
|
|
@@ -127,7 +127,7 @@ const ComponentAfterSchema = z.object({
|
|
|
127
127
|
data: z.unknown(),
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
-
export const projectSceneComponentAdd =
|
|
130
|
+
export const projectSceneComponentAdd = defineTool({
|
|
131
131
|
name: 'project.scene.component.add',
|
|
132
132
|
summary: 'Attach a new named component to an entity.',
|
|
133
133
|
description:
|
|
@@ -157,7 +157,7 @@ export const projectSceneComponentAdd = defineOperation({
|
|
|
157
157
|
const entity = requireEntityById(scene.entities, input.entityId);
|
|
158
158
|
const existing = entity.components ?? {};
|
|
159
159
|
if (input.componentName in existing) {
|
|
160
|
-
throw new
|
|
160
|
+
throw new ToolError(
|
|
161
161
|
'COMPONENT_ALREADY_EXISTS',
|
|
162
162
|
`Entity "${input.entityId}" already has a component named "${input.componentName}" — use project.scene.component.update instead.`,
|
|
163
163
|
{ entityId: input.entityId, componentName: input.componentName },
|
|
@@ -196,7 +196,7 @@ const ProjectSceneComponentUpdateInput = z.object({
|
|
|
196
196
|
baseHash: BaseHashField,
|
|
197
197
|
});
|
|
198
198
|
|
|
199
|
-
export const projectSceneComponentUpdate =
|
|
199
|
+
export const projectSceneComponentUpdate = defineTool({
|
|
200
200
|
name: 'project.scene.component.update',
|
|
201
201
|
summary: 'Merge field changes onto an existing named component.',
|
|
202
202
|
description: 'Delegates to applyDiff’s `update` op with a merged components record.',
|
|
@@ -226,7 +226,7 @@ export const projectSceneComponentUpdate = defineOperation({
|
|
|
226
226
|
const existing = entity.components ?? {};
|
|
227
227
|
const currentData = existing[input.componentName];
|
|
228
228
|
if (currentData === undefined) {
|
|
229
|
-
throw new
|
|
229
|
+
throw new ToolError(
|
|
230
230
|
'COMPONENT_NOT_FOUND',
|
|
231
231
|
`Entity "${input.entityId}" has no component named "${input.componentName}".`,
|
|
232
232
|
{ entityId: input.entityId, componentName: input.componentName },
|
|
@@ -266,7 +266,7 @@ const ProjectSceneComponentRemoveInput = z.object({
|
|
|
266
266
|
baseHash: BaseHashField,
|
|
267
267
|
});
|
|
268
268
|
|
|
269
|
-
export const projectSceneComponentRemove =
|
|
269
|
+
export const projectSceneComponentRemove = defineTool({
|
|
270
270
|
name: 'project.scene.component.remove',
|
|
271
271
|
summary: 'Detach a named component from an entity.',
|
|
272
272
|
description:
|
|
@@ -300,7 +300,7 @@ export const projectSceneComponentRemove = defineOperation({
|
|
|
300
300
|
const existing = entity.components ?? {};
|
|
301
301
|
const currentData = existing[input.componentName];
|
|
302
302
|
if (currentData === undefined) {
|
|
303
|
-
throw new
|
|
303
|
+
throw new ToolError(
|
|
304
304
|
'COMPONENT_NOT_FOUND',
|
|
305
305
|
`Entity "${input.entityId}" has no component named "${input.componentName}".`,
|
|
306
306
|
{ entityId: input.entityId, componentName: input.componentName },
|
|
@@ -329,7 +329,7 @@ export const projectSceneComponentRemove = defineOperation({
|
|
|
329
329
|
});
|
|
330
330
|
|
|
331
331
|
/** Register every B2 `project.scene.component.*` operation onto `registry`. */
|
|
332
|
-
export function registerComponentOperations(registry:
|
|
332
|
+
export function registerComponentOperations(registry: ToolRegistry): void {
|
|
333
333
|
registry.register(projectSceneComponentList);
|
|
334
334
|
registry.register(projectSceneComponentAdd);
|
|
335
335
|
registry.register(projectSceneComponentUpdate);
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
import { readFileSync } from 'node:fs';
|
|
28
28
|
import { z } from 'zod';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
29
|
+
import { ToolError } from '../errors.js';
|
|
30
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
31
31
|
import {
|
|
32
32
|
listProjectFiles,
|
|
33
33
|
NO_PROJECT_ROOT_ERROR,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
// project.story.discover
|
|
41
41
|
// ---------------------------------------------------------------------------
|
|
42
42
|
|
|
43
|
-
export const projectStoryDiscover =
|
|
43
|
+
export const projectStoryDiscover = defineTool({
|
|
44
44
|
name: 'project.story.discover',
|
|
45
45
|
summary: 'List every Storybook CSF story module (*.stories.tsx / *.stories.ts) in the project.',
|
|
46
46
|
description:
|
|
@@ -68,7 +68,7 @@ export const projectStoryDiscover = defineOperation({
|
|
|
68
68
|
// project.theatre.discover
|
|
69
69
|
// ---------------------------------------------------------------------------
|
|
70
70
|
|
|
71
|
-
export const projectTheatreDiscover =
|
|
71
|
+
export const projectTheatreDiscover = defineTool({
|
|
72
72
|
name: 'project.theatre.discover',
|
|
73
73
|
summary:
|
|
74
74
|
'List every committed Theatre project-state file (*.theatre-project.json) in the project.',
|
|
@@ -112,7 +112,7 @@ const ProjectTheatreValidateInput = z.object({
|
|
|
112
112
|
.describe('Validate this raw document instead of reading `theatreProjectPath`.'),
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
-
export const projectTheatreValidate =
|
|
115
|
+
export const projectTheatreValidate = defineTool({
|
|
116
116
|
name: 'project.theatre.validate',
|
|
117
117
|
summary:
|
|
118
118
|
'Validate a Theatre project-state file’s OUTER shape (sheetsById/definitionVersion/revisionHistory).',
|
|
@@ -148,7 +148,7 @@ export const projectTheatreValidate = defineOperation({
|
|
|
148
148
|
const absPath = resolveProjectPath(projectRoot, input.theatreProjectPath);
|
|
149
149
|
json = JSON.parse(readFileSync(absPath, 'utf-8'));
|
|
150
150
|
} else {
|
|
151
|
-
throw new
|
|
151
|
+
throw new ToolError(
|
|
152
152
|
'BAD_INPUT',
|
|
153
153
|
'One of theatreProjectPath or document must be given.',
|
|
154
154
|
{},
|
|
@@ -176,7 +176,7 @@ function looksLikeXStateMachine(text: string): { importsXstate: boolean; defines
|
|
|
176
176
|
return { importsXstate, definesMachine };
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
export const projectXstateDiscover =
|
|
179
|
+
export const projectXstateDiscover = defineTool({
|
|
180
180
|
name: 'project.xstate.discover',
|
|
181
181
|
summary:
|
|
182
182
|
'Best-effort static discovery of TypeScript modules that appear to define an XState machine.',
|
|
@@ -230,7 +230,7 @@ const ProjectXstateValidateInput = z.object({
|
|
|
230
230
|
machinePath: z.string().describe('Project-relative path to a TypeScript module to check.'),
|
|
231
231
|
});
|
|
232
232
|
|
|
233
|
-
export const projectXstateValidate =
|
|
233
|
+
export const projectXstateValidate = defineTool({
|
|
234
234
|
name: 'project.xstate.validate',
|
|
235
235
|
summary:
|
|
236
236
|
'Best-effort static check that a TypeScript module imports xstate and defines a machine.',
|
|
@@ -260,7 +260,7 @@ export const projectXstateValidate = defineOperation({
|
|
|
260
260
|
});
|
|
261
261
|
|
|
262
262
|
/** Register every B2 story/Theatre/XState discovery operation onto `registry`. */
|
|
263
|
-
export function registerDiscoveryOperations(registry:
|
|
263
|
+
export function registerDiscoveryOperations(registry: ToolRegistry): void {
|
|
264
264
|
registry.register(projectStoryDiscover);
|
|
265
265
|
registry.register(projectTheatreDiscover);
|
|
266
266
|
registry.register(projectTheatreValidate);
|
|
@@ -23,8 +23,8 @@ import type { applyDiff } from '@vgai/engine/scene/scene-apply';
|
|
|
23
23
|
import type { SceneEntity } from '@vgai/engine/scene/scene-types';
|
|
24
24
|
import { SceneEntitySchema } from '@vgai/engine/scene/schema/entity';
|
|
25
25
|
import { z } from 'zod';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
26
|
+
import { ToolError } from '../errors.js';
|
|
27
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
28
28
|
import {
|
|
29
29
|
APPLY_DIFF_FAILED_ERROR,
|
|
30
30
|
applyDiffOrThrow,
|
|
@@ -73,7 +73,7 @@ function finalizeSceneMutation<TBefore, TAfter>(
|
|
|
73
73
|
parseSceneFile(result, scenePath);
|
|
74
74
|
} catch (err) {
|
|
75
75
|
if (err instanceof SceneParseError) {
|
|
76
|
-
throw new
|
|
76
|
+
throw new ToolError('SCENE_INVALID', `Result fails validation: ${err.message}`, {
|
|
77
77
|
issues: err.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
|
|
78
78
|
});
|
|
79
79
|
}
|
|
@@ -103,7 +103,7 @@ const ProjectSceneEntityAddInput = z.object({
|
|
|
103
103
|
baseHash: BaseHashField,
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
export const projectSceneEntityAdd =
|
|
106
|
+
export const projectSceneEntityAdd = defineTool({
|
|
107
107
|
name: 'project.scene.entity.add',
|
|
108
108
|
summary: 'Insert a new entity into a scene, by parent id + index.',
|
|
109
109
|
description:
|
|
@@ -183,7 +183,7 @@ const ProjectSceneEntityUpdateInput = z.object({
|
|
|
183
183
|
baseHash: BaseHashField,
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
-
export const projectSceneEntityUpdate =
|
|
186
|
+
export const projectSceneEntityUpdate = defineTool({
|
|
187
187
|
name: 'project.scene.entity.update',
|
|
188
188
|
summary: 'Merge field changes onto an existing entity, addressed by stable id.',
|
|
189
189
|
description:
|
|
@@ -252,7 +252,7 @@ const ProjectSceneEntityMoveInput = z.object({
|
|
|
252
252
|
baseHash: BaseHashField,
|
|
253
253
|
});
|
|
254
254
|
|
|
255
|
-
export const projectSceneEntityMove =
|
|
255
|
+
export const projectSceneEntityMove = defineTool({
|
|
256
256
|
name: 'project.scene.entity.move',
|
|
257
257
|
summary: 'Reparent and/or reorder an existing entity, addressed by stable id.',
|
|
258
258
|
description: 'Builds a single `move` DiffOp and delegates to applyDiff.',
|
|
@@ -307,7 +307,7 @@ const ProjectSceneEntityRemoveInput = z.object({
|
|
|
307
307
|
baseHash: BaseHashField,
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
-
export const projectSceneEntityRemove =
|
|
310
|
+
export const projectSceneEntityRemove = defineTool({
|
|
311
311
|
name: 'project.scene.entity.remove',
|
|
312
312
|
summary: 'Delete an entity (and its subtree), addressed by stable id.',
|
|
313
313
|
description: 'Builds a single `remove` DiffOp and delegates to applyDiff.',
|
|
@@ -354,7 +354,7 @@ export const projectSceneEntityRemove = defineOperation({
|
|
|
354
354
|
});
|
|
355
355
|
|
|
356
356
|
/** Register every B2 `project.scene.entity.*` operation onto `registry`. */
|
|
357
|
-
export function registerEntityOperations(registry:
|
|
357
|
+
export function registerEntityOperations(registry: ToolRegistry): void {
|
|
358
358
|
registry.register(projectSceneEntityAdd);
|
|
359
359
|
registry.register(projectSceneEntityUpdate);
|
|
360
360
|
registry.register(projectSceneEntityMove);
|
package/src/project/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* B2 — `project.*` operations
|
|
3
3
|
* (docs/AI-NATIVE-AUTHORING-IMPLEMENTATION-SPEC.md §8 B2). Registered
|
|
4
|
-
* SEPARATELY from B1's `
|
|
5
|
-
* so B1's own registry tests — which assert `
|
|
4
|
+
* SEPARATELY from B1's `registerBuiltinTools` (see `../operations.ts`)
|
|
5
|
+
* so B1's own registry tests — which assert `registerBuiltinTools`
|
|
6
6
|
* registers "exactly the three B1 sample operations" — are unaffected; the
|
|
7
7
|
* default `operations` singleton (`../index.ts`) calls both.
|
|
8
8
|
*/
|
|
@@ -37,7 +37,7 @@ export {
|
|
|
37
37
|
writeFileAtomic,
|
|
38
38
|
} from './shared.js';
|
|
39
39
|
|
|
40
|
-
import type {
|
|
40
|
+
import type { ToolRegistry } from '../registry.js';
|
|
41
41
|
import { registerAssetOperations } from './asset-operations.js';
|
|
42
42
|
import { registerComponentOperations } from './component-operations.js';
|
|
43
43
|
import { registerDiscoveryOperations } from './discovery-operations.js';
|
|
@@ -48,7 +48,7 @@ import { registerManifestOperations } from './manifest-operations.js';
|
|
|
48
48
|
import { registerSceneOperations } from './scene-operations.js';
|
|
49
49
|
|
|
50
50
|
/** Register every B2 `project.*` operation onto `registry`. */
|
|
51
|
-
export function registerProjectOperations(registry:
|
|
51
|
+
export function registerProjectOperations(registry: ToolRegistry): void {
|
|
52
52
|
registerManifestOperations(registry);
|
|
53
53
|
registerSceneOperations(registry);
|
|
54
54
|
registerEntityOperations(registry);
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { InputMapFileSchema } from '@vgai/engine/input/schema';
|
|
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
|
BaseHashField,
|
|
19
19
|
CONFLICT_ERROR,
|
|
@@ -51,7 +51,7 @@ const ProjectInputMapReadInput = z.object({
|
|
|
51
51
|
),
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
export const projectInputMapRead =
|
|
54
|
+
export const projectInputMapRead = defineTool({
|
|
55
55
|
name: 'project.inputMap.read',
|
|
56
56
|
summary: 'Read + validate an .inputmap.json file.',
|
|
57
57
|
description:
|
|
@@ -82,7 +82,7 @@ export const projectInputMapRead = defineOperation({
|
|
|
82
82
|
const json: unknown = JSON.parse(raw);
|
|
83
83
|
const parsed = InputMapFileSchema.safeParse(json);
|
|
84
84
|
if (!parsed.success) {
|
|
85
|
-
throw new
|
|
85
|
+
throw new ToolError(
|
|
86
86
|
'INPUT_MAP_INVALID',
|
|
87
87
|
`${input.inputMapPath} failed input-map validation.`,
|
|
88
88
|
{
|
|
@@ -109,7 +109,7 @@ const ProjectInputMapValidateInput = z.object({
|
|
|
109
109
|
.describe('Validate this raw document instead of reading `inputMapPath`.'),
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
export const projectInputMapValidate =
|
|
112
|
+
export const projectInputMapValidate = defineTool({
|
|
113
113
|
name: 'project.inputMap.validate',
|
|
114
114
|
summary: 'Validate an input map file or raw document against the real input-map schema.',
|
|
115
115
|
description:
|
|
@@ -142,7 +142,7 @@ export const projectInputMapValidate = defineOperation({
|
|
|
142
142
|
const absPath = resolveProjectPath(projectRoot, input.inputMapPath);
|
|
143
143
|
json = JSON.parse(readFileWithHash(absPath).raw);
|
|
144
144
|
} else {
|
|
145
|
-
throw new
|
|
145
|
+
throw new ToolError('BAD_INPUT', 'One of inputMapPath or inputMap must be given.', {});
|
|
146
146
|
}
|
|
147
147
|
const parsed = InputMapFileSchema.safeParse(json);
|
|
148
148
|
if (!parsed.success) return { valid: false, issues: formatIssues(parsed.error.issues) };
|
|
@@ -166,7 +166,7 @@ const ProjectInputMapUpdateInput = z.object({
|
|
|
166
166
|
baseHash: BaseHashField,
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
-
export const projectInputMapUpdate =
|
|
169
|
+
export const projectInputMapUpdate = defineTool({
|
|
170
170
|
name: 'project.inputMap.update',
|
|
171
171
|
summary: 'Add, replace, or delete actions in an input map — dry-run capable, conflict-checked.',
|
|
172
172
|
description:
|
|
@@ -201,7 +201,7 @@ export const projectInputMapUpdate = defineOperation({
|
|
|
201
201
|
|
|
202
202
|
const parsed = InputMapFileSchema.safeParse(merged);
|
|
203
203
|
if (!parsed.success) {
|
|
204
|
-
throw new
|
|
204
|
+
throw new ToolError(
|
|
205
205
|
'INPUT_MAP_INVALID',
|
|
206
206
|
'The patched input map failed schema validation.',
|
|
207
207
|
{
|
|
@@ -226,7 +226,7 @@ export const projectInputMapUpdate = defineOperation({
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
/** Register every B2 `project.inputMap.*` operation onto `registry`. */
|
|
229
|
-
export function registerInputMapOperations(registry:
|
|
229
|
+
export function registerInputMapOperations(registry: ToolRegistry): void {
|
|
230
230
|
registry.register(projectInputMapRead);
|
|
231
231
|
registry.register(projectInputMapValidate);
|
|
232
232
|
registry.register(projectInputMapUpdate);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Read-only operation-registry projection of first-contact folder inspection. */
|
|
2
2
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import {
|
|
4
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
5
5
|
import { inspectProject, type ProjectInspection } from './inspection.js';
|
|
6
6
|
import { nodeProjectInspectionReader } from './inspection-node.js';
|
|
7
7
|
import { NO_PROJECT_ROOT_ERROR, requireProjectRoot } from './shared.js';
|
|
@@ -18,7 +18,7 @@ const ProjectInspectionResult = z.object({
|
|
|
18
18
|
nextAction: z.string(),
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
export const projectInspect =
|
|
21
|
+
export const projectInspect = defineTool({
|
|
22
22
|
name: 'project.inspect',
|
|
23
23
|
summary: 'Inspect this folder as a possible VGAI or existing browser-game project.',
|
|
24
24
|
description:
|
|
@@ -38,6 +38,6 @@ export const projectInspect = defineOperation({
|
|
|
38
38
|
},
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
export function registerInspectionOperations(registry:
|
|
41
|
+
export function registerInspectionOperations(registry: ToolRegistry): void {
|
|
42
42
|
registry.register(projectInspect);
|
|
43
43
|
}
|
|
@@ -15,8 +15,8 @@ import { existsSync } from 'node:fs';
|
|
|
15
15
|
import { loadGameManifest } from '@vgai/engine/manifest/load';
|
|
16
16
|
import { GameManifestSchema } from '@vgai/engine/manifest/schema';
|
|
17
17
|
import { z } from 'zod';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
18
|
+
import { ToolError } from '../errors.js';
|
|
19
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
20
20
|
import {
|
|
21
21
|
BaseHashField,
|
|
22
22
|
CONFLICT_ERROR,
|
|
@@ -73,7 +73,7 @@ const ProjectDiscoverResult = z
|
|
|
73
73
|
})
|
|
74
74
|
.describe('A one-call survey of the project at ctx.projectRoot.');
|
|
75
75
|
|
|
76
|
-
export const projectDiscover =
|
|
76
|
+
export const projectDiscover = defineTool({
|
|
77
77
|
name: 'project.discover',
|
|
78
78
|
summary:
|
|
79
79
|
"Survey a project's manifest, scenes, input maps, stories, and Theatre project state files.",
|
|
@@ -151,7 +151,7 @@ const ProjectManifestReadResult = z
|
|
|
151
151
|
})
|
|
152
152
|
.describe('Raw manifest read result.');
|
|
153
153
|
|
|
154
|
-
export const projectManifestRead =
|
|
154
|
+
export const projectManifestRead = defineTool({
|
|
155
155
|
name: 'project.manifest.read',
|
|
156
156
|
summary: 'Read the raw vgai.game.json manifest for the project.',
|
|
157
157
|
description:
|
|
@@ -193,7 +193,7 @@ const ProjectManifestValidateResult = z
|
|
|
193
193
|
})
|
|
194
194
|
.describe('Structured manifest validation result — never throws for an invalid document.');
|
|
195
195
|
|
|
196
|
-
export const projectManifestValidate =
|
|
196
|
+
export const projectManifestValidate = defineTool({
|
|
197
197
|
name: 'project.manifest.validate',
|
|
198
198
|
summary: 'Validate the project manifest against the real engine schema + cross-field rules.',
|
|
199
199
|
description:
|
|
@@ -272,7 +272,7 @@ const ProjectManifestUpdateResult = mutationResultSchema(
|
|
|
272
272
|
.describe('The manifest document after the patch (or that WOULD result).'),
|
|
273
273
|
);
|
|
274
274
|
|
|
275
|
-
export const projectManifestUpdate =
|
|
275
|
+
export const projectManifestUpdate = defineTool({
|
|
276
276
|
name: 'project.manifest.update',
|
|
277
277
|
summary: 'Patch name/version/resolution on vgai.game.json, dry-run capable, conflict-checked.',
|
|
278
278
|
description:
|
|
@@ -311,7 +311,7 @@ export const projectManifestUpdate = defineOperation({
|
|
|
311
311
|
|
|
312
312
|
const parsed = GameManifestSchema.safeParse(merged);
|
|
313
313
|
if (!parsed.success) {
|
|
314
|
-
throw new
|
|
314
|
+
throw new ToolError(
|
|
315
315
|
'INVALID_MANIFEST',
|
|
316
316
|
'The patched manifest failed schema validation.',
|
|
317
317
|
{
|
|
@@ -324,7 +324,7 @@ export const projectManifestUpdate = defineOperation({
|
|
|
324
324
|
try {
|
|
325
325
|
loadGameManifest(merged);
|
|
326
326
|
} catch (err) {
|
|
327
|
-
throw new
|
|
327
|
+
throw new ToolError(
|
|
328
328
|
'INVALID_MANIFEST',
|
|
329
329
|
'The patched manifest failed cross-field validation.',
|
|
330
330
|
{
|
|
@@ -349,7 +349,7 @@ export const projectManifestUpdate = defineOperation({
|
|
|
349
349
|
});
|
|
350
350
|
|
|
351
351
|
/** Register every B2 `project.discover` / `project.manifest.*` operation onto `registry`. */
|
|
352
|
-
export function registerManifestOperations(registry:
|
|
352
|
+
export function registerManifestOperations(registry: ToolRegistry): void {
|
|
353
353
|
registry.register(projectDiscover);
|
|
354
354
|
registry.register(projectManifestRead);
|
|
355
355
|
registry.register(projectManifestValidate);
|
|
@@ -24,8 +24,8 @@ import { ApplyDiffError, applyDiff } from '@vgai/engine/scene/scene-apply';
|
|
|
24
24
|
import { SceneDiffSchema } from '@vgai/engine/scene/scene-diff-schema';
|
|
25
25
|
import type { SceneFile } from '@vgai/engine/scene/scene-types';
|
|
26
26
|
import { z } from 'zod';
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
27
|
+
import { ToolError } from '../errors.js';
|
|
28
|
+
import { defineTool, type ToolRegistry } from '../registry.js';
|
|
29
29
|
import {
|
|
30
30
|
BaseHashField,
|
|
31
31
|
CONFLICT_ERROR,
|
|
@@ -102,7 +102,7 @@ export function readAndParseScene(
|
|
|
102
102
|
try {
|
|
103
103
|
json = JSON.parse(raw);
|
|
104
104
|
} catch (err) {
|
|
105
|
-
throw new
|
|
105
|
+
throw new ToolError(
|
|
106
106
|
'SCENE_INVALID',
|
|
107
107
|
`${scenePath} is not valid JSON: ${err instanceof Error ? err.message : err}`,
|
|
108
108
|
{
|
|
@@ -115,7 +115,7 @@ export function readAndParseScene(
|
|
|
115
115
|
return { absPath, hash, scene };
|
|
116
116
|
} catch (err) {
|
|
117
117
|
if (err instanceof SceneParseError) {
|
|
118
|
-
throw new
|
|
118
|
+
throw new ToolError('SCENE_INVALID', err.message, { issues: formatIssues(err.issues) });
|
|
119
119
|
}
|
|
120
120
|
throw err;
|
|
121
121
|
}
|
|
@@ -130,7 +130,7 @@ export function applyDiffOrThrow(
|
|
|
130
130
|
return applyDiff(scene, patch);
|
|
131
131
|
} catch (err) {
|
|
132
132
|
if (err instanceof ApplyDiffError) {
|
|
133
|
-
throw new
|
|
133
|
+
throw new ToolError('APPLY_DIFF_FAILED', err.message, {
|
|
134
134
|
opIndex: err.opIndex,
|
|
135
135
|
opType: err.opType,
|
|
136
136
|
entityId: err.entityId,
|
|
@@ -159,7 +159,7 @@ const ProjectSceneReadResult = z
|
|
|
159
159
|
})
|
|
160
160
|
.describe('Scene read result.');
|
|
161
161
|
|
|
162
|
-
export const projectSceneRead =
|
|
162
|
+
export const projectSceneRead = defineTool({
|
|
163
163
|
name: 'project.scene.read',
|
|
164
164
|
summary: 'Read + validate a .vscn.json scene file.',
|
|
165
165
|
description:
|
|
@@ -205,7 +205,7 @@ const ProjectSceneValidateResult = z
|
|
|
205
205
|
.object({ valid: z.boolean(), issues: z.array(z.string()) })
|
|
206
206
|
.describe('Structured validation result — never throws for a malformed scene.');
|
|
207
207
|
|
|
208
|
-
export const projectSceneValidate =
|
|
208
|
+
export const projectSceneValidate = defineTool({
|
|
209
209
|
name: 'project.scene.validate',
|
|
210
210
|
summary: 'Validate a scene file or raw scene document against the real scene schema.',
|
|
211
211
|
description:
|
|
@@ -241,7 +241,7 @@ export const projectSceneValidate = defineOperation({
|
|
|
241
241
|
}
|
|
242
242
|
json = JSON.parse(readFileWithHash(absPath).raw);
|
|
243
243
|
} else {
|
|
244
|
-
throw new
|
|
244
|
+
throw new ToolError('BAD_INPUT', 'One of scenePath or scene must be given.', {});
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
try {
|
|
@@ -279,7 +279,7 @@ const ProjectSceneDiffResult = z
|
|
|
279
279
|
})
|
|
280
280
|
.describe('What applying this patch would do — no write, ever.');
|
|
281
281
|
|
|
282
|
-
export const projectSceneDiff =
|
|
282
|
+
export const projectSceneDiff = defineTool({
|
|
283
283
|
name: 'project.scene.diff',
|
|
284
284
|
summary: 'Preview a SceneDiff patch against a scene file without writing anything.',
|
|
285
285
|
description:
|
|
@@ -317,7 +317,7 @@ export const projectSceneDiff = defineOperation({
|
|
|
317
317
|
return { wouldBeValid: true, issues: [], opCounts, entitiesTouched };
|
|
318
318
|
} catch (err) {
|
|
319
319
|
const message =
|
|
320
|
-
err instanceof
|
|
320
|
+
err instanceof ToolError
|
|
321
321
|
? err.message
|
|
322
322
|
: err instanceof SceneParseError
|
|
323
323
|
? err.message
|
|
@@ -348,7 +348,7 @@ const ProjectSceneApplyResult = mutationResultSchema(
|
|
|
348
348
|
.describe('The scene document after the patch (or that WOULD result).'),
|
|
349
349
|
);
|
|
350
350
|
|
|
351
|
-
export const projectSceneApply =
|
|
351
|
+
export const projectSceneApply = defineTool({
|
|
352
352
|
name: 'project.scene.apply',
|
|
353
353
|
summary: 'Apply a SceneDiff patch to a scene file — dry-run capable, conflict-checked.',
|
|
354
354
|
description:
|
|
@@ -381,7 +381,7 @@ export const projectSceneApply = defineOperation({
|
|
|
381
381
|
parseSceneFile(result, input.scenePath);
|
|
382
382
|
} catch (err) {
|
|
383
383
|
if (err instanceof SceneParseError) {
|
|
384
|
-
throw new
|
|
384
|
+
throw new ToolError(
|
|
385
385
|
'SCENE_INVALID',
|
|
386
386
|
`applyDiff produced a scene that fails validation: ${err.message}`,
|
|
387
387
|
{ issues: formatIssues(err.issues) },
|
|
@@ -394,7 +394,7 @@ export const projectSceneApply = defineOperation({
|
|
|
394
394
|
// write (dry-run or real) exactly like `vgai apply-diff`.
|
|
395
395
|
const refErrors = dereferenceNewAssetRefs(scene, result, absPath);
|
|
396
396
|
if (refErrors.length > 0) {
|
|
397
|
-
throw new
|
|
397
|
+
throw new ToolError(
|
|
398
398
|
'ASSET_REF_INVALID',
|
|
399
399
|
`The patch introduces ${refErrors.length} broken asset reference(s): ` +
|
|
400
400
|
refErrors.map((e) => `${e.field} -> "${e.path}": ${e.reason}`).join('; '),
|
|
@@ -418,7 +418,7 @@ export const projectSceneApply = defineOperation({
|
|
|
418
418
|
});
|
|
419
419
|
|
|
420
420
|
/** Register every B2 `project.scene.*` operation onto `registry`. */
|
|
421
|
-
export function registerSceneOperations(registry:
|
|
421
|
+
export function registerSceneOperations(registry: ToolRegistry): void {
|
|
422
422
|
registry.register(projectSceneRead);
|
|
423
423
|
registry.register(projectSceneValidate);
|
|
424
424
|
registry.register(projectSceneDiff);
|