@mulmoclaude/shapescript-plugin 1.3.0 → 2.0.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.
Files changed (52) hide show
  1. package/README.md +84 -14
  2. package/dist/core/definition.d.ts.map +1 -1
  3. package/dist/core/dispatch.d.ts +8 -3
  4. package/dist/core/dispatch.d.ts.map +1 -1
  5. package/dist/core/index.d.ts +5 -2
  6. package/dist/core/index.d.ts.map +1 -1
  7. package/dist/core/paths.d.ts +5 -0
  8. package/dist/core/paths.d.ts.map +1 -1
  9. package/dist/core-BvTjfhU2.js +53 -0
  10. package/dist/core-DZvhTmuk.cjs +1 -0
  11. package/dist/core.cjs +1 -1
  12. package/dist/core.js +4 -3
  13. package/dist/export/tool.d.ts +45 -0
  14. package/dist/export/tool.d.ts.map +1 -0
  15. package/dist/export/usdz.d.ts +17 -0
  16. package/dist/export/usdz.d.ts.map +1 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.js +4 -4
  19. package/dist/lang/de.d.ts.map +1 -1
  20. package/dist/lang/en.d.ts.map +1 -1
  21. package/dist/lang/es.d.ts.map +1 -1
  22. package/dist/lang/fr.d.ts.map +1 -1
  23. package/dist/lang/ja.d.ts.map +1 -1
  24. package/dist/lang/ko.d.ts.map +1 -1
  25. package/dist/lang/messages.d.ts +2 -0
  26. package/dist/lang/messages.d.ts.map +1 -1
  27. package/dist/lang/ptBR.d.ts.map +1 -1
  28. package/dist/lang/zh.d.ts.map +1 -1
  29. package/dist/render.cjs +2 -2
  30. package/dist/render.js +9 -9
  31. package/dist/samples-CXhuDdDd.js +1038 -0
  32. package/dist/samples-DGD0Kjwg.cjs +276 -0
  33. package/dist/shapescript/evaluator.d.ts +27 -4
  34. package/dist/shapescript/evaluator.d.ts.map +1 -1
  35. package/dist/shapescript/parser.d.ts +18 -0
  36. package/dist/shapescript/parser.d.ts.map +1 -1
  37. package/dist/shapescript/toThreeJS.d.ts +42 -2
  38. package/dist/shapescript/toThreeJS.d.ts.map +1 -1
  39. package/dist/shapescript/types.d.ts +22 -4
  40. package/dist/shapescript/types.d.ts.map +1 -1
  41. package/dist/style.css +1 -1
  42. package/dist/{toThreeJS-B5LiF110.js → toThreeJS-FsP-Na75.js} +341 -284
  43. package/dist/toThreeJS-MvllBF9e.cjs +10 -0
  44. package/dist/vue/View.vue.d.ts.map +1 -1
  45. package/dist/vue/index.d.ts +1 -1
  46. package/dist/vue/index.d.ts.map +1 -1
  47. package/dist/vue.cjs +41 -22
  48. package/dist/vue.js +1784 -1721
  49. package/package.json +1 -1
  50. package/dist/samples-DHEKUNs5.cjs +0 -186
  51. package/dist/samples-SaXsqbHJ.js +0 -180
  52. package/dist/toThreeJS-BOBpx5Dc.cjs +0 -10
package/README.md CHANGED
@@ -13,6 +13,7 @@ name, and the `Present3D*` type names, are renamed throughout.
13
13
  | Entry | Contents |
14
14
  | ------------- | ------------------------------------------------------------------------------------------------------------------------ |
15
15
  | `.` | `TOOL_NAME`, `TOOL_DEFINITION`, `executePresentShapeScript`, `pluginCore`, `samples`, `parseShapeScript`, `astToThreeJS`, `executeShapeScriptDispatch` + the `artifacts/shapes` path rules |
16
+ | `.` (export) | `shapeScriptToUsdz`, `sceneToUsdz`, `USDZ_MIME_TYPE`, `USDZ_EXTENSION`, and the **`exportShapeScriptUsdz`** tool (`executeExportShapeScriptUsdz`, `EXPORT_USDZ_*`). Browser-safe: it needs no canvas, so the View's "Download USDZ" button and a host's MCP tool run the same code. |
16
17
  | `./render` | **server-only** — `renderShapeScriptSheet` and the render page. Rasterises a model to a PNG with Puppeteer's headless Chromium (an OPTIONAL peer); a host without one gets `RenderUnavailableError` carrying the install hint. |
17
18
  | `./vue` | the `ToolPlugin` (View + Preview + `SYSTEM_PROMPT`), plus everything on `.` |
18
19
  | `./style.css` | the compiled component styles (Vite lib mode does not auto-inject them) |
@@ -39,18 +40,42 @@ for i in 1 to count {
39
40
  });
40
41
  ```
41
42
 
43
+ ## USDZ export
44
+
45
+ `exportShapeScriptUsdz` writes a model out as a USDZ archive (AR Quick Look on Apple devices, or
46
+ any USD viewer). A host wires it against the same `{ files: { artifacts, byPath? } }` context shape
47
+ `executeShapeScriptDispatch` takes — a full `FileOps`, or just `read` / `write` / `exists`
48
+ (`ShapeFileOps`) — no browser, no `node:*`:
49
+
50
+ ```ts
51
+ import { executeExportShapeScriptUsdz, EXPORT_USDZ_TOOL_NAME, EXPORT_USDZ_DESCRIPTION, EXPORT_USDZ_SCHEMA, EXPORT_USDZ_PROMPT } from "@mulmoclaude/shapescript-plugin";
52
+
53
+ // register { name: EXPORT_USDZ_TOOL_NAME, description: EXPORT_USDZ_DESCRIPTION, inputSchema: EXPORT_USDZ_SCHEMA }
54
+ const { message, filePath } = await executeExportShapeScriptUsdz({ files: shapeFiles }, args);
55
+ ```
56
+
57
+ The file lands at `artifacts/shapes/<slug>-<epoch-ms>-<token>.usdz`. The View's **Download USDZ**
58
+ button builds the same archive in the browser with `shapeScriptToUsdz` and saves it locally.
59
+ USDZ units are metres, so `size 1` is one metre in AR.
60
+
42
61
  ## ShapeScript language
43
62
 
44
63
  - **Primitives**: `cube`, `sphere`, `cylinder`, `cone`, `torus`, `circle`, `square`, `polygon`
45
- - **Properties**: `position X Y Z`, `rotation X Y Z`, `size X Y Z`, `color R G B` (0–1), `opacity`
64
+ - **Properties**: `position X Y Z`, `orientation ROLL YAW PITCH` (alias `rotation`), `size X Y Z`, `color R G B` (0–1), `opacity`
46
65
  - **CSG**: `union`, `difference`, `intersection`, `xor`, `stencil`
47
66
  - **Builders**: `extrude`, `loft`, `lathe`, `fill`, `hull`
48
67
  - **Variables & expressions**: `define`, arithmetic / comparison / boolean operators, parentheses
49
68
  - **Control flow**: `for … in … to … step`, `if` / `else`, `switch` / `case`
50
69
  - **Built-ins**: `round floor ceil abs sign sqrt pow min max`, `sin cos tan asin acos atan atan2`
51
- (radians), `dot cross length normalize sum`
70
+ (radians), `dot cross length normalize sum`, `rnd`
71
+ - **Commands**: `detail N`, `seed N` (both scoped to the enclosing block), `color`, and the relative
72
+ `rotate` / `translate` / `scale`
52
73
 
53
74
  A function call takes **no space** before its parenthesis: `sin(x)` is a call, `sin (x)` is not.
75
+ Arguments are a value list, so upstream's `max(0 (j - 1))` and `max(0, j - 1)` both work; write the
76
+ space-separated form when a script also has to open in the upstream app. Upstream's bare
77
+ `max 0 (j - 1)` (no parentheses) is not supported. This parser also accepts several statements on
78
+ one line (`define a 1 define b 2`); upstream requires one per line, so portable scripts keep to that.
54
79
 
55
80
  ## Storage
56
81
 
@@ -106,33 +131,77 @@ hull {
106
131
  }
107
132
  extrude { polygon { sides 5 } }
108
133
  fill { square }
109
- lathe path { point 1 0 curve 0 2 1 -1 }
134
+ lathe path {
135
+ point 0 0
136
+ point 1 0
137
+ curve 1.5 1
138
+ point 1 2
139
+ point 0 2
140
+ }
141
+
142
+ // Paths: absolute points, Bézier control points, a frame moved by rotate/translate/scale.
143
+ extrude path {
144
+ point 0 0
145
+ point 1 0
146
+ point 1 1
147
+ point 0 1
148
+ point 0 0
149
+ }
150
+ fill path {
151
+ for 0 to 8 {
152
+ curve 0 1
153
+ rotate 1 / 8
154
+ }
155
+ }
110
156
 
111
157
  // Stencil changes surface material without cutting away the first shape.
112
158
  stencil {
113
159
  cube { color 1 0 0 }
114
- cube { position 0.5 0 0 color 0 1 0 }
160
+ cube {
161
+ position 0.5 0 0
162
+ color 0 1 0
163
+ }
115
164
  }
116
165
 
117
166
  define offsets ((1 2 3), (4 5 6))
118
167
  cube { position offsets[0].x offsets[1].y offsets.count }
119
168
  ```
