@snaptrude/plugin-core 0.9.16 → 0.9.18-voids-20261016.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.
Files changed (107) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/api-manifest.full.json +10406 -0
  3. package/api-manifest.json +827 -51
  4. package/dist/api/analysis/daylight.d.ts +5 -5
  5. package/dist/api/analysis/solar.d.ts +2 -2
  6. package/dist/api/core/camera/index.d.ts +29 -0
  7. package/dist/api/core/camera/index.d.ts.map +1 -1
  8. package/dist/api/core/geom/create/index.d.ts +7 -1
  9. package/dist/api/core/geom/create/index.d.ts.map +1 -1
  10. package/dist/api/core/geom/update/contour.d.ts +8 -2
  11. package/dist/api/core/geom/update/contour.d.ts.map +1 -1
  12. package/dist/api/core/zoom/index.d.ts +13 -0
  13. package/dist/api/core/zoom/index.d.ts.map +1 -1
  14. package/dist/api/design/bim.d.ts +209 -0
  15. package/dist/api/design/bim.d.ts.map +1 -0
  16. package/dist/api/design/boolean/index.d.ts +2 -0
  17. package/dist/api/design/boolean/index.d.ts.map +1 -1
  18. package/dist/api/design/catalog.d.ts +320 -0
  19. package/dist/api/design/catalog.d.ts.map +1 -0
  20. package/dist/api/design/create/bulk-items.d.ts +65 -25
  21. package/dist/api/design/create/bulk-items.d.ts.map +1 -1
  22. package/dist/api/design/create/index.d.ts +272 -99
  23. package/dist/api/design/create/index.d.ts.map +1 -1
  24. package/dist/api/design/create/opening-fields.d.ts +13 -12
  25. package/dist/api/design/create/opening-fields.d.ts.map +1 -1
  26. package/dist/api/design/delete/index.d.ts +1 -0
  27. package/dist/api/design/delete/index.d.ts.map +1 -1
  28. package/dist/api/design/doors/index.d.ts +18 -24
  29. package/dist/api/design/doors/index.d.ts.map +1 -1
  30. package/dist/api/design/family.d.ts +797 -27
  31. package/dist/api/design/family.d.ts.map +1 -1
  32. package/dist/api/design/index.d.ts +16 -0
  33. package/dist/api/design/index.d.ts.map +1 -1
  34. package/dist/api/design/networks.d.ts +1703 -0
  35. package/dist/api/design/networks.d.ts.map +1 -0
  36. package/dist/api/design/query/index.d.ts +42 -32
  37. package/dist/api/design/query/index.d.ts.map +1 -1
  38. package/dist/api/design/selection/index.d.ts +10 -10
  39. package/dist/api/design/types/index.d.ts +40 -24
  40. package/dist/api/design/types/index.d.ts.map +1 -1
  41. package/dist/api/design/update/index.d.ts +43 -3
  42. package/dist/api/design/update/index.d.ts.map +1 -1
  43. package/dist/api/design/windows/index.d.ts +8 -8
  44. package/dist/api/design/windows/index.d.ts.map +1 -1
  45. package/dist/api/presentation/aiInspiration.d.ts +10 -10
  46. package/dist/api/presentation/annotate.d.ts +38 -22
  47. package/dist/api/presentation/annotate.d.ts.map +1 -1
  48. package/dist/api/presentation/drawingContract.d.ts +32 -0
  49. package/dist/api/presentation/drawingContract.d.ts.map +1 -0
  50. package/dist/api/presentation/drawings.d.ts +3523 -0
  51. package/dist/api/presentation/drawings.d.ts.map +1 -0
  52. package/dist/api/presentation/export.d.ts +23 -5
  53. package/dist/api/presentation/export.d.ts.map +1 -1
  54. package/dist/api/presentation/index.d.ts +41 -12
  55. package/dist/api/presentation/index.d.ts.map +1 -1
  56. package/dist/api/presentation/placedViews.d.ts +106 -6
  57. package/dist/api/presentation/placedViews.d.ts.map +1 -1
  58. package/dist/api/presentation/sections.d.ts +461 -0
  59. package/dist/api/presentation/sections.d.ts.map +1 -0
  60. package/dist/api/presentation/shapes.d.ts +2 -2
  61. package/dist/api/presentation/sheets.d.ts +175 -19
  62. package/dist/api/presentation/sheets.d.ts.map +1 -1
  63. package/dist/api/presentation/viewPresets.d.ts +222 -0
  64. package/dist/api/presentation/viewPresets.d.ts.map +1 -0
  65. package/dist/api/presentation/views.d.ts +103 -5
  66. package/dist/api/presentation/views.d.ts.map +1 -1
  67. package/dist/api/presentation/walkthroughs.d.ts +6 -6
  68. package/dist/errors/codes.d.ts +3 -1
  69. package/dist/errors/codes.d.ts.map +1 -1
  70. package/dist/index.cjs +3749 -2328
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.js +3616 -2328
  73. package/dist/index.js.map +1 -1
  74. package/package.json +1 -1
  75. package/scripts/generate-manifest.mjs +5 -0
  76. package/src/api/core/camera/index.ts +29 -0
  77. package/src/api/core/geom/create/index.ts +7 -1
  78. package/src/api/core/geom/update/contour.ts +8 -2
  79. package/src/api/core/zoom/index.ts +13 -0
  80. package/src/api/design/bim.ts +121 -0
  81. package/src/api/design/boolean/index.ts +2 -0
  82. package/src/api/design/catalog.ts +203 -0
  83. package/src/api/design/create/bulk-items.ts +57 -17
  84. package/src/api/design/create/index.ts +288 -120
  85. package/src/api/design/create/opening-fields.ts +15 -12
  86. package/src/api/design/delete/index.ts +1 -0
  87. package/src/api/design/doors/index.ts +58 -42
  88. package/src/api/design/family.ts +662 -32
  89. package/src/api/design/index.ts +34 -4
  90. package/src/api/design/networks.ts +607 -0
  91. package/src/api/design/query/index.ts +12 -2
  92. package/src/api/design/types/index.ts +31 -24
  93. package/src/api/design/update/index.ts +44 -3
  94. package/src/api/design/windows/index.ts +40 -22
  95. package/src/api/presentation/annotate.ts +90 -58
  96. package/src/api/presentation/drawingContract.ts +70 -0
  97. package/src/api/presentation/drawings.ts +1179 -0
  98. package/src/api/presentation/export.ts +32 -6
  99. package/src/api/presentation/index.ts +48 -14
  100. package/src/api/presentation/placedViews.ts +119 -28
  101. package/src/api/presentation/sections.ts +420 -0
  102. package/src/api/presentation/sheets.ts +181 -20
  103. package/src/api/presentation/viewPresets.ts +241 -0
  104. package/src/api/presentation/views.ts +46 -6
  105. package/src/errors/codes.ts +7 -0
  106. package/test/drawingContract.test.mjs +288 -0
  107. package/test/errors.test.mjs +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snaptrude/plugin-core",
