@snaptrude/plugin-core 0.9.14 → 0.9.16-networks-20261008.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 (73) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/api/analysis/daylight.d.ts +5 -5
  3. package/dist/api/analysis/solar.d.ts +2 -2
  4. package/dist/api/core/camera/index.d.ts +418 -0
  5. package/dist/api/core/camera/index.d.ts.map +1 -1
  6. package/dist/api/core/index.d.ts +4 -4
  7. package/dist/api/core/index.d.ts.map +1 -1
  8. package/dist/api/core/layers.d.ts +377 -255
  9. package/dist/api/core/layers.d.ts.map +1 -1
  10. package/dist/api/core/proposals/index.d.ts +4 -3
  11. package/dist/api/core/proposals/index.d.ts.map +1 -1
  12. package/dist/api/core/storeys/index.d.ts +12 -0
  13. package/dist/api/core/storeys/index.d.ts.map +1 -1
  14. package/dist/api/core/storeys/layers.d.ts +408 -0
  15. package/dist/api/core/storeys/layers.d.ts.map +1 -0
  16. package/dist/api/core/tags.d.ts +3 -3
  17. package/dist/api/design/bim.d.ts +209 -0
  18. package/dist/api/design/bim.d.ts.map +1 -0
  19. package/dist/api/design/catalog.d.ts +242 -0
  20. package/dist/api/design/catalog.d.ts.map +1 -0
  21. package/dist/api/design/create/bulk-items.d.ts +55 -3
  22. package/dist/api/design/create/bulk-items.d.ts.map +1 -1
  23. package/dist/api/design/create/index.d.ts +77 -22
  24. package/dist/api/design/create/index.d.ts.map +1 -1
  25. package/dist/api/design/family.d.ts +576 -12
  26. package/dist/api/design/family.d.ts.map +1 -1
  27. package/dist/api/design/index.d.ts +16 -0
  28. package/dist/api/design/index.d.ts.map +1 -1
  29. package/dist/api/design/networks.d.ts +1703 -0
  30. package/dist/api/design/networks.d.ts.map +1 -0
  31. package/dist/api/design/query/index.d.ts +30 -30
  32. package/dist/api/design/selection/index.d.ts +12 -12
  33. package/dist/api/design/types/index.d.ts +40 -24
  34. package/dist/api/design/types/index.d.ts.map +1 -1
  35. package/dist/api/design/update/index.d.ts +113 -3
  36. package/dist/api/design/update/index.d.ts.map +1 -1
  37. package/dist/api/presentation/aiInspiration.d.ts +23 -23
  38. package/dist/api/presentation/camera.d.ts +265 -0
  39. package/dist/api/presentation/camera.d.ts.map +1 -0
  40. package/dist/api/presentation/index.d.ts +14 -0
  41. package/dist/api/presentation/index.d.ts.map +1 -1
  42. package/dist/api/presentation/placedViews.d.ts +1 -1
  43. package/dist/api/presentation/views.d.ts +3 -1
  44. package/dist/api/presentation/views.d.ts.map +1 -1
  45. package/dist/api/presentation/walkthroughs.d.ts +1350 -0
  46. package/dist/api/presentation/walkthroughs.d.ts.map +1 -0
  47. package/dist/index.cjs +3886 -2598
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.js +3744 -2595
  50. package/dist/index.js.map +1 -1
  51. package/package.json +1 -1
  52. package/scripts/generate-manifest.mjs +5 -0
  53. package/scripts/generate-manifest.test.mjs +14 -3
  54. package/src/api/core/camera/index.ts +400 -1
  55. package/src/api/core/index.ts +4 -4
  56. package/src/api/core/layers.ts +380 -173
  57. package/src/api/core/proposals/index.ts +4 -3
  58. package/src/api/core/storeys/index.ts +14 -0
  59. package/src/api/core/storeys/layers.ts +339 -0
  60. package/src/api/design/bim.ts +121 -0
  61. package/src/api/design/catalog.ts +128 -0
  62. package/src/api/design/create/bulk-items.ts +74 -2
  63. package/src/api/design/create/index.ts +92 -36
  64. package/src/api/design/family.ts +448 -17
  65. package/src/api/design/index.ts +34 -4
  66. package/src/api/design/networks.ts +607 -0
  67. package/src/api/design/types/index.ts +31 -24
  68. package/src/api/design/update/index.ts +121 -4
  69. package/src/api/presentation/camera.ts +289 -0
  70. package/src/api/presentation/index.ts +14 -0
  71. package/src/api/presentation/views.ts +3 -1
  72. package/src/api/presentation/walkthroughs.ts +1201 -0
  73. package/api-manifest.json +0 -9117
@@ -1,6 +1,7 @@
1
1
  import * as z from "zod";
2
2
  import { PluginApiReturn } from "../../types";
3
3
  import { BrepHandle, ComponentHandle } from "../../handles";
