@mulmoclaude/shapescript-plugin 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -51,6 +51,92 @@ for i in 1 to count {
51
51
 
52
52
  A function call takes **no space** before its parenthesis: `sin(x)` is a call, `sin (x)` is not.
53
53
 
54
+ ## Validation and errors
55
+
56
+ `executePresentShapeScript` checks arguments, parses the source, evaluates expressions,
57
+ and builds geometry headlessly before returning success. Temporary geometry is disposed.
58
+ Failures are returned as values, with **no `data` field**, so the host does not open a
59
+ broken visualization. The same diagnostic is available as `error` and `jsonData.error`
60
+ (the latter is included in the calling agent's tool response):
61
+
62
+ ```ts
63
+ const result = await executePresentShapeScript(context, {
64
+ title: "Example", script: "cube { size missing }",
65
+ });
66
+ if ("error" in result) {
67
+ console.log(result.error.code, result.error.message);
68
+ // EVALUATION_ERROR, "Undefined variable: missing"
69
+ }
70
+ ```
71
+
72
+ Codes: `INVALID_ARGUMENT`, `PARSE_ERROR`, `EVALUATION_ERROR`, `LIMIT_EXCEEDED`.
73
+ Parse diagnostics include `line` and `column` when available. Invalid input does not
74
+ throw from the tool handler. Successful results retain their existing `{ title, data: { script } }`
75
+ contract. Validation executes the script, including geometry construction; the browser
76
+ constructs it again for display. The source editor also validates geometry before saving.
77
+
78
+ ## Builders and additional expressions
79
+
80
+ ```text
81
+ // Loft joins sections and caps the ends; hull forms a convex envelope.
82
+ loft {
83
+ square
84
+ translate 0 0 2
85
+ circle
86
+ }
87
+ hull {
88
+ cube { position -1 0 0 }
89
+ cube { position 1 0 0 }
90
+ }
91
+ extrude { polygon { sides 5 } }
92
+ fill { square }
93
+ lathe path { point 1 0 curve 0 2 1 -1 }
94
+
95
+ // Stencil changes surface material without cutting away the first shape.
96
+ stencil {
97
+ cube { color 1 0 0 }
98
+ cube { position 0.5 0 0 color 0 1 0 }
99
+ }
100
+
101
+ define offsets ((1 2 3), (4 5 6))
102
+ cube { position offsets[0].x offsets[1].y offsets.count }
103
+ ```
104
+
105
+ Also supported: `pi`, `tau`, `true`, `false`, scientific notation, unary `+`,
106
+ short-circuit `and`/`or`, string literals, `join`/`trim`, tuple arguments to `min`/`max`,
107
+ zero-based tuple/string subscripts, `.count`, vector `.x/.y/.z/.w`, color
108
+ `.red/.green/.blue/.alpha` (or `.r/.g/.b/.a`), custom shape definitions with options,
109
+ and `polygon { sides N }` (integer 3–256). Lathe samples curved profiles, and inline
110
+ builder paths use the same parser as nested paths, including loops and definitions.
111
+
112
+ ## Compatibility and limits
113
+
114
+ This is the plugin's documented modeling subset, **not complete compatibility with
115
+ [upstream ShapeScript](https://shapescript.info/mac/)**. It preserves existing plugin
116
+ conventions: primitive sphere/circle sizes specify radii; rotation/orientation properties
117
+ and trig functions use radians; relative rotate/orientation commands and path rotation
118
+ use turns (`1 = 360°`). Path point/curve coordinates are relative steps, and curve
119
+ control coordinates are offsets from the endpoint. Upstream uses different conventions.
120
+
121
+ Loft accepts ordered, closed planar sections with one perimeter each, resamples differing
122
+ vertex counts, interpolates linearly, and triangulates the end caps. Sections must enclose
123
+ a volume. Hull accepts geometry from child meshes and filled paths. Primitive profiles
124
+ for fill/extrude must lie in XY; holes, swept/twisted extrusion, and arbitrary 3D path
125
+ commands are not implemented. Imports, textures, text/fonts, lights/camera declarations,
126
+ arbitrary objects, and general user-defined functions remain outside this subset.
127
+ Unsupported commands and failed CSG operations return errors instead of silently
128
+ substituting different geometry. As with other polygonal CSG engines, degenerate or
129
+ self-intersecting inputs may fail.
130
+
131
+ `rnd` and `rand()` draw from a seeded generator (`randomSeed`, default
132
+ `DEFAULT_RANDOM_SEED`) rather than `Math.random()`: one script is evaluated twice — once
133
+ on the server, which validates it, and again in the browser, which renders it — and an
134
+ unseeded generator lets those two runs take different branches.
135
+
136
+ Conversion limits cover nodes, loop/path work, detail, aggregate vertices (including CSG
137
+ intermediates), and a coarse wall-clock budget checked between nodes — it refuses to start
138
+ the next node once the budget is spent, but cannot interrupt one long boolean.
139
+
54
140
  ## Scripts
55
141
 
56
142
  ```bash
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/core/definition.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAE9C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;CA4I3B,CAAC"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/core/definition.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAE9C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;CAsK3B,CAAC"}
@@ -1,4 +1,4 @@
1
- export type { PresentShapeScriptData, PresentShapeScriptArgs, PresentShapeScriptResult, PresentShapeScriptRenderedResult } from "./types";
1
+ export type { PresentShapeScriptData, PresentShapeScriptArgs, PresentShapeScriptResult, PresentShapeScriptRenderedResult, PresentShapeScriptErrorResult, PresentShapeScriptExecutionResult, ShapeScriptDiagnostic, } from "./types";
2
2
  export { TOOL_NAME, TOOL_DEFINITION } from "./definition";
3
3
  export { pluginCore, presentShapeScript, executePresentShapeScript } from "./plugin";
4
4
  export { samples } from "./samples";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,gCAAgC,EAAE,MAAM,SAAS,CAAC;AAC1I,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,gCAAgC,EAChC,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import type { ToolContext, ToolPluginCore } from "gui-chat-protocol";
2
- import type { PresentShapeScriptArgs, PresentShapeScriptData, PresentShapeScriptRenderedResult } from "./types";
2
+ import type { PresentShapeScriptArgs, PresentShapeScriptData, PresentShapeScriptExecutionResult } from "./types";
3
3
  import { TOOL_NAME, TOOL_DEFINITION } from "./definition";
4
- export declare const presentShapeScript: (_context: ToolContext, args: PresentShapeScriptArgs) => Promise<PresentShapeScriptRenderedResult>;
4
+ export declare const presentShapeScript: (_context: ToolContext, args: PresentShapeScriptArgs) => Promise<PresentShapeScriptExecutionResult>;
5
5
  export declare const pluginCore: ToolPluginCore<PresentShapeScriptData, unknown, PresentShapeScriptArgs>;
6
6
  export { TOOL_NAME, TOOL_DEFINITION };
7
- export declare const executePresentShapeScript: (_context: ToolContext, args: PresentShapeScriptArgs) => Promise<PresentShapeScriptRenderedResult>;
7
+ export declare const executePresentShapeScript: (_context: ToolContext, args: PresentShapeScriptArgs) => Promise<PresentShapeScriptExecutionResult>;
8
8
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/core/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,gCAAgC,EAAE,MAAM,SAAS,CAAC;AAChH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAK1D,eAAO,MAAM,kBAAkB,GAAU,UAAU,WAAW,EAAE,MAAM,sBAAsB,KAAG,OAAO,CAAC,gCAAgC,CAkBtI,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,sBAAsB,EAAE,OAAO,EAAE,sBAAsB,CAM9F,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACtC,eAAO,MAAM,yBAAyB,aA7Ba,WAAW,QAAQ,sBAAsB,KAAG,OAAO,CAAC,gCAAgC,CA6B5E,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/core/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,iCAAiC,EAAyB,MAAM,SAAS,CAAC;AACxI,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAO1D,eAAO,MAAM,kBAAkB,GAAU,UAAU,WAAW,EAAE,MAAM,sBAAsB,KAAG,OAAO,CAAC,iCAAiC,CAkCvI,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,sBAAsB,EAAE,OAAO,EAAE,sBAAsB,CAM9F,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACtC,eAAO,MAAM,yBAAyB,aA7Ca,WAAW,QAAQ,sBAAsB,KAAG,OAAO,CAAC,iCAAiC,CA6C7E,CAAC"}
@@ -19,4 +19,18 @@ export type PresentShapeScriptResult = ToolResult<PresentShapeScriptData>;
19
19
  export type PresentShapeScriptRenderedResult = PresentShapeScriptResult & {
20
20
  data: PresentShapeScriptData;
21
21
  };
22
+ export interface ShapeScriptDiagnostic {
23
+ code: "INVALID_ARGUMENT" | "PARSE_ERROR" | "EVALUATION_ERROR" | "LIMIT_EXCEEDED";
24
+ message: string;
25
+ line?: number;
26
+ column?: number;
27
+ }
28
+ /** Errors carry no renderable data; jsonData is returned to the calling agent. */
29
+ export type PresentShapeScriptErrorResult = ToolResult<never, {
30
+ error: ShapeScriptDiagnostic;
31
+ }> & {
32
+ data?: never;
33
+ error: ShapeScriptDiagnostic;
34
+ };
35
+ export type PresentShapeScriptExecutionResult = PresentShapeScriptRenderedResult | PresentShapeScriptErrorResult;
22
36
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,wBAAwB,GAAG;IACxE,IAAI,EAAE,sBAAsB,CAAC;CAC9B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,wBAAwB,GAAG;IACxE,IAAI,EAAE,sBAAsB,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,kBAAkB,GAAG,aAAa,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kFAAkF;AAClF,MAAM,MAAM,6BAA6B,GAAG,UAAU,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,qBAAqB,CAAA;CAAE,CAAC,GAAG;IAChG,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,qBAAqB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG,gCAAgC,GAAG,6BAA6B,CAAC"}
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./toThreeJS-CtWReTrz.cjs");exports.TOOL_DEFINITION=e.Ln,exports.TOOL_NAME=e.Rn,exports.astToThreeJS=e.t,exports.executePresentShapeScript=e.Pn,exports.parseShapeScript=e.Mn,exports.pluginCore=e.Fn,exports.presentShapeScript=e.In,exports.samples=e.Nn;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-D6hOBqbS.cjs");exports.TOOL_DEFINITION=e.Rn,exports.TOOL_NAME=e.zn,exports.astToThreeJS=e.a,exports.executePresentShapeScript=e.n,exports.parseShapeScript=e.Ln,exports.pluginCore=e.r,exports.presentShapeScript=e.i,exports.samples=e.t;
package/dist/core.js CHANGED
@@ -1,2 +1,2 @@
1
- import { Fn as e, In as t, Ln as n, Mn as r, Nn as i, Pn as a, Rn as o, t as s } from "./toThreeJS-DjFysw4f.js";
2
- export { n as TOOL_DEFINITION, o as TOOL_NAME, s as astToThreeJS, a as executePresentShapeScript, r as parseShapeScript, e as pluginCore, t as presentShapeScript, i as samples };
1
+ import { Ln as e, Rn as t, a as n, i as r, n as i, r as a, t as o, zn as s } from "./samples-BwRpwZSm.js";
2
+ export { t as TOOL_DEFINITION, s as TOOL_NAME, n as astToThreeJS, i as executePresentShapeScript, e as parseShapeScript, a as pluginCore, r as presentShapeScript, o as samples };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./toThreeJS-CtWReTrz.cjs");require("./core.cjs"),exports.TOOL_DEFINITION=e.Ln,exports.TOOL_NAME=e.Rn,exports.astToThreeJS=e.t,exports.executePresentShapeScript=e.Pn,exports.parseShapeScript=e.Mn,exports.pluginCore=e.Fn,exports.presentShapeScript=e.In,exports.samples=e.Nn;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-D6hOBqbS.cjs");require("./core.cjs"),exports.TOOL_DEFINITION=e.Rn,exports.TOOL_NAME=e.zn,exports.astToThreeJS=e.a,exports.executePresentShapeScript=e.n,exports.parseShapeScript=e.Ln,exports.pluginCore=e.r,exports.presentShapeScript=e.i,exports.samples=e.t;
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { Fn as e, In as t, Ln as n, Mn as r, Nn as i, Pn as a, Rn as o, t as s } from "./toThreeJS-DjFysw4f.js";
1
+ import { Ln as e, Rn as t, a as n, i as r, n as i, r as a, t as o, zn as s } from "./samples-BwRpwZSm.js";
2
2
  import "./core.js";
3
- export { n as TOOL_DEFINITION, o as TOOL_NAME, s as astToThreeJS, a as executePresentShapeScript, r as parseShapeScript, e as pluginCore, t as presentShapeScript, i as samples };
3
+ export { t as TOOL_DEFINITION, s as TOOL_NAME, n as astToThreeJS, i as executePresentShapeScript, e as parseShapeScript, a as pluginCore, r as presentShapeScript, o as samples };