120
169
 
121
- Also supported: `pi`, `tau`, `true`, `false`, scientific notation, unary `+`,
170
+ Also supported: `pi`, `tau` (plugin-only; upstream has no `tau`, so portable scripts write `2 * pi`), `true`, `false`, scientific notation, unary `+`,
122
171
  short-circuit `and`/`or`, string literals, `join`/`trim`, tuple arguments to `min`/`max`,
123
- zero-based tuple/string subscripts, `.count`, vector `.x/.y/.z/.w`, color
172
+ zero-based tuple/string subscripts, `.count`, ordinal members `.first` … `.tenth`, `.last`,
173
+ `.allButFirst`, `.allButLast`, vector `.x/.y/.z/.w`, color
124
174
  `.red/.green/.blue/.alpha` (or `.r/.g/.b/.a`), custom shape definitions with options,
125
175
  and `polygon { sides N }` (integer 3–256). Lathe samples curved profiles, and inline
126
176
  builder paths use the same parser as nested paths, including loops and definitions.
127
177
 
178
+ ## Units and path semantics — same as upstream
179
+
180
+ Since 2.0.0 the plugin follows the [upstream ShapeScript](https://shapescript.info/mac/)
181
+ conventions, so a script written against the upstream docs renders the same here:
182
+
183
+ - `size` is the **diameter** of `sphere`, `cylinder`, `cone`, `circle`, `polygon` and `torus`
184
+ (a bare `sphere` fits the unit cube) and the edge length of `cube` / `square`.
185
+ - `orientation` (alias `rotation`) and `rotate` take **half-turns** as `roll yaw pitch` —
186
+ rotations about Z, Y and X applied in that order, `0.5` = 90°, positive clockwise (Euclid's
187
+ sign). A lone value is a roll; four values are `angle x y z`. Trig *functions* still use radians.
188
+ - Path `point` / `curve` coordinates are **absolute** in the path's frame; `rotate`, `translate`
189
+ and `scale` inside a path move that frame for later points. `curve` is a quadratic Bézier
190
+ **control point** — the outline passes through the neighbouring `point`s, and two `curve`s in
191
+ a row get an implicit on-curve midpoint (eight in an octagon draw a circle). A path block may
192
+ carry `position` / `orientation` / `size` of its own, which is how a `loft` section is placed in
193
+ 3D; `lathe` refuses a placed profile.
194
+ - `rnd` uses upstream's generator (`x = x · 1664525 + 1013904223 mod 2³²`, seed 0) and `seed N`
195
+ reseeds it for the enclosing block only.
196
+
197
+ Deviations that remain: an *open* path whose first or last point is a `curve` treats it as a
198
+ corner (upstream extrapolates a tangent), and path points are 2D. The gap list lives in
199
+ [`plans/feat-shapescript-upstream-parity.md`](../../../plans/feat-shapescript-upstream-parity.md).
200
+
128
201
  ## Compatibility and limits
129
202
 
130
203
  This is the plugin's documented modeling subset, **not complete compatibility with
131
- [upstream ShapeScript](https://shapescript.info/mac/)**. It preserves existing plugin
132
- conventions: primitive sphere/circle sizes specify radii; rotation/orientation properties
133
- and trig functions use radians; relative rotate/orientation commands and path rotation
134
- use turns (`1 = 360°`). Path point/curve coordinates are relative steps, and curve
135
- control coordinates are offsets from the endpoint. Upstream uses different conventions.
204
+ upstream ShapeScript**.
136
205
 
137
206
  Loft accepts ordered, closed planar sections with one perimeter each, resamples differing
138
207
  vertex counts, interpolates linearly, and triangulates the end caps. Sections must enclose
@@ -145,9 +214,10 @@ substituting different geometry. As with other polygonal CSG engines, degenerate
145
214
  self-intersecting inputs may fail.
146
215
 
147
216
  `rnd` and `rand()` draw from a seeded generator (`randomSeed`, default
148
- `DEFAULT_RANDOM_SEED`) rather than `Math.random()`: one script is evaluated twice — once
149
- on the server, which validates it, and again in the browser, which renders it — and an
150
- unseeded generator lets those two runs take different branches.
217
+ `DEFAULT_RANDOM_SEED` = 0, overridable in-script with `seed`) rather than `Math.random()`:
218
+ one script is evaluated twice — once on the server, which validates it, and again in the
219
+ browser, which renders it — and an unseeded generator lets those two runs take different
220
+ branches.
151
221
 
152
222
  Conversion limits cover nodes (100,000), loop/path work (100,000 iterations), detail (3–256),
153
223
  aggregate vertices (5,000,000, including CSG intermediates), and a coarse 30-second wall-clock
@@ -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;;;;;;;;;;;;;;;;;;;;;;CA4K3B,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;;;;;;;;;;;;;;;;;;;;;;CA8O3B,CAAC"}
@@ -1,12 +1,17 @@
1
1
  import type { FileOps } from "gui-chat-protocol";
2
2
  import type { ShapeScriptDispatchArgs } from "./contract";
3
+ /** The three FileOps methods this plugin's file paths actually use. A host's
4
+ * full `FileOps` satisfies it; so does a three-method object, which is what
5
+ * lets a host wire the `exportShapeScriptUsdz` MCP tool without reaching into
6
+ * its plugin runtime for a complete FileOps (that import cycles in MulmoClaude). */
7
+ export type ShapeFileOps = Pick<FileOps, "read" | "write" | "exists">;
3
8
  /** Capabilities the dispatch router needs: the generic, shared
4
9
  * `files.artifacts` FileOps, plus — for hosts that let presentShapeScript
5
10
  * open sources outside `artifacts/shapes/` — `files.byPath`. */
6
11
  export interface ShapeScriptDispatchContext {
7
12
  files: {
8
- artifacts: FileOps;
9
- byPath?: FileOps;
13
+ artifacts: ShapeFileOps;
14
+ byPath?: ShapeFileOps;
10
15
  };
11
16
  }
12
17
  /** The FileOps that owns a given source, plus the path in that FileOps' terms.
@@ -14,7 +19,7 @@ export interface ShapeScriptDispatchContext {
14
19
  * capability an older host provides, and what writes there — while anything
15
20
  * else needs the host's `files.byPath`. */
16
21
  export declare function locateShape(context: ShapeScriptDispatchContext, filePath: string): {
17
- files: FileOps;
22
+ files: ShapeFileOps;
18
23
  rel: string;
19
24
  } | null;
20
25
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/core/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D;;iEAEiE;AACjE,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACjD;AAED;;;4CAG4C;AAC5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKzH;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,0BAA0B,EACnC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAqChD"}
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/core/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D;;;qFAGqF;AACrF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAC;AAEtE;;iEAEiE;AACjE,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;CAC3D;AAED;;;4CAG4C;AAC5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAK9H;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,0BAA0B,EACnC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAqChD"}
@@ -3,10 +3,13 @@ export { TOOL_NAME, TOOL_DEFINITION } from "./definition";
3
3
  export { pluginCore, presentShapeScript, executePresentShapeScript } from "./plugin";
4
4
  export type { ShapeScriptExecuteContext } from "./plugin";
5
5
  export { executeShapeScriptDispatch, locateShape } from "./dispatch";
6
- export type { ShapeScriptDispatchContext } from "./dispatch";
6
+ export type { ShapeScriptDispatchContext, ShapeFileOps } from "./dispatch";
7
7
  export { isShapeScriptDispatchArgs, readLoadShapeResult, readSaveShapeResult } from "./contract";
8
8
  export type { LoadShapeArgs, SaveShapeArgs, ShapeScriptDispatchArgs, ShapeScriptDispatchResult } from "./contract";
9
- export { isPresentableShapePath, isShapeArtifactPath, shapeArtifactPath, toArtifactsRelative, SHAPE_EXTENSIONS } from "./paths";
9
+ export { isPresentableShapePath, isShapeArtifactPath, shapeArtifactPath, usdzArtifactPath, toArtifactsRelative, SHAPE_EXTENSIONS } from "./paths";
10
+ export { sceneToUsdz, shapeScriptToUsdz, USDZ_MIME_TYPE, USDZ_EXTENSION } from "../export/usdz";
11
+ export { executeExportShapeScriptUsdz, EXPORT_USDZ_TOOL_NAME, EXPORT_USDZ_DESCRIPTION, EXPORT_USDZ_PROMPT, EXPORT_USDZ_SCHEMA, EXPORT_USDZ_TOOL_TIMEOUT_MS, } from "../export/tool";
12
+ export type { ExportUsdzResult } from "../export/tool";
10
13
  export { samples } from "./samples";
11
14
  export { parseShapeScript } from "../shapescript/parser";
12
15
  export { astToThreeJS } from "../shapescript/toThreeJS";
@@ -1 +1 @@
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,YAAY,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACnH,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChI,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,YAAY,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACnH,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAIlJ,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,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"}
@@ -21,6 +21,11 @@ export interface ShapePath {
21
21
  * `write` replaces the first model with no error anywhere (codex on #3056).
22
22
  * `token` is injectable so a test can assert the whole filename. */
23
23
  export declare function shapeArtifactPath(title: string | undefined, now?: Date, token?: string): ShapePath;
24
+ /** Build a fresh path for a USDZ export, beside the `.shape` sources in the
25
+ * same flat `artifacts/shapes/` directory — an export is opened by name too,
26
+ * and the user finds it next to the model it came from. Same collision rule as
27
+ * `shapeArtifactPath`. */
28
+ export declare function usdzArtifactPath(title: string | undefined, now?: Date, token?: string): ShapePath;
24
29
  /**
25
30
  * Strict guard for a workspace-relative path the caller claims is an existing
26
31
  * ShapeScript artifact. Rejects anything outside `artifacts/shapes/`,
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAoBA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,qBAAsB,CAAC;AAEpD;yDACyD;AACzD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,SAAsB,GAAG,MAAM,CAEzF;AAED,MAAM,WAAW,SAAS;IACxB;sDACkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB;gEAC4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAeD;;;;;;;;qEAQqE;AACrE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,GAAE,IAAiB,EAAE,KAAK,GAAE,MAAsB,GAAG,SAAS,CAW7H;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI1D;AAED;;sDAEsD;AACtD,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;+DAG+D;AAC/D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAoBA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,qBAAsB,CAAC;AAEpD;yDACyD;AACzD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,SAAsB,GAAG,MAAM,CAEzF;AAED,MAAM,WAAW,SAAS;IACxB;sDACkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB;gEAC4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAeD;;;;;;;;qEAQqE;AACrE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,GAAE,IAAiB,EAAE,KAAK,GAAE,MAAsB,GAAG,SAAS,CAW7H;AAED;;;2BAG2B;AAC3B,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,GAAE,IAAiB,EAAE,KAAK,GAAE,MAAsB,GAAG,SAAS,CAW5H;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI1D;AAED;;sDAEsD;AACtD,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;+DAG+D;AAC/D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D"}
@@ -0,0 +1,53 @@
1
+ import { _ as e, a as t, u as n } from "./samples-CXhuDdDd.js";
2
+ import { t as r } from "./toThreeJS-FsP-Na75.js";
3
+ //#region src/export/tool.ts
4
+ var i = "exportShapeScriptUsdz", a = r + 3e4, o = "Export a ShapeScript model to a USDZ file (Apple's AR / 3D format, openable with AR Quick Look on iPhone, iPad and Mac) and save it under artifacts/shapes/. Returns the saved path. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file. USDZ units are metres, so a `size 1` cube becomes a one-metre object in AR — scale the model in the script if that is not what the user wants.", s = "Use exportShapeScriptUsdz when the user wants to take a 3D model out of the chat — to view it in AR, open it in a 3D app, or share the file. It saves a .usdz next to the model's .shape file and returns the path; tell the user where it is. The user can also press \"Download USDZ\" in the model's view themselves.", c = {
5
+ type: "object",
6
+ properties: {
7
+ script: {
8
+ type: "string",
9
+ description: "ShapeScript source to export. Provide either this or `path`, not both."
10
+ },
11
+ path: {
12
+ type: "string",
13
+ description: "Path to an existing .shape file to export (e.g. one presentShapeScript saved under artifacts/shapes/)."
14
+ },
15
+ title: {
16
+ type: "string",
17
+ description: "Name for the exported file; it is slugified into the filename. Defaults to the .shape file's own name when `path` is given."
18
+ }
19
+ },
20
+ required: []
21
+ };
22
+ function l(e) {
23
+ return typeof e == "string" && e.trim() !== "" ? e : void 0;
24
+ }
25
+ function u(e) {
26
+ return (e.split(/[\\/]/).pop() ?? e).replace(/\.shape$/i, "");
27
+ }
28
+ async function d(e, t) {
29
+ let r = l(t.script), i = l(t.path), a = l(t.title);
30
+ if (r && i) throw Error("Provide either `script` or `path`, not both");
31
+ if (r) return {
32
+ script: r,
33
+ title: a
34
+ };
35
+ if (!i) throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)");
36
+ let o = n(e, i);
37
+ if (!o) throw Error("`path` must name a .shape file, without `.` / `..` segments");
38
+ if (!await o.files.exists(o.rel)) throw Error(`No ShapeScript exists at ${i}`);
39
+ return {
40
+ script: await o.files.read(o.rel),
41
+ title: a ?? u(i)
42
+ };
43
+ }
44
+ async function f(n, r) {
45
+ let { script: i, title: a } = await d(n, r), o = await t(i), { relPath: s, filePath: c } = e(a);
46
+ return await n.files.artifacts.write(s, o), {
47
+ message: `Saved USDZ to ${c} (${o.byteLength} bytes). Open it with AR Quick Look or any USD viewer.`,
48
+ filePath: c,
49
+ bytes: o.byteLength
50
+ };
51
+ }
52
+ //#endregion
53
+ export { a, i, s as n, f as o, c as r, o as t };
@@ -0,0 +1 @@
1
+ const e=require("./samples-DGD0Kjwg.cjs"),t=require("./toThreeJS-MvllBF9e.cjs");var n=`exportShapeScriptUsdz`,r=t.t+3e4,i="Export a ShapeScript model to a USDZ file (Apple's AR / 3D format, openable with AR Quick Look on iPhone, iPad and Mac) and save it under artifacts/shapes/. Returns the saved path. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file. USDZ units are metres, so a `size 1` cube becomes a one-metre object in AR — scale the model in the script if that is not what the user wants.",a=`Use exportShapeScriptUsdz when the user wants to take a 3D model out of the chat — to view it in AR, open it in a 3D app, or share the file. It saves a .usdz next to the model's .shape file and returns the path; tell the user where it is. The user can also press "Download USDZ" in the model's view themselves.`,o={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to export. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to export (e.g. one presentShapeScript saved under artifacts/shapes/).`},title:{type:`string`,description:"Name for the exported file; it is slugified into the filename. Defaults to the .shape file's own name when `path` is given."}},required:[]};function s(e){return typeof e==`string`&&e.trim()!==``?e:void 0}function c(e){return(e.split(/[\\/]/).pop()??e).replace(/\.shape$/i,``)}async function l(t,n){let r=s(n.script),i=s(n.path),a=s(n.title);if(r&&i)throw Error("Provide either `script` or `path`, not both");if(r)return{script:r,title:a};if(!i)throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)");let o=e.u(t,i);if(!o)throw Error("`path` must name a .shape file, without `.` / `..` segments");if(!await o.files.exists(o.rel))throw Error(`No ShapeScript exists at ${i}`);return{script:await o.files.read(o.rel),title:a??c(i)}}async function u(t,n){let{script:r,title:i}=await l(t,n),a=await e.a(r),{relPath:o,filePath:s}=e._(i);return await t.files.artifacts.write(o,a),{message:`Saved USDZ to ${s} (${a.byteLength} bytes). Open it with AR Quick Look or any USD viewer.`,filePath:s,bytes:a.byteLength}}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return i}});
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DHEKUNs5.cjs"),t=require("./toThreeJS-BOBpx5Dc.cjs");exports.SHAPE_EXTENSIONS=e.s,exports.TOOL_DEFINITION=e.f,exports.TOOL_NAME=e.p,exports.astToThreeJS=t.n,exports.executePresentShapeScript=e.n,exports.executeShapeScriptDispatch=e.a,exports.isPresentableShapePath=e.c,exports.isShapeArtifactPath=e.l,exports.isShapeScriptDispatchArgs=t.Ln,exports.locateShape=e.o,exports.parseShapeScript=t.Pn,exports.pluginCore=e.r,exports.presentShapeScript=e.i,exports.readLoadShapeResult=t.Rn,exports.readSaveShapeResult=t.zn,exports.samples=e.t,exports.shapeArtifactPath=e.u,exports.toArtifactsRelative=e.d;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DGD0Kjwg.cjs"),t=require("./toThreeJS-MvllBF9e.cjs"),n=require("./core-DZvhTmuk.cjs");exports.EXPORT_USDZ_DESCRIPTION=n.t,exports.EXPORT_USDZ_PROMPT=n.n,exports.EXPORT_USDZ_SCHEMA=n.r,exports.EXPORT_USDZ_TOOL_NAME=n.i,exports.EXPORT_USDZ_TOOL_TIMEOUT_MS=n.a,exports.SHAPE_EXTENSIONS=e.d,exports.TOOL_DEFINITION=e.v,exports.TOOL_NAME=e.y,exports.USDZ_EXTENSION=e.n,exports.USDZ_MIME_TYPE=e.r,exports.astToThreeJS=t.r,exports.executeExportShapeScriptUsdz=n.o,exports.executePresentShapeScript=e.o,exports.executeShapeScriptDispatch=e.l,exports.isPresentableShapePath=e.f,exports.isShapeArtifactPath=e.p,exports.isShapeScriptDispatchArgs=t.zn,exports.locateShape=e.u,exports.parseShapeScript=t.In,exports.pluginCore=e.s,exports.presentShapeScript=e.c,exports.readLoadShapeResult=t.Bn,exports.readSaveShapeResult=t.Vn,exports.samples=e.t,exports.sceneToUsdz=e.i,exports.shapeArtifactPath=e.m,exports.shapeScriptToUsdz=e.a,exports.toArtifactsRelative=e.g,exports.usdzArtifactPath=e._;
package/dist/core.js CHANGED
@@ -1,3 +1,4 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./samples-SaXsqbHJ.js";
2
- import { Ln as p, Pn as m, Rn as h, n as g, zn as _ } from "./toThreeJS-B5LiF110.js";
3
- export { u as SHAPE_EXTENSIONS, r as TOOL_DEFINITION, c as TOOL_NAME, g as astToThreeJS, o as executePresentShapeScript, e as executeShapeScriptDispatch, t as isPresentableShapePath, a as isShapeArtifactPath, p as isShapeScriptDispatchArgs, s as locateShape, m as parseShapeScript, l as pluginCore, i as presentShapeScript, h as readLoadShapeResult, _ as readSaveShapeResult, d as samples, f as shapeArtifactPath, n as toArtifactsRelative };
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h, v as g, y as _ } from "./samples-CXhuDdDd.js";
2
+ import { Bn as v, In as y, Vn as b, r as x, zn as S } from "./toThreeJS-FsP-Na75.js";
3
+ import { a as C, i as w, n as T, o as E, r as D, t as O } from "./core-BvTjfhU2.js";
4
+ export { O as EXPORT_USDZ_DESCRIPTION, T as EXPORT_USDZ_PROMPT, D as EXPORT_USDZ_SCHEMA, w as EXPORT_USDZ_TOOL_NAME, C as EXPORT_USDZ_TOOL_TIMEOUT_MS, r as SHAPE_EXTENSIONS, g as TOOL_DEFINITION, _ as TOOL_NAME, l as USDZ_EXTENSION, f as USDZ_MIME_TYPE, x as astToThreeJS, E as executeExportShapeScriptUsdz, u as executePresentShapeScript, s as executeShapeScriptDispatch, i as isPresentableShapePath, d as isShapeArtifactPath, S as isShapeScriptDispatchArgs, h as locateShape, y as parseShapeScript, p as pluginCore, n as presentShapeScript, v as readLoadShapeResult, b as readSaveShapeResult, m as samples, o as sceneToUsdz, c as shapeArtifactPath, t as shapeScriptToUsdz, a as toArtifactsRelative, e as usdzArtifactPath };
@@ -0,0 +1,45 @@
1
+ import { type ShapeScriptDispatchContext } from "../core/dispatch";
2
+ export declare const EXPORT_USDZ_TOOL_NAME = "exportShapeScriptUsdz";
3
+ /** Milliseconds a host must allow this tool before its own transport gives up.
4
+ * Conversion may legitimately spend its whole `DEFAULT_MAX_DURATION_MS` on a
5
+ * near-limit model, and serialising the result to USDZ (plus the write) comes
6
+ * AFTER that — a transport sized to the conversion alone aborts an export that
7
+ * was about to succeed, exactly as #3056 found for `renderShapeScript`. */
8
+ export declare const EXPORT_USDZ_TOOL_TIMEOUT_MS: number;
9
+ export declare const EXPORT_USDZ_DESCRIPTION = "Export a ShapeScript model to a USDZ file (Apple's AR / 3D format, openable with AR Quick Look on iPhone, iPad and Mac) and save it under artifacts/shapes/. Returns the saved path. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file. USDZ units are metres, so a `size 1` cube becomes a one-metre object in AR \u2014 scale the model in the script if that is not what the user wants.";
10
+ export declare const EXPORT_USDZ_PROMPT = "Use exportShapeScriptUsdz when the user wants to take a 3D model out of the chat \u2014 to view it in AR, open it in a 3D app, or share the file. It saves a .usdz next to the model's .shape file and returns the path; tell the user where it is. The user can also press \"Download USDZ\" in the model's view themselves.";
11
+ /** The tool's JSON schema, in the shape both a gui-chat-protocol `ToolDefinition`
12
+ * (`parameters`) and an MCP tool (`inputSchema`) take. */
13
+ export declare const EXPORT_USDZ_SCHEMA: {
14
+ type: "object";
15
+ properties: {
16
+ script: {
17
+ type: string;
18
+ description: string;
19
+ };
20
+ path: {
21
+ type: string;
22
+ description: string;
23
+ };
24
+ title: {
25
+ type: string;
26
+ description: string;
27
+ };
28
+ };
29
+ required: string[];
30
+ };
31
+ /** What one call did: the sentence the agent reads, and the path for a host
32
+ * that wants to log or link it. */
33
+ export interface ExportUsdzResult {
34
+ message: string;
35
+ /** Workspace-relative, `artifacts/shapes/<slug>-<epoch>-<token>.usdz`. */
36
+ filePath: string;
37
+ bytes: number;
38
+ }
39
+ /**
40
+ * Run one `exportShapeScriptUsdz` call. Throws on a missing / invalid source
41
+ * and on ShapeScript errors — the host's own error path reports those to the
42
+ * model, exactly as it does for `renderShapeScript`.
43
+ */
44
+ export declare function executeExportShapeScriptUsdz(context: ShapeScriptDispatchContext, args: Record<string, unknown>): Promise<ExportUsdzResult>;
45
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/export/tool.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAKhF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D;;;;4EAI4E;AAC5E,eAAO,MAAM,2BAA2B,QAAmC,CAAC;AAE5E,eAAO,MAAM,uBAAuB,6aACmY,CAAC;AAExa,eAAO,MAAM,kBAAkB,kUAC6R,CAAC;AAE7T;2DAC2D;AAC3D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;cAgBb,MAAM,EAAE;CACzB,CAAC;AAEF;oCACoC;AACpC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AA0BD;;;;GAIG;AACH,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,0BAA0B,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAUhJ"}
@@ -0,0 +1,17 @@
1
+ import * as THREE from "three";
2
+ import { type ConversionOptions } from "../shapescript/toThreeJS";
3
+ /** The MIME type a `.usdz` is served / downloaded as (Apple's registration). */
4
+ export declare const USDZ_MIME_TYPE = "model/vnd.usdz+zip";
5
+ /** The extension a USDZ archive carries. */
6
+ export declare const USDZ_EXTENSION = ".usdz";
7
+ /** Serialise an already-built Three.js object tree to a USDZ archive.
8
+ *
9
+ * `quickLookCompatible` lets Apple's AR Quick Look open the file, which is the
10
+ * main reason anyone wants USDZ; the flag costs nothing elsewhere. */
11
+ export declare function sceneToUsdz(object: THREE.Object3D): Promise<Uint8Array<ArrayBuffer>>;
12
+ /** Parse, evaluate and export one ShapeScript source. Geometry is built the
13
+ * same way `presentShapeScript` validates it (same converter, same limits),
14
+ * solid rather than wireframe, and released once serialised — the CSG buffers
15
+ * are the expensive part and nothing keeps them after this. */
16
+ export declare function shapeScriptToUsdz(script: string, options?: Omit<ConversionOptions, "wireframe">): Promise<Uint8Array<ArrayBuffer>>;
17
+ //# sourceMappingURL=usdz.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usdz.d.ts","sourceRoot":"","sources":["../../src/export/usdz.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGhF,gFAAgF;AAChF,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,4CAA4C;AAC5C,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;uEAGuE;AACvE,wBAAsB,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAI1F;AAED;;;gEAGgE;AAChE,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAO5I"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DHEKUNs5.cjs"),t=require("./toThreeJS-BOBpx5Dc.cjs");require("./core.cjs"),exports.SHAPE_EXTENSIONS=e.s,exports.TOOL_DEFINITION=e.f,exports.TOOL_NAME=e.p,exports.astToThreeJS=t.n,exports.executePresentShapeScript=e.n,exports.executeShapeScriptDispatch=e.a,exports.isPresentableShapePath=e.c,exports.isShapeArtifactPath=e.l,exports.isShapeScriptDispatchArgs=t.Ln,exports.locateShape=e.o,exports.parseShapeScript=t.Pn,exports.pluginCore=e.r,exports.presentShapeScript=e.i,exports.readLoadShapeResult=t.Rn,exports.readSaveShapeResult=t.zn,exports.samples=e.t,exports.shapeArtifactPath=e.u,exports.toArtifactsRelative=e.d;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DGD0Kjwg.cjs"),t=require("./toThreeJS-MvllBF9e.cjs"),n=require("./core-DZvhTmuk.cjs");exports.EXPORT_USDZ_DESCRIPTION=n.t,exports.EXPORT_USDZ_PROMPT=n.n,exports.EXPORT_USDZ_SCHEMA=n.r,exports.EXPORT_USDZ_TOOL_NAME=n.i,exports.EXPORT_USDZ_TOOL_TIMEOUT_MS=n.a,exports.SHAPE_EXTENSIONS=e.d,exports.TOOL_DEFINITION=e.v,exports.TOOL_NAME=e.y,exports.USDZ_EXTENSION=e.n,exports.USDZ_MIME_TYPE=e.r,exports.astToThreeJS=t.r,exports.executeExportShapeScriptUsdz=n.o,exports.executePresentShapeScript=e.o,exports.executeShapeScriptDispatch=e.l,exports.isPresentableShapePath=e.f,exports.isShapeArtifactPath=e.p,exports.isShapeScriptDispatchArgs=t.zn,exports.locateShape=e.u,exports.parseShapeScript=t.In,exports.pluginCore=e.s,exports.presentShapeScript=e.c,exports.readLoadShapeResult=t.Bn,exports.readSaveShapeResult=t.Vn,exports.samples=e.t,exports.sceneToUsdz=e.i,exports.shapeArtifactPath=e.m,exports.shapeScriptToUsdz=e.a,exports.toArtifactsRelative=e.g,exports.usdzArtifactPath=e._;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./samples-SaXsqbHJ.js";
2
- import { Ln as p, Pn as m, Rn as h, n as g, zn as _ } from "./toThreeJS-B5LiF110.js";
3
- import "./core.js";
4
- export { u as SHAPE_EXTENSIONS, r as TOOL_DEFINITION, c as TOOL_NAME, g as astToThreeJS, o as executePresentShapeScript, e as executeShapeScriptDispatch, t as isPresentableShapePath, a as isShapeArtifactPath, p as isShapeScriptDispatchArgs, s as locateShape, m as parseShapeScript, l as pluginCore, i as presentShapeScript, h as readLoadShapeResult, _ as readSaveShapeResult, d as samples, f as shapeArtifactPath, n as toArtifactsRelative };
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h, v as g, y as _ } from "./samples-CXhuDdDd.js";
2
+ import { Bn as v, In as y, Vn as b, r as x, zn as S } from "./toThreeJS-FsP-Na75.js";
3
+ import { a as C, i as w, n as T, o as E, r as D, t as O } from "./core-BvTjfhU2.js";
4
+ export { O as EXPORT_USDZ_DESCRIPTION, T as EXPORT_USDZ_PROMPT, D as EXPORT_USDZ_SCHEMA, w as EXPORT_USDZ_TOOL_NAME, C as EXPORT_USDZ_TOOL_TIMEOUT_MS, r as SHAPE_EXTENSIONS, g as TOOL_DEFINITION, _ as TOOL_NAME, l as USDZ_EXTENSION, f as USDZ_MIME_TYPE, x as astToThreeJS, E as executeExportShapeScriptUsdz, u as executePresentShapeScript, s as executeShapeScriptDispatch, i as isPresentableShapePath, d as isShapeArtifactPath, S as isShapeScriptDispatchArgs, h as locateShape, y as parseShapeScript, p as pluginCore, n as presentShapeScript, v as readLoadShapeResult, b as readSaveShapeResult, m as samples, o as sceneToUsdz, c as shapeArtifactPath, t as shapeScriptToUsdz, a as toArtifactsRelative, e as usdzArtifactPath };
@@ -1 +1 @@
1
- {"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../src/lang/de.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../src/lang/de.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/lang/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/lang/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/lang/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/lang/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fr.d.ts","sourceRoot":"","sources":["../../src/lang/fr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"fr.d.ts","sourceRoot":"","sources":["../../src/lang/fr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ja.d.ts","sourceRoot":"","sources":["../../src/lang/ja.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"ja.d.ts","sourceRoot":"","sources":["../../src/lang/ja.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ko.d.ts","sourceRoot":"","sources":["../../src/lang/ko.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"ko.d.ts","sourceRoot":"","sources":["../../src/lang/ko.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
@@ -8,5 +8,7 @@ export interface Messages {
8
8
  scriptEditorLabel: string;
9
9
  applyChanges: string;
10
10
  saveError: string;
11
+ downloadUsdz: string;
12
+ exportError: string;
11
13
  }
12
14
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/lang/messages.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/lang/messages.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ptBR.d.ts","sourceRoot":"","sources":["../../src/lang/ptBR.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,IAAI,EAAE,QAUX,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"ptBR.d.ts","sourceRoot":"","sources":["../../src/lang/ptBR.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,IAAI,EAAE,QAYX,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"zh.d.ts","sourceRoot":"","sources":["../../src/lang/zh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAUT,CAAC;AAEF,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"zh.d.ts","sourceRoot":"","sources":["../../src/lang/zh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,QAAA,MAAM,EAAE,EAAE,QAYT,CAAC;AAEF,eAAe,EAAE,CAAC"}
package/dist/render.cjs CHANGED
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));const c=require("./toThreeJS-BOBpx5Dc.cjs");let l=require("node:fs/promises"),u=require("node:module"),d=require("node:url"),f=require("node:path");f=s(f,1);function p(e){let t=Math.ceil(Math.sqrt(e));return{columns:t,rows:Math.ceil(e/t)}}function m(e,t,n){return`import { AmbientLight, Box3, DirectionalLight, GridHelper, MathUtils, ObjectLoader, OrthographicCamera, PerspectiveCamera, Scene, Sphere, Vector3, WebGLRenderer } from ${JSON.stringify(e)};
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));const c=require("./toThreeJS-MvllBF9e.cjs");let l=require("node:fs/promises"),u=require("node:module"),d=require("node:url"),f=require("node:path");f=s(f,1);function p(e){let t=Math.ceil(Math.sqrt(e));return{columns:t,rows:Math.ceil(e/t)}}function m(e,t,n){return`import { AmbientLight, Box3, DirectionalLight, GridHelper, MathUtils, ObjectLoader, OrthographicCamera, PerspectiveCamera, Scene, Sphere, Vector3, WebGLRenderer } from ${JSON.stringify(e)};
2
2
 
3
3
  const config = ${t};
4
4
  const { columns, rows } = ${n};
@@ -79,4 +79,4 @@ window.__shapeSheet = sheet.toDataURL("image/png");`}function g(e){let{threeUrl:
79
79
  <canvas id="sheet"></canvas>
80
80
  <script type="module">
81
81
  ${`${m(t,JSON.stringify({views:r,width:i,height:a,zoom:o,projection:s,scene:n}),JSON.stringify(p(r.length)))}\n${h()}`}
82
- <\/script>`}var _=1e3;function v(e){return e instanceof Error?e.message:String(e)}var y=60*_,b=30*_,x=9e4,S="renderShapeScript needs Puppeteer's headless Chromium, which this host does not have. Run `npx puppeteer browsers install chrome`, then retry. Everything else, including presentShapeScript, works without it.",C=class extends Error{};function w(e,t){try{e?.(t)}catch{}}function T(){let e={}.url;if(typeof e==`string`&&e.length>0)return e;if(typeof __filename==`string`)return(0,d.pathToFileURL)(__filename).href;throw Error(`shapescript render: cannot locate this module to resolve three from`)}var E=(0,u.createRequire)(T());function D(e){return c.In(e)&&typeof e.launch==`function`}async function ee(){try{let e=await import(`puppeteer`);return D(e)?e:c.In(e)&&D(e.default)?e.default:null}catch{return null}}function te(){try{return(0,u.createRequire)(E.resolve(`@mulmoclaude/shapescript-plugin/package.json`))}catch{return E}}function O(){let e=te().resolve(`three`);return e.endsWith(`three.cjs`)?e.replace(/three\.cjs$/,`three.module.js`):e}var k=`https://shapescript.invalid`,A=`${k}/render.html`,j=`./three.module.js`;async function M(e,t,n){let r;try{r=new URL(e)}catch{return null}if(r.origin!==k)return null;let i=f.default.posix.basename(r.pathname);return i===`render.html`?{contentType:`text/html; charset=utf-8`,body:t}:/^three[\w.-]*\.js$/.test(i)?{contentType:`text/javascript; charset=utf-8`,body:await(0,l.readFile)(f.default.join(n,i),`utf-8`)}:null}async function N(e,t){let n=f.default.dirname(O());await e.setRequestInterception(!0),e.on(`request`,e=>{(async()=>{try{let r=await M(e.url(),t,n);await(r?e.respond({status:200,...r}):e.abort())}catch{}})()})}async function P(e){let t=await ee();if(!t)throw new C(S);let n=c.n(c.Pn(e.script)).toJSON(),r=g({...e,threeUrl:j,sceneJson:n}),i;try{i=await t.launch({headless:!0,timeout:b,args:[`--enable-unsafe-swiftshader`,`--use-gl=swiftshader`]})}catch(e){throw new C(`${S} (launch failed: ${v(e)})`)}try{let e=await i.newPage();await e.setViewport({width:800,height:600});let t=[];e.on(`pageerror`,e=>t.push(e.message)),await N(e,r),await e.goto(A,{waitUntil:`load`});try{await e.waitForFunction(`typeof window.__shapeSheet === 'string'`,{timeout:y})}catch(e){let n=t.length>0?`the render page failed: ${t.join(`; `)}`:v(e);throw Error(n,{cause:e})}let n=await e.evaluate(`window.__shapeSheet`);if(typeof n!=`string`||!n.startsWith(`data:image/png;base64,`))throw Error(`the render page produced no image`);return n.slice(22)}finally{await i.close().catch(t=>w(e.onWarning,`chromium close failed: ${v(t)}`))}}var F=30,I=25,L=1,R=480,z=900,B=160,V=85,H=x+3e4,U=`renderShapeScript`,W="Render a ShapeScript model to a PNG image and save it, so you can LOOK at the model you wrote and check it before showing it to the user. Returns the image path — read that file to see the result. By default it renders four camera angles onto one sheet, because a single view cannot settle what is in front of what. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file.",G=`Use renderShapeScript to CHECK a 3D model you wrote before presenting it — it saves a PNG and returns the path, which you then read to see what the model actually looks like. Fix what you see and re-render. Rendering needs a local headless browser; if it reports one is missing, say so and continue with presentShapeScript rather than retrying.`,K={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to render. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to render (e.g. one presentShapeScript saved under artifacts/shapes/).`},azimuth:{type:`number`,description:`Camera rotation around the model in degrees, 0 = looking from +Z. Default ${F}. In the default four-view sheet this is the FIRST view's angle; the others are offset from it.`},elevation:{type:`number`,description:`Camera height in degrees above the horizon, 90 = straight down. Default ${I}. Avoid 0 and 90 for the main view — an axis-aligned shot flattens depth.`},zoom:{type:`number`,description:`Multiplier on the automatic framing, which fits the whole model. 1 = fit (default), 2 = twice as close, 0.5 = further out. Prefer this over guessing a camera distance: it means the same thing at any model scale.`},views:{type:`string`,enum:[`quad`,`single`],description:"`quad` (default) renders four angles on one sheet — use it to judge shape and layout. `single` renders only `azimuth`/`elevation`, for a close look at one detail."},projection:{type:`string`,enum:[`perspective`,`orthographic`],description:"`perspective` (default) looks natural; `orthographic` keeps parallel edges parallel, which is better for comparing proportions."},width:{type:`number`,description:`Pixel width of ONE view. Default ${R}, clamped to ${B}–${z}.`},height:{type:`number`,description:`Pixel height of ONE view. Default ${R}, clamped to ${B}–${z}.`}},required:[]};function q(e,t){return typeof e!=`number`||!Number.isFinite(e)?t:Math.min(z,Math.max(B,Math.round(e)))}function J(e,t){return typeof e==`number`&&Number.isFinite(e)?e:t}var Y=e=>`${Math.round(e)}°`;function X(e,t,n){let r=(e,t,n)=>({azimuth:e,elevation:t,label:`${n} — az ${Y(e)}, el ${Y(t)}`});return n?[r(e,t,`view`)]:[r(e,t,`front-right`),r(e+90,t,`back-right`),r(e+180,t,`back-left`),r(e,V,`top`)]}async function Z(e,t){let n=typeof t.script==`string`&&t.script.trim()!==``?t.script:void 0,r=typeof t.path==`string`&&t.path.trim()!==``?t.path:void 0;if(n&&r)throw Error("Provide either `script` or `path`, not both");if(n)return n;if(r)return e.readShape(r);throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)")}function Q(e,t,n,r){return{script:t,views:n,width:q(e.width,R),height:q(e.height,R),zoom:Math.max(J(e.zoom,L),.01),projection:e.projection===`orthographic`?`orthographic`:`perspective`,...r?{onWarning:r}:{}}}function $(e,t){let n=t.map(e=>e.label).join(`; `);return`Saved render to ${e} (${t.length===1?`1 view`:`${t.length} views`}: ${n}). Read that file to see the model.`}async function ne(e,t){let n=await Z(e,t),r=X(J(t.azimuth,F),J(t.elevation,I),t.views===`single`);try{let i=await P(Q(t,n,r,e.onWarning));return{message:$(await e.saveImage(i),r),rendered:!0}}catch(t){if(t instanceof C)return w(e.onWarning,`renderShapeScript: unavailable — ${t.message}`),{message:t.message,rendered:!1};throw t}}exports.CHROMIUM_HINT=S,exports.LAUNCH_TIMEOUT_MS=b,exports.RENDER_BUDGET_MS=x,exports.RENDER_SHAPE_SCRIPT_DESCRIPTION=W,exports.RENDER_SHAPE_SCRIPT_PROMPT=G,exports.RENDER_SHAPE_SCRIPT_SCHEMA=K,exports.RENDER_SHAPE_SCRIPT_TOOL_NAME=U,exports.RENDER_TIMEOUT_MS=y,exports.RENDER_TOOL_TIMEOUT_MS=H,exports.RenderUnavailableError=C,exports.buildRenderPage=g,exports.executeRenderShapeScript=ne,exports.gridFor=p,exports.renderOptionsFrom=Q,exports.renderShapeScriptSheet=P,exports.savedMessage=$,exports.viewAngles=X;
82
+ <\/script>`}var _=1e3;function v(e){return e instanceof Error?e.message:String(e)}var y=60*_,b=30*_,x=9e4,S="renderShapeScript needs Puppeteer's headless Chromium, which this host does not have. Run `npx puppeteer browsers install chrome`, then retry. Everything else, including presentShapeScript, works without it.",C=class extends Error{};function w(e,t){try{e?.(t)}catch{}}function T(){let e={}.url;if(typeof e==`string`&&e.length>0)return e;if(typeof __filename==`string`)return(0,d.pathToFileURL)(__filename).href;throw Error(`shapescript render: cannot locate this module to resolve three from`)}var E=(0,u.createRequire)(T());function D(e){return c.Rn(e)&&typeof e.launch==`function`}async function ee(){try{let e=await import(`puppeteer`);return D(e)?e:c.Rn(e)&&D(e.default)?e.default:null}catch{return null}}function te(){try{return(0,u.createRequire)(E.resolve(`@mulmoclaude/shapescript-plugin/package.json`))}catch{return E}}function O(){let e=te().resolve(`three`);return e.endsWith(`three.cjs`)?e.replace(/three\.cjs$/,`three.module.js`):e}var k=`https://shapescript.invalid`,A=`${k}/render.html`,j=`./three.module.js`;async function M(e,t,n){let r;try{r=new URL(e)}catch{return null}if(r.origin!==k)return null;let i=f.default.posix.basename(r.pathname);return i===`render.html`?{contentType:`text/html; charset=utf-8`,body:t}:/^three[\w.-]*\.js$/.test(i)?{contentType:`text/javascript; charset=utf-8`,body:await(0,l.readFile)(f.default.join(n,i),`utf-8`)}:null}async function N(e,t){let n=f.default.dirname(O());await e.setRequestInterception(!0),e.on(`request`,e=>{(async()=>{try{let r=await M(e.url(),t,n);await(r?e.respond({status:200,...r}):e.abort())}catch{}})()})}async function P(e){let t=await ee();if(!t)throw new C(S);let n=c.r(c.In(e.script)).toJSON(),r=g({...e,threeUrl:j,sceneJson:n}),i;try{i=await t.launch({headless:!0,timeout:b,args:[`--enable-unsafe-swiftshader`,`--use-gl=swiftshader`]})}catch(e){throw new C(`${S} (launch failed: ${v(e)})`)}try{let e=await i.newPage();await e.setViewport({width:800,height:600});let t=[];e.on(`pageerror`,e=>t.push(e.message)),await N(e,r),await e.goto(A,{waitUntil:`load`});try{await e.waitForFunction(`typeof window.__shapeSheet === 'string'`,{timeout:y})}catch(e){let n=t.length>0?`the render page failed: ${t.join(`; `)}`:v(e);throw Error(n,{cause:e})}let n=await e.evaluate(`window.__shapeSheet`);if(typeof n!=`string`||!n.startsWith(`data:image/png;base64,`))throw Error(`the render page produced no image`);return n.slice(22)}finally{await i.close().catch(t=>w(e.onWarning,`chromium close failed: ${v(t)}`))}}var F=30,I=25,L=1,R=480,z=900,B=160,V=85,H=x+3e4,U=`renderShapeScript`,W="Render a ShapeScript model to a PNG image and save it, so you can LOOK at the model you wrote and check it before showing it to the user. Returns the image path — read that file to see the result. By default it renders four camera angles onto one sheet, because a single view cannot settle what is in front of what. Takes the same source as presentShapeScript: inline `script`, or `path` to a saved .shape file.",G=`Use renderShapeScript to CHECK a 3D model you wrote before presenting it — it saves a PNG and returns the path, which you then read to see what the model actually looks like. Fix what you see and re-render. Rendering needs a local headless browser; if it reports one is missing, say so and continue with presentShapeScript rather than retrying.`,K={type:`object`,properties:{script:{type:`string`,description:"ShapeScript source to render. Provide either this or `path`, not both."},path:{type:`string`,description:`Path to an existing .shape file to render (e.g. one presentShapeScript saved under artifacts/shapes/).`},azimuth:{type:`number`,description:`Camera rotation around the model in degrees, 0 = looking from +Z. Default ${F}. In the default four-view sheet this is the FIRST view's angle; the others are offset from it.`},elevation:{type:`number`,description:`Camera height in degrees above the horizon, 90 = straight down. Default ${I}. Avoid 0 and 90 for the main view — an axis-aligned shot flattens depth.`},zoom:{type:`number`,description:`Multiplier on the automatic framing, which fits the whole model. 1 = fit (default), 2 = twice as close, 0.5 = further out. Prefer this over guessing a camera distance: it means the same thing at any model scale.`},views:{type:`string`,enum:[`quad`,`single`],description:"`quad` (default) renders four angles on one sheet — use it to judge shape and layout. `single` renders only `azimuth`/`elevation`, for a close look at one detail."},projection:{type:`string`,enum:[`perspective`,`orthographic`],description:"`perspective` (default) looks natural; `orthographic` keeps parallel edges parallel, which is better for comparing proportions."},width:{type:`number`,description:`Pixel width of ONE view. Default ${R}, clamped to ${B}–${z}.`},height:{type:`number`,description:`Pixel height of ONE view. Default ${R}, clamped to ${B}–${z}.`}},required:[]};function q(e,t){return typeof e!=`number`||!Number.isFinite(e)?t:Math.min(z,Math.max(B,Math.round(e)))}function J(e,t){return typeof e==`number`&&Number.isFinite(e)?e:t}var Y=e=>`${Math.round(e)}°`;function X(e,t,n){let r=(e,t,n)=>({azimuth:e,elevation:t,label:`${n} — az ${Y(e)}, el ${Y(t)}`});return n?[r(e,t,`view`)]:[r(e,t,`front-right`),r(e+90,t,`back-right`),r(e+180,t,`back-left`),r(e,V,`top`)]}async function Z(e,t){let n=typeof t.script==`string`&&t.script.trim()!==``?t.script:void 0,r=typeof t.path==`string`&&t.path.trim()!==``?t.path:void 0;if(n&&r)throw Error("Provide either `script` or `path`, not both");if(n)return n;if(r)return e.readShape(r);throw Error("Provide either `script` (inline source) or `path` (an existing .shape file)")}function Q(e,t,n,r){return{script:t,views:n,width:q(e.width,R),height:q(e.height,R),zoom:Math.max(J(e.zoom,L),.01),projection:e.projection===`orthographic`?`orthographic`:`perspective`,...r?{onWarning:r}:{}}}function $(e,t){let n=t.map(e=>e.label).join(`; `);return`Saved render to ${e} (${t.length===1?`1 view`:`${t.length} views`}: ${n}). Read that file to see the model.`}async function ne(e,t){let n=await Z(e,t),r=X(J(t.azimuth,F),J(t.elevation,I),t.views===`single`);try{let i=await P(Q(t,n,r,e.onWarning));return{message:$(await e.saveImage(i),r),rendered:!0}}catch(t){if(t instanceof C)return w(e.onWarning,`renderShapeScript: unavailable — ${t.message}`),{message:t.message,rendered:!1};throw t}}exports.CHROMIUM_HINT=S,exports.LAUNCH_TIMEOUT_MS=b,exports.RENDER_BUDGET_MS=x,exports.RENDER_SHAPE_SCRIPT_DESCRIPTION=W,exports.RENDER_SHAPE_SCRIPT_PROMPT=G,exports.RENDER_SHAPE_SCRIPT_SCHEMA=K,exports.RENDER_SHAPE_SCRIPT_TOOL_NAME=U,exports.RENDER_TIMEOUT_MS=y,exports.RENDER_TOOL_TIMEOUT_MS=H,exports.RenderUnavailableError=C,exports.buildRenderPage=g,exports.executeRenderShapeScript=ne,exports.gridFor=p,exports.renderOptionsFrom=Q,exports.renderShapeScriptSheet=P,exports.savedMessage=$,exports.viewAngles=X;
package/dist/render.js CHANGED
@@ -1,4 +1,4 @@
1
- import { In as e, Pn as t, n } from "./toThreeJS-B5LiF110.js";
1
+ import { In as e, Rn as t, r as n } from "./toThreeJS-FsP-Na75.js";
2
2
  import { readFile as r } from "node:fs/promises";
3
3
  import { createRequire as i } from "node:module";
4
4
  import { pathToFileURL as a } from "node:url";
@@ -91,13 +91,13 @@ function y() {
91
91
  throw Error("shapescript render: cannot locate this module to resolve three from");
92
92
  }
93
93
  var b = i(y());
94
- function x(t) {
95
- return e(t) && typeof t.launch == "function";
94
+ function x(e) {
95
+ return t(e) && typeof e.launch == "function";
96
96
  }
97
97
  async function S() {
98
98
  try {
99
- let t = await import("puppeteer");
100
- return x(t) ? t : e(t) && x(t.default) ? t.default : null;
99
+ let e = await import("puppeteer");
100
+ return x(e) ? e : t(e) && x(e.default) ? e.default : null;
101
101
  } catch {
102
102
  return null;
103
103
  }
@@ -145,11 +145,11 @@ async function k(e, t) {
145
145
  })();
146
146
  });
147
147
  }
148
- async function A(e) {
148
+ async function A(t) {
149
149
  let r = await S();
150
150
  if (!r) throw new _(g);
151
- let i = n(t(e.script)).toJSON(), a = u({
152
- ...e,
151
+ let i = n(e(t.script)).toJSON(), a = u({
152
+ ...t,
153
153
  threeUrl: D,
154
154
  sceneJson: i
155
155
  }), o;
@@ -180,7 +180,7 @@ async function A(e) {
180
180
  if (typeof n != "string" || !n.startsWith("data:image/png;base64,")) throw Error("the render page produced no image");
181
181
  return n.slice(22);
182
182
  } finally {
183
- await o.close().catch((t) => v(e.onWarning, `chromium close failed: ${f(t)}`));
183
+ await o.close().catch((e) => v(t.onWarning, `chromium close failed: ${f(e)}`));
184
184
  }
185
185
  }
186
186
  //#endregion