4
+ import { NetworkFamilyContract } from "./networks";
4
5
  /**
5
6
  * `snaptrude.design.family.*` — author NATIVE parametric families from a JSON spec.
6
7
  *
@@ -11,19 +12,36 @@ import { BrepHandle, ComponentHandle } from "../../handles";
11
12
  * compiles that into a live parametric definition the user can place, flex and
12
13
  * save to their library.
13
14
  *
14
- * ## Workflow
15
+ * ## Generic component workflow
15
16
  *
16
17
  * ```
17
- * getReference() read the spec DSL once — grammar, ops, expressions, example
18
- * prepare({ bundle }) validate + compile + show a live ghost; nothing committed
18
+ * getReference() read the spec DSL once — grammar, ops, expressions, examples
19
+ * getExamples() worked example families by discipline; getExamples({ id }) for one
20
+ * prepare({ bundle }) validate + compile; nothing committed, nothing in the viewport
19
21
  * flex({ values }) re-run at new values; returns the geometry delta
20
22
  * place({ position }) put it in the model — saves the family as the first instance drops
21
23
  * place() save the family, then arm placement — the USER clicks to drop it
24
+ * create() save an EDIT of a saved family — the app asks the user
22
25
  * create({ teamId }) share with a team; a save with nothing placed also drops one instance
23
26
  * ```
24
27
  *
25
28
  * `place` saves the prepared family to the user's personal library, so it
26
- * survives reload with no extra step; finish on `place`, not on `create`.
29
+ * survives reload with no extra step; finish a NEW generic component on
30
+ * `place`, not on `create` (`create` ends only an edit of a saved family, below).
31
+ *
32
+ * For architectural families, use `create({ name })` to save the prepared recipe.
33
+ * Read `design.catalog` and pass the saved `{ id, version }` reference to the
34
+ * native `design.create` method with its contour, wall profile, or straight axis.
35
+ * Standalone placement does not create a native host. Selecting a Draw type
36
+ * does not register an API type. Native creator values use mm, while this
37
+ * generic family API uses SU. Read `family_authoring` for the full workflow.
38
+ *
39
+ * ## Changing a saved family
40
+ *
41
+ * Open it with `get({ id })` or `get({ component })`, edit with `prepare` /
42
+ * `flex`, then `create()`. The app — not the agent — asks the user whether to
43
+ * update that family (this project's placed copies move to the new version) or
44
+ * save a new family. Do not ask this yourself; report the returned `decision`.
27
45
  *
28
46
  * ## Read getReference() first
29
47
  *
@@ -81,6 +99,28 @@ export declare abstract class PluginDesignFamilyApi {
81
99
  * ```
82
100
  */
83
101
  abstract getReference(): PluginApiReturn<PluginFamilyReference>;
102
+ /**
103
+ * Worked example families to learn from: real, tested bundles by discipline
104
+ * (architecture, structure, MEP, furniture). With no `id`, returns the
105
+ * catalogue — each example's id, label, discipline and the patterns it
106
+ * teaches — filtered by `discipline` / `tag` when given. With an `id`,
107
+ * returns that example's full bundle. Fetch the one closest to the task
108
+ * before authoring and borrow its patterns; examples are patterns to
109
+ * combine, not templates to copy whole.
110
+ *
111
+ * @param args - `{ id }` for one bundle, or `{ discipline?, tag? }` to list
112
+ * @returns The catalogue, or one example with its bundle
113
+ *
114
+ * @examplePrompt Show me an example of a structural family
115
+ * @examplePrompt How is a hosted door family written?
116
+ *
117
+ * # Example
118
+ * ```ts
119
+ * const list = await snaptrude.design.family.getExamples({ discipline: "mep" })
120
+ * const ex = await snaptrude.design.family.getExamples({ id: list[0].id })
121
+ * ```
122
+ */
123
+ abstract getExamples(args?: PluginDesignFamilyGetExamplesArgs): PluginApiReturn<PluginFamilyExampleSummary[] | PluginFamilyExample>;
84
124
  /**
85
125
  * Validate, compile and preview a family spec. Nothing is committed to the
86
126
  * model or the library — call {@linkcode PluginDesignFamilyApi.place} to put
@@ -132,16 +172,36 @@ export declare abstract class PluginDesignFamilyApi {
132
172
  */
133
173
  abstract flex(args: PluginDesignFamilyFlexArgs): PluginApiReturn<PluginFamilyFlexResult>;
134
174
  /**
135
- * The prepared family's spec bundle, or `null` when nothing is prepared.
175
+ * A family's spec bundle: the prepared draft's, or — to CHANGE a saved
176
+ * family — that family's recipe, opened as the new draft.
177
+ *
178
+ * - No arguments: the prepared draft, or `null` when nothing is prepared.
179
+ * - `{ id, version? }`: open a saved family from the library (newest version
180
+ * when `version` is omitted).
181
+ * - `{ component }`: open the family (at its version) of that placed copy.
182
+ *
183
+ * Opening makes the recipe the current draft and returns `editing` — which
184
+ * saved family it is. Edit it with `prepare` / `flex`, then call `create`.
185
+ * On that save the APP shows the user its own window asking whether to
186
+ * update the family (every placed copy in this project moves to the new
187
+ * version) or save it as a new family — "new family" is the default. Never
188
+ * ask the user this yourself, and never promise either outcome: report what
189
+ * `create` returns.
136
190
  *
137
- * @returns The draft bundle, or `null`
191
+ * @param args Optional: which saved family to open
192
+ * @returns The bundle (plus `editing` when it edits a saved family), or `null`
193
+ *
194
+ * @examplePrompt Make the chairs I placed 50 mm wider
195
+ * @examplePrompt Change the Louvre Screen family so its blades are deeper
138
196
  *
139
197
  * # Example
140
198
  * ```ts
141
- * const bundle = await snaptrude.design.family.get()
199
+ * const draft = await snaptrude.design.family.get()
200
+ * const family = await snaptrude.design.family.get({ component })
201
+ * // family.editing → { familyId, version, name, library }
142
202
  * ```
143
203
  */
144
- abstract get(): PluginApiReturn<PluginFamilyBundle | null>;
204
+ abstract get(args?: PluginDesignFamilyGetArgs): PluginApiReturn<PluginFamilyGetResult | null>;
145
205
  /**
146
206
  * Every parametric family registered in this session — native and imported.
147
207
  *
@@ -155,6 +215,23 @@ export declare abstract class PluginDesignFamilyApi {
155
215
  * ```
156
216
  */
157
217
  abstract list(): PluginApiReturn<PluginFamilySummary[]>;
