@womp/spark-agent 5.2.3 → 5.4.0
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/dist/agent-run.d.ts +1 -1
- package/dist/agent-tools.js +30 -12
- package/dist/capabilities/materials.d.ts +45 -0
- package/dist/capabilities/materials.js +89 -0
- package/dist/capabilities/scene.d.ts +21 -0
- package/dist/capabilities/scene.js +13 -13
- package/dist/capabilities.d.ts +1 -0
- package/dist/capabilities.js +1 -0
- package/dist/error-diagnostics.d.ts +24 -0
- package/dist/error-diagnostics.js +53 -0
- package/dist/generated/materials-declarations.d.ts +1 -0
- package/dist/generated/materials-declarations.js +3 -0
- package/dist/kakapo.d.ts +1 -0
- package/dist/kakapo.js +1 -0
- package/dist/materials/composition.d.ts +64 -0
- package/dist/materials/composition.js +121 -0
- package/dist/materials/graph.d.ts +79 -0
- package/dist/materials/graph.js +336 -0
- package/dist/materials/inspection.d.ts +40 -0
- package/dist/materials/inspection.js +54 -0
- package/dist/materials/recipes.d.ts +12 -0
- package/dist/materials/recipes.js +284 -0
- package/dist/materials/reference.d.ts +2 -0
- package/dist/materials/reference.js +97 -0
- package/dist/materials/shaping.d.ts +294 -0
- package/dist/materials/shaping.js +184 -0
- package/dist/materials/structure.d.ts +2 -0
- package/dist/materials/structure.js +12 -0
- package/dist/materials/surface-recipes.d.ts +78 -0
- package/dist/materials/surface-recipes.js +193 -0
- package/dist/materials/types.d.ts +222 -0
- package/dist/materials/types.js +1 -0
- package/dist/models.d.ts +7 -0
- package/dist/models.js +8 -0
- package/dist/pricing.js +5 -0
- package/dist/prompt.d.ts +1 -1
- package/dist/prompt.js +32 -32
- package/dist/sdk-materials-host.d.ts +9 -0
- package/dist/sdk-materials-host.js +360 -0
- package/dist/server/standalone.js +6 -1
- package/dist/ui.d.ts +50 -6
- package/package.json +2 -2
package/dist/agent-run.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare function parseAgentRunArgs(args: string[]): {
|
|
|
8
8
|
output: string | undefined;
|
|
9
9
|
images: string[];
|
|
10
10
|
settings: {
|
|
11
|
-
modelId: "gpt-6-astra" | "gpt-6-sol" | "gpt-6-luna" | "gemini-3.8-flash" | "claude-opus-5-5" | "claude-fable-5";
|
|
11
|
+
modelId: "gpt-6-astra" | "gpt-6.1-sol" | "gpt-6-sol" | "gpt-6-luna" | "gemini-3.8-flash" | "claude-opus-5-5" | "claude-fable-5";
|
|
12
12
|
reasoningEffort: ReasoningEffort;
|
|
13
13
|
};
|
|
14
14
|
} | null;
|
package/dist/agent-tools.js
CHANGED
|
@@ -54,7 +54,16 @@ export function createSparkTools(options) {
|
|
|
54
54
|
if (previous === undefined)
|
|
55
55
|
return;
|
|
56
56
|
const text = previous + inputTextDelta;
|
|
57
|
-
|
|
57
|
+
let value = completedInputString(text, field);
|
|
58
|
+
if (value === undefined && field === "name") {
|
|
59
|
+
try {
|
|
60
|
+
const input = JSON.parse(text);
|
|
61
|
+
const names = input?.names;
|
|
62
|
+
if (Array.isArray(names) && names.every(name => typeof name === "string" && name.length > 0))
|
|
63
|
+
value = names.join(", ").slice(0, 160);
|
|
64
|
+
}
|
|
65
|
+
catch { /* The streamed input is not complete yet. */ }
|
|
66
|
+
}
|
|
58
67
|
if (value === undefined) {
|
|
59
68
|
inputs.set(toolCallId, text);
|
|
60
69
|
return;
|
|
@@ -70,18 +79,27 @@ export function createSparkTools(options) {
|
|
|
70
79
|
return {
|
|
71
80
|
read_skill: tool({
|
|
72
81
|
...inputLabels("name"),
|
|
73
|
-
description: "Read
|
|
74
|
-
inputSchema: z.
|
|
82
|
+
description: "Read required skills together with names, or one skill with name. Returns instructions, TypeScript API declarations, and JavaScript examples from the available directory.",
|
|
83
|
+
inputSchema: z.union([
|
|
84
|
+
z.object({ names: z.array(z.string().min(1).max(160)).min(1) }).strict(),
|
|
85
|
+
z.object({ name: z.string().min(1).max(160) }).strict(),
|
|
86
|
+
]),
|
|
75
87
|
execute: (input, { toolCallId }) => execute({ id: toolCallId, name: "read_skill", input }, async () => {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
const read = (requested) => {
|
|
89
|
+
const skill = options.capabilities.skills.find(({ name }) => name === requested);
|
|
90
|
+
if (skill === undefined) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
error: `Skill unavailable: ${requested}`,
|
|
94
|
+
available: options.capabilities.skills.map(({ name }) => name),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return { ok: true, ...skill };
|
|
98
|
+
};
|
|
99
|
+
if ("name" in input)
|
|
100
|
+
return read(input.name);
|
|
101
|
+
const skills = [...new Set(input.names)].map(read);
|
|
102
|
+
return { ok: skills.every(skill => skill.ok), skills };
|
|
85
103
|
}),
|
|
86
104
|
}),
|
|
87
105
|
execute_javascript: tool({
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SparkCapability, SparkInvocationContext } from "../capabilities.js";
|
|
2
|
+
import { type MaterialInspectionOptions, type MaterialInspectionResult, type MaterialInspectionHost } from "../materials/inspection.js";
|
|
3
|
+
import type { MaterialCatalog, MaterialCatalogOptions, MaterialNode, MaterialNodeOptions, MaterialRecipeOptions, MaterialGraph, MaterialField, MaterialFieldOptions, MaterialCompositionOptions, MaterialShapeOptions, MaterialSnapshot, MaterialWrite, MaterialWriteResult } from "../materials/types.js";
|
|
4
|
+
export type * from "../materials/types.js";
|
|
5
|
+
export type { MaterialInspectionOptions, MaterialInspectionResult, MaterialInspectionHost } from "../materials/inspection.js";
|
|
6
|
+
export type MaterialStatus = {
|
|
7
|
+
/** null means this observation failed, not that the queue is empty. */
|
|
8
|
+
remaining: number | null;
|
|
9
|
+
/** null means this observation failed, not that all resources loaded. */
|
|
10
|
+
pendingResources: Record<string, string[]> | null;
|
|
11
|
+
errors?: {
|
|
12
|
+
source: "compiler-progress" | "pending-resources";
|
|
13
|
+
message: string;
|
|
14
|
+
}[];
|
|
15
|
+
shaderDiagnostics?: {
|
|
16
|
+
status: "unavailable";
|
|
17
|
+
reason: string;
|
|
18
|
+
};
|
|
19
|
+
rendering: "unverified";
|
|
20
|
+
explanation: string;
|
|
21
|
+
};
|
|
22
|
+
export type WompMaterialsApi = {
|
|
23
|
+
catalog(options?: MaterialCatalogOptions): Promise<MaterialCatalog>;
|
|
24
|
+
read(materialId?: number): Promise<MaterialSnapshot>;
|
|
25
|
+
node(options: MaterialNodeOptions): MaterialNode;
|
|
26
|
+
/** Build an editable starting graph; reads live descriptors internally and does not commit. */
|
|
27
|
+
recipe(options: MaterialRecipeOptions): Promise<MaterialGraph>;
|
|
28
|
+
/** Terminal-free scalar structure, editable before composition. */
|
|
29
|
+
field(options: MaterialFieldOptions): Promise<MaterialField>;
|
|
30
|
+
/** Merge arbitrary scalar fields and independently wire color, finish and relief. No commit. */
|
|
31
|
+
compose(options: MaterialCompositionOptions): Promise<MaterialGraph>;
|
|
32
|
+
/** Shape a field analytically with editable controls; no commit or descriptor inspection needed. */
|
|
33
|
+
shape(field: MaterialField, options: MaterialShapeOptions): Promise<MaterialField>;
|
|
34
|
+
/** Available when the host supplies scene captures. Primes, waits and returns joint inspection views. */
|
|
35
|
+
inspect?: (options: MaterialInspectionOptions) => Promise<MaterialInspectionResult>;
|
|
36
|
+
write(options: MaterialWrite): Promise<MaterialWriteResult>;
|
|
37
|
+
status(): Promise<MaterialStatus>;
|
|
38
|
+
};
|
|
39
|
+
export interface MaterialsHost {
|
|
40
|
+
catalog(options: MaterialCatalogOptions, context: SparkInvocationContext): Promise<MaterialCatalog>;
|
|
41
|
+
read(materialId: number | undefined, context: SparkInvocationContext): Promise<MaterialSnapshot>;
|
|
42
|
+
write(options: MaterialWrite, context: SparkInvocationContext): Promise<MaterialWriteResult>;
|
|
43
|
+
status(context: SparkInvocationContext): Promise<MaterialStatus>;
|
|
44
|
+
}
|
|
45
|
+
export declare function createMaterialsCapability(host: MaterialsHost, captures?: MaterialInspectionHost): SparkCapability<WompMaterialsApi>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { WOMP_MATERIALS_DECLARATIONS } from "../generated/materials-declarations.js";
|
|
2
|
+
import { catalogOptionsSchema, makeMaterialNode, materialId, writeSchema, } from "../materials/graph.js";
|
|
3
|
+
import { MATERIALS_REFERENCE } from "../materials/reference.js";
|
|
4
|
+
import { MATERIALS_RECIPES } from "../materials/recipes.js";
|
|
5
|
+
import { MATERIALS_STRUCTURE_GUIDANCE, MATERIALS_QUALITY_GUIDANCE } from "../materials/structure.js";
|
|
6
|
+
import { makeMaterialShape, materialShapeOperations, materialShapeSchema } from "../materials/shaping.js";
|
|
7
|
+
import { inspectMaterial, materialInspectionSchema } from "../materials/inspection.js";
|
|
8
|
+
import { makeMaterialField, materialFieldOperations, materialFieldSchema, makeMaterialRecipe, materialRecipeOperations, materialRecipeSchema, MATERIAL_RECIPE_RELIEF_GUIDANCE } from "../materials/surface-recipes.js";
|
|
9
|
+
import { makeMaterialComposition, materialCompositionOperations, materialCompositionSchema } from "../materials/composition.js";
|
|
10
|
+
export function createMaterialsCapability(host, captures) {
|
|
11
|
+
return {
|
|
12
|
+
skills: [
|
|
13
|
+
{
|
|
14
|
+
name: "procedural-materials",
|
|
15
|
+
version: "15",
|
|
16
|
+
description: "Discover live texture resources, build procedural shader layers, edit material constants, clone and assign materials.",
|
|
17
|
+
instructions: `Use womp.materials for procedural surface appearance.
|
|
18
|
+
recipe() builds editable grid, noise, grain and woven starting graphs and resolves live operation selectors internally. Use it directly for these patterns; no preliminary descriptor dump is needed. It does not write or assign a material. featureSize is in object-coordinate units for coordinateSpace:'object', or physical millimeters for 'world'; vector components use graph axes. Object mapping follows the owning carrier and its transforms; world mapping stays fixed in the scene. Grid includes major cells at featureSize and minor cells at one tenth of it, with lower minor contrast. colorA is the base and colorB the grid-line color. Use shallow relief for probes.
|
|
19
|
+
field() builds terminal-free noise, grain, woven, grid or cellular structures. It shares the recipe coordinate/feature-size convention; rotation is in degrees. cellMode selects a cellular pattern or boundary mask; remap controls contrast and can invert a mask. compose() merges these fields or arbitrary custom {graph,source:{node,slot}} fields, wiring independent color, roughness and combined height/bump weights. Color/roughness weights are nonnegative and sum to at most 1; fields must be normalized to 0..1. Relief weights may be signed. This is generic construction, not a finished material preset. Keep broad variation, defining shapes and fine roughness/relief separate. Independent feature colors use shape palette and blend; compose preserves their RGB with color low zero, high one, and weight one. Scalar channels consume X.
|
|
20
|
+
Coordinate axes are known: scene.access public X corresponds to negative renderer Z, public Y to renderer Y, public Z to negative renderer X. World-space featureSize uses renderer axes in physical mm: for grain running along public X, make Z the largest feature-size component, such as {x:1,y:1,z:40}; public Z uses the largest X component. These are orientation examples; choose sizes from the target. Object-space coordinates additionally follow carrier transforms and primitive/mesh mapping. A symmetric grid measures spacing/stretch but cannot establish axis identity. Use the known basis plus carrier transforms, or physical world mapping when local axis identity is uncertain; world mapping remains scene anchored.
|
|
21
|
+
${MATERIALS_STRUCTURE_GUIDANCE}
|
|
22
|
+
Composed controls are named Constants. Palette colors, roughness endpoints, metalness and overall relief are exposed for editing; structural weights and centering stay internal. SDK write results include parameters with current referenceId, value and color; print only the controls relevant to refinement. Change those through constants without rebuilding the graph, preserving the counterpart value/color. Use the new handles after resets/replacements; when a host omits parameters, recover them from read().
|
|
23
|
+
${MATERIAL_RECIPE_RELIEF_GUIDANCE}
|
|
24
|
+
${MATERIALS_QUALITY_GUIDANCE}
|
|
25
|
+
For custom operations, use exact names from catalog().operations; request catalog({operations:[...]}) only for descriptors not already known in this conversation. Request includeTextures:true when you need texture resource names. Request refreshTextures:true after adding/replacing texture resources or switching resource context. Never infer availability from files on the agent's machine or persist catalogue indices as texture identity.
|
|
26
|
+
read() lists materials and direct users; read(id) returns native base data and graph layers. Existing material edits affect every reference, including Geometry Nodes/OpenSCAD references not listed as direct users. To isolate an edit, use cloneFrom with objectIds. Shader storage shared with another material is copied automatically.
|
|
27
|
+
Use node() to construct literals and encode ramps, texture names and option payloads. For custom nodes, discover unfamiliar descriptors before connecting output slots to input slots. OutputMaterial needs connections; its unconnected ports inherit the incoming material.
|
|
28
|
+
write replaces the full layers array when supplied. Preserve unrelated layers, nodes and references from read. Omit layers for assignment/constant-only edits. When rebuilding an existing graph, carry forward intended Constant overrides; omitted overrides reset with replacement nodes, including finish controls. constants entries require both value and color; preserve the counterpart when editing one. A null entry resets a Constant and returns its new reference ID: read again before further edits.
|
|
29
|
+
Base properties and names remain available through scene.access; material names have a 63-character limit. Procedural colors, including recipe palettes, Constant colors and ramp stops, are linear RGB in 0..1. Decode display RGB before supplying it; for this renderer's gamma-2.2 base colors use (channel/255)**2.2. Do not apply this conversion to roughness, metalness, height or normals, or to colors already linear. Graph coordinates use native conventions, not scene.access's mm convenience API.
|
|
30
|
+
Writes use the host's protected scene access, persistence, permissions and receipts. Read current layers before replacing them. After an uncertain commit/save, inspect receipts and scene state; do not replay blindly.
|
|
31
|
+
status() reports independent global compiler-queue and pending-resource observations. A null field means its query failed; errors identifies the source. Per-shader diagnostics are unavailable. Catalogue names do not establish texture channels, color space or normal convention; choose decoding only when the resource encoding is known. Applied means committed. When inspect is available, use inspect({views:[...]}) after writes; it primes registration once, polls status without screenshot loops and captures the angles sequentially. Emit every returned frame within the same execution for joint comparison. queueSettled describes observations, not visual correctness; Report pending/unavailable observations honestly; fewer frames than requested means inspection is incomplete. When inspect is unavailable, prime with a screenshot, then observe status and capture the needed angles.`,
|
|
32
|
+
declarations: WOMP_MATERIALS_DECLARATIONS,
|
|
33
|
+
examples: [
|
|
34
|
+
"const fields = await Promise.all([womp.materials.field({pattern:'noise',coordinateSpace:'world',featureSize:8}),womp.materials.field({pattern:'noise',coordinateSpace:'world',featureSize:0.2})]); const graph = await womp.materials.compose({fields,color:{low:{x:0.2,y:0.15,z:0.1},high:{x:0.4,y:0.3,z:0.2},weights:[0.7,0.1]},roughness:{low:0.6,high:0.9,weights:[0.1,0.8]},relief:{mode:'height',scale:0.003,weights:[0.3,0.05]}}); const result = await womp.materials.write({materialId,layers:[graph]}); print({materialId:result.materialId,parameters:result.parameters?.filter(p=>['relief.scale','color.low','color.high','roughness.low','roughness.high'].includes(p.name))});",
|
|
35
|
+
"const graph = await womp.materials.recipe({pattern:'grid',coordinateSpace:'object',featureSize:1,colorA:{x:0.45,y:0.35,z:0.2},colorB:{x:0.02,y:0.02,z:0.02},roughnessA:0.45,roughnessB:0.45,relief:'height',reliefScale:0.0003}); print(await womp.materials.write({cloneFrom:materialId,layers:[graph],objectIds:[objectId]}));",
|
|
36
|
+
"const graph = await womp.materials.recipe({pattern:'noise',coordinateSpace:'world',featureSize:2,colorA:{x:0.6,y:0.55,z:0.45},colorB:{x:0.65,y:0.6,z:0.5},roughnessA:0.8,roughnessB:0.85,relief:'height',reliefScale:0.003}); print(await womp.materials.write({materialId,layers:[graph],objectIds:[objectId]}));",
|
|
37
|
+
"print(await womp.materials.write({cloneFrom: materialId, objectIds: [objectId]}));",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "procedural-materials-reference",
|
|
42
|
+
version: "8",
|
|
43
|
+
description: "Native material graph contracts, units, layer semantics and binary payload helpers.",
|
|
44
|
+
instructions: MATERIALS_REFERENCE,
|
|
45
|
+
declarations: "",
|
|
46
|
+
examples: [],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "procedural-materials-recipes",
|
|
50
|
+
version: "9",
|
|
51
|
+
description: "Generic mapping, scalar-field composition, generator, color and normal/bump snippets, plus isolated cloning and Constant reset workflows.",
|
|
52
|
+
instructions: MATERIALS_RECIPES,
|
|
53
|
+
declarations: "",
|
|
54
|
+
examples: [],
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
createApi: (context) => ({
|
|
58
|
+
catalog: (options) => host.catalog(catalogOptionsSchema.parse(options ?? {}), context),
|
|
59
|
+
read: (id) => host.read(id === undefined ? undefined : materialId.parse(id), context),
|
|
60
|
+
node: (options) => {
|
|
61
|
+
context.signal.throwIfAborted();
|
|
62
|
+
return makeMaterialNode(options);
|
|
63
|
+
},
|
|
64
|
+
recipe: async (options) => {
|
|
65
|
+
const parsed = materialRecipeSchema.parse(options);
|
|
66
|
+
const catalogue = await host.catalog({ operations: materialRecipeOperations(parsed) }, context);
|
|
67
|
+
return makeMaterialRecipe(parsed, catalogue);
|
|
68
|
+
},
|
|
69
|
+
field: async (options) => {
|
|
70
|
+
const parsed = materialFieldSchema.parse(options);
|
|
71
|
+
const catalogue = await host.catalog({ operations: materialFieldOperations(parsed) }, context);
|
|
72
|
+
return makeMaterialField(parsed, catalogue);
|
|
73
|
+
},
|
|
74
|
+
compose: async (options) => {
|
|
75
|
+
const parsed = materialCompositionSchema.parse(options);
|
|
76
|
+
const catalogue = await host.catalog({ operations: materialCompositionOperations(parsed) }, context);
|
|
77
|
+
return makeMaterialComposition(parsed, catalogue);
|
|
78
|
+
},
|
|
79
|
+
shape: async (field, options) => {
|
|
80
|
+
const parsed = materialShapeSchema.parse({ ...options, field });
|
|
81
|
+
const catalogue = await host.catalog({ operations: materialShapeOperations(parsed) }, context);
|
|
82
|
+
return makeMaterialShape(parsed, catalogue);
|
|
83
|
+
},
|
|
84
|
+
...(captures ? { inspect: (options) => inspectMaterial(host, captures, materialInspectionSchema.parse(options), context) } : {}),
|
|
85
|
+
write: (options) => host.write(writeSchema.parse(options), context),
|
|
86
|
+
status: () => host.status(context),
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import type { CameraConfiguration } from "@womp/kakapo-sdk";
|
|
2
3
|
import type { ArtifactRef, SparkCapability, SparkInvocationContext } from "../capabilities.js";
|
|
3
4
|
import type { WompSceneDraft } from "./scene-draft.js";
|
|
@@ -29,4 +30,24 @@ export interface SceneHost {
|
|
|
29
30
|
access<T>(callback: (draft: WompSceneDraft) => T | Promise<T>, context: SparkInvocationContext): Promise<T>;
|
|
30
31
|
screenshot(options: SceneScreenshotOptions, context: SparkInvocationContext): Promise<ArtifactRef>;
|
|
31
32
|
}
|
|
33
|
+
export declare const screenshotOptions: z.ZodObject<{
|
|
34
|
+
camera: z.ZodOptional<z.ZodObject<{
|
|
35
|
+
position: z.ZodObject<{
|
|
36
|
+
x: z.ZodNumber;
|
|
37
|
+
y: z.ZodNumber;
|
|
38
|
+
z: z.ZodNumber;
|
|
39
|
+
}, z.core.$strict>;
|
|
40
|
+
target: z.ZodObject<{
|
|
41
|
+
x: z.ZodNumber;
|
|
42
|
+
y: z.ZodNumber;
|
|
43
|
+
z: z.ZodNumber;
|
|
44
|
+
}, z.core.$strict>;
|
|
45
|
+
projection: z.ZodOptional<z.ZodEnum<{
|
|
46
|
+
perspective: "perspective";
|
|
47
|
+
orthographic: "orthographic";
|
|
48
|
+
}>>;
|
|
49
|
+
horizontalFovDegrees: z.ZodOptional<z.ZodNumber>;
|
|
50
|
+
orthographicWidth: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
}, z.core.$strict>>;
|
|
52
|
+
}, z.core.$strict>;
|
|
32
53
|
export declare function createSceneCapability(host: SceneHost): SparkCapability<WompSceneApi>;
|
|
@@ -24,7 +24,7 @@ function readHealthObjectIds(objectIds) {
|
|
|
24
24
|
throw new Error(`scene.health takes object ids from scene.access(): whole numbers from 0 up, in an array. ${named} ${invalid.length === 1 ? "is not one" : "are not ids"}.`);
|
|
25
25
|
}
|
|
26
26
|
const cameraVector = z.object({ x: z.number().finite(), y: z.number().finite(), z: z.number().finite() }).strict();
|
|
27
|
-
const screenshotOptions = z.object({
|
|
27
|
+
export const screenshotOptions = z.object({
|
|
28
28
|
camera: z.object({
|
|
29
29
|
position: cameraVector,
|
|
30
30
|
target: cameraVector,
|
|
@@ -40,7 +40,7 @@ export function createSceneCapability(host) {
|
|
|
40
40
|
name: "scene-editing",
|
|
41
41
|
version: "45",
|
|
42
42
|
description: "Inspect the open scene and edit its objects, materials, curves, and environment.",
|
|
43
|
-
instructions: `Use womp.scene.access(callback) for both inspection and edits. Inspect targets inside each callback using scene.nodes({ name, type, parentId, ids, offset, limit }) and detailed getters; filters are optional, name is a case-insensitive substring, and results default to 100 (maximum 1000). Page with offset as needed. Inspection reflects changes made in the callback. scene.unitMultiplier gives project units. Do not reuse an earlier inspection as current state.
|
|
43
|
+
instructions: `Use womp.scene.access(callback) for both inspection and edits. Inspect targets inside each callback using scene.nodes({ name, type, parentId, ids, offset, limit }) and detailed getters; filters are optional, name is a case-insensitive substring, and results default to 100 (maximum 1000). Page with offset as needed. Inspection reflects changes made in the callback. scene.unitMultiplier gives project units. Do not reuse an earlier inspection as current state.
|
|
44
44
|
Use womp.scene.health() to refresh whole-scene health or womp.scene.health(objectIds) to check specific objects (mapped to their owning Areas).
|
|
45
45
|
Health is requested only through scene.health(); access does not request it automatically. It is renderer feedback, not proof that the latest edit finished evaluating. Request it when needed to verify the result.
|
|
46
46
|
Unavailable, stale, or unverified feedback must not trigger blind regeneration or a claim that the model passed. Hosts without health services return unverified health with a reason.
|
|
@@ -52,8 +52,8 @@ are properties of that draft. The draft expires when the callback ends. Await as
|
|
|
52
52
|
Do not start unrelated operations from inside an access. Draft handles expire when its callback returns. An unchanged draft does not submit or save anything.
|
|
53
53
|
Preserve the existing scene unless asked to remove or replace content. Use semantic object names and reuse
|
|
54
54
|
known IDs when editing rather than creating duplicates. Distances follow the current project's units
|
|
55
|
-
(scene.unitMultiplier is 1 for millimetres, 0.1 for centimetres, approximately 0.0393701 for inches).
|
|
56
|
-
Convert a dimension in millimetres to project units by multiplying it by scene.unitMultiplier.
|
|
55
|
+
(scene.unitMultiplier is 1 for millimetres, 0.1 for centimetres, approximately 0.0393701 for inches).
|
|
56
|
+
Convert a dimension in millimetres to project units by multiplying it by scene.unitMultiplier.
|
|
57
57
|
The SDK-backed draft clamps dimension writes to 0.01–1000 mm per component before converting to native units; this is an adapter limit, not a scene-wide size limit. Read back dimensions when physical size matters.
|
|
58
58
|
Area size is a dimensionless scale; Group size stays fixed at one. Lights must be created at root (parentId 0); their size has x/y dimensions.
|
|
59
59
|
Light power is linear emitted intensity before collimation, not a percentage or physical unit: doubling it doubles emission, not tone-mapped pixel brightness. Valid ranges are 0–${maxLightIntensity("rect")} for Rect/Sphere and 0–${maxLightIntensity("distant")} for Distant; these limits are not brightness targets. A light-type change preserves intensity and rejects values outside the new type's range; lower intensity first if needed. Rect size is width/height; Sphere uses x as diameter; Distant uses direction, not position or size.
|
|
@@ -108,15 +108,15 @@ Check font, HDR, and material catalogs before selecting names. A host can explic
|
|
|
108
108
|
unavailable. Selecting an HDR resets its intensity; apply a custom intensity after selecting it.
|
|
109
109
|
For library materials, use listSuperMaterials(), then await materialImport(name) inside scene.access and assign the returned numeric ID the way that object requires: nodeSetMaterialId or curvePointSetMaterialId for scene nodes, the FlowIR SetMaterial node for a Geometry Nodes graph. A failed import rolls back the draft.
|
|
110
110
|
Filter large read results with JavaScript and print only useful details.
|
|
111
|
-
After a major edit, capture a screenshot outside the transaction and emitImage its reference.
|
|
112
|
-
screenshot({ camera: { position: {x,y,z}, target: {x,y,z}, projection: 'perspective', horizontalFovDegrees: 60 } })
|
|
113
|
-
sets a world-space camera in the same Womp coordinates and project units as scene positions (Y-up).
|
|
114
|
-
For orthographic framing use projection: 'orthographic' and orthographicWidth in project units instead of FOV.
|
|
115
|
-
Direction is derived from position/target; do not use coincident points or an exactly vertical viewing direction.
|
|
116
|
-
Omitted projection/lens settings come from the active camera. Pass the camera again for repeatable captures.
|
|
117
|
-
For object-focused screenshots, identify the requested object and frame it using world-space bounds. Convert local bounds using the object’s and applicable ancestor transforms, including translation, rotation, and scale; do not transform world-space bounds again. Reuse established framing when appropriate and avoid clipping the subject.
|
|
118
|
-
Omitting camera captures the active viewport without auto-fit. Use it when the user asks about the current viewport or clearly refers to what is visible on screen, not on the assumption that it shows the requested object.
|
|
119
|
-
Respect the host's camera-lock restrictions. Verify silhouette,
|
|
111
|
+
After a major edit, capture a screenshot outside the transaction and emitImage its reference.
|
|
112
|
+
screenshot({ camera: { position: {x,y,z}, target: {x,y,z}, projection: 'perspective', horizontalFovDegrees: 60 } })
|
|
113
|
+
sets a world-space camera in the same Womp coordinates and project units as scene positions (Y-up).
|
|
114
|
+
For orthographic framing use projection: 'orthographic' and orthographicWidth in project units instead of FOV.
|
|
115
|
+
Direction is derived from position/target; do not use coincident points or an exactly vertical viewing direction.
|
|
116
|
+
Omitted projection/lens settings come from the active camera. Pass the camera again for repeatable captures.
|
|
117
|
+
For object-focused screenshots, identify the requested object and frame it using world-space bounds. Convert local bounds using the object’s and applicable ancestor transforms, including translation, rotation, and scale; do not transform world-space bounds again. Reuse established framing when appropriate and avoid clipping the subject.
|
|
118
|
+
Omitting camera captures the active viewport without auto-fit. Use it when the user asks about the current viewport or clearly refers to what is visible on screen, not on the assumption that it shows the requested object.
|
|
119
|
+
Respect the host's camera-lock restrictions. Verify silhouette,
|
|
120
120
|
connections, openings, proportions, and materials before claiming completion. Use the owning top-level Area for scene-space bounds;
|
|
121
121
|
OpenSCAD part bounds are local to the part; individual primitive and curve bounds are unsupported. Renderer bounds and resize calls
|
|
122
122
|
must finish before subsequent writes. Inside scene.access, complete renderer-backed bounds reads before the first
|
package/dist/capabilities.d.ts
CHANGED
package/dist/capabilities.js
CHANGED
|
@@ -6,6 +6,12 @@ export type SparkErrorDiagnostics = {
|
|
|
6
6
|
code?: string;
|
|
7
7
|
status?: number;
|
|
8
8
|
requestId?: string;
|
|
9
|
+
eventType?: string;
|
|
10
|
+
issues?: {
|
|
11
|
+
code: string;
|
|
12
|
+
path: (string | number)[];
|
|
13
|
+
expected?: string;
|
|
14
|
+
}[];
|
|
9
15
|
cause?: SparkErrorDiagnostics;
|
|
10
16
|
};
|
|
11
17
|
export declare const sparkErrorDiagnosticsSchema: z.ZodObject<{
|
|
@@ -15,12 +21,24 @@ export declare const sparkErrorDiagnosticsSchema: z.ZodObject<{
|
|
|
15
21
|
code: z.ZodOptional<z.ZodString>;
|
|
16
22
|
status: z.ZodOptional<z.ZodNumber>;
|
|
17
23
|
requestId: z.ZodOptional<z.ZodString>;
|
|
24
|
+
eventType: z.ZodOptional<z.ZodString>;
|
|
25
|
+
issues: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
26
|
+
code: z.ZodString;
|
|
27
|
+
path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
28
|
+
expected: z.ZodOptional<z.ZodString>;
|
|
29
|
+
}, z.core.$strip>>>;
|
|
18
30
|
cause: z.ZodOptional<z.ZodObject<{
|
|
19
31
|
message: z.ZodString;
|
|
20
32
|
name: z.ZodOptional<z.ZodString>;
|
|
21
33
|
code: z.ZodOptional<z.ZodString>;
|
|
22
34
|
status: z.ZodOptional<z.ZodNumber>;
|
|
23
35
|
requestId: z.ZodOptional<z.ZodString>;
|
|
36
|
+
eventType: z.ZodOptional<z.ZodString>;
|
|
37
|
+
issues: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
38
|
+
code: z.ZodString;
|
|
39
|
+
path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
40
|
+
expected: z.ZodOptional<z.ZodString>;
|
|
41
|
+
}, z.core.$strip>>>;
|
|
24
42
|
}, z.core.$strip>>;
|
|
25
43
|
}, z.core.$strip>>;
|
|
26
44
|
message: z.ZodString;
|
|
@@ -28,5 +46,11 @@ export declare const sparkErrorDiagnosticsSchema: z.ZodObject<{
|
|
|
28
46
|
code: z.ZodOptional<z.ZodString>;
|
|
29
47
|
status: z.ZodOptional<z.ZodNumber>;
|
|
30
48
|
requestId: z.ZodOptional<z.ZodString>;
|
|
49
|
+
eventType: z.ZodOptional<z.ZodString>;
|
|
50
|
+
issues: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
51
|
+
code: z.ZodString;
|
|
52
|
+
path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
53
|
+
expected: z.ZodOptional<z.ZodString>;
|
|
54
|
+
}, z.core.$strip>>>;
|
|
31
55
|
}, z.core.$strip>;
|
|
32
56
|
export declare function sparkErrorDiagnostics(error: unknown): SparkErrorDiagnostics;
|
|
@@ -5,6 +5,12 @@ const fields = {
|
|
|
5
5
|
code: z.string().max(128).optional(),
|
|
6
6
|
status: z.number().int().min(100).max(599).optional(),
|
|
7
7
|
requestId: z.string().max(128).optional(),
|
|
8
|
+
eventType: z.string().max(128).optional(),
|
|
9
|
+
issues: z.array(z.object({
|
|
10
|
+
code: z.string().max(64),
|
|
11
|
+
path: z.array(z.union([z.string().max(128), z.number().int().nonnegative()])).max(16),
|
|
12
|
+
expected: z.string().max(32).optional(),
|
|
13
|
+
})).max(32).optional(),
|
|
8
14
|
};
|
|
9
15
|
const causeSchema = z.object(fields);
|
|
10
16
|
export const sparkErrorDiagnosticsSchema = z.object({
|
|
@@ -68,6 +74,41 @@ function text(value, limit = 1024) {
|
|
|
68
74
|
.slice(0, limit);
|
|
69
75
|
}
|
|
70
76
|
const PLACEHOLDER = /\[(?:payload|data|url|credential) omitted\]/gu;
|
|
77
|
+
// Zod union errors nest issues. Keep schema facts, never messages, input,
|
|
78
|
+
// received values or literal/enum alternatives (which can contain user data).
|
|
79
|
+
function validationIssues(value) {
|
|
80
|
+
const result = [];
|
|
81
|
+
let remaining = 128;
|
|
82
|
+
const walk = (items, depth) => {
|
|
83
|
+
if (!Array.isArray(items) || depth > 8)
|
|
84
|
+
return;
|
|
85
|
+
for (const item of items) {
|
|
86
|
+
if (--remaining < 0 || result.length === 32)
|
|
87
|
+
return;
|
|
88
|
+
const issue = record(item);
|
|
89
|
+
if (issue.code === "invalid_union") {
|
|
90
|
+
const branches = issue.errors ?? issue.unionErrors;
|
|
91
|
+
if (Array.isArray(branches) && branches.length) {
|
|
92
|
+
for (const branch of branches.slice(0, 32)) {
|
|
93
|
+
walk(Array.isArray(branch) ? branch : record(branch).issues, depth + 1);
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (typeof issue.code === "string" && Array.isArray(issue.path)) {
|
|
99
|
+
const code = text(issue.code, 64);
|
|
100
|
+
const path = issue.path.slice(0, 16).map(part => typeof part === "number" && Number.isSafeInteger(part) && part >= 0
|
|
101
|
+
? part : text(part, 128) ?? "[key omitted]");
|
|
102
|
+
const expected = typeof issue.expected === "string" &&
|
|
103
|
+
/^(string|number|boolean|object|array|null|undefined|bigint|symbol|function|date|integer|int|float|never|unknown|any|void|map|set|promise|nan)$/.test(issue.expected)
|
|
104
|
+
? issue.expected : undefined;
|
|
105
|
+
result.push({ code, path, ...(expected === undefined ? {} : { expected }) });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
walk(value, 0);
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
71
112
|
/** Whether redacted text still says anything once its placeholders are removed. */
|
|
72
113
|
function informative(value) {
|
|
73
114
|
return value !== undefined && /[\p{L}\p{N}]/u.test(value.replace(PLACEHOLDER, ""));
|
|
@@ -113,9 +154,21 @@ export function sparkErrorDiagnostics(error) {
|
|
|
113
154
|
result.status = status;
|
|
114
155
|
if (requestId)
|
|
115
156
|
result.requestId = requestId;
|
|
157
|
+
const eventType = source.eventType ?? (source.name === "AI_TypeValidationError" ? record(source.value).type : undefined);
|
|
158
|
+
if (typeof eventType === "string" && /^(response\.[a-z_.]+|error)$/.test(eventType) && eventType.length <= 128)
|
|
159
|
+
result.eventType = eventType;
|
|
160
|
+
const issues = validationIssues(source.issues);
|
|
161
|
+
if (issues.length)
|
|
162
|
+
result.issues = issues;
|
|
116
163
|
const cause = source.cause ?? source.lastError;
|
|
117
164
|
if (depth < 2 && cause !== undefined && !seen.has(cause))
|
|
118
165
|
result.cause = visit(cause, depth + 1);
|
|
166
|
+
const details = issues.length ? issues : result.cause?.issues;
|
|
167
|
+
if ((name === "AI_TypeValidationError" || name === "ZodError") && details?.length) {
|
|
168
|
+
result.message = text(`Validation failed${result.eventType ? ` (${result.eventType})` : ""}: ${details.slice(0, 3)
|
|
169
|
+
.map(issue => `${issue.path.join(".") || "<root>"}: ${issue.code}${issue.expected ? ` (expected ${issue.expected})` : ""}`)
|
|
170
|
+
.join("; ")}`);
|
|
171
|
+
}
|
|
119
172
|
return result;
|
|
120
173
|
};
|
|
121
174
|
return visit(error, 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WOMP_MATERIALS_DECLARATIONS = "declare const womp: { materials: {\n\"catalog\": ((options?: undefined | {\n\"refreshTextures\"?: undefined | false | true;\n\"includeTextures\"?: undefined | false | true;\n\"operations\"?: undefined | Array<string>;\n}) => Promise<{\n\"operations\": Array<{\n\"op\": string;\n\"category\": string;\n\"title\": string;\n}>;\n\"nodes\": {\n[key: string]: {\n\"type\": string;\n\"title\": string;\n\"description\": string;\n\"inputs\": Array<{\n\"title\": string;\n\"type\": string;\n\"values\"?: undefined | Array<string>;\n}>;\n\"outputs\": Array<{\n\"title\": string;\n\"type\": string;\n\"values\"?: undefined | Array<string>;\n}>;\n};\n};\n\"textureCount\": number;\n\"textures\"?: undefined | Array<string>;\n\"textureMetadata\"?: undefined | {\n\"channels\": \"unknown\";\n\"colorSpace\": \"unknown\";\n\"normalConvention\": \"unknown\";\n\"reason\": string;\n};\n}>);\n\"read\": ((materialId?: undefined | number) => Promise<{\n\"materials\": Array<{\n\"id\": number;\n\"shaderIds\": Array<number>;\n\"objectIds\": Array<number>;\n}>;\n\"material\"?: undefined | {\n\"id\": number;\n\"data\": {\n[key: string]: unknown;\n};\n\"layers\": Array<null | {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>;\n};\n\"diagnostics\": Array<string>;\n}>);\n\"node\": ((options: {\n\"op\": string;\n\"name\"?: undefined | string;\n\"reference_id\"?: undefined | number;\n\"inputs\"?: undefined | {\n[key: string]: number | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n};\n\"texture\"?: undefined | string;\n\"ramp\"?: undefined | Array<{\n\"position\": number;\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>;\n\"options\"?: undefined | Array<{\n\"name\": string;\n\"value\": number;\n}>;\n}) => {\n\"op\": string;\n[key: string]: unknown;\n});\n\"recipe\": ((options: {\n\"pattern\": \"noise\" | \"grain\" | \"woven\" | \"grid\";\n\"coordinateSpace\": \"object\" | \"world\";\n\"featureSize\": number | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"colorA\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"colorB\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"roughnessA\": number;\n\"roughnessB\": number;\n\"metalness\"?: undefined | number;\n\"detail\"?: undefined | number;\n\"relief\": \"height\" | \"bump\";\n\"reliefScale\": number;\n}) => Promise<{\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>);\n\"field\": ((options: {\n\"pattern\": \"noise\" | \"grain\" | \"woven\" | \"grid\" | \"cells\";\n\"coordinateSpace\": \"object\" | \"world\";\n\"featureSize\": number | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"detail\"?: undefined | number;\n\"rotation\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"cellMode\"?: undefined | \"Distance\" | \"Edge distance\" | \"Color\" | \"Smooth Distance\" | \"Smooth Color\";\n\"remap\"?: undefined | {\n\"low\": number;\n\"high\": number;\n};\n}) => Promise<{\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}>);\n\"compose\": ((options: {\n\"fields\": Array<{\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}>;\n\"color\"?: undefined | {\n\"low\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"high\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"weights\": Array<number>;\n};\n\"roughness\"?: undefined | {\n\"low\": number;\n\"high\": number;\n\"weights\": Array<number>;\n};\n\"metalness\"?: undefined | number;\n\"relief\"?: undefined | {\n\"mode\": \"height\" | \"bump\";\n\"scale\": number;\n\"weights\": Array<number>;\n\"center\"?: undefined | number;\n};\n}) => Promise<{\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>);\n\"shape\": ((field: {\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}, options: {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"remap\";\n\"low\": number;\n\"high\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"ridge\";\n\"center\": number;\n\"width\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"periodic\";\n\"coordinates\"?: undefined | number;\n\"axis\": 0 | 1 | 2;\n\"sharpness\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"warp\";\n\"coordinates\"?: undefined | number;\n\"frequency\": number;\n\"amplitude\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"palette\";\n\"mode\": \"Constant\" | \"Linear\" | \"Smooth\";\n\"stops\": Array<{\n\"position\": number;\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"blend\";\n\"overlay\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n} | {\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n};\n\"mask\": number | {\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n};\n}) => Promise<{\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}>);\n\"inspect\"?: undefined | ((options: {\n\"views\": Array<{\n\"camera\"?: undefined | {\n\"position\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"target\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"projection\"?: undefined | \"perspective\" | \"orthographic\";\n\"horizontalFovDegrees\"?: undefined | number;\n\"orthographicWidth\"?: undefined | number;\n};\n}>;\n\"timeoutMs\"?: undefined | number;\n}) => Promise<{\n\"frames\": Array<{\n\"id\": string;\n\"mediaType\": string;\n\"name\"?: undefined | string;\n}>;\n\"queueSettled\": false | true;\n\"timedOut\": false | true;\n\"status\": {\n\"remaining\": null | number;\n\"pendingResources\": null | {\n[key: string]: Array<string>;\n};\n\"errors\"?: undefined | Array<{\n\"source\": \"compiler-progress\" | \"pending-resources\";\n\"message\": string;\n}>;\n\"shaderDiagnostics\"?: undefined | {\n\"status\": \"unavailable\";\n\"reason\": string;\n};\n\"rendering\": \"unverified\";\n\"explanation\": string;\n};\n}>);\n\"write\": ((options: {\n\"materialId\"?: undefined | number;\n\"cloneFrom\"?: undefined | number;\n\"layers\"?: undefined | Array<null | {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>;\n\"constants\"?: undefined | {\n[key: string]: null | {\n\"value\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n};\n};\n\"objectIds\"?: undefined | Array<number>;\n}) => Promise<{\n\"materialId\": number;\n\"objectIds\": Array<number>;\n\"referenceIdChanges\": {\n[key: string]: number;\n};\n\"parameters\"?: undefined | Array<{\n\"name\": string;\n\"referenceId\": number;\n\"value\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"exposed\"?: undefined | false | true;\n}>;\n\"status\": \"applied\";\n\"rendering\": \"unverified\";\n}>);\n\"status\": (() => Promise<{\n\"remaining\": null | number;\n\"pendingResources\": null | {\n[key: string]: Array<string>;\n};\n\"errors\"?: undefined | Array<{\n\"source\": \"compiler-progress\" | \"pending-resources\";\n\"message\": string;\n}>;\n\"shaderDiagnostics\"?: undefined | {\n\"status\": \"unavailable\";\n\"reason\": string;\n};\n\"rendering\": \"unverified\";\n\"explanation\": string;\n}>);\n} };\ndeclare function print(...values: unknown[]): void;\ndeclare function emitImage(ref: { id: string; mediaType: string; name?: string }, options?: { inspect?: boolean }): Promise<void>;\ndeclare function emitFile(ref: { id: string; mediaType: string; name?: string }): Promise<void>;\n";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Generated by scripts/generate-skill-declarations.mjs.
|
|
2
|
+
// prettier-ignore
|
|
3
|
+
export const WOMP_MATERIALS_DECLARATIONS = "declare const womp: { materials: {\n\"catalog\": ((options?: undefined | {\n\"refreshTextures\"?: undefined | false | true;\n\"includeTextures\"?: undefined | false | true;\n\"operations\"?: undefined | Array<string>;\n}) => Promise<{\n\"operations\": Array<{\n\"op\": string;\n\"category\": string;\n\"title\": string;\n}>;\n\"nodes\": {\n[key: string]: {\n\"type\": string;\n\"title\": string;\n\"description\": string;\n\"inputs\": Array<{\n\"title\": string;\n\"type\": string;\n\"values\"?: undefined | Array<string>;\n}>;\n\"outputs\": Array<{\n\"title\": string;\n\"type\": string;\n\"values\"?: undefined | Array<string>;\n}>;\n};\n};\n\"textureCount\": number;\n\"textures\"?: undefined | Array<string>;\n\"textureMetadata\"?: undefined | {\n\"channels\": \"unknown\";\n\"colorSpace\": \"unknown\";\n\"normalConvention\": \"unknown\";\n\"reason\": string;\n};\n}>);\n\"read\": ((materialId?: undefined | number) => Promise<{\n\"materials\": Array<{\n\"id\": number;\n\"shaderIds\": Array<number>;\n\"objectIds\": Array<number>;\n}>;\n\"material\"?: undefined | {\n\"id\": number;\n\"data\": {\n[key: string]: unknown;\n};\n\"layers\": Array<null | {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>;\n};\n\"diagnostics\": Array<string>;\n}>);\n\"node\": ((options: {\n\"op\": string;\n\"name\"?: undefined | string;\n\"reference_id\"?: undefined | number;\n\"inputs\"?: undefined | {\n[key: string]: number | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n};\n\"texture\"?: undefined | string;\n\"ramp\"?: undefined | Array<{\n\"position\": number;\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>;\n\"options\"?: undefined | Array<{\n\"name\": string;\n\"value\": number;\n}>;\n}) => {\n\"op\": string;\n[key: string]: unknown;\n});\n\"recipe\": ((options: {\n\"pattern\": \"noise\" | \"grain\" | \"woven\" | \"grid\";\n\"coordinateSpace\": \"object\" | \"world\";\n\"featureSize\": number | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"colorA\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"colorB\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"roughnessA\": number;\n\"roughnessB\": number;\n\"metalness\"?: undefined | number;\n\"detail\"?: undefined | number;\n\"relief\": \"height\" | \"bump\";\n\"reliefScale\": number;\n}) => Promise<{\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>);\n\"field\": ((options: {\n\"pattern\": \"noise\" | \"grain\" | \"woven\" | \"grid\" | \"cells\";\n\"coordinateSpace\": \"object\" | \"world\";\n\"featureSize\": number | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"detail\"?: undefined | number;\n\"rotation\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"cellMode\"?: undefined | \"Distance\" | \"Edge distance\" | \"Color\" | \"Smooth Distance\" | \"Smooth Color\";\n\"remap\"?: undefined | {\n\"low\": number;\n\"high\": number;\n};\n}) => Promise<{\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}>);\n\"compose\": ((options: {\n\"fields\": Array<{\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}>;\n\"color\"?: undefined | {\n\"low\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"high\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"weights\": Array<number>;\n};\n\"roughness\"?: undefined | {\n\"low\": number;\n\"high\": number;\n\"weights\": Array<number>;\n};\n\"metalness\"?: undefined | number;\n\"relief\"?: undefined | {\n\"mode\": \"height\" | \"bump\";\n\"scale\": number;\n\"weights\": Array<number>;\n\"center\"?: undefined | number;\n};\n}) => Promise<{\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>);\n\"shape\": ((field: {\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}, options: {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"remap\";\n\"low\": number;\n\"high\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"ridge\";\n\"center\": number;\n\"width\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"periodic\";\n\"coordinates\"?: undefined | number;\n\"axis\": 0 | 1 | 2;\n\"sharpness\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"warp\";\n\"coordinates\"?: undefined | number;\n\"frequency\": number;\n\"amplitude\": number;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"palette\";\n\"mode\": \"Constant\" | \"Linear\" | \"Smooth\";\n\"stops\": Array<{\n\"position\": number;\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>;\n} | {\n\"name\"?: undefined | string;\n} & {\n\"kind\": \"blend\";\n\"overlay\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n} | {\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n};\n\"mask\": number | {\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n};\n}) => Promise<{\n\"graph\": {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n};\n\"source\": {\n\"node\": number;\n\"slot\": number;\n};\n}>);\n\"inspect\"?: undefined | ((options: {\n\"views\": Array<{\n\"camera\"?: undefined | {\n\"position\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"target\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"projection\"?: undefined | \"perspective\" | \"orthographic\";\n\"horizontalFovDegrees\"?: undefined | number;\n\"orthographicWidth\"?: undefined | number;\n};\n}>;\n\"timeoutMs\"?: undefined | number;\n}) => Promise<{\n\"frames\": Array<{\n\"id\": string;\n\"mediaType\": string;\n\"name\"?: undefined | string;\n}>;\n\"queueSettled\": false | true;\n\"timedOut\": false | true;\n\"status\": {\n\"remaining\": null | number;\n\"pendingResources\": null | {\n[key: string]: Array<string>;\n};\n\"errors\"?: undefined | Array<{\n\"source\": \"compiler-progress\" | \"pending-resources\";\n\"message\": string;\n}>;\n\"shaderDiagnostics\"?: undefined | {\n\"status\": \"unavailable\";\n\"reason\": string;\n};\n\"rendering\": \"unverified\";\n\"explanation\": string;\n};\n}>);\n\"write\": ((options: {\n\"materialId\"?: undefined | number;\n\"cloneFrom\"?: undefined | number;\n\"layers\"?: undefined | Array<null | {\n\"nodes\": Array<{\n\"op\": string;\n[key: string]: unknown;\n}>;\n\"connections\": Array<{\n\"input_node\": number;\n\"input_slot\": number;\n\"output_node\": number;\n\"output_slot\": number;\n\"flags\"?: undefined | number;\n}>;\n}>;\n\"constants\"?: undefined | {\n[key: string]: null | {\n\"value\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n};\n};\n\"objectIds\"?: undefined | Array<number>;\n}) => Promise<{\n\"materialId\": number;\n\"objectIds\": Array<number>;\n\"referenceIdChanges\": {\n[key: string]: number;\n};\n\"parameters\"?: undefined | Array<{\n\"name\": string;\n\"referenceId\": number;\n\"value\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"color\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"exposed\"?: undefined | false | true;\n}>;\n\"status\": \"applied\";\n\"rendering\": \"unverified\";\n}>);\n\"status\": (() => Promise<{\n\"remaining\": null | number;\n\"pendingResources\": null | {\n[key: string]: Array<string>;\n};\n\"errors\"?: undefined | Array<{\n\"source\": \"compiler-progress\" | \"pending-resources\";\n\"message\": string;\n}>;\n\"shaderDiagnostics\"?: undefined | {\n\"status\": \"unavailable\";\n\"reason\": string;\n};\n\"rendering\": \"unverified\";\n\"explanation\": string;\n}>);\n} };\ndeclare function print(...values: unknown[]): void;\ndeclare function emitImage(ref: { id: string; mediaType: string; name?: string }, options?: { inspect?: boolean }): Promise<void>;\ndeclare function emitFile(ref: { id: string; mediaType: string; name?: string }): Promise<void>;\n";
|
package/dist/kakapo.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export { createSdkOpenScadHost, type SdkOpenScadHostOptions, } from "./sdk-opens
|
|
|
8
8
|
export { createSdkSceneHealthHost } from "./sdk-scene-health-host.js";
|
|
9
9
|
export * from "./scene-health.js";
|
|
10
10
|
export * from "./repair-state.js";
|
|
11
|
+
export { createSdkMaterialsHost, type SdkMaterialsHostOptions } from "./sdk-materials-host.js";
|
package/dist/kakapo.js
CHANGED
|
@@ -6,3 +6,4 @@ export { createSdkOpenScadHost, } from "./sdk-openscad-host.js";
|
|
|
6
6
|
export { createSdkSceneHealthHost } from "./sdk-scene-health-host.js";
|
|
7
7
|
export * from "./scene-health.js";
|
|
8
8
|
export * from "./repair-state.js";
|
|
9
|
+
export { createSdkMaterialsHost } from "./sdk-materials-host.js";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { MaterialCatalog, MaterialCompositionOptions, MaterialGraph } from "./types.js";
|
|
3
|
+
export declare const materialCompositionSchema: z.ZodObject<{
|
|
4
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
5
|
+
graph: z.ZodObject<{
|
|
6
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
7
|
+
op: z.ZodString;
|
|
8
|
+
name: z.ZodOptional<z.ZodString>;
|
|
9
|
+
location: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
x: z.ZodNumber;
|
|
11
|
+
y: z.ZodNumber;
|
|
12
|
+
}, z.core.$strict>>;
|
|
13
|
+
editor_flags: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
reference_id: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
out: z.ZodOptional<z.ZodObject<{
|
|
16
|
+
x: z.ZodNumber;
|
|
17
|
+
y: z.ZodNumber;
|
|
18
|
+
z: z.ZodNumber;
|
|
19
|
+
}, z.core.$strict>>;
|
|
20
|
+
}, z.core.$catchall<z.ZodType<import("./types.js").MaterialJson, unknown, z.core.$ZodTypeInternals<import("./types.js").MaterialJson, unknown>>>>>;
|
|
21
|
+
connections: z.ZodArray<z.ZodObject<{
|
|
22
|
+
input_node: z.ZodNumber;
|
|
23
|
+
input_slot: z.ZodNumber;
|
|
24
|
+
output_node: z.ZodNumber;
|
|
25
|
+
output_slot: z.ZodNumber;
|
|
26
|
+
flags: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodLiteral<2>]>>;
|
|
27
|
+
}, z.core.$strict>>;
|
|
28
|
+
}, z.core.$catchall<z.ZodType<import("./types.js").MaterialJson, unknown, z.core.$ZodTypeInternals<import("./types.js").MaterialJson, unknown>>>>;
|
|
29
|
+
source: z.ZodObject<{
|
|
30
|
+
node: z.ZodNumber;
|
|
31
|
+
slot: z.ZodNumber;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
}, z.core.$strict>>;
|
|
34
|
+
color: z.ZodOptional<z.ZodObject<{
|
|
35
|
+
low: z.ZodObject<{
|
|
36
|
+
x: z.ZodNumber;
|
|
37
|
+
y: z.ZodNumber;
|
|
38
|
+
z: z.ZodNumber;
|
|
39
|
+
}, z.core.$strict>;
|
|
40
|
+
high: z.ZodObject<{
|
|
41
|
+
x: z.ZodNumber;
|
|
42
|
+
y: z.ZodNumber;
|
|
43
|
+
z: z.ZodNumber;
|
|
44
|
+
}, z.core.$strict>;
|
|
45
|
+
weights: z.ZodArray<z.ZodNumber>;
|
|
46
|
+
}, z.core.$strict>>;
|
|
47
|
+
roughness: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
low: z.ZodNumber;
|
|
49
|
+
high: z.ZodNumber;
|
|
50
|
+
weights: z.ZodArray<z.ZodNumber>;
|
|
51
|
+
}, z.core.$strict>>;
|
|
52
|
+
metalness: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
relief: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
mode: z.ZodEnum<{
|
|
55
|
+
height: "height";
|
|
56
|
+
bump: "bump";
|
|
57
|
+
}>;
|
|
58
|
+
scale: z.ZodNumber;
|
|
59
|
+
weights: z.ZodArray<z.ZodNumber>;
|
|
60
|
+
center: z.ZodOptional<z.ZodNumber>;
|
|
61
|
+
}, z.core.$strict>>;
|
|
62
|
+
}, z.core.$strict>;
|
|
63
|
+
export declare function materialCompositionOperations(options: MaterialCompositionOptions): string[];
|
|
64
|
+
export declare function makeMaterialComposition(options: MaterialCompositionOptions, catalogue: MaterialCatalog): MaterialGraph;
|