3
- "version": "0.9.16",
3
+ "version": "0.9.18-voids-20261016.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -115,6 +115,11 @@ export function buildManifest({ includeOptional = false } = {}) {
115
115
  const cls = classes.get(className)
116
116
  if (!cls) return
117
117
 
118
+ // Domain network namespaces inherit their transport methods. Include these
119
+ // leaves so discovery exposes the same API as the generic worker proxy.
120
+ const base = cls.getExtends()?.getExpression().getText()
121
+ if (base && classes.has(base)) walk(base, pathPrefix)
122
+
118
123
  // Leaf methods on this namespace.
119
124
  for (const method of cls.getMethods()) {
120
125
  const name = method.getName()
@@ -17,6 +17,11 @@ import { Vec3Components, Vec3Handle } from "../../../handles"
17
17
  * Positions are world coordinates in internal `babylon` units (1 unit =
18
18
  * 0.254 m, Y up); yaw is degrees clockwise from +z seen from above, pitch is
19
19
  * degrees above level.
20
+ *
21
+ * While Present mode is open these calls set the Design frame a view saved in
22
+ * Present (`presentation.views.create`) is taken from; they never move the
23
+ * Present sheet canvas. To pan, zoom or screenshot the Present canvas, use
24
+ * {@linkcode PluginPresentationCameraApi} (`presentation.camera`).
20
25
  */
21
26
  export abstract class PluginCameraApi {
22
27
  constructor() {}
@@ -25,6 +30,10 @@ export abstract class PluginCameraApi {
25
30
  * Point the camera: place its eye at `eye` looking toward `target` (world
26
31
  * coordinates, internal `babylon` units). View-state only — not undoable.
27
32
  *
33
+ * While Present is open this sets the Design frame a view saved in Present
34
+ * is taken from; it never moves the Present sheet canvas; use
35
+ * `presentation.camera` for that.
36
+ *
28
37
  * @param eye - Camera position as a {@linkcode Vec3Handle}
29
38
  * @param target - Point the camera looks at as a {@linkcode Vec3Handle}
30
39
  * @returns `true` once the camera has been positioned.
@@ -51,6 +60,10 @@ export abstract class PluginCameraApi {
51
60
  * perspective) view. Mirrors the canvas view menu. View-state only — not
52
61
  * undoable. The orthographic presets exit 2D mode first if needed.
53
62
  *
63
+ * While Present is open this sets the Design frame a view saved in Present
64
+ * is taken from; it never moves the Present sheet canvas; use
65
+ * `presentation.camera` for that.
66
+ *
54
67
  * @param view - The standard view to snap to ({@linkcode PluginStandardView})
55
68
  * @returns `true` once the view has been applied.
56
69
  *
@@ -91,6 +104,10 @@ export abstract class PluginCameraApi {
91
104
  * 2D/3D toggle: `3d` enters the isometric perspective view, `2d` drops to the
92
105
  * orthographic plan of the active storey. View-state only — not undoable.
93
106
  *
107
+ * While Present is open this sets the Design frame a view saved in Present
108
+ * is taken from; it never moves the Present sheet canvas; use
109
+ * `presentation.camera` for that.
110
+ *
94
111
  * @param mode - `"2d"` or `"3d"` ({@linkcode PluginCameraMode})
95
112
  * @returns `true` once the mode switch has been requested.
96
113
  *
@@ -135,6 +152,10 @@ export abstract class PluginCameraApi {
135
152
  * `"orthographic"` is accepted as a no-op, while `"perspective"` is
136
153
  * rejected — switch to 3D first via `setMode("3d")`.
137
154
  *
155
+ * While Present is open this sets the Design frame a view saved in Present
156
+ * is taken from; it never moves the Present sheet canvas; use
157
+ * `presentation.camera` for that.
158
+ *
138
159
  * @param projection - `"perspective"` or `"orthographic"` ({@linkcode PluginCameraProjection})
139
160
  * @returns `true` once the projection has been applied.
140
161
  *
@@ -158,6 +179,10 @@ export abstract class PluginCameraApi {
158
179
  * action. View-state only — not undoable. Canonical home of the zoom-extents
159
180
  * read (the deprecated `core.zoom.extents`).
160
181
  *
182
+ * While Present is open this sets the Design frame a view saved in Present
183
+ * is taken from; it never moves the Present sheet canvas; use
184
+ * `presentation.camera` for that.
185
+ *
161
186
  * @returns `true` once the camera has been framed to the scene.
162
187
  *
163
188
  * @examplePrompt Zoom out so I can see the whole model
@@ -177,6 +202,10 @@ export abstract class PluginCameraApi {
177
202
  * undoable. Canonical home of the zoom-to-selection read (the deprecated
178
203
  * `core.zoom.selection`).
179
204
  *
205
+ * While Present is open this sets the Design frame a view saved in Present
206
+ * is taken from; it never moves the Present sheet canvas; use
207
+ * `presentation.camera` for that.
208
+ *
180
209
  * @returns `true` if there was a selection to frame; `false` if nothing is
181
210
  * selected (no-op).
182
211
  *
@@ -317,6 +317,9 @@ export abstract class PluginGeomCreateApi {
317
317
  * Create a contour from an outer profile plus zero or more inner profiles (holes).
318
318
  * Host API call — returns a handle.
319
319
  *
320
+ * A hole here is part of the footprint and cannot be moved or deleted later;
321
+ * for an editable hole in a slab use `design.create.void`.
322
+ *
320
323
  * @param outer The outer boundary loop
321
324
  * @param holes Optional inner hole loops
322
325
  * @returns The new contour as a {@linkcode ContourHandle}
@@ -688,6 +691,9 @@ export abstract class PluginGeomCreateApi {
688
691
  * The first boolean call loads the OpenCascade geometry kernel (a wasm of
689
692
  * tens of MB — expect a pause of seconds); subsequent calls are fast.
690
693
  *
694
+ * Returns a detached solid; to cut an editable hole in a slab, floor or roof
695
+ * in the model use `design.create.void`.
696
+ *
691
697
  * @param a The solid to subtract from
692
698
  * @param b The solid to remove from `a`
693
699
  * @returns `a` minus `b` as a new {@linkcode BrepHandle}
@@ -696,7 +702,7 @@ export abstract class PluginGeomCreateApi {
696
702
  *
697
703
  * @examplePrompt Subtract the courtyard from the building mass
698
704
  * @examplePrompt Cut this solid out of that one
699
- * @examplePrompt Punch a hole through the slab with this box
705
+ * @examplePrompt Subtract this box solid from that solid
700
706
  *
701
707
  * # Example
702
708
  * ```ts
@@ -156,12 +156,15 @@ export abstract class PluginGeomUpdateContourApi {
156
156
  * Add a hole to a contour by appending an inner profile. Immutable — returns a NEW
157
157
  * contour and leaves the input unchanged.
158
158
  *
159
+ * Edits a contour value only; for an editable hole in an existing slab, floor
160
+ * or roof use `design.create.void`.
161
+ *
159
162
  * @param contour The contour to add a hole to
160
163
  * @param hole The inner profile to add as a hole
161
164
  * @returns The contour with the added hole as a NEW {@linkcode ContourHandle}
162
165
  *
163
166
  * @examplePrompt Cut a hole in this shape
164
- * @examplePrompt Punch an opening through this floor outline
167
+ * @examplePrompt Punch an opening through this outline
165
168
  *
166
169
  * # Example
167
170
  * ```ts
@@ -181,12 +184,15 @@ export abstract class PluginGeomUpdateContourApi {
181
184
  * Remove a hole from a contour by inner-profile index. Immutable — returns a NEW
182
185
  * contour and leaves the input unchanged.
183
186
  *
187
+ * Edits a contour value only; for an editable hole in an existing slab, floor
188
+ * or roof use `design.create.void`.
189
+ *
184
190
  * @param contour The contour to remove a hole from
185
191
  * @param index Zero-based index of the inner profile (hole) to remove
186
192
  * @returns The contour with the hole removed as a NEW {@linkcode ContourHandle}
187
193
  *
188
194
  * @examplePrompt Remove the hole from this shape
189
- * @examplePrompt Fill in the opening in this floor outline
195
+ * @examplePrompt Fill in the opening in this outline
190
196
  *
191
197
  * # Example
192
198
  * ```ts
@@ -5,6 +5,11 @@ import { PluginApiReturn } from "../../../types"
5
5
  *
6
6
  * Frame the viewport camera onto scene geometry — mirrors the canvas zoom menu
7
7
  * ("Zoom extents" / "Zoom to selection"). Accessed via `snaptrude.core.zoom`.
8
+ *
9
+ * While Present mode is open these calls set the Design frame a view saved in
10
+ * Present (`presentation.views.create`) is taken from; they never move the
11
+ * Present sheet canvas. To pan, zoom or screenshot the Present canvas, use
12
+ * {@linkcode PluginPresentationCameraApi} (`presentation.camera`).
8
13
  */
9
14
  export abstract class PluginZoomApi {
10
15
  constructor() {}
@@ -12,6 +17,10 @@ export abstract class PluginZoomApi {
12
17
  /**
13
18
  * Zoom (fit) the camera to all geometry in the scene — the "zoom extents" action.
14
19
  *
20
+ * While Present is open this sets the Design frame a view saved in Present
21
+ * is taken from; it never moves the Present sheet canvas; use
22
+ * `presentation.camera` for that.
23
+ *
15
24
  * @returns `true` once the camera has been framed to the scene.
16
25
  *
17
26
  * @examplePrompt Zoom out so I can see the whole model
@@ -32,6 +41,10 @@ export abstract class PluginZoomApi {
32
41
  /**
33
42
  * Zoom (fit) the camera to the current selection.
34
43
  *
44
+ * While Present is open this sets the Design frame a view saved in Present
45
+ * is taken from; it never moves the Present sheet canvas; use
46
+ * `presentation.camera` for that.
47
+ *
35
48
  * @returns `true` if there was a selection to frame; `false` if nothing is
36
49
  * selected (no-op).
37
50
  *
@@ -0,0 +1,121 @@
1
+ import * as z from "zod"
2
+ import { ComponentHandle } from "../../handles"
3
+ import type { PluginApiReturn } from "../../types"
4
+ import { PluginConstructionType, PluginFamilyValues } from "./catalog"
5
+ import { PluginFamilyBundleSchema } from "./family"
6
+
7
+ const id = z.string().min(1).max(300)
8
+ const spaces = z.array(ComponentHandle).min(1).max(1000)
9
+
10
+ /** Read scope. Omit spaces to inspect the active proposal's sketch spaces. */
11
+ export const PluginBimContextArgs = z.object({ spaces: spaces.optional() }).strict()
12
+ export type PluginBimContextArgs = z.infer<typeof PluginBimContextArgs>
13
+
14
+ /** Directed graph edge. Side A lies along world-up × curve-direction; side B is opposite.
15
+ * Region IDs are snapshot identifiers, not component handles. Null means no adjacent region.
16
+ */
17
+ export const PluginBimEdge = z.object({
18
+ id,
19
+ startMm: z.tuple([z.number(), z.number(), z.number()]),
20
+ endMm: z.tuple([z.number(), z.number(), z.number()]),
21
+ lengthMm: z.number(),
22
+ heightMm: z.number(),
23
+ sideA: id.nullable(),
24
+ sideB: id.nullable(),
25
+ wall: ComponentHandle.nullable(),
26
+ supported: z.boolean(),
27
+ })
28
+ export type PluginBimEdge = z.infer<typeof PluginBimEdge>
29
+
30
+ /** Construction context is detached. Revision covers geometry, room metadata and construction state. */
31
+ export const PluginBimContext = z.object({
32
+ revision: id,
33
+ proposalId: id,
34
+ units: z.literal("mm"),
35
+ spaces: z.array(z.object({
36
+ component: ComponentHandle,
37
+ label: z.string(),
38
+ storey: z.number(),
39
+ eligible: z.boolean(),
40
+ reason: z.string().optional(),
41
+ })),
42
+ regions: z.array(z.object({ id, spaces: z.array(ComponentHandle) })),
43
+ edges: z.array(PluginBimEdge),
44
+ })
45
+ export type PluginBimContext = z.infer<typeof PluginBimContext>
46
+
47
+ /** Plan-local key selects either an existing construction or a new project-only native recipe.
48
+ * Bundles use the native DSL's SU/unit-expression rules; values overrides use mm/degrees.
49
+ */
50
+ export const PluginBimConstruction = z.union([
51
+ z.object({ key: id, reference: PluginConstructionType }).strict(),
52
+ z.object({ key: id, bundle: PluginFamilyBundleSchema }).strict(),
53
+ ])
54
+ export type PluginBimConstruction = z.infer<typeof PluginBimConstruction>
55
+
56
+ /** Every unwalled edge in the selected scope needs exactly one assignment.
57
+ * The first authored layer faces sideA unless reversed. Alignment sets the initial core-centre offset.
58
+ * Later parameter edits preserve the offset and reject invalid core alignment.
59
+ */
60
+ export const PluginBimWallAssignment = z.object({
61
+ edgeId: id,
62
+ construction: id,
63
+ values: PluginFamilyValues.optional(),
64
+ reversed: z.boolean(),
65
+ alignment: z.literal("coreCentre"),
66
+ }).strict()
67
+ export type PluginBimWallAssignment = z.infer<typeof PluginBimWallAssignment>
68
+
69
+ export const PluginBimPrepareArgs = z.object({
70
+ revision: id,
71
+ spaces,
72
+ constructions: z.array(PluginBimConstruction).max(1000),
73
+ walls: z.array(PluginBimWallAssignment).max(10000),
74
+ }).strict()
75
+ export type PluginBimPrepareArgs = z.infer<typeof PluginBimPrepareArgs>
76
+
77
+ /** Expected recipe/plan failures are diagnostics. No scene or library change occurs during prepare. */
78
+ export const PluginBimPreparation = z.object({
79
+ ok: z.boolean(),
80
+ preparationId: id.optional(),
81
+ diagnostics: z.array(z.object({ path: z.string(), message: z.string() })),
82
+ })
83
+ export type PluginBimPreparation = z.infer<typeof PluginBimPreparation>
84
+ export const PluginBimCreateArgs = z.object({ preparationId: id }).strict()
85
+
86
+ /** Source IDs identify removed sketch spaces, not live handles. Successful storeys share one undo step.
87
+ * Failed storeys remain spaces. Cancellation rolls back the whole conversion. Persistence is queued
88
+ * through normal model commands; this result is not a durable server-save acknowledgement.
89
+ */
90
+ export const PluginBimResult = z.object({
91
+ status: z.enum(["created", "partial", "cancelled", "unchanged"]),
92
+ convertedSpaceIds: z.array(z.string()),
93
+ created: z.array(ComponentHandle),
94
+ kept: z.array(z.object({ space: ComponentHandle, reason: z.string() })),
95
+ })
96
+ export type PluginBimResult = z.infer<typeof PluginBimResult>
97
+
98
+ /** Agent-driven Sketch-to-BIM. Uses PG2 topology; never redraws routes or publishes library families. */
99
+ export abstract class PluginDesignBimApi {
100
+ /** Read room adjacency and native conversion eligibility in the active proposal.
101
+ * @param options Optional explicit spaces; filters edges but keeps adjacent room metadata.
102
+ * @returns Rooms, directed boundaries in mm, eligibility and revision.
103
+ * @examplePrompt Inspect the rooms on each side of these sketch wall boundaries
104
+ */
105
+ abstract getContext(options?: PluginBimContextArgs): PluginApiReturn<PluginBimContext>
106
+
107
+ /** Stage a complete wall-construction assignment. A new prepare replaces this plugin's prior plan.
108
+ * @param plan Exact context revision, selected spaces, constructions and edge assignments.
109
+ * @returns Diagnostics or an opaque preparation ID, scoped to the caller and current project.
110
+ * @examplePrompt Validate wall layer assignments before converting sketch rooms to BIM
111
+ */
112
+ abstract prepare(plan: PluginBimPrepareArgs): PluginApiReturn<PluginBimPreparation>
113
+
114
+ /** Execute native Sketch-to-BIM. Revalidates scope, catalogue access and construction before mutation.
115
+ * Uses native progress/cancel controls and worker cancellation. Floors/roofs retain project defaults.
116
+ * @param preparationId ID returned by prepare. Consumed once; stale or foreign IDs throw PRECONDITION_FAILED.
117
+ * @returns Created component handles and explicit converted/kept outcomes, including partial success.
118
+ * @examplePrompt Convert these sketch rooms to BIM with wall layers chosen for each room boundary
119
+ */
120
+ abstract create(preparationId: string): PluginApiReturn<PluginBimResult>
121
+ }
@@ -59,6 +59,8 @@ export abstract class PluginDesignBooleanApi {
59
59
  * boolean (CSG) subtraction that carves the tools' volume out of the target and
60
60
  * commits the remainder as a single undoable step.
61
61
  *
62
+ * Masses only. Slabs, floors and roofs take holes through `design.create.void`.
63
+ *
62
64
  * ORDER-SENSITIVE: the host seeds `[target, ...tools]`; index 0 is the arg brep,
63
65
  * the rest are tool breps. `deleted` includes the target AND every tool;
64
66
  * `created` is the remainder mass(es).
@@ -0,0 +1,203 @@
1
+ import * as z from "zod"
2
+ import { ContourHandle, LineHandle, Vec3Handle } from "../../handles"
3
+ import type { PluginApiReturn } from "../../types"
4
+ import {
5
+ PluginFamilyDefinitionParameter,
6
+ PluginFamilyBundleSchema,
7
+ } from "./family"
8
+ import { NetworkFamilyContract } from "./networks"
9
+
10
+ /** Exact saved family identity. A label or a selected Draw type is not an identity. */
11
+ export const PluginSavedFamilyReference = z
12
+ .object({
13
+ id: z.string().min(1),
14
+ version: z.number().int().positive(),
15
+ })
16
+ .strict()
17
+ export type PluginSavedFamilyReference = z.infer<
18
+ typeof PluginSavedFamilyReference
19
+ >
20
+
21
+ /** Public overrides: physical lengths use mm, angles use degrees. Omitted values retain defaults. */
22
+ export const PluginFamilyValues = z.record(
23
+ z.string(),
24
+ z.union([z.number().finite(), z.string(), z.boolean()]),
25
+ )
26
+ export type PluginFamilyValues = z.infer<typeof PluginFamilyValues>
27
+
28
+ /** Native construction uses a saved family or a project assembly token from the catalogue. */
29
+ export const PluginConstructionType = z.union([
30
+ PluginSavedFamilyReference,
31
+ z.string().min(1),
32
+ ])
33
+ export type PluginConstructionType = z.infer<typeof PluginConstructionType>
34
+
35
+ /** Family owns its layers/section. Geometry owns the footprint/axis; it is never a values override. */
36
+ export const PluginFamilyPlacement = z
37
+ .object({
38
+ type: PluginConstructionType,
39
+ values: PluginFamilyValues.optional(),
40
+ })
41
+ .strict()
42
+ export type PluginFamilyPlacement = z.infer<typeof PluginFamilyPlacement>
43
+
44
+ /** Sparse native family edit. Omitted type keeps the component's exact saved reference. */
45
+ export const PluginFamilyUpdates = PluginFamilyPlacement.partial().refine(
46
+ (updates) => updates.type !== undefined || updates.values !== undefined,
47
+ { message: "Supply a type or parameter values" },
48
+ )
49
+ export type PluginFamilyUpdates = z.infer<typeof PluginFamilyUpdates>
50
+
51
+ export const PluginFamilyFloorOptions = PluginFamilyPlacement.extend({
52
+ position: Vec3Handle.optional(),
53
+ })
54
+ export type PluginFamilyFloorOptions = z.infer<typeof PluginFamilyFloorOptions>
55
+ export const PluginFamilySlabOptions = PluginFamilyPlacement.extend({
56
+ direction: z.enum(["up", "down"]).optional(),
57
+ })
58
+ export type PluginFamilySlabOptions = z.infer<typeof PluginFamilySlabOptions>
59
+ export const PluginFamilyCeilingOptions = PluginFamilyPlacement.extend({
60
+ heightFromFloor: z.number().finite().optional(),
61
+ })
62
+ export type PluginFamilyCeilingOptions = z.infer<
63
+ typeof PluginFamilyCeilingOptions
64
+ >
65
+ export const PluginFamilyContourArgs = z.object({
66
+ contour: ContourHandle,
67
+ options: PluginFamilyPlacement,
68
+ })
69
+ export const PluginFamilyAxisArgs = z.object({
70
+ axis: LineHandle,
71
+ options: PluginFamilyPlacement,
72
+ })
73
+
74
+ /** Inventory includes architectural recipes, ordinary PCs, and the existing placement libraries. */
75
+ export const PluginCatalogKind = z.enum([
76
+ "wall",
77
+ "floor",
78
+ "slab",
79
+ "roof",
80
+ "ceiling",
81
+ "beam",
82
+ "column",
83
+ "component",
84
+ "door",
85
+ "window",
86
+ "furniture",
87
+ ])
88
+ export type PluginCatalogKind = z.infer<typeof PluginCatalogKind>
89
+ export const PluginCatalogReference = z.union([
90
+ PluginSavedFamilyReference,
91
+ // Project assemblies retain kind:name; asset tokens retain the underlying library identity.
92
+ z.string().min(1),
93
+ ])
94
+ export type PluginCatalogReference = z.infer<typeof PluginCatalogReference>
95
+
96
+ /** Read-only capability record. Availability is checked again on every mutation. */
97
+ export const PluginCatalogEntry = z.object({
98
+ reference: PluginCatalogReference,
99
+ label: z.string(),
100
+ kind: PluginCatalogKind,
101
+ source: z.enum(["native", "revit", "project", "asset"]),
102
+ createMethods: z.array(z.string()),
103
+ updateMethods: z.array(z.string()),
104
+ requirements: z.array(z.string()),
105
+ unsupportedReason: z.string().optional(),
106
+ parameters: z.array(PluginFamilyDefinitionParameter).optional(),
107
+ /** Parameter keys owned by native placement geometry, never accepted as values overrides. */
108
+ geometryParameters: z.array(z.string()),
109
+ network: NetworkFamilyContract.optional(),
110
+ /** get() includes the native wall recipe without opening a Family Studio draft.
111
+ * Bare recipe lengths use SU; parameter metadata and public values overrides use mm.
112
+ */
113
+ construction: PluginFamilyBundleSchema.optional(),
114
+ })
115
+ export type PluginCatalogEntry = z.infer<typeof PluginCatalogEntry>
116
+ export const PluginCatalogListArgs = z.object({
117
+ kind: PluginCatalogKind.optional(),
118
+ })
119
+ export const PluginCatalogGetArgs = z.object({
120
+ reference: PluginCatalogReference,
121
+ })
122
+
123
+ /** Search metadata is extensible. A slash separates category path segments. */
124
+ export const PluginCatalogSearchArgs = z
125
+ .object({
126
+ query: z.string().trim().max(200).optional(),
127
+ category: z.string().trim().max(1000).optional(),
128
+ limit: z.number().int().min(1).max(50).optional(),
129
+ cursor: z.string().min(1).max(16384).optional(),
130
+ })
131
+ .strict()
132
+ export type PluginCatalogSearchArgs = z.infer<typeof PluginCatalogSearchArgs>
133
+
134
+ /** Browse one hierarchy level without enumerating families or fetching recipe bodies. */
135
+ export const PluginCatalogListCategoriesArgs = z
136
+ .object({
137
+ parent: z.string().trim().max(1000).optional(),
138
+ after: z.string().max(1000).optional(),
139
+ limit: z.number().int().min(1).max(100).optional(),
140
+ })
141
+ .strict()
142
+ export type PluginCatalogListCategoriesArgs = z.infer<
143
+ typeof PluginCatalogListCategoriesArgs
144
+ >
145
+
146
+ /** Metadata only: the category does not establish placement capabilities or recipe validity. */
147
+ export const PluginCatalogCategory = z.object({
148
+ categoryPath: z.array(z.string()).min(1),
149
+ hasChildren: z.boolean(),
150
+ })
151
+ export type PluginCatalogCategory = z.infer<typeof PluginCatalogCategory>
152
+
153
+ /** Metadata only. Read get(reference) to validate a selected family and inspect placement methods. */
154
+ export const PluginCatalogSummary = z.object({
155
+ reference: PluginCatalogReference,
156
+ label: z.string(),
157
+ categoryPath: z.array(z.string()),
158
+ description: z.string(),
159
+ source: PluginCatalogEntry.shape.source,
160
+ })
161
+ export type PluginCatalogSummary = z.infer<typeof PluginCatalogSummary>
162
+ export const PluginCatalogSearchResult = z.object({
163
+ items: z.array(PluginCatalogSummary),
164
+ nextCursor: z.string().nullable(),
165
+ })
166
+ export type PluginCatalogSearchResult = z.infer<
167
+ typeof PluginCatalogSearchResult
168
+ >
169
+
170
+ /** Shared read surface over existing libraries. Does not publish, register, or place definitions. */
171
+ export abstract class PluginDesignCatalogApi {
172
+ /**
173
+ * Discover categories from accessible saved families and current project constructions.
174
+ * Omit parent for roots; pass a slash-separated returned path for its direct children.
175
+ * This metadata read does not fetch recipes, include unsaved drafts or legacy mesh inventories,
176
+ * or establish capabilities. Use search then get before placement. Names retain their case.
177
+ * @param args Parent path, exclusive after-name, and page limit (default 50, maximum 100).
178
+ * For another page at the same parent, pass the last item's final categoryPath segment as after.
179
+ * @returns Categories in Unicode code-point order, with descendant flags. Stop when a page has
180
+ * fewer than limit items. Live pagination is not a snapshot. Metadata-service failures reject.
181
+ */
182
+ abstract listCategories(
183
+ args?: PluginCatalogListCategoriesArgs,
184
+ ): PluginApiReturn<PluginCatalogCategory[]>
185
+ /**
186
+ * Search accessible saved-family and project-construction metadata without downloading recipes.
187
+ * Categories are data, not an SDK enum. Legacy mesh inventories and unsaved drafts are excluded.
188
+ * Inspect selected references with get before placement; a search match does not prove validity
189
+ * or supported behavior. Pagination reads live data, not a snapshot. Failures reject.
190
+ * @param args Text/category filters, page limit (default 20, maximum 50), and opaque cursor.
191
+ * @returns Compact metadata and continuation. Continue until nextCursor is null or a suitable
192
+ * family is found. Concurrent changes can leave an empty page with continuation.
193
+ */
194
+ abstract search(
195
+ args?: PluginCatalogSearchArgs,
196
+ ): PluginApiReturn<PluginCatalogSearchResult>
197
+ /** @param kind Optional element filter. @returns Accessible entries and their supported API paths. */
198
+ abstract list(kind?: PluginCatalogKind): PluginApiReturn<PluginCatalogEntry[]>
199
+ /** @param reference Exact reference from search or list. @returns The current entry, or null when unavailable. */
200
+ abstract get(
201
+ reference: PluginCatalogReference,
202
+ ): PluginApiReturn<PluginCatalogEntry | null>
203
+ }
@@ -1,6 +1,13 @@
1
1
  import * as z from "zod"
2
- import { ContourHandle, ProfileHandle, Vec3Handle } from "../../../handles"
2
+ import {
3
+ ComponentHandle,
4
+ ContourHandle,
5
+ ProfileHandle,
6
+ Vec3Handle,
7
+ } from "../../../handles"
3
8
  import { PluginOpeningBaseOptions } from "./opening-fields"
9
+ import { PluginWallType } from "../types"
10
+ import { PluginFamilyValues } from "../catalog"
4
11
 
5
12
  /**
6
13
  * Maximum items per bulk `design.create.*` call. A bounded request keeps
@@ -88,7 +95,7 @@ export type PluginWallTopProfile = z.infer<typeof PluginWallTopProfile>
88
95
  * | `profile` | {@linkcode ProfileHandle} | Ordered curve chain (wall centerlines) |
89
96
  * | `height` | `number`? | Wall height (Snaptrude units, > 0; default engine default) |
90
97
  * | `thickness` | `number`? | Wall thickness (Snaptrude units, > 0; default: `wallType`'s total layer thickness when given, else engine default) |
91
- * | `wallType` | `string`? | Wall type name from `design.types.list("wall")` — layers/material/thickness defaults (default generic) |
98
+ * | `wallType` | {@linkcode PluginWallType}? | Legacy name/id or exact native `{ id, version }` pin from `design.types.list("wall")` (default generic) |
92
99
  * | `storey` | `number`? (int) | Target storey (must exist) — the run's walls are assigned + lifted to its base in the same undo entry (default: geometry-derived) |
93
100
  * | `topProfiles` | ({@linkcode PluginWallTopProfile} \| `null`)[]? | Top edge per curve of `profile`, same order; a `null` or missing entry keeps that wall flat at `height`. Raked / gabled walls (straight curves only) |
94
101
  */
@@ -96,9 +103,11 @@ export const PluginCreateWallRunItem = z.object({
96
103
  profile: ProfileHandle,
97
104
  height: z.number().optional(),
98
105
  thickness: z.number().optional(),
99
- wallType: z.string().min(1).optional(),
106
+ wallType: PluginWallType.optional(),
100
107
  storey: z.number().int().optional(),
101
108
  topProfiles: z.array(PluginWallTopProfile.nullable()).optional(),
109
+ /** Optional family overrides in mm/degrees. Host length/height stay geometry inputs. */
110
+ values: PluginFamilyValues.optional(),
102
111
  })
103
112
  export type PluginCreateWallRunItem = z.infer<typeof PluginCreateWallRunItem>
104
113
 
@@ -143,22 +152,23 @@ export type PluginCreateFloorItems = z.infer<typeof PluginCreateFloorItems>
143
152
 
144
153
  /**
145
154
  * One door to place via {@linkcode PluginDesignCreateApi.doors} — the same
146
- * fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}, so the
147
- * size overrides singular {@linkcode PluginDesignCreateApi.door} lacks are
148
- * available per item. `facing` and `hinge` are WORLD POINTS, not directions:
149
- * `facing` on the side of the wall the door swings open to, `hinge` near the
150
- * jamb it is hinged on. Rejects unknown fields.
155
+ * fields as a `"door"` {@linkcode PluginDesignCreateOpeningOptions}.
156
+ * Values are evaluated before cutting. Numeric lengths use SU; unit strings
157
+ * are accepted in values. `facing` selects local +Z; `hinge` sets the declared
158
+ * hand enum (left = local -X, right = +X). Both are world points.
151
159
  *
152
160
  * | Property | Type | Description |
153
161
  * |---|---|---|
154
- * | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
162
+ * | `familyId` | `string` | Hosted door family definition ID |
163
+ * | `version` | `number`? | Exact version; newest known by default |
164
+ * | `values` | `Record<string, number \| string>`? | Authored parameter overrides |
155
165
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the door |
156
166
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
157
167
  * | `facing` | {@linkcode Vec3Handle}? | World point on the side the door swings open to (default engine-chosen) |
158
- * | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the door is hinged on (default the catalog item's authored side) |
168
+ * | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires hand control |
159
169
  * | `label` | `string`? | Instance name (optional) |
160
- * | `width` | `number`? | Width override (Snaptrude units, > 0; default the catalog item's) |
161
- * | `height` | `number`? | Height override (Snaptrude units, > 0; default the catalog item's) |
170
+ * | `width` | `number`? | Declared width parameter (SU, > 0), not evaluated hole width |
171
+ * | `height` | `number`? | Declared height parameter (SU, > 0) |
162
172
  */
163
173
  export const PluginCreateDoorItem = z
164
174
  .object({ ...PluginOpeningBaseOptions })
@@ -183,15 +193,17 @@ export type PluginCreateDoorItems = z.infer<typeof PluginCreateDoorItems>
183
193
  *
184
194
  * | Property | Type | Description |
185
195
  * |---|---|---|
186
- * | `catalogId` | `string` | Library id: team `_id` or general `fullName` |
196
+ * | `familyId` | `string` | Hosted window family definition ID |
197
+ * | `version` | `number`? | Exact version; newest known by default |
198
+ * | `values` | `Record<string, number \| string>`? | Authored parameter overrides; numeric lengths use SU |
187
199
  * | `hostWall` | {@linkcode ComponentHandle} | The wall to host the window |
188
200
  * | `position` | {@linkcode Vec3Handle} | World point projected onto the wall |
189
201
  * | `facing` | {@linkcode Vec3Handle}? | World point on the side the window opens to (default engine-chosen) |
190
- * | `hinge` | {@linkcode Vec3Handle}? | World point near the jamb the window is hinged on (default the catalog item's authored side) |
202
+ * | `hinge` | {@linkcode Vec3Handle}? | World point near the hinged jamb; requires hand control |
191
203
  * | `label` | `string`? | Instance name (optional) |
192
- * | `width` | `number`? | Width override (Snaptrude units, > 0; default the catalog item's) |
193
- * | `height` | `number`? | Height override (Snaptrude units, > 0; default the catalog item's) |
194
- * | `sillHeight` | `number`? | Wall base to window bottom (Snaptrude units, ≥ 0; default the catalog item's) |
204
+ * | `width` | `number`? | Declared width parameter (SU, > 0), not evaluated hole width |
205
+ * | `height` | `number`? | Declared height parameter (SU, > 0) |
206
+ * | `sillHeight` | `number`? | Declared sill parameter (SU, ≥ 0); position Y is ignored |
195
207
  */
196
208
  export const PluginCreateWindowItem = z
197
209
  .object({
@@ -252,3 +264,31 @@ export const PluginCreateFurnitureItems = z
252
264
  export type PluginCreateFurnitureItems = z.infer<
253
265
  typeof PluginCreateFurnitureItems
254
266
  >
267
+
268
+ // ---------------------------------------------------------------------------
269
+ // voids
270
+ // ---------------------------------------------------------------------------
271
+
272
+ /**
273
+ * One void to cut via {@linkcode PluginDesignCreateApi.voids} — the same fields as
274
+ * {@linkcode PluginDesignCreateApi.void}. Rejects unknown fields.
275
+ *
276
+ * | Property | Type | Description |
277
+ * | --- | --- | --- |
278
+ * | `host` | {@linkcode ComponentHandle} | The slab, floor, roof or ceiling to cut through. Not a wall. |
279
+ * | `outline` | {@linkcode ProfileHandle} | Closed, flat plan outline in world SU (all points at one height). That height is ignored: it is dropped straight onto the host's top face. |
280
+ */
281
+ export const PluginCreateVoidItem = z
282
+ .object({
283
+ host: ComponentHandle,
284
+ outline: ProfileHandle,
285
+ })
286
+ .strict()
287
+ export type PluginCreateVoidItem = z.infer<typeof PluginCreateVoidItem>
288
+
289
+ /** The `items` array of {@linkcode PluginDesignCreateApi.voids} (1…1000; the host takes at most 200, 50 per host). */
290
+ export const PluginCreateVoidItems = z
291
+ .array(PluginCreateVoidItem)
292
+ .min(1)
293
+ .max(PLUGIN_CREATE_BATCH_LIMIT)
294
+ export type PluginCreateVoidItems = z.infer<typeof PluginCreateVoidItems>