218
+ /**
219
+ * Read one saved catalog definition without opening a draft or placing geometry.
220
+ * Both id and version are required. The catalog checks access on every read.
221
+ * Length defaults and bounds are in mm, ready for network graph overrides;
222
+ * angle parameters retain degrees, identified by each parameter's unit.
223
+ * existing getParameters/place/setParameters continue to use Snaptrude units.
224
+ * Defaults include current catalog overrides, which can change without a new version.
225
+ * No scene, registry, history, or persistence state is changed.
226
+ * Missing/inaccessible pins and invalid recipes fail; no latest-version fallback.
227
+ * This metadata does not certify connectors or engineering compatibility.
228
+ *
229
+ * @param args Exact saved catalog id and version, from list()
230
+ * @returns Compact parameter metadata, not geometry or the recipe bundle
231
+ * @example
232
+ * const definition = await snaptrude.design.family.getDefinition({ id, version })
233
+ */
234
+ abstract getDefinition(args: PluginDesignFamilyGetDefinitionArgs): PluginApiReturn<PluginFamilyDefinition>;
158
235
  /**
159
236
  * Put a family into the model — either the prepared draft or any family from
160
237
  * {@linkcode PluginDesignFamilyApi.list}.
@@ -177,6 +254,13 @@ export declare abstract class PluginDesignFamilyApi {
177
254
  * To COPY a placed component, place its family again at the new position with
178
255
  * the same `values` — there is no separate copy call.
179
256
  *
257
+ * HOSTED families (doors, windows — anything with an `opening`, a `host`
258
+ * block, or a void with `cuts: "host"`) take `host`: a wall or a placed
259
+ * family. The family is set into the host's face nearest `position` (the
260
+ * host's middle when omitted), and the host is cut — a system wall by the
261
+ * wall cutter, a family by its own recipe. Host-bound parameters then follow
262
+ * the host (a door's wall thickness follows the wall).
263
+ *
180
264
  * @param args Which family, where, and at what parameter values
181
265
  * @returns What was placed; `component` is present only in positioned mode
182
266
  *
@@ -196,6 +280,9 @@ export declare abstract class PluginDesignFamilyApi {
196
280
  *
197
281
  * // interactive — the user clicks
198
282
  * await snaptrude.design.family.place()
283
+ *
284
+ * // hosted — a door in a wall, near a point along it
285
+ * await snaptrude.design.family.place({ id: doorId, host: wall, position: { x: 3, y: 0, z: 0 } })
199
286
  * ```
200
287
  */
201
288
  abstract place(args?: PluginDesignFamilyPlaceArgs): PluginApiReturn<PluginFamilyPlaceResult>;
@@ -232,6 +319,34 @@ export declare abstract class PluginDesignFamilyApi {
232
319
  * that does not is accepted and stored (it round-trips to Revit) but nothing
233
320
  * visible happens — say so rather than claiming a change the user cannot see.
234
321
  *
322
+ * NESTED children: `children: { "<path>": { key: value } }` sets a nested
323
+ * child's own values (every copy of it). A value its parent sets is sent up
324
+ * to what it follows when that is a plain relationship; otherwise it is
325
+ * refused with what to change instead (see `refused`).
326
+ *
327
+ * LINKS: `links: { key: { from, expr } }` makes this family's `key` follow
328
+ * another placed object — `from` is a family (it reports its parameters and
329
+ * outputs) or a wall (it reports thickness, length, height); `expr` is an
330
+ * expression over those reports. `null` removes a link. Links that would
331
+ * make objects follow each other in a loop are refused. Values accept unit
332
+ * literals ("600mm").
333
+ *
334
+ * RELATIONS: `relations: { add: [...], remove: ["r1"] }` sets how the family
335
+ * sits against other placed objects or cuts its host:
336
+ * - `attach` — `{ kind: "attach", side: "base" | "top", to: <object> | { level, face? }, offset? }`:
337
+ * sits on a surface, or its top reaches one (reports `reach`, `gap`, `surface`).
338
+ * - `join` — `{ kind: "join", end, to: <family>, toEnd, bindOther? }`: its end moves onto
339
+ * the other's end (reports `angle`, `absAngle`, `mitre`).
340
+ * - `span` — `{ kind: "span", from, to, at? }`: pinned between two objects, running along
341
+ * its +X (reports `distance`, `run`, `rise`, `slope`, `from.*`, `to.*`).
342
+ * - `path` — `{ kind: "path", from? | points, closed? }`: follows a wall's centreline, a
343
+ * family's run or given points (reports `length`; the recipe reads the path).
344
+ * - `cut` — `{ kind: "cut", to: "host" }`: applies recipe voids to the current host.
345
+ * Removing it closes the opening without detaching or deleting the family.
346
+ * Door/window placement adds it. Hosting alone does not cut. No parameter binds.
347
+ * Placement relations take `bind: { <param>: "<expression over its reports>" }`; bound
348
+ * parameters are read-only. A relation with an existing `id` replaces it.
349
+ *
235
350
  * `length` values are Snaptrude units: the same 254 mm unit as the kernel's
236
351
  * internal (`"babylon"`) unit — convert the user's number with
237
352
  * `core.units.convert` first; a bare `400` is 400 SU, not 400 mm. Kernel part
@@ -246,6 +361,15 @@ export declare abstract class PluginDesignFamilyApi {
246
361
  * # Example
247
362
  * ```ts
248
363
  * await snaptrude.design.family.setParameters({ component, values: { seats: 8 } })
364
+ * await snaptrude.design.family.setParameters({ component, children: { chair: { width: "380mm" } } })
365
+ * await snaptrude.design.family.setParameters({
366
+ * component: railing,
367
+ * links: { steps: { from: stair, expr: "steps" }, side: { from: stair, expr: "width - 40mm" } },
368
+ * })
369
+ * await snaptrude.design.family.setParameters({
370
+ * component: post,
371
+ * relations: { add: [{ kind: "attach", side: "top", to: slab, bind: { height: "reach" } }] },
372
+ * })
249
373
  * ```
250
374
  */
251
375
  abstract setParameters(args: PluginDesignFamilySetParametersArgs): PluginApiReturn<PluginFamilyInstanceParameters>;
@@ -256,8 +380,17 @@ export declare abstract class PluginDesignFamilyApi {
256
380
  * in the model yet, one instance is also dropped at the centre of the current
257
381
  * view on the active storey (`placed: true`), so a save is never invisible.
258
382
  *
383
+ * When the draft edits a saved family (opened with `get({ id })` /
384
+ * `get({ component })`), or its name is already taken in that library, the
385
+ * APP asks the user in its own window whether to save a new version of that
386
+ * family — every placed copy in this project moves to it, and families
387
+ * nesting it may be offered theirs — or a new family ("new family" is the
388
+ * default). The agent never asks this itself and cannot answer the window.
389
+ * `decision` reports what the user chose; `"cancelled"` means nothing was
390
+ * saved (`ok: false`) and nothing will auto-save until `create` is called again.
391
+ *
259
392
  * @param args Optional library name and team scope
260
- * @returns The catalogued definition's id and version
393
+ * @returns The catalogued definition's id and version, and what the user chose
261
394
  *
262
395
  * @examplePrompt Save this as a family called Vertical Louvre
263
396
  * @examplePrompt Add it to my library
@@ -292,6 +425,20 @@ export declare abstract class PluginDesignFamilyApi {
292
425
  */
293
426
  abstract delete(args?: PluginDesignFamilyDeleteArgs): PluginApiReturn<PluginFamilyDeleteResult>;
294
427
  }
428
+ /** One worked example in the catalogue returned by `getExamples`. */
429
+ export interface PluginFamilyExampleSummary {
430
+ id: string;
431
+ label: string;
432
+ discipline: "architecture" | "structure" | "mep" | "furniture";
433
+ /** The patterns it demonstrates, e.g. "nesting", "slot", "path", "union", "trim". */
434
+ teaches: string[];
435
+ /** Size of the bundle as compact JSON, kilobytes — what fetching it costs. */
436
+ sizeKB: number;
437
+ }
438
+ /** One worked example with its full bundle, from `getExamples({ id })`. */
439
+ export interface PluginFamilyExample extends PluginFamilyExampleSummary {
440
+ bundle: PluginFamilyBundle;
441
+ }
295
442
  /** The family-spec DSL reference returned by `getReference`. */
296
443
  export interface PluginFamilyReference {
297
444
  /** Grammar, op table, expression whitelist, repair contract, worked example. */
@@ -309,6 +456,31 @@ export interface PluginFamilyReference {
309
456
  export interface PluginFamilyBundle {
310
457
  root: Record<string, unknown>;
311
458
  deps?: Record<string, Record<string, unknown>>;
459
+ /** Connector metadata saved with the recipe; network placement evaluates these expressions. */
460
+ network?: NetworkFamilyContract;
461
+ }
462
+ /** Which saved family a draft edits. */
463
+ export interface PluginFamilyEditing {
464
+ /** Library id of the family being edited. */
465
+ familyId: string;
466
+ /** The version that was opened. */
467
+ version: number;
468
+ /** Its library name — an update saves under this name. */
469
+ name: string;
470
+ /** "your library", or the team library's name. */
471
+ library: string;
472
+ }
473
+ /** What `get` returns: the bundle, plus `editing` when the draft edits a saved family. */
474
+ export interface PluginFamilyGetResult extends PluginFamilyBundle {
475
+ editing?: PluginFamilyEditing;
476
+ }
477
+ /** A family at a version, as `create` reports parents it did or did not update. */
478
+ export interface PluginFamilyVersionRef {
479
+ id: string;
480
+ name: string;
481
+ version: number;
482
+ /** Set when the user chose to update it but the update failed. */
483
+ error?: string;
312
484
  }
313
485
  /** Axis-aligned extents of a built family. Snaptrude units (1 SU = 254 mm), +Y up. */
314
486
  export interface PluginFamilyBBox {
@@ -342,7 +514,11 @@ export interface PluginFamilyParameter {
342
514
  export interface PluginFamilyDiagnostic {
343
515
  /** JSON pointer, e.g. `"/root/geometry/2/body/0/w"`. */
344
516
  path: string;
345
- code: "schema" | "bad-expression" | "unknown-name" | "unknown-def" | "cycle" | "duplicate-name" | "unbounded-repeat" | "depth" | "bad-dimension" | "proportion";
517
+ code: "schema" | "bad-expression" | "unknown-name" | "unknown-def" | "cycle" | "duplicate-name" | "unbounded-repeat" | "depth" | "bad-dimension" | "proportion"
518
+ /** A part the geometry kernel could not build exactly; drawn approximately. */
519
+ | "kernel-fallback"
520
+ /** A part whose hole loop crosses its outline. */
521
+ | "profile-hole";
346
522
  message: string;
347
523
  hint?: string;
348
524
  }
@@ -437,6 +613,93 @@ export interface PluginFamilySummary {
437
613
  */
438
614
  kind: "native" | "revit";
439
615
  }
616
+ /** Exact catalog pin. Unsaved session definitions are not catalog inventory. */
617
+ export declare const PluginDesignFamilyGetDefinitionArgs: z.ZodObject<{
618
+ id: z.ZodString;
619
+ version: z.ZodNumber;
620
+ }, z.core.$strip>;
621
+ export type PluginDesignFamilyGetDefinitionArgs = z.infer<typeof PluginDesignFamilyGetDefinitionArgs>;
622
+ /** Saved-family metadata. Physical lengths use mm; angle entries retain degrees. */
623
+ export declare const PluginFamilyDefinitionParameter: z.ZodObject<{
624
+ key: z.ZodString;
625
+ label: z.ZodString;
626
+ type: z.ZodEnum<{
627
+ boolean: "boolean";
628
+ enum: "enum";
629
+ length: "length";
630
+ text: "text";
631
+ integer: "integer";
632
+ }>;
633
+ unit: z.ZodOptional<z.ZodEnum<{
634
+ mm: "mm";
635
+ degrees: "degrees";
636
+ }>>;
637
+ default: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
638
+ min: z.ZodOptional<z.ZodNumber>;
639
+ max: z.ZodOptional<z.ZodNumber>;
640
+ options: z.ZodOptional<z.ZodArray<z.ZodString>>;
641
+ drivesGeometry: z.ZodBoolean;
642
+ readOnly: z.ZodBoolean;
643
+ formulaDriven: z.ZodBoolean;
644
+ isInstance: z.ZodBoolean;
645
+ }, z.core.$strip>;
646
+ export type PluginFamilyDefinitionParameter = z.infer<typeof PluginFamilyDefinitionParameter>;
647
+ /** Read-only catalog inventory. Boolean defaults retain the family DSL's Yes/No strings. */
648
+ export declare const PluginFamilyDefinition: z.ZodObject<{
649
+ id: z.ZodString;
650
+ version: z.ZodNumber;
651
+ label: z.ZodString;
652
+ category: z.ZodOptional<z.ZodString>;
653
+ lengthUnit: z.ZodLiteral<"mm">;
654
+ parameters: z.ZodArray<z.ZodObject<{
655
+ key: z.ZodString;
656
+ label: z.ZodString;
657
+ type: z.ZodEnum<{
658
+ boolean: "boolean";
659
+ enum: "enum";
660
+ length: "length";
661
+ text: "text";
662
+ integer: "integer";
663
+ }>;
664
+ unit: z.ZodOptional<z.ZodEnum<{
665
+ mm: "mm";
666
+ degrees: "degrees";
667
+ }>>;
668
+ default: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
669
+ min: z.ZodOptional<z.ZodNumber>;
670
+ max: z.ZodOptional<z.ZodNumber>;
671
+ options: z.ZodOptional<z.ZodArray<z.ZodString>>;
672
+ drivesGeometry: z.ZodBoolean;
673
+ readOnly: z.ZodBoolean;
674
+ formulaDriven: z.ZodBoolean;
675
+ isInstance: z.ZodBoolean;
676
+ }, z.core.$strip>>;
677
+ network: z.ZodOptional<z.ZodObject<{
678
+ schemaVersion: z.ZodLiteral<1>;
679
+ role: z.ZodEnum<{
680
+ pipe: "pipe";
681
+ duct: "duct";
682
+ wire: "wire";
683
+ cable: "cable";
684
+ conduit: "conduit";
685
+ cableDuct: "cableDuct";
686
+ cableTray: "cableTray";
687
+ connector: "connector";
688
+ equipment: "equipment";
689
+ }>;
690
+ lengthParameter: z.ZodOptional<z.ZodString>;
691
+ ports: z.ZodArray<z.ZodObject<{
692
+ id: z.ZodString;
693
+ position: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
694
+ direction: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
695
+ size: z.ZodString;
696
+ height: z.ZodOptional<z.ZodString>;
697
+ widthDirection: z.ZodOptional<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>>;
698
+ systems: z.ZodArray<z.ZodString>;
699
+ }, z.core.$strict>>;
700
+ }, z.core.$strict>>;
701
+ }, z.core.$strip>;
702
+ export type PluginFamilyDefinition = z.infer<typeof PluginFamilyDefinition>;
440
703
  /** What `place` reports. */
441
704
  export interface PluginFamilyPlaceResult {
442
705
  ok: boolean;
@@ -464,6 +727,108 @@ export interface PluginFamilyInstanceParameters {
464
727
  parts?: PluginFamilyPart[];
465
728
  /** Present when `getParameters` was asked for a `snapshot`. */
466
729
  snapshot?: PluginFamilySnapshot;
730
+ /** The family's `outputs`, as last built. */
731
+ reports?: Record<string, number | string>;
732
+ /** Every declared nested child, as last built. */
733
+ children?: PluginFamilyNestedChild[];
734
+ /** Parameters that follow another object (links) or the host. */
735
+ follows?: PluginFamilyFollow[];
736
+ /** Where a hosted family sits: a system wall, or a family by id. */
737
+ host?: ({
738
+ kind: "wall";
739
+ } | {
740
+ kind: "family";
741
+ id: string;
742
+ }) & {
743
+ /** True when the host no longer has room for it: it is out of the model until it fits again. */
744
+ parked?: boolean;
745
+ };
746
+ /** Guests hosted in THIS family that no longer fit it (parked); they return when they fit. */
747
+ parkedGuests?: {
748
+ id: string;
749
+ family: string;
750
+ }[];
751
+ /** How it sits against other placed objects (attach, join, span, path), with current reports. */
752
+ relations?: PluginFamilyRelation[];
753
+ /** setParameters only: the edits refused, each with what to change instead. */
754
+ refused?: string[];
755
+ }
756
+ /** A nested child of a placed family. */
757
+ export interface PluginFamilyNestedChild {
758
+ /** "chair", or "chair/cushion" for a child of a child — the key for `children` edits. */
759
+ path: string;
760
+ label: string;
761
+ /** The family it is now (a slot's current pick). */
762
+ family: string;
763
+ familyLabel: string;
764
+ /** How many copies the parent places. */
765
+ copies: number;
766
+ slot?: {
767
+ expr: string;
768
+ options: string[];
769
+ };
770
+ values: Record<string, number | string>;
771
+ /** Values the parent sets, with the expression it sets them by. */
772
+ setBy: Record<string, string | undefined>;
773
+ reports: Record<string, number | string>;
774
+ }
775
+ /** A placed relation as stored, plus what it measures now. */
776
+ export type PluginFamilyRelation = PluginFamilyRelationInput & {
777
+ id: string;
778
+ /** "Attached to", "Joins", "Spans between", "Along a path", "Cuts host". */
779
+ label: string;
780
+ summary: string;
781
+ /** False when a target is gone: the family stayed where it was. */
782
+ live: boolean;
783
+ reports: Record<string, number | string>;
784
+ };
785
+ /** One relation to add (`relations.add`). Targets are handles, except a cut's symbolic "host". */
786
+ export type PluginFamilyRelationInput = {
787
+ /** Replaces the relation with this id; a new one gets "r1", "r2"… */
788
+ id?: string;
789
+ /** This family's parameter → an expression over the relation's reports and own parameters. */
790
+ bind?: Record<string, string>;
791
+ } & ({
792
+ kind: "attach";
793
+ side: "base" | "top";
794
+ to: ComponentHandle | {
795
+ level: number;
796
+ face?: "base" | "top";
797
+ };
798
+ offset?: number;
799
+ } | {
800
+ kind: "join";
801
+ end: "start" | "end";
802
+ to: ComponentHandle;
803
+ toEnd: "start" | "end";
804
+ /** The other family's parameters, over the same reports. */
805
+ bindOther?: Record<string, string>;
806
+ } | {
807
+ kind: "span";
808
+ from: ComponentHandle;
809
+ to: ComponentHandle;
810
+ at?: "top" | "centre" | "base";
811
+ } | {
812
+ kind: "path";
813
+ from?: ComponentHandle;
814
+ points?: [number, number, number][];
815
+ closed?: boolean;
816
+ } | {
817
+ /** Apply recipe voids to the existing host without adding another host ID. */
818
+ kind: "cut";
819
+ to: "host";
820
+ bind?: never;
821
+ });
822
+ /** One parameter that follows something else. */
823
+ export interface PluginFamilyFollow {
824
+ key: string;
825
+ /** "relation": set by a placed relation — `from` is the relation's id. */
826
+ kind: "link" | "host" | "relation";
827
+ /** The source's id. */
828
+ from: string;
829
+ fromLabel: string;
830
+ /** The expression over the source's reports (for a host: the report name). */
831
+ expr: string;
467
832
  }
468
833
  /** What `create` reports. */
469
834
  export interface PluginFamilyCreateResult {
@@ -475,6 +840,36 @@ export interface PluginFamilyCreateResult {
475
840
  placed?: boolean;
476
841
  /** Host guidance for the caller, e.g. that an instance was placed at the view centre. */
477
842
  hint?: string;
843
+ /**
844
+ * What the user chose in the app's window: `"version"` (a new version of
845
+ * the saved family), `"new"` (a new family), `"cancelled"` (nothing saved).
846
+ * `"saved"` = no question was needed.
847
+ */
848
+ decision?: "version" | "new" | "cancelled" | "saved";
849
+ /** The library name it was saved under. */
850
+ name?: string;
851
+ /** Placed copies in this project moved to the new version (the family's and updated parents'). */
852
+ movedCopies?: number;
853
+ /** What the moved copies lost because the new version no longer has it. */
854
+ dropped?: {
855
+ values: Array<{
856
+ copy: string;
857
+ key: string;
858
+ }>;
859
+ childValues: Array<{
860
+ copy: string;
861
+ path: string;
862
+ }>;
863
+ follows: Array<{
864
+ copy: string;
865
+ key: string;
866
+ kind: "link" | "relation";
867
+ }>;
868
+ };
869
+ /** Families nesting this one that the user chose to update, at their new versions. */
870
+ parentsUpdated?: PluginFamilyVersionRef[];
871
+ /** Families nesting this one that keep their version. */
872
+ parentsKept?: PluginFamilyVersionRef[];
478
873
  error?: string;
479
874
  }
480
875
  /** What `delete` reports. */
@@ -497,6 +892,30 @@ export interface PluginFamilyDeleteResult {
497
892
  export declare const PluginFamilyBundleSchema: z.ZodObject<{
498
893
  root: z.ZodRecord<z.ZodString, z.ZodUnknown>;
499
894
  deps: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
895
+ network: z.ZodOptional<z.ZodObject<{
896
+ schemaVersion: z.ZodLiteral<1>;
897
+ role: z.ZodEnum<{
898
+ pipe: "pipe";
899
+ duct: "duct";
900
+ wire: "wire";
901
+ cable: "cable";
902
+ conduit: "conduit";
903
+ cableDuct: "cableDuct";
904
+ cableTray: "cableTray";
905
+ connector: "connector";
906
+ equipment: "equipment";
907
+ }>;
908
+ lengthParameter: z.ZodOptional<z.ZodString>;
909
+ ports: z.ZodArray<z.ZodObject<{
910
+ id: z.ZodString;
911
+ position: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
912
+ direction: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
913
+ size: z.ZodString;
914
+ height: z.ZodOptional<z.ZodString>;
915
+ widthDirection: z.ZodOptional<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>>;
916
+ systems: z.ZodArray<z.ZodString>;
917
+ }, z.core.$strict>>;
918
+ }, z.core.$strict>>;
500
919
  }, z.core.$strip>;
501
920
  /**
502
921
  * Arguments for {@linkcode PluginDesignFamilyApi.prepare}.
@@ -517,7 +936,24 @@ export declare const PluginFamilyBundleSchema: z.ZodObject<{
517
936
  * the viewport is not moved — and comes back as a PNG data URL in the result's
518
937
  * `snapshot.image`. Through the agent's `run_worker`, return the result and the
519
938
  * image reaches the model as an image.
939
+ *
940
+ * `focus` makes it a close-up: `{ parts: ["seat", "back", "slat@*"] }` frames
941
+ * those parts (`*` matches any run of characters; nested names are `a/b`) with
942
+ * a margin of a quarter of their size (at least 50 mm), so a joint is "the two
943
+ * parts that meet"; `{ box: { min, max } }` frames a region in family space
944
+ * (Snaptrude units, +Y up). Every other part is still drawn; the dimension line
945
+ * then gives the framed region and the result says `closeUp: true`. A part
946
+ * name that matches nothing fails the snapshot with a list of real names.
520
947
  */
948
+ export declare const PluginFamilySnapshotFocus: z.ZodUnion<readonly [z.ZodObject<{
949
+ parts: z.ZodArray<z.ZodString>;
950
+ }, z.core.$strip>, z.ZodObject<{
951
+ box: z.ZodObject<{
952
+ min: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
953
+ max: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
954
+ }, z.core.$strip>;
955
+ }, z.core.$strip>]>;
956
+ export type PluginFamilySnapshotFocus = z.infer<typeof PluginFamilySnapshotFocus>;
521
957
  export declare const PluginFamilySnapshotOption: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
522
958
  views: z.ZodOptional<z.ZodArray<z.ZodEnum<{
523
959
  top: "top";
@@ -526,6 +962,14 @@ export declare const PluginFamilySnapshotOption: z.ZodUnion<readonly [z.ZodBoole
526
962
  iso: "iso";
527
963
  }>>>;
528
964
  tileSize: z.ZodOptional<z.ZodNumber>;
965
+ focus: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
966
+ parts: z.ZodArray<z.ZodString>;
967
+ }, z.core.$strip>, z.ZodObject<{
968
+ box: z.ZodObject<{
969
+ min: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
970
+ max: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
971
+ }, z.core.$strip>;
972
+ }, z.core.$strip>]>>;
529
973
  }, z.core.$strip>]>;
530
974
  export type PluginFamilySnapshotOption = z.infer<typeof PluginFamilySnapshotOption>;
531
975
  /** The picture block on prepare / flex / getParameters results when `snapshot` was asked for. */
@@ -534,9 +978,11 @@ export interface PluginFamilySnapshot {
534
978
  /** PNG data URL of the composed sheet. */
535
979
  image?: string;
536
980
  views?: ("iso" | "front" | "right" | "top")[];
537
- /** [width, height, depth] in Snaptrude units. */
981
+ /** [width, height, depth] in Snaptrude units — of the framed region when `closeUp`. */
538
982
  size?: [number, number, number];
539
983
  ms?: number;
984
+ /** True when the sheet is a close-up (`focus`), not the whole family. */
985
+ closeUp?: boolean;
540
986
  /** Set when the picture could not be taken (e.g. the legacy renderer); the call itself still succeeded. */
541
987
  error?: string;
542
988
  }
@@ -544,10 +990,58 @@ export declare const PluginDesignFamilyPrepareArgs: z.ZodObject<{
544
990
  bundle: z.ZodOptional<z.ZodObject<{
545
991
  root: z.ZodRecord<z.ZodString, z.ZodUnknown>;
546
992
  deps: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
993
+ network: z.ZodOptional<z.ZodObject<{
994
+ schemaVersion: z.ZodLiteral<1>;
995
+ role: z.ZodEnum<{
996
+ pipe: "pipe";
997
+ duct: "duct";
998
+ wire: "wire";
999
+ cable: "cable";
1000
+ conduit: "conduit";
1001
+ cableDuct: "cableDuct";
1002
+ cableTray: "cableTray";
1003
+ connector: "connector";
1004
+ equipment: "equipment";
1005
+ }>;
1006
+ lengthParameter: z.ZodOptional<z.ZodString>;
1007
+ ports: z.ZodArray<z.ZodObject<{
1008
+ id: z.ZodString;
1009
+ position: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
1010
+ direction: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
1011
+ size: z.ZodString;
1012
+ height: z.ZodOptional<z.ZodString>;
1013
+ widthDirection: z.ZodOptional<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>>;
1014
+ systems: z.ZodArray<z.ZodString>;
1015
+ }, z.core.$strict>>;
1016
+ }, z.core.$strict>>;
547
1017
  }, z.core.$strip>>;
548
1018
  spec: z.ZodOptional<z.ZodObject<{
549
1019
  root: z.ZodRecord<z.ZodString, z.ZodUnknown>;
550
1020
  deps: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
1021
+ network: z.ZodOptional<z.ZodObject<{
1022
+ schemaVersion: z.ZodLiteral<1>;
1023
+ role: z.ZodEnum<{
1024
+ pipe: "pipe";
1025
+ duct: "duct";
1026
+ wire: "wire";
1027
+ cable: "cable";
1028
+ conduit: "conduit";
1029
+ cableDuct: "cableDuct";
1030
+ cableTray: "cableTray";
1031
+ connector: "connector";
1032
+ equipment: "equipment";
1033
+ }>;
1034
+ lengthParameter: z.ZodOptional<z.ZodString>;
1035
+ ports: z.ZodArray<z.ZodObject<{
1036
+ id: z.ZodString;
1037
+ position: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
1038
+ direction: z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>;
1039
+ size: z.ZodString;
1040
+ height: z.ZodOptional<z.ZodString>;
1041
+ widthDirection: z.ZodOptional<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodString], null>>;
1042
+ systems: z.ZodArray<z.ZodString>;
1043
+ }, z.core.$strict>>;
1044
+ }, z.core.$strict>>;
551
1045
  }, z.core.$strip>>;
552
1046
  snapshot: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
553
1047
  views: z.ZodOptional<z.ZodArray<z.ZodEnum<{
@@ -557,6 +1051,14 @@ export declare const PluginDesignFamilyPrepareArgs: z.ZodObject<{
557
1051
  iso: "iso";
558
1052
  }>>>;
559
1053
  tileSize: z.ZodOptional<z.ZodNumber>;
1054
+ focus: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
1055
+ parts: z.ZodArray<z.ZodString>;
1056
+ }, z.core.$strip>, z.ZodObject<{
1057
+ box: z.ZodObject<{
1058
+ min: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
1059
+ max: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
1060
+ }, z.core.$strip>;
1061
+ }, z.core.$strip>]>>;
560
1062
  }, z.core.$strip>]>>;
561
1063
  }, z.core.$strip>;
562
1064
  export type PluginDesignFamilyPrepareArgs = z.infer<typeof PluginDesignFamilyPrepareArgs>;
@@ -578,9 +1080,53 @@ export declare const PluginDesignFamilyFlexArgs: z.ZodObject<{
578
1080
  iso: "iso";
579
1081
  }>>>;
580
1082
  tileSize: z.ZodOptional<z.ZodNumber>;
1083
+ focus: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
1084
+ parts: z.ZodArray<z.ZodString>;
1085
+ }, z.core.$strip>, z.ZodObject<{
1086
+ box: z.ZodObject<{
1087
+ min: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
1088
+ max: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
1089
+ }, z.core.$strip>;
1090
+ }, z.core.$strip>]>>;
581
1091
  }, z.core.$strip>]>>;
582
1092
  }, z.core.$strip>;
583
1093
  export type PluginDesignFamilyFlexArgs = z.infer<typeof PluginDesignFamilyFlexArgs>;
1094
+ /**
1095
+ * Arguments for {@linkcode PluginDesignFamilyApi.get}. All optional — no
1096
+ * arguments returns the prepared draft.
1097
+ *
1098
+ * | Property | Type | Description |
1099
+ * |---|---|---|
1100
+ * | `id` | `string` | A saved family to open for editing, from {@linkcode PluginDesignFamilyApi.list} |
1101
+ * | `version` | `number` | Exact version to open; defaults to the newest |
1102
+ * | `component` | {@linkcode ComponentHandle} | Open the family of this placed copy, at its version |
1103
+ */
1104
+ export declare const PluginDesignFamilyGetArgs: z.ZodObject<{
1105
+ id: z.ZodOptional<z.ZodString>;
1106
+ version: z.ZodOptional<z.ZodNumber>;
1107
+ component: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>>;
1108
+ }, z.core.$strip>;
1109
+ export type PluginDesignFamilyGetArgs = z.infer<typeof PluginDesignFamilyGetArgs>;
1110
+ /**
1111
+ * Arguments for {@linkcode PluginDesignFamilyApi.getExamples}.
1112
+ *
1113
+ * | Property | Type | Description |
1114
+ * |---|---|---|
1115
+ * | `id` | `string` | One example's id — returns its bundle |
1116
+ * | `discipline` | `string` | List only this discipline: architecture, structure, mep, furniture |
1117
+ * | `tag` | `string` | List only examples teaching this pattern (e.g. "path", "union") |
1118
+ */
1119
+ export declare const PluginDesignFamilyGetExamplesArgs: z.ZodObject<{
1120
+ id: z.ZodOptional<z.ZodString>;
1121
+ discipline: z.ZodOptional<z.ZodEnum<{
1122
+ architecture: "architecture";
1123
+ structure: "structure";
1124
+ mep: "mep";
1125
+ furniture: "furniture";
1126
+ }>>;
1127
+ tag: z.ZodOptional<z.ZodString>;
1128
+ }, z.core.$strip>;
1129
+ export type PluginDesignFamilyGetExamplesArgs = z.infer<typeof PluginDesignFamilyGetExamplesArgs>;
584
1130
  /**
585
1131
  * Arguments for {@linkcode PluginDesignFamilyApi.create}.
586
1132
  *
@@ -630,6 +1176,7 @@ export declare const PluginDesignFamilyPlaceArgs: z.ZodObject<{
630
1176
  rotation: z.ZodOptional<z.ZodNumber>;
631
1177
  values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
632
1178
  storey: z.ZodOptional<z.ZodNumber>;
1179
+ host: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>>;
633
1180
  }, z.core.$strip>;
634
1181
  export type PluginDesignFamilyPlaceArgs = z.infer<typeof PluginDesignFamilyPlaceArgs>;
635
1182
  /**
@@ -649,6 +1196,14 @@ export declare const PluginDesignFamilyGetParametersArgs: z.ZodObject<{
649
1196
  iso: "iso";
650
1197
  }>>>;
651
1198
  tileSize: z.ZodOptional<z.ZodNumber>;
1199
+ focus: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
1200
+ parts: z.ZodArray<z.ZodString>;
1201
+ }, z.core.$strip>, z.ZodObject<{
1202
+ box: z.ZodObject<{
1203
+ min: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
1204
+ max: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
1205
+ }, z.core.$strip>;
1206
+ }, z.core.$strip>]>>;
652
1207
  }, z.core.$strip>]>>;
653
1208
  }, z.core.$strip>;
654
1209
  export type PluginDesignFamilyGetParametersArgs = z.infer<typeof PluginDesignFamilyGetParametersArgs>;
@@ -662,7 +1217,16 @@ export type PluginDesignFamilyGetParametersArgs = z.infer<typeof PluginDesignFam
662
1217
  */
663
1218
  export declare const PluginDesignFamilySetParametersArgs: z.ZodObject<{
664
1219
  component: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
665
- values: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
1220
+ values: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>>;
1221
+ children: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>>;
1222
+ links: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
1223
+ from: z.ZodPipe<z.ZodString, z.ZodTransform<ComponentHandle, string>>;
1224
+ expr: z.ZodString;
1225
+ }, z.core.$strip>, z.ZodNull]>>>;
1226
+ relations: z.ZodOptional<z.ZodObject<{
1227
+ add: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
1228
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
1229
+ }, z.core.$strip>>;
666
1230
  }, z.core.$strip>;
667
1231
  export type PluginDesignFamilySetParametersArgs = z.infer<typeof PluginDesignFamilySetParametersArgs>;
668
1232
  //# sourceMappingURL=family.d.